diff -Nru opencryptoki-3.16.0+dfsg/ChangeLog opencryptoki-3.17.0+dfsg+20220202.b40982e/ChangeLog --- opencryptoki-3.16.0+dfsg/ChangeLog 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/ChangeLog 2022-02-02 15:05:41.000000000 +0100 @@ -1,3 +1,9 @@ ++ openCryptoki 3.17 +- tools: added function to list keys to p11sak +- common: added support for OpenSSL 3.0 +- common: added support for event notifications +- ICA: added SW fallbacks + + openCryptoki 3.16 - EP11: protected-key option - EP11: support attribute-bound keys diff -Nru opencryptoki-3.16.0+dfsg/configure.ac opencryptoki-3.17.0+dfsg+20220202.b40982e/configure.ac --- opencryptoki-3.16.0+dfsg/configure.ac 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/configure.ac 2022-02-02 15:05:41.000000000 +0100 @@ -1,12 +1,12 @@ dnl Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) -AC_INIT([openCryptoki],[3.16.0],[opencryptoki-tech@lists.sourceforge.net],[],[https://github.com/opencryptoki/opencryptoki]) +AC_INIT([openCryptoki],[3.17.0],[https://github.com/opencryptoki/opencryptoki/issues],[],[https://github.com/opencryptoki/opencryptoki]) AC_CONFIG_SRCDIR([testcases/common/common.c]) dnl Needed for $target! AC_CANONICAL_TARGET -AM_INIT_AUTOMAKE([-Wall -Wno-portability foreign subdir-objects]) +AM_INIT_AUTOMAKE([-Wall -Wno-override -Wno-portability foreign subdir-objects]) dnl Checks for header files. AC_DISABLE_STATIC @@ -39,10 +39,8 @@ AC_FUNC_ALLOCA AC_FUNC_CHOWN AC_FUNC_FORK -AC_FUNC_MALLOC AC_FUNC_MKTIME AC_FUNC_MMAP -AC_FUNC_REALLOC AC_FUNC_STRERROR_R AC_CHECK_FUNCS([atexit ftruncate gettimeofday localtime_r memchr memmove \ memset mkdir munmap regcomp select socket strchr strcspn \ @@ -65,13 +63,9 @@ AC_MSG_ERROR(['flex' is missing on your system. Please install 'flex'.]) fi -AC_PROG_YACC -if test "x$YACC" = "xyacc"; then - # AC_PROG_YACC only checks for yacc replacements, not for yacc itself - AC_CHECK_PROG([YACC_FOUND], [yacc], [yes], [no]) - if test "x$YACC_FOUND" = "xno"; then - AC_MSG_ERROR(['YACC' program is missing on your system. Please install 'bison'.]) - fi +AC_CHECK_PROG([YACC], [bison], [bison], [no]) +if test "x$YACC" = "xno"; then + AC_MSG_ERROR(['bison' program is missing on your system. Please install 'bison'.]) fi AC_CHECK_LIB([itm], [_ITM_commitTransaction], [itm=yes], [itm=no]) @@ -195,6 +189,12 @@ [], [enable_pkcstok_migrate=yes]) +dnl --- pkcsstats +AC_ARG_ENABLE([pkcsstats], + AS_HELP_STRING([--enable-pkcsstats],[build pkcsstats tool @<:@default=enabled@:>@]), + [], + [enable_pkcsstats=yes]) + dnl --- dnl --- Check for external software dnl --- Define what to check based on enabled features @@ -234,6 +234,12 @@ AS_HELP_STRING([--with-systemd@<:@=DIR@:>@],[systemd system unit files location]), [], [with_systemd=no]) + +dnl --- libudev development files +AC_ARG_WITH([libudev], + AS_HELP_STRING([--with-libudev@<:@=DIR@:>@],[libudev development files location]), + [], + [with_libudev=check]) dnl --- dnl --- @@ -266,28 +272,21 @@ OPENSSL_LIBS= if test "x$with_openssl" != "xno"; then if test "x$with_openssl" != "xyes" -a "x$with_openssl" != "xcheck"; then - OPENSSL_CFLAGS="-I$with_openssl" + OPENSSL_CFLAGS="-I$with_openssl/include" OPENSSL_LIBS="-L$with_openssl" fi old_cflags="$CFLAGS" old_libs="$LIBS" CFLAGS="$CFLAGS $OPENSSL_CFLAGS" LIBS="$LIBS $OPENSSL_LIBS" - AC_CHECK_HEADER([openssl/ssl.h], [], [ - if test "x$with_openssl" != "xcheck"; then - AC_MSG_ERROR([Build with OpenSSL requested but OpenSSL headers couldn't be found]) - fi - with_openssl=no + AC_CHECK_HEADER([openssl/evp.h], [], [ + AC_MSG_ERROR([OpenSSL 1.1.1 or later is required but OpenSSL headers couldn't be found]) ]) if test "x$with_openssl" != "xno"; then - AC_CHECK_LIB([crypto], [RSA_generate_key], [ + AC_CHECK_LIB([crypto], [EVP_sha3_256], [ OPENSSL_LIBS="$OPENSSL_LIBS -lcrypto" - with_openssl=yes - ], [ - if test "x$with_openssl" != "xcheck"; then - AC_MSG_ERROR([Build with OpenSSL requested but OpenSSL libraries couldn't be found]) - fi - with_openssl=no + with_openssl=yes], [ + AC_MSG_ERROR([OpenSSL 1.1.1 or later is required but OpenSSL libraries version 1.1.1 or later couldn't be found]) ]) fi if test "x$with_openssl" = "xno"; then @@ -295,6 +294,9 @@ LIBS="$old_libs" fi fi +if test "x$with_openssl" != "xyes"; then + AC_MSG_ERROR([OpenSSL 1.1.1 or later is required but build without OpenSSL was requested]) +fi AC_SUBST([OPENSSL_CFLAGS]) AC_SUBST([OPENSSL_LIBS]) @@ -438,6 +440,46 @@ AC_SUBST([XCRYPTOLINZ_CFLAGS]) AC_SUBST([XCRYPTOLINZ_LIBS]) +dnl --- with_libudev +LIBUDEV_CFLAGS= +LIBUDEV_LIBS= +if test "x$with_libudev" != "xno"; then + if test "x$with_libudev" != "xyes" -a "x$with_libudev" != "xcheck"; then + LIBUDEV_CFLAGS="-I$with_libudev" + LIBUDEV_LIBS="-L$with_libudev" + fi + old_cflags="$CFLAGS" + old_libs="$LIBS" + CFLAGS="$CFLAGS $LIBUDEV_CFLAGS" + LIBS="$LIBS $LIBUDEV_LIBS" + # Use libudev only on s390 platforms, only s390 emits AP related uevents + case $target in + *s390x* | *s390*) + CFLAGS="$CFLAGS -DWITH_LIBUDEV" + ;; + *) + if test "x$with_libudev" != "xyes"; then + with_libudev=no + echo "Default to 'with_libudev=no' on non-s390 platforms" + fi + ;; + esac + if test "x$with_libudev" != "xno"; then + AC_CHECK_HEADER([libudev.h], [with_libudev=yes], [ + AC_MSG_ERROR([Build with libudev requested but libudev headers couldn't be found]) + ]) + AC_CHECK_LIB([udev], [udev_monitor_new_from_netlink], [with_libudev=yes], [ + AC_MSG_ERROR([Build with libudev requested but libudev libraries couldn't be found]) + ]) + fi + if test "x$with_libudev" = "xno"; then + CFLAGS="$old_cflags" + LIBS="$old_libs" + fi +fi +AC_SUBST([LIBUDEV_CFLAGS]) +AC_SUBST([LIBUDEV_LIBS]) +AM_CONDITIONAL([HAVE_LIBUDEV], [test "x$with_libudev" = "xyes"]) dnl --- dnl --- Now check enabled features, while making sure every required @@ -601,6 +643,9 @@ dnl --- enable_pkcstok_migrate AM_CONDITIONAL([ENABLE_PKCSTOK_MIGRATE], [test "x$enable_pkcstok_migrate" = "xyes"]) +dnl --- enable_pkcsstats +AM_CONDITIONAL([ENABLE_PKCSSTATS], [test "x$enable_pkcsstats" = "xyes"]) + dnl --- enable_locks if test "x$enable_locks" != "xno"; then enable_locks=yes @@ -624,6 +669,15 @@ # At this point, CFLAGS is set to something sensible AC_PROG_CC AC_PROG_CXX +# AC_PROG_CXX will return "g++" even if no c++ compiler is installed. +# Check for that case, and issue an error if so. +AC_LANG_PUSH([C++]) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM( + [[#ifndef __cplusplus + #error "broken C++" + #endif]])],, + [AC_MSG_ERROR([C++ compiler is missing on your system. Please install 'gcc-c++'.])]) +AC_LANG_POP([C++]) AC_CONFIG_MACRO_DIRS([m4]) @@ -636,7 +690,11 @@ man/man1/pkcsep11_migrate.1 \ man/man1/pkcsep11_session.1 \ man/man1/pkcstok_migrate.1 \ + man/man1/pkcsstats.1 \ man/man5/opencryptoki.conf.5 \ + man/man5/p11sak_defined_attrs.conf.5 \ + man/man5/strength.conf.5 \ + man/man5/policy.conf.5 \ man/man7/opencryptoki.7 \ man/man8/pkcsslotd.8]) @@ -649,8 +707,10 @@ echo " Library build: $enable_library" echo " Systemd service: $enable_systemd" echo " Build with locks: $enable_locks" +echo " Build with libudev: $with_libudev" echo " Build p11sak tool: $enable_p11sak" echo " token migrate tool: $enable_pkcstok_migrate" +echo " statistics tool: $enable_pkcsstats" echo echo "Enabled token types:" echo " ICA token: $enable_icatok" diff -Nru opencryptoki-3.16.0+dfsg/debian/changelog opencryptoki-3.17.0+dfsg+20220202.b40982e/debian/changelog --- opencryptoki-3.16.0+dfsg/debian/changelog 2022-02-07 16:44:49.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/debian/changelog 2022-02-15 09:30:48.000000000 +0100 @@ -1,3 +1,22 @@ +opencryptoki (3.17.0+dfsg+20220202.b40982e-0ubuntu1) jammy; urgency=medium + + * New upstream release LP: #1959419, LP: #1959577 + based on 3.17 + master (b40982e) at date 20220202 + - Update d/p/01-disable-testcases.patch + - Refresh d/p/03-dlopen-soname.patch + - Update and Refresh d/p/04-pkcsslotd-cmdline-args.patch + - Drop lp1928780-SOFT-Check-the-EC-Key-on-C_CreateObject-and-C_Derive.patch + - Add libudev-dev to d/control Build-Depends + - Remove 'BSD' entry for usr/lib/pkcs11/aep_stdll/* from d/copyright, + since this (sub-)folder got removed + - Update relevant IBM license years in d/copyright + - Remove testcases/crypto/abfunc.c from Files-Excluded in d/copyright, + since it's clearly under IBM copyright, that is listed further down + - Upstream 'doc' folder is now required and cannot be excluded anymore, + hence changed Files-Excluded from doc to more specific doc/README.* + + -- Frank Heimes Tue, 15 Feb 2022 09:30:48 +0100 + opencryptoki (3.16.0+dfsg-0ubuntu3) jammy; urgency=medium * No-change rebuild against libica4 diff -Nru opencryptoki-3.16.0+dfsg/debian/control opencryptoki-3.17.0+dfsg+20220202.b40982e/debian/control --- opencryptoki-3.16.0+dfsg/debian/control 2021-07-26 16:12:44.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/debian/control 2022-02-15 09:30:48.000000000 +0100 @@ -13,7 +13,8 @@ flex, libitm1 [!armhf], libica-dev [s390x], - libldap2-dev + libldap2-dev, + libudev-dev Standards-Version: 4.1.1 Homepage: https://github.com/opencryptoki/opencryptoki @@ -26,7 +27,7 @@ lsb-base (>= 3.0-6) Multi-Arch: foreign Description: PKCS#11 implementation (daemon) - openCryptoki is a PKCS#11 Cryptographic Token Interface Standard + openCryptoki is a PKCS#11 Cryptographic Token Interface Standard implementation. It includes drivers and libraries to enable IBM cryptographic hardware such as Trusted Computing Platform (TPM) cryptographic devices as well as a software token for testing. diff -Nru opencryptoki-3.16.0+dfsg/debian/copyright opencryptoki-3.17.0+dfsg+20220202.b40982e/debian/copyright --- opencryptoki-3.16.0+dfsg/debian/copyright 2021-07-26 18:52:19.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/debian/copyright 2022-02-15 09:30:48.000000000 +0100 @@ -1,12 +1,12 @@ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Author: Kent Yoder Download: http://opencryptoki.sourceforge.net/ -Files-Excluded: testcases/crypto/abfunc.c - doc +Files-Excluded: + doc/README.* Files: * Copyright: - (C) 2001-2009 IBM, Corp. + (C) 1997-2021 IBM, Corp. (C) 2000-2003 Corrent, Corp. License: CPL THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC @@ -224,34 +224,6 @@ after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. -Files: usr/lib/pkcs11/aep_stdll/* -Copyright: (C) 1999-2002 AEP Systems Ltd. -License: BSD - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - . - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - . - 2. Redistributions in binary form must reproduce the above copyright notice, - list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - . - 3. Neither the name of AEP Systems Ltd. nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - . - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - Files: debian/* Copyright: 2007-2009 Daniel Baumann , 2016 Canonical Ltd diff -Nru opencryptoki-3.16.0+dfsg/debian/libopencryptoki-dev.install opencryptoki-3.17.0+dfsg+20220202.b40982e/debian/libopencryptoki-dev.install --- opencryptoki-3.16.0+dfsg/debian/libopencryptoki-dev.install 2021-07-26 16:12:44.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/debian/libopencryptoki-dev.install 2022-02-15 09:30:48.000000000 +0100 @@ -1,4 +1,5 @@ #! /usr/bin/dh-exec -/usr/include +/usr/include/* +/usr/include/opencryptoki/* /usr/lib/${DEB_HOST_MULTIARCH}/opencryptoki/*.so diff -Nru opencryptoki-3.16.0+dfsg/debian/opencryptoki.install opencryptoki-3.17.0+dfsg+20220202.b40982e/debian/opencryptoki.install --- opencryptoki-3.16.0+dfsg/debian/opencryptoki.install 2021-07-26 16:12:44.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/debian/opencryptoki.install 2022-02-15 09:30:48.000000000 +0100 @@ -1,6 +1,7 @@ #! /usr/bin/dh-exec /usr/sbin /usr/share/man +/usr/share/doc/opencryptoki/*-example.conf /usr/lib/${DEB_HOST_MULTIARCH}/opencryptoki/stdll/*.so /usr/lib/tmpfiles.d/opencryptoki.conf /var/lib/opencryptoki diff -Nru opencryptoki-3.16.0+dfsg/debian/opencryptoki.install.s390x opencryptoki-3.17.0+dfsg+20220202.b40982e/debian/opencryptoki.install.s390x --- opencryptoki-3.16.0+dfsg/debian/opencryptoki.install.s390x 2021-07-26 16:12:44.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/debian/opencryptoki.install.s390x 2022-02-15 09:30:48.000000000 +0100 @@ -1,10 +1,11 @@ #! /usr/bin/dh-exec /usr/sbin /usr/share/man +/usr/share/doc/opencryptoki/*-example.conf /usr/lib/${DEB_HOST_MULTIARCH}/opencryptoki/stdll/*.so /usr/lib/tmpfiles.d/opencryptoki.conf /var/lib/opencryptoki /etc/opencryptoki/opencryptoki.conf /lib/systemd/system/pkcsslotd.service /etc/opencryptoki/ep11tok.conf -/etc/opencryptoki/ep11cpfilter.conf \ No newline at end of file +/etc/opencryptoki/ep11cpfilter.conf diff -Nru opencryptoki-3.16.0+dfsg/debian/patches/01-disable-testcases.patch opencryptoki-3.17.0+dfsg+20220202.b40982e/debian/patches/01-disable-testcases.patch --- opencryptoki-3.16.0+dfsg/debian/patches/01-disable-testcases.patch 2021-07-26 18:55:27.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/debian/patches/01-disable-testcases.patch 2022-02-15 09:07:34.000000000 +0100 @@ -8,7 +8,7 @@ @@ -1,7 +1,7 @@ dnl Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) - AC_INIT([openCryptoki],[3.16.0],[opencryptoki-tech@lists.sourceforge.net],[],[https://github.com/opencryptoki/opencryptoki]) + AC_INIT([openCryptoki],[3.17.0],[https://github.com/opencryptoki/opencryptoki/issues],[],[https://github.com/opencryptoki/opencryptoki]) -AC_CONFIG_SRCDIR([testcases/common/common.c]) +AC_CONFIG_SRCDIR([usr/include/pkcs11.h]) diff -Nru opencryptoki-3.16.0+dfsg/debian/patches/03-dlopen-soname.patch opencryptoki-3.17.0+dfsg+20220202.b40982e/debian/patches/03-dlopen-soname.patch --- opencryptoki-3.16.0+dfsg/debian/patches/03-dlopen-soname.patch 2021-07-26 18:55:27.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/debian/patches/03-dlopen-soname.patch 2022-02-15 09:09:53.000000000 +0100 @@ -15,7 +15,7 @@ --- a/usr/sbin/pkcsconf/pkcsconf.c +++ b/usr/sbin/pkcsconf/pkcsconf.c -@@ -1121,7 +1121,7 @@ +@@ -1134,7 +1134,7 @@ * error */ /* The host machine should have the right library in the * LD_LIBRARY_PATH */ @@ -37,7 +37,7 @@ if (evar == NULL) { --- a/usr/sbin/pkcsep11_session/pkcsep11_session.c +++ b/usr/sbin/pkcsep11_session/pkcsep11_session.c -@@ -210,7 +210,7 @@ +@@ -212,7 +212,7 @@ CK_RV (*func_list)() = NULL; void *d; char *evar; diff -Nru opencryptoki-3.16.0+dfsg/debian/patches/04-pkcsslotd-cmdline-args.patch opencryptoki-3.17.0+dfsg+20220202.b40982e/debian/patches/04-pkcsslotd-cmdline-args.patch --- opencryptoki-3.16.0+dfsg/debian/patches/04-pkcsslotd-cmdline-args.patch 2021-07-26 16:12:44.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/debian/patches/04-pkcsslotd-cmdline-args.patch 2022-02-15 09:17:27.000000000 +0100 @@ -4,11 +4,9 @@ logging to files, only useful for debugging but controllable at runtime, not compile time. -Index: opencryptoki-3.15.1+dfsg/usr/sbin/pkcsslotd/daemon.c -=================================================================== ---- opencryptoki-3.15.1+dfsg.orig/usr/sbin/pkcsslotd/daemon.c -+++ opencryptoki-3.15.1+dfsg/usr/sbin/pkcsslotd/daemon.c -@@ -32,3 +32,9 @@ BOOL IsDaemon(void) +--- a/usr/sbin/pkcsslotd/daemon.c ++++ b/usr/sbin/pkcsslotd/daemon.c +@@ -32,3 +32,9 @@ return (BOOL) ((Daemon) && (IveDaemonized)); } @@ -18,11 +16,9 @@ + Daemon = Val; + return OldVal; +} -Index: opencryptoki-3.15.1+dfsg/usr/sbin/pkcsslotd/log.c -=================================================================== ---- opencryptoki-3.15.1+dfsg.orig/usr/sbin/pkcsslotd/log.c -+++ opencryptoki-3.15.1+dfsg/usr/sbin/pkcsslotd/log.c -@@ -469,7 +469,6 @@ BOOL PKCS_Log(pLogHandle phLog, char *fm +--- a/usr/sbin/pkcsslotd/log.c ++++ b/usr/sbin/pkcsslotd/log.c +@@ -469,7 +469,6 @@ } /* Don't log to a separate log file in production mode */ @@ -30,7 +26,7 @@ if (pInfo->Filename != NULL) { FILE *fd; -@@ -490,9 +489,6 @@ BOOL PKCS_Log(pLogHandle phLog, char *fm +@@ -490,9 +489,6 @@ } } /* end if pInfo->Filename */ @@ -40,7 +36,7 @@ /* Always log to syslog, if we're using it */ if (pInfo->UseSyslog) { -@@ -643,6 +639,24 @@ void InfoLog(char *Format, ...) +@@ -643,6 +639,24 @@ } @@ -65,11 +61,9 @@ /*********************************************************************** * InitLogging - -Index: opencryptoki-3.15.1+dfsg/usr/sbin/pkcsslotd/log.h -=================================================================== ---- opencryptoki-3.15.1+dfsg.orig/usr/sbin/pkcsslotd/log.h -+++ opencryptoki-3.15.1+dfsg/usr/sbin/pkcsslotd/log.h -@@ -100,6 +100,7 @@ BOOL PKCS_Log(LogHandle *phLog, char *Fo +--- a/usr/sbin/pkcsslotd/log.h ++++ b/usr/sbin/pkcsslotd/log.h +@@ -100,6 +100,7 @@ BOOL NewLoggingFacility(char *ID, pLoggingFacility pStuff); BOOL CloseLoggingFacility(LogHandle hLog); BOOL GetCurrentTimeString(char *Buffer); @@ -77,11 +71,9 @@ u_int32 SetDebugLevel(u_int32 Val); u_int32 GetDebugLevel(void); -Index: opencryptoki-3.15.1+dfsg/usr/sbin/pkcsslotd/pkcsslotd.h -=================================================================== ---- opencryptoki-3.15.1+dfsg.orig/usr/sbin/pkcsslotd/pkcsslotd.h -+++ opencryptoki-3.15.1+dfsg/usr/sbin/pkcsslotd/pkcsslotd.h -@@ -70,6 +70,7 @@ extern Slot_Mgr_Socket_t socketData; +--- a/usr/sbin/pkcsslotd/pkcsslotd.h ++++ b/usr/sbin/pkcsslotd/pkcsslotd.h +@@ -67,6 +67,7 @@ ***********************/ BOOL IsDaemon(void); @@ -89,10 +81,8 @@ BOOL StopGCThread(void *Ptr); BOOL StartGCThread(Slot_Mgr_Shr_t *MemPtr); BOOL CheckForGarbage(Slot_Mgr_Shr_t *MemPtr); -Index: opencryptoki-3.15.1+dfsg/usr/sbin/pkcsslotd/slotmgr.c -=================================================================== ---- opencryptoki-3.15.1+dfsg.orig/usr/sbin/pkcsslotd/slotmgr.c -+++ opencryptoki-3.15.1+dfsg/usr/sbin/pkcsslotd/slotmgr.c +--- a/usr/sbin/pkcsslotd/slotmgr.c ++++ b/usr/sbin/pkcsslotd/slotmgr.c @@ -8,6 +8,8 @@ * https://opensource.org/licenses/cpl1.0.php */ @@ -102,8 +92,8 @@ #include #include #include -@@ -51,6 +53,9 @@ struct parse_data { - char errbuf[256]; +@@ -49,6 +51,9 @@ + int mode; }; +/* for getopt via unitstd */ @@ -112,8 +102,8 @@ /* We make main() able to modify Daemon so that we can daemonize or not based on a command-line argument -@@ -485,6 +490,23 @@ static struct parsefuncs slotmgr_parsefu - }; +@@ -605,6 +610,23 @@ + } /***************************************** + * usage() - @@ -136,15 +126,15 @@ * main() - * You know what main does. * Comment block for ease of spotting -@@ -496,6 +518,7 @@ int main(int argc, char *argv[], char *e +@@ -615,6 +637,7 @@ + int main(int argc, char *argv[], char *envp[]) { int ret, i; - struct parse_data parsedata; + int option; /**********************************/ /* Read in command-line arguments */ -@@ -505,9 +528,42 @@ int main(int argc, char *argv[], char *e +@@ -624,9 +647,42 @@ /* FIXME: Argument for debug level */ /* FIXME: Arguments affecting the log files, whether to use syslog, etc. * (Read conf file?) */ diff -Nru opencryptoki-3.16.0+dfsg/debian/patches/lp1928780-SOFT-Check-the-EC-Key-on-C_CreateObject-and-C_Derive.patch opencryptoki-3.17.0+dfsg+20220202.b40982e/debian/patches/lp1928780-SOFT-Check-the-EC-Key-on-C_CreateObject-and-C_Derive.patch --- opencryptoki-3.16.0+dfsg/debian/patches/lp1928780-SOFT-Check-the-EC-Key-on-C_CreateObject-and-C_Derive.patch 2021-07-26 18:55:27.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/debian/patches/lp1928780-SOFT-Check-the-EC-Key-on-C_CreateObject-and-C_Derive.patch 1970-01-01 01:00:00.000000000 +0100 @@ -1,52 +0,0 @@ -From 4e3b43c3d8844402c04a66b55c6c940f965109f0 Mon Sep 17 00:00:00 2001 -From: Ingo Franzki -Date: Mon, 3 May 2021 10:05:07 +0200 -Subject: [PATCH] SOFT: Check the EC Key on C_CreateObject and C_DeriveKey - -When constructing an OpenSSL EC public or private key from PKCS#11 -attributes or ECDH public data, check that the key is valid, i.e. that -the point is on the curve. - -This prevents one from creating an EC key object via C_CreateObject with -invalid key data. It also prevents C_DeriveKey to derive a secret using -ECDH with an EC public key (public data) that uses a different curve -or is invalid by other means. - -Signed-off-by: Ingo Franzki ---- - usr/lib/soft_stdll/soft_specific.c | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/usr/lib/soft_stdll/soft_specific.c b/usr/lib/soft_stdll/soft_specific.c -index c30be1da..aeff39a9 100644 ---- a/usr/lib/soft_stdll/soft_specific.c -+++ b/usr/lib/soft_stdll/soft_specific.c -@@ -4365,6 +4365,12 @@ static CK_RV fill_ec_key_from_pubkey(EC_KEY *ec_key, const CK_BYTE *data, - goto out; - } - -+ if (!EC_KEY_check_key(ec_key)) { -+ TRACE_ERROR("EC_KEY_check_key failed\n"); -+ rc = CKR_PUBLIC_KEY_INVALID; -+ goto out; -+ } -+ - out: - if (allocated && ecpoint != NULL) - free(ecpoint); -@@ -4404,6 +4410,12 @@ static CK_RV fill_ec_key_from_privkey(EC_KEY *ec_key, const CK_BYTE *data, - goto out; - } - -+ if (!EC_KEY_check_key(ec_key)) { -+ TRACE_ERROR("EC_KEY_check_key failed\n"); -+ rc = CKR_FUNCTION_FAILED; -+ goto out; -+ } -+ - out: - if (point != NULL) - EC_POINT_free(point); --- -2.31.1 - diff -Nru opencryptoki-3.16.0+dfsg/debian/patches/series opencryptoki-3.17.0+dfsg+20220202.b40982e/debian/patches/series --- opencryptoki-3.16.0+dfsg/debian/patches/series 2021-07-26 18:55:27.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/debian/patches/series 2022-02-15 09:23:43.000000000 +0100 @@ -2,4 +2,3 @@ 03-dlopen-soname.patch 04-pkcsslotd-cmdline-args.patch -lp1928780-SOFT-Check-the-EC-Key-on-C_CreateObject-and-C_Derive.patch diff -Nru opencryptoki-3.16.0+dfsg/doc/coding_style.md opencryptoki-3.17.0+dfsg+20220202.b40982e/doc/coding_style.md --- opencryptoki-3.16.0+dfsg/doc/coding_style.md 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/doc/coding_style.md 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,193 @@ +# OpenCryptoki coding style + +This document describes the preferred coding style for the OpenCryptoki project +and its related projects (openssl-ibmca and openssl-ibmpkcs11). Coding style is +always of personal taste, but defining one coding style makes the maintenance of +the project easier and gives a standard face for the source code, something that +this projects have been lacking for the past years. + +The inspiration and formatting of this document came from the Linux Kernel +coding style document, but make no assumption as the coding style differ from +each other on some aspects. + +## 0. Setting up automatic code style check + +To help developers on checking if their code changes are following the coding +style format, we created a pre-commit git hook which is shared under .githooks/ +directory. This hook will use GNU indent to check your code changes. + +You might wonder "why we ask for user confirmation?". Well, we don't want to +create a overhead for developers that are working on feature branches and their +code changes are not yet ready for a pull request. + +To set up the pre-commit hook, each developer after cloning the project needs +to run: +$ ln -s ../../.githooks/pre-commit .git/hooks/pre-commit + +## 1. Indentation + +Tabs are 4 space characters, differently from many projects that define it as 8 +characters. The main idea behind this is that 4 characters should give you a +clear idea about where a block of control starts and ends. + +## 2. Line length + +To keep the code readable and maintainable, the limit on the length of lines is +80 columns and this is a strongly preferred limit. + +## 3. Placing Braces and Spaces + +Here we follow Kernighan and Ritchie teachings. An opening brace is put last on +the line, and put the closing brace first, e.g.: + +``` + if (x == 0) { + do_y(); + } +``` + +This applies to all non-function statement blocks (if, switch, for, while, do). +Another example: + +``` + switch (value) { + case 1: + return "one"; + case 2: + return "two"; + case 3: + return "three"; + default: + return NULL; + } +``` + +However, there is one special case, functions: their opening brace stays at the +beginning of the next line, e.g.: + +``` + int func(int x) + { + do_something(); + } +``` + +Follow other examples: + +``` + do { + do_something(); + } while (condition); +``` + +``` + if (x == 1) { + do_one(); + } else if (x > 1) { + do_two(); + } else { + do_three(); + } +``` + +It is not necessary to use braces when there is only a single statement, e.g.: + +``` + if (x == 1) + do_something(); +``` + +and + +``` + if (x == 1) + do_something(); + else + do_something_else(); +``` + +This does not apply when only one branch in a conditional statement is a single +statement. In this, case use braces in all branches, e.g.: + +``` + if (x == 1) { + do_something(); + do_something_more(); + } else { + do_something_else(); + } +``` + +### 3.1. Spaces + +Always use a space after these keywords: +``` if, switch, case, for, do, while ``` + +E.g.: +``` + if (condition) { + .. + } +``` + +The following keywords should not have a space between them and their +parentheses: +``` sizeof, typeof ``` + +E.g.: +``` + s = sizeof(struct alg); +``` + +Do **not** add spaces around (inside) parenthesized expressions, e.g.: +``` + if ( x == 1 ) { + .. + } +``` + +When declaring a pointer or a function that returns a pointer type, the ``*`` +must be put adjacent to the data name or function name, e.g.: +``` + int *ptr; + void ptrcopy(int *dest, char *src); + int *get_address(int *ptr); +``` + +Use one space on each side of the following operators: +``` = + - < > * / % | & ^ <= >= == != ? : ``` + +but no space after unary operators: +``` & * + - ~ ! ``` + +no space before postfix/after prefix increment and decrement operators: +``` ++ -- ``` + +and no space around the ``.`` and ``->`` structure member operators. + +Do **not** leave trailing whitespace at the end of lines. + +## 4. Naming + +Avoid using CamelCase. It is preferred to name variables and functions by +including an underscore between words, e.g.: +``` + int person_counter; +``` + +## 5. Commenting + +Comments in the code make everyone's life easier, but don't be too verbose. +Focus on **what** your function does and less on **how** it does. + +The preferred style for long multi-line comments is: + +``` + /* + * This is a multi-line comment. + * + * A column of asterisks on the left side, with beginning and ending + * almost-blank lines. + */ +``` + diff -Nru opencryptoki-3.16.0+dfsg/doc/doc.mk opencryptoki-3.17.0+dfsg+20220202.b40982e/doc/doc.mk --- opencryptoki-3.16.0+dfsg/doc/doc.mk 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/doc/doc.mk 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,7 @@ +doc_DATA = doc/strength-example.conf +nodist_doc_DATA = doc/policy-example.conf + +doc/policy-example.conf: tools/policyexamplegen + $(AM_V_GEN) $(MKDIR_P) doc && tools/policyexamplegen > doc/policy-example.conf + +EXTRA_DIST += $(doc_DATA) diff -Nru opencryptoki-3.16.0+dfsg/doc/opencryptoki-howto.md opencryptoki-3.17.0+dfsg+20220202.b40982e/doc/opencryptoki-howto.md --- opencryptoki-3.16.0+dfsg/doc/opencryptoki-howto.md 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/doc/opencryptoki-howto.md 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,866 @@ +# PKCS #11 openCryptoki for Linux HOWTO + +v1 - Kristin Thomas - kristint@us.ibm.com + +v2 - Eduardo Barretto - ebarretto@linux.vnet.ibm.com + +This HOWTO describes the implementation of the RSA Security Inc./Organization +for the Advancement of Structured Information Standards (OASIS) Public Key +Cryptographic Standard #11 (PKCS #11) cryptoki application program interface +(API) on Linux (openCryptoki). The HOWTO explains what services openCryptoki +provides and how to build and install it. Additional resources and a simple +sample program are also provided. + +## Table of contents +1. [Copyright Notice and Disclaimer](#1-copyright-notice-and-disclaimer)
+2. [Introduction](#2-introduction)
+3. [What is openCryptoki?](#3-what-is-opencryptoki)
+4. [Architectural Overview](#4-architectural-overview)
+ 4.1. [Slot Manager](#41-slot-manager)
+ 4.2. [Main API](#42-main-api)
+ 4.3. [Slot Token Dynamic Link + Libraries](#43-slot-token-dynamic-link-libraries)
+ 4.4. [Shared Memory](#44-shared-memory)
+5. [Getting Started with openCryptoki](#5-getting-started-with-opencryptoki)
+ 5.1. [System Requirements](#51-system-requirements)
+ 5.2. [Obtaining openCryptoki](#52-obtaining-opencryptoki)
+ 5.3. [Compiling and Installing + openCryptoki](#53-compiling-and-installing-opencryptoki)
+6. [Configuring openCryptoki](#6-configuring-opencryptoki)
+7. [Components of openCryptoki](#7-components-of-opencryptoki)
+ 7.1. [Slot Manager Daemon](#71-slot-manager-daemon)
+ 7.2. [libopencryptoki.so](#72-libopencryptokiso)
+ 7.3. [Slot Token DLLs](#73-slot-token-dlls)
+  7.3.1. [Trusted Module Platform](#731-trusted-module-platform-tpm)
+  7.3.2. [IBM Cryptographic Architecture (ICA)](#732-ibm-cryptographic-architecture-ica)
+  7.3.3. [IBM Common Cryptographic Architecture (CCA)](#733-ibm-common-cryptographic-architecture-cca)
+  7.3.4. [Software Token](#734-software-token)
+  7.3.5. [IBM Enterprise PKCS #11 (EP11)](#735-ibm-enterprise-pkcs-11-ep11)
+  7.3.6. [IBM Integrated Cryptographic Service Facility (ICSF)](#736-ibm-integrated-cryptographic-service-facility-icsf)
+8. [Applications and openCryptoki](#8-application-and-opencryptoki)
+ 8.1. [Making openCryptoki Available to + Applications](#81-making-opencryptoki-available-to-applications)
+ 8.2. [Writing an Application](#82-writing-an-application)
+9. [Resources](#9-resources)
+10. [Appendix A: Sample Program](#10-appendix-a-sample-program)
+ 10.1. [Sample Program](#101-sample-program)
+ 10.2. [Makefile](#102-makefile)
+ + +### 1. Copyright Notice and Disclaimer + +Copyright © 2001 - 2017 IBM Corporation. All rights reserved. + +This document may be reproduced or distributed in any form without prior +permission provided the copyright notice is retained on all copies. Modified +versions of this document may be freely distributed, provided that they are +clearly identified as such, and this copyright is included intact. + +This document is provided "AS IS," with no express or implied warranties. Use +the information in this document at your own risk. + +**Special Notices** + +This publication/presentation was produced in the United States. IBM may not +offer the products, programs, services or features discussed herein in other +countries, and the information may be subject to change without notice. Consult +your local IBM business contact for information on the products, programs, +services, and features available in your area. Any reference to an IBM product, +program, service, or feature is not intended to state or imply that only IBM’s +product, program, service, or feature may be used. Any functionally equivalent +product, program, service, or feature that does not infringe on IBM’s +intellectual property rights may be used instead. + +Questions on the capabilities of non-IBM products should be addressed to +suppliers of those products. IBM may have patents or pending patent applications +covering subject matter in this presentation. Furnishing this presentation does +not give you any license to these patents. Send license inquiries, in writing, +to IBM Director of Licensing, IBM Corporation, New Castle Drive, Armonk, NY +10504-1785 USA. All statements regarding IBM’s future direction and intent are +subject to change or withdrawal without notice, and represent goals and +objectives only. Contact your local IBM office or IBM authorized reseller for +the full text of a specific Statement of General Direction. + +The information contained in this presentation has not been submitted to any +formal IBM test and is distributed "AS IS." While each item may have have been +reviewed by IBM for accuracy in a specific situation, there is no guarantee that +the same or similar results will be obtained elsewhere. The use of this +information or the implementation of any techniques described herein is a +customer responsibility and depends on the customer’s ability to evaluate and +integrate them into the customer’s operational environment. Customers attempting +to adapt these techniques to their own environments do so at their own risk. + +The information contained in this document represents the current views of IBM +on the issues discussed as of the date of publication. IBM cannot guarantee the +accuracy of any information presented after the date of publication. + +Any performance data in this document was determined in a controlled +environment. Therefore, the results obtained in other operating environments may +vary significantly. Some measurements quoted in this book may have been made on +development-level systems. There is no guarantee these measurements will be the +same on generally-available systems. Some measurements quoted in this book may +have been estimated through extrapolation. Actual results may vary. Users of +this book should verify the applicable data for their specific environment. + +A full list of U.S. trademarks owned by IBM may be found at +http://www.ibm.com/legal/copytrade.shtml. Linux is a trademark of Linus +Torvalds. Other company, product, and service names may be trademarks or service +marks of others. + + +### 2. Introduction + +Cryptography is rapidly becoming a critical part of our daily lives. However, +the application of cryptographic technology adds a heavy computational burden to +today's server platforms. More systems are beginning to use specialized hardware +to offload the computations, as well as to help ensure the security of secret +key material. In this HOWTO we will discuss openCryptoki, an API that is rapidly +becoming the defacto, non-Windows-platform industry standard for interfacing +between cryptographic hardware and user space applications. In particular we +will introduce the specifics of the PKCS #11 implementation to IBM cryptographic +hardware (openCryptoki). + + +### 3. What is openCryptoki? + +openCryptoki is an implementation of the PKCS #11 API that allows interfacing to +devices (such as a smart card, smart disk, or PCMCIA card) that hold +cryptographic information and perform cryptographic functions. openCryptoki +provides application portability by isolating the application from the details +of the cryptographic device. Isolating the application also provides an added +level of security because all cryptographic information stays within the device. +The openCryptoki API provides a standard programming interface between +applications and all kinds of portable cryptographic devices. + + +### 4. Architectural Overview + +openCryptoki consists of a slot manager and an API for Slot Token Dynamic Link +Libraries (STDLLs). The slot manager runs as a daemon to control the number of +slots provided to applications, and it interacts with applications using a +shared memory region. Each device that has a token associated with it places +that token into a slot in the slot manager database. The shared memory region +allows for proper sharing of state information between applications to help +ensure conformance with the PKCS #11 specification. + +#### 4.1. Slot Manager + +The Slot Manager Daemon (_pkcsslotd_) manages slots (and therefore tokens) in +the system. A fixed number of processes can be attached to _pkcsslotd_, so a +static table in shared memory is used. The current limit of the table is 1000 +processes using the subsystem. The daemon sets up this shared memory upon +initialization and acts as a garbage collector thereafter, helping to ensure +that only active processes remain registered. When a process attaches to a slot +and opens a session, _pkcsslotd_ will make future processes aware that a process +has a session open and will lock out certain function calls, if the they need +exclusive access to the given token. The daemon will constantly search through +its region of shared memory and make sure that when a process is attached to a +token it is actually running. If an attached process terminates abnormally, +_pkcsslotd_ will "clean up" after the process and free the slot for use by other +processes. + +#### 4.2. Main API + +The main API for the STDLLs lies in /usr/lib/opencryptoki/libopencryptoki.so. +This API includes all the functions as outlined in the PKCS #11 API +specification. The main API provides each application with the slot management +facility. The API also loads token specific modules (STDLLs) the provide the +token specific operations (cryptographic operations and session and object +management). STDLLs are customized for each token type and have specific +functions, such as an initialization routine, to allow the token to work with +the slot manager. When an application initializes the subsystem with the +__C_Initialize__ call, the API will load the STDLL shared objects for all the +tokens that exist in the configuration (residing in the shared memory) and +invoke the token specific initialization routines. + +#### 4.3. Slot Token Dynamic Link Libraries + +STDLLs are plug-in modules to the main API. They provide token-specific +functions beyond the main API functions. Specific devices can be supported by +building an STDLLs for the device. Each STDLLs must provide at least a token +specific initialization function. If the device is an intelligent device, such +as a hardware adapter that supports multiple mechanisms, the STDLL can be thin +because much of the session information can be stored on the device. If the +device only performs a simple cryptographic function, all of the objects must be +managed by the software. This flexibility allows the STDLLs to support any +cryptographic device. + +#### 4.4. Shared Memory + +The slot manager sets up its database in a region of shared memory. Since the +maximum number of processes allowed to attach to _pkcsslotd_ is finite, a +fixed amount of memory can be set aside for token management. This fixed memory +allotment management allows applications easier access to token state +information and helps ensure conformance with the PKCS #11 specification. + +### 5. Getting Started with openCryptoki + +This section describes the system requirements for openCryptoki. It also +explains where you can get openCryptoki and how to compile and install it. + +#### 5.1. System Requirements + +openCryptoki installs by default a software token that relies on software to +deliver the crypto functions. So it is possible to install it even if you don't +have physical (hardware) token. + +The following lists show the system requirements for running openCryptoki. + +**Hardware Requirements** + +- openCryptoki is supported on ppc64, s390x and x86. + +**Software Requirements** + +- Linux operating system running at least a 2.2.16 kernel +- Device drivers and associated support libraries for the installed tokens (some +of the header files from those distributions may also be required) + +#### 5.2. Obtaining openCryptoki + +The openCryptoki project and source code is hosted on +[GitHub](https://github.com/opencryptoki/opencryptoki). You can find +openCryptoki releases (tarball) on GitHub and, as well, on +[SourceForge](https://sourceforge.net/projects/opencryptoki/). +For any issue, questions or development related subjects, please contact us on +the [mailing list](https://sourceforge.net/p/opencryptoki/mailman/). + +#### 5.3. Compiling and Installing openCryptoki + +Assuming that the device support (and header files) for the required devices are +on the system, then you can build openCryptoki by entering the source code main +directory and do the following: + +1. Run the bootstrap.sh script by typing: + +``` $ ./bootstrap.sh ``` + +2. Configure the source code by typing: + +``` $ ./configure ``` + + If you're planning to install the package into your home directory or to a + location other than `/usr/local` then add the flag `--prefix=PATH` to + `configure`. For example, if your home directory is `/home/luser` you can + configure the package to install itself there by invoking: + +``` $ ./configure --prefix=/home/luser ``` + + If your stdll headers and libraries are not under any standard path, you will + need to pass the paths to your files for the configure script. For instance: + +``` $ CPPFLAGS="-L/path/lib" LDFLAGS="-I/path/include" ./configure ``` + + See `./configure --help` for info on various options. The default behavior is + to build a default token implicitly. For the s390 platform, the default token + is ICA. For other platforms, the default token is the software token. Other + tokens may be enabled using the corresponding `--enable-` configuration + option provided the appropriate libraries are available. + + While running, `configure` prints some messages telling which features is it + checking for. + +3. Compile the package by typing: + +``` $ make ``` + +4. openCryptoki defaults to be usable by anyone who is in the group ``pkcs11``, +Add the pkcs11 group before installing it, by typing as root the command: + +``` # groupadd pkcs11 ``` + + In addition, add the necessary user to the pkcs11 group (root doesn't need to + be in the pkcs11 group): + +``` # usermod -G pkcs11 ``` + +5. Type `make install` (as root) to install the programs and any data files and +documentation. During installation, the following files go to the following +directories: + +``` + /prefix/sbin/pkcsconf + /prefix/sbin/pkcsslotd + /prefix/sbin/pkcsicsf + /prefix/libdir/libopencryptoki.so + /prefix/libdir/libopencryptoki.so.0 + /prefix/libdir/opencryptoki/libopencryptoki.so + /prefix/libdir/opencryptoki/libopencryptoki.so.0 + /prefix/libdir/opencryptoki/libopencryptoki.so.0.0.0 + /prefix/var/lib/opencryptoki + /prefix/etc/opencryptoki/opencryptoki.conf +``` + + Token objects, which may be optionally built, go to the following locations: + +``` + /prefix/libdir/opencryptoki/stdll/libpkcs11_cca.so + /prefix/libdir/opencryptoki/stdll/libpkcs11_cca.so.0 + /prefix/libdir/opencryptoki/stdll/libpkcs11_cca.so.0.0.0 + /prefix/libdir/opencryptoki/stdll/libpkcs11_ep11.so + /prefix/libdir/opencryptoki/stdll/libpkcs11_ep11.so.0 + /prefix/libdir/opencryptoki/stdll/libpkcs11_ep11.so.0.0.0 + /prefix/libdir/opencryptoki/stdll/libpkcs11_ica.so + /prefix/libdir/opencryptoki/stdll/libpkcs11_ica.so.0 + /prefix/libdir/opencryptoki/stdll/libpkcs11_ica.so.0.0.0 + /prefix/libdir/opencryptoki/stdll/libpkcs11_icsf.so + /prefix/libdir/opencryptoki/stdll/libpkcs11_icsf.so.0 + /prefix/libdir/opencryptoki/stdll/libpkcs11_icsf.so.0.0.0 + /prefix/libdir/opencryptoki/stdll/libpkcs11_sw.so + /prefix/libdir/opencryptoki/stdll/libpkcs11_sw.so.0 + /prefix/libdir/opencryptoki/stdll/libpkcs11_sw.so.0.0.0 + /prefix/libdir/opencryptoki/stdll/libpkcs11_tpm.so + /prefix/libdir/opencryptoki/stdll/libpkcs11_tpm.so.0 + /prefix/libdir/opencryptoki/stdll/libpkcs11_tpm.so.0.0.0 +``` + + where `prefix` is either `/usr/local/` or the PATH that you specified in the + `--prefix` flag. `libdir` is the name of the library directory, for 32-bit + libraries it is usually `lib` and for 64-bit libraries it is usually `lib64`. + + To maintain backwards compatibility, some additional symlinks are generated + (note that these are deprecated and applications should migrate to use the + LSB-compliant name and locations for libraries and executable): + +``` + /prefix/lib/opencryptoki/PKCS11_API.so + - Symlink to /prefix/lib/opencryptoki/libopencryptoki.so + + /prefix/lib/opencryptoki/stdll/PKCS11_CCA.so + - Symlink to /prefix/lib/opencryptoki/stdll/libpkcs11_cca.so + + /prefix/lib/opencryptoki/stdll/PKCS11_EP11.so + - Symlink to /prefix/lib/opencryptoki/stdll/libpkcs11_ep11.so + + /prefix/lib/opencryptoki/stdll/PKCS11_ICA.so + - Symlink to /prefix/lib/opencryptoki/stdll/libpkcs11_ica.so + + /prefix/lib/opencryptoki/stdll/PKCS11_ICSF.so + - Symlink to /prefix/lib/opencryptoki/stdll/libpkcs11_icsf.so + + /prefix/lib/opencryptoki/stdll/PKCS11_SW.so + - Symlink to /prefix/lib/opencryptoki/stdll/libpkcs11_sw.so + + /prefix/lib/pkcs11/PKCS11_API.so + - Symlink to /prefix/lib/opencryptoki/libopencryptoki.so + + /prefix/lib/pkcs11 + - Directory created if non-existent + + /prefix/lib/pkcs11/methods + - Symlink to /prefix/sbin + + /prefix/lib/pkcs11/stdll + - Symlink to /prefix/lib/opencryptoki/stdll + + /prefix/etc/pkcs11 + - Symlink to /prefix/var/lib/opencryptoki +``` + + If any of these directories do not presently exist, they will be created on + demand. Note that if `prefix` is `/usr`, then `/prefix/var` and `/prefix/etc` + resolve to `/var` and `/etc`. On the `make install` stage, if content exists + in the old `/prefix/etc/pkcs11` directory, it will be migrated to the new + `/prefix/var/lib/opencryptoki` location. + + If you are installing in your home directory make sure that `/home/luser/bin` + is in your path. If you're using the bash shell add this line at the end of + your `.bashrc` file: + +``` + PATH="/home/luser/bin:${PATH}" + export PATH +``` + + If you are using csh or tcsh, then use this line instead: + +``` setenv PATH /home/luser/bin:${PATH} ``` + + By prepending your home directory to the rest of the PATH you can override + systemwide installed software with your own custom installation. + + +### 6. Configuring openCryptoki + +See: +https://www.ibm.com/support/knowledgecenter/linuxonibm/com.ibm.linux.z.lxce/lxce_stackoverview.html + +Prior to version 3, openCryptoki used `pk_config_data` as its configuration +file. This file was created upon running `pkcs11_startup`. In version 3, +`pkcs11_startup` and `pk_config_data` have been removed and replaced with a +customizable config file named, `opencryptoki.conf`. It contains an entry for +each token currently supported by openCryptoki. However, only those token, whose +hardware and software requirements are available on the local system, will show +up as present and available upon running the `pkcsconf -t` command. + +Before using, each token must be first initialized. You can select the token +with the `-c` command line option; refer to the documentation linked to above +for further instructions. + +Initialize a particular token by running `pkcsconf`: + +``` $ pkcsconf -I -c ``` + +In this version of openCryptoki, the default SO PIN is `87654321`. This should +be changed to a different PIN value before use. + +You can change the SO PIN by running pkcsconf : + +``` $ pkcsconf -P -c ``` + +You can initialize and change the user PIN by typing: + +``` $ pkcsconf -u -c ``` + +You can later change the user PIN again by typing: + +``` $ pkcsconf -p -c ``` + +### 7. Components of openCryptoki + +This section describes the different components of the openCryptoki subsystem. + +#### 7.1. Slot Manager Daemon + +The slot manager daemon is an executable (`/usr/sbin/pkcsslotd`) that reads in +`/etc/opencryptoki/opencryptoki.conf`, populating shared memory according to +what devices have been found within the system. `pkcsslotd` then continues +running as a daemon. Any other applications attempting to use the subsystem must +first attach to the shared memory region and register as part of the API +initialization process, so `pkcsslotd` is aware of the application. If +`/etc/opencryptoki/opencryptoki.conf/` is changed, `pkcsslotd` must be stopped +and restarted to read in the new configuration file. The daemon can be stopped +by issuing the `pkill pkcsslotd` command or through systemd `systemctl stop +pkcsslotd`. The daemon will not terminate if there are any applications using +the subsystem. + +#### 7.2. libopencryptoki.so + +This library contains the main API (`/usr/lib/opencryptoki/libopencryptoki.so`) +and is loaded by any application that uses any PKCS #11 token managed by the +subsystem. Before an application uses a token, it must load the API and call +`C_Initialize`, as per the PKCS #11 specification. The loading operation is +performed by the application using the dlopen facilities. + +#### 7.3. Slot Token DLLs + +Six STDLLs ship in the initial offering. These support Trusted Platfrom Module +(TPM, <2.0), IBM Cryptographic Architecture (ICA), IBM Common Cryptographic +Architecture (CCA), Soft Token, IBM Enterprise PKCS #11 (EP11) and IBM +Integrated Cryptographic Service Facility (ICSF). + + **Note**: The compilation process attempts to build all of the tokens that + are supported on the target platform, as well as all of the required support + programs. If some of the headers and libraries are not present, those + components will not be built. + +##### 7.3.1. Trusted Module Platform (TPM) + +In order to be able to build the TPM stdll you first need: + +1. Enable tpm in BIOS settings. + +2. Install trousers, trousers-devel, tpm-tools and tpm-tools-pkcs11 as root. +Package names can differ depending on the Linux distribution. + +3. As root run the following commands: + +``` + Start the tcsd daemon + # /etc/init.d/tcsd start or # systemctl start tcsd + + Enter tpm passwords + # tpm_takeownership + Enter owner password: + Confirm password: + Enter SRK password: + Confirm password: + + # tpm_setpresence + Enter owner password: + Physical Presence Status: + Command Enable: true + Hardware Enable: false + Lifetime Lock: true + Physical presence: false + Lock: true +``` + +After setting up the TPM the openCryptoki compilation should automatically +build the tpm stdll. If it doesn't, then please run: + +``` ./configure --enable-tpmtok ``` + +For more information check [README.tpm_stdll](README.tpm_stdll) + +##### 7.3.2. IBM Cryptographic Architecture (ICA) + +The IBM Cryptographic Architecture (ICA) is a hardware token that is available +only for s390 systems. If you are in this platform and have the necessary +hardware, you can build openCryptoki with the ICA stdll. To achieve it you need +first install the `libica` package. This package is available in the Linux +distributions repositories. + +##### 7.3.3. IBM Common Cryptographic Architecture (CCA) + +The IBM Common Cryptographic Architecture (CCA) is also a hardware token that is +only available for the s390 architecture. If you are in this platform and have +the necessary hardware then you can build openCryptoki with the CCA stdll. +First, you need to install the csulcca library on your system. To get this +package click +[here](https://www-03.ibm.com/security/cryptocards/pciecc2/lonzsoftware.shtml) +and be sure to choose the package corresponding to your crypto card version. + +For more information about CCA, read [README.cca_stdll](README.cca_stdll) +and [README.pkcscca_migrate](README.pkcscca_migrate). + +##### 7.3.4. Software Token + +This token is a software emulation of a token. All the cryptographic operations +needed will be run in a software implementation of such cryptographic +algorithms. This implementation is given by OpenSSL and the Soft token is built +by default with openCryptoki. + +##### 7.3.5. IBM Enterprise PKCS #11 (EP11) + +This is another hardware token for the s390 architecture. In order to be able to +build openCryptoki with EP11 stdll download the necessary library from +[here](https://www-03.ibm.com/security/cryptocards/pciecc2/lonzsoftware.shtml). +Be sure to choose the driver corresponding to your crypto card version. + +For more information about EP11, please refer to +[README.ep11_stdll](README.ep11_stdll). + +##### 7.3.6. IBM Integrated Cryptographic Service Facility (ICSF) + +The ICSF token is a remote crypto token. The actual crypto operations are +performed remotely on a s390 server and all the PKCS #11 key objects are stored +remotely on the server. This calls to the remote server are done via LDAP. + +So, to build openCryptoki with LDAP, you need to install on the client side: +`openldap, openldap-clients and openldap-devel`. + +For more information about ICSF, head over to +[README.icsf_stdll](README.icsf_stdll). + +### 8. Application and openCryptoki + +This section describes how to make openCryptoki available to applications and +provides an example of how to write such an application. + +#### 8.1. Making openCryptoki Available to Applications + +Many applications use PKCS #11 tokens. Most of these applications must be +configured to load specific shared object (DLL) for the token. In the case of +openCryptoki, only one module (`/usr/lib/opencryptoki/libopencryptoki.so`) must +be loaded for access to all the tokens currently running in the subsystem. +Multiple token types are supported, with each type taking up a slot in the +subsystem according to the implementation specifics of the plug-in module. + +If devices are added or removed, the PKCS #11 slot where the token resides may +change. For this reason, applications should locate the specific token by the +token label provided when the token is initialized and not assume that a +specific slot always contains the desired token. + +For application-specific configuration information relating to the exploitations +of PKCS #11, refer to the application's documentation. + +#### 8.2. Writing an Application + +To develop an application that uses openCryptoki, you must first load the shared +object using the dynamic library calls. Then call C_GetFunctionList. For +example, the following routines loads the shared library and gets the function +list for subsequent calls. + +``` +CK_FUNCTION_LIST *funcs; + +int do_GetFunctionList(void) +{ + CK_RV rc; + CK_RV (*pfoo)(); + void *d; + char *e; + char f[]="/usr/lib/pkcs11/PKCS11_API.so" + + printf("do_GetFunctionList...\n"); + + d = dlopen(f, RTLD_NOW); + if (d == NULL) + return FALSE; + + pfoo = (CK_RV (*)())dlsym(d, "C_GetFunctionList"); + if (pfoo == NULL) + return FALSE; + + rc = pfoo(&funcs); + + if (rc != CKR_OK) { + show_error("C_GetFunctionList rc=%d\n", rc); + return FALSE; + } + + printf("Looks okay...\n"); + return TRUE; +} +``` + +Once loaded, the application must call the `C_Initialize` function. In the +previous example, the function would be invoked with the following lines: + +``` +CK_C_INITIALIZE_ARGS cinit_args; +memset(&cinit_args, 0x0, sizeof(cinit_args)); +funcs->C_Initialize(&cinit_args); +``` + +Refer to the PKCS #11 specification available from the OASIS web site +(https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=pkcs11) for more +options. + + **Note**: openCryptoki requires that operating systems threads be allowed. If + other thread routines are passed in, they are ignored. If the `no-os` threads + argument is set in the initialize arguments structure, the call to + C_Initialize will fail. + + +### 9. Resources + +For additional information about PKCS #11 and openCryptoki, see the following +resources: + +* openCryptoki on [GitHub](https://github.com/opencryptoki/opencryptoki) +* OASIS [PKCS #11 Specification](https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=pkcs11) +* [IBM Cryptocards](https://www-03.ibm.com/security/cryptocards/) +* openCryptoki +[mailing-list](https://sourceforge.net/projects/opencryptoki/lists/opencryptoki-tech) + + +### 10. Appendix A: Sample Program + +The following sample program prints out all of the current tokens and slots in +use in the system. If you want to build the sample program, you will also need +the `Makefile` after the sample. + +#### 10.1. Sample Program + +``` +#include +#include +#include +#include +#include +#include + +#define CFG_SLOT 0x0004 +#define CFG_PKCS_INFO 0X0008 +#define CFG_TOKEN_INFO 0x0010 + +CK_RV init(void); +CK_RV cleanup(void); +CK_RV get_slot_list(int, CK_CHAR_PTR); +CK_RV display_slot_info(void); +CK_RV display_token_info(void); + +void *dll_ptr; +CK_FUNCTION_LIST_PTR function_ptr = NULL; +CK_SLOT_ID_PTR slot_list = NULL; +CK_ULONG slot_count = 0; +int in_slot; + +int main(int argc, char *argv[]) +{ + CK_RV rc; /* Return Code */ + CK_FLAGS flags = 0; /* Bit Mask for what options were passed in */ + CK_CHAR_PTR slot = NULL; /* The PKCS slot number */ + + /* Load the PKCS11 library */ + init(); + + /* Get the slot list and indicate if a slot number was passed in or not */ + get_slot_list(flags, slot); + + /* Display the current token and slot info */ + display_token_info(); + display_slot_info(); + + /* We are done, free the memory we may have allocated */ + free(slot); + return rc; +} + +CK_RV get_slot_list(int cond, CK_CHAR_PTR slot) +{ + CK_RV rc; /* Return code */ + + /* Find out how many tokens are present in the slots */ + rc = function_ptr->C_GetSlotList(TRUE, NULL_PTR, &slot_count); + if (rc != CKR_OK) { + printf("Error getting number of slots: 0x%X\n", rc); + return rc; + } + + /* Allocate enough space for the slots information */ + slot_list = (CK_SLOT_ID_PTR) malloc(slot_count*sizeof(CK_SLOT_ID)); + + rc = function_ptr->C_GetSlotList(TRUE, slot_list, &slot_count); + if (rc != CKR_OK) { + printf("Error getting slot list: 0x%X\n", rc); + return rc; + } + + return rc; +} + +CK_RV display_slot_info(void) +{ + CK_RV rc; /* Return Code */ + CK_SLOT_INFO slot_info; /* Structure to hold slot information */ + int lcv; /* Loop Control Variable */ + + for (lcv = 0; lcv < slot_count; lcv++) { + /* Get the info for the slot we are examining and store in slot_info */ + rc = function_ptr->C_GetSlotInfo(slot_list[lcv], &slot_info); + if (rc != CKR_OK) { + printf("Error getting the slot info: 0x%X\n", rc); + return rc; + } + + /* Display the slot information */ + printf("Slot #%d Info\n", slot_list[lcv]); + printf("\tDescription: %.64s\n", slot_info.slotDescription); + printf("\tManufacturer: %.32s\n", slot_info.manufacturerID); + printf("\tFlags: 0x%X\n", slot_info.flags); + printf("\tHardware Version: %d.%d\n", slot_info.hardwareVersion.major, + slot_info.hardwareVersion.minor); + printf("\tFirmware Version: %d.%d\n", slot_info.firmwareVersion.major, + slot_info.firmwareVersion.minor); + } + return CKR_OK; +} + +CK_RV display_token_info(void) +{ + CK_RV rc; /* Return Code */ + CK_TOKEN_INFO token_info; /* Structure to hold token information */ + int lcv; /* Loop Control Variable */ + + for (lcv = 0; lcv < slot_count; lcv++) { + /* Get the Token info for each slot in the system */ + rc = function_ptr->C_GetTokenInfo(slot_list[lcv], &token_info); + if (rc != CKR_OK) { + printf("Error getting token info: 0x%X\n", rc); + return rc; + } + + /* Display the token information */ + printf("Token #%d Info:\n", slot_list[lcv]); + printf("\tLabel: %.32s\n", token_info.label); + printf("\tManufacturer: %.32s\n", token_info.manufacturerID); + printf("\tModel: %.16s\n", token_info.model); + printf("\tSerial Number: %.16s\n", token_info.serialNumber); + printf("\tFlags: 0x%X\n", token_info.flags); + printf("\tSessions: %d/%d\n", token_info.ulSessionCount, + token_info.ulMaxSessionCount); + printf("\tR/W Sessions: %d/%d\n", token_info.ulRwSessionCount, + token_info.ulMaxRwSessionCount); + printf("\tPIN Length: %d-%d\n", token_info.ulMinPinLen, + token_info.ulMaxPinLen); + printf("\tPublic Memory: 0x%X/0x%X\n", token_info.ulFreePublicMemory, + token_info.ulTotalPublicMemory); + printf("\tPrivate Memory: 0x%X/0x%X\n", token_info.ulFreePrivateMemory, + token_info.ulTotalPrivateMemory); + printf("\tHardware Version: %d.%d\n", token_info.hardwareVersion.major, + token_info.hardwareVersion.minor); + printf("\tFirmware Version: %d.%d\n", token_info.firmwareVersion.major, + token_info.firmwareVersion.minor); + printf("\tTime: %.16s\n", token_info.utcTime); + } + return CKR_OK; +} + +CK_RV init(void) +{ + CK_RV rc; /* Return Code */ + void (*sym_ptr)(); /* Pointer for the DLL */ + + /* Open the PKCS11 API Shared Library, and inform the user if there is an + * error + */ + dll_ptr = dlopen("/usr/lib/opencryptoki/libopencryptoki.so", RTLD_NOW); + if (!dll_ptr) { + rc = errno; + printf("Error loading PKCS#11 library: 0x%X\n", rc); + fflush(stdout); + return rc; + } + + /* Get the list of the PKCS11 functions this token supports */ + sym_ptr = (void (*) ())dlsym(dll_ptr, "C_GetFunctionList"); + if (!sym_ptr) { + rc = errno; + printf("Error getting function list: 0x%X\n", rc); + fflush(stdout); + cleanup(); + } + + sym_ptr(&function_ptr); + + /* If we get here, we know the slot manager is running and we can use PKCS11 + * calls, so we will execute the PKCS11 Initialize command. + */ + rc = function_ptr->C_Initialize(NULL); + if (rc != CKR_OK) { + printf("Error initializing the PKCS11 library: 0x%X\n", rc); + fflush(stdout); + cleanup(); + } + + return CKR_OK; +} + +CK_RV cleanup(void) +{ + CK_RV rc; /* Return Code */ + + /* To clean up we will free the slot list we create, call the Finalize + * routine for PKCS11 and close the dynamically linked library + */ + free(slot_list); + rc = function_ptr->C_Finalize(NULL); + if (dll_ptr) + dlclose(dll_ptr); + + exit(rc); +} +``` + +#### 10.2. Makefile + +``` +VPATH = ... + +INCS = -I../. -I../../../../../include/pkcs11 +CFLAGS = $(OPTLVL) $(INCS) -DAPI -DDEV -D_THREAD_SAFE -DLINUX -DDEBUG -DSPINXL + +CC = gcc +LD = gcc + +LIBS = -ldl -lpthread + +OBJS = sample.o + +.c.o: ; $(CC) -c $(CFLAGS) -o $@ $< + +all: sample + +sample: $(OBJS) +${CC} ${OBJS} $(LIBS) -o $@ + +TARGET = sample + +build: $(TARGET) + +clean: +rm -f *.so *.o $(TARGET) +``` diff -Nru opencryptoki-3.16.0+dfsg/doc/strength-example.conf opencryptoki-3.17.0+dfsg+20220202.b40982e/doc/strength-example.conf --- opencryptoki-3.16.0+dfsg/doc/strength-example.conf 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/doc/strength-example.conf 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,35 @@ +# OpenCryptoki strength example corresponding to NIST recommendations +# See https://www.keylength.com/en/4/ +# Move/copy to /etc/opencryptoki/strength.cfg to use it with opencryptoki. +# Then chown it to root:pkcs11 and chmod it to 0640. + +version strength-0 + +strength 112 { + MOD_EXP = 2048 + ECC = 224 + SYMMETRIC = 112 + digest = 224 + signature = 112 +} +strength 128 { + MOD_EXP = 3072 + ECC = 256 + SYMMETRIC = 128 + digest = 256 + signature = 128 +} +strength 192 { + MOD_EXP = 7680 + ECC = 384 + SYMMETRIC = 192 + digest = 384 + signature = 192 +} +strength 256 { + MOD_EXP = 15360 + ECC = 512 + SYMMETRIC = 256 + digest = 512 + signature = 256 +} diff -Nru opencryptoki-3.16.0+dfsg/doc/system_resources opencryptoki-3.17.0+dfsg+20220202.b40982e/doc/system_resources --- opencryptoki-3.16.0+dfsg/doc/system_resources 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/doc/system_resources 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,76 @@ +The following are the system resources used by openCryptoki as of +openCryptoki-3.8 release. + +1.Shared memory = 1 per token + 1 segment between pkcsslotd & api = 7 max currently + a. Between pkcsslotd and api + The pkcsslotd daemon has its own shared memory segment that it creates + and shares with API. Part of the data is now passed through sockets but + there is still some data shared via shared memory. + + b. Each token has its own shared memory segment. Opencryptoki processes + attach to the token segment and shared memory acts as a global state + tracking mechanism. + # ls /dev/shm + var.lib.opencryptoki.ccatok var.lib.opencryptoki.swtok + var.lib.opencryptoki.ep11tok var.lib.opencryptoki.tpm.root + var.lib.opencryptoki.lite + +2. Sockets - 1 +Unix socket between pkcsslotd and api to transfer slot information. + +3. Files + a. Lock files - 1 global API LCK file + 1 per token (except tpm) = 6 max + currently + 1 lock file per user on tpm token + # ls -lh /var/lock/opencryptoki/ + LCK..APIlock + ccatok/LCK..ccatok + ep11tok/LCK..ep11tok + icsf/LCK..icsf + lite/LCK..lite + swtok/LCK..swtok + tpm//LCK..tpm + + b. Trace files - These are generated based on the environment variable + OPENCRYPTOKI_TRACE_LEVEL per process in /var/log/opencryptoki. No max + limit. + + c. Config files - 2 + # ls -lh /etc/opencryptoki/ + total 8.0K + -rw-r--r--. 1 root root 390 Mar 31 10:55 ep11tok.conf + -rw-r--r--. 1 root root 674 Mar 31 10:55 opencryptoki.conf + + d. Token data files - 3 files per token + 1 additional RACF file for icsf + token + 1 MK_PRIVATE file for tpm token = 20 + NVTOK.DAT - Token data like user pin, so pin etc + MK_SO - Master key used for internal encryption hashed with SOPIN. This + file does not exist on tpm token. + MK_USER - Master key used for internal encryption hashed with USERPIN. + This file does not exist on tpm token. + RACF - icsf racf password encrypted. tpm token has wrapped keys per user + /var/lib/opencryptoki/tpm/${USER}/PRIVATE_ROOT_KEY.pem + /var/lib/opencryptoki/tpm/${USER}/PUBLIC_ROOT_KEY.pem + + e. Token object files - 1 OBJ_IDX file per token and the private object + files. = 6 + as many number of private token objects for tokens + OBJ_IDX - A list of current token objects. + +4. Semaphores +The following depend on the number of processes accessing openCryptoki on the system. + a. The structure API_Proc_Struct_t is allocated per process. It has a thread + level mutex and a session level mutex to lock btree accesses. So two + mutexes per process. + + b. Per process Global Mutex used in API. - 1 + + c. There are 5 mutexes used in common directory per process - 5 + pthread_mutex_t native_mutex ; + MUTEX pkcs_mutex, obj_list_mutex, sess_list_mutex, login_mutex; + +The following are mutexes local to tokens. + d. Soft token has two mutexes - 1 + e. ica token - 1 + +5. There are 5 global btrees (in memory) for holding the session mapping +information, session objects, public token and private token objects +information. diff -Nru opencryptoki-3.16.0+dfsg/.gitignore opencryptoki-3.17.0+dfsg+20220202.b40982e/.gitignore --- opencryptoki-3.16.0+dfsg/.gitignore 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/.gitignore 2022-02-02 15:05:41.000000000 +0100 @@ -393,13 +393,7 @@ usr/lib/ica_s390_stdll/opencryptoki_stdll_libpkcs11_ica_la-ica_specific.lo usr/lib/icsf_stdll/.dirstamp usr/lib/icsf_stdll/.libs/ -usr/lib/icsf_stdll/icsf_config_lexer.c -usr/lib/icsf_stdll/icsf_config_parse.c -usr/lib/icsf_stdll/icsf_config_parse.h -usr/lib/icsf_stdll/icsf_config_parse.output usr/lib/icsf_stdll/opencryptoki_stdll_libpkcs11_icsf_la-icsf.lo -usr/lib/icsf_stdll/opencryptoki_stdll_libpkcs11_icsf_la-icsf_config_lexer.lo -usr/lib/icsf_stdll/opencryptoki_stdll_libpkcs11_icsf_la-icsf_config_parse.lo usr/lib/icsf_stdll/opencryptoki_stdll_libpkcs11_icsf_la-icsf_specific.lo usr/lib/icsf_stdll/opencryptoki_stdll_libpkcs11_icsf_la-new_host.lo usr/lib/icsf_stdll/opencryptoki_stdll_libpkcs11_icsf_la-pbkdf.lo @@ -429,18 +423,12 @@ usr/sbin/pkcsicsf/pkcsicsf usr/sbin/pkcsicsf/usr_sbin_pkcsicsf_pkcsicsf-pkcsicsf.o usr/sbin/pkcsslotd/.dirstamp -usr/sbin/pkcsslotd/lexer.c -usr/sbin/pkcsslotd/parser.c -usr/sbin/pkcsslotd/parser.h -usr/sbin/pkcsslotd/parser.output usr/sbin/pkcsslotd/pkcsslotd usr/sbin/pkcsslotd/usr_sbin_pkcsslotd_pkcsslotd-daemon.o usr/sbin/pkcsslotd/usr_sbin_pkcsslotd_pkcsslotd-err.o usr/sbin/pkcsslotd/usr_sbin_pkcsslotd_pkcsslotd-garbage_linux.o -usr/sbin/pkcsslotd/usr_sbin_pkcsslotd_pkcsslotd-lexer.o usr/sbin/pkcsslotd/usr_sbin_pkcsslotd_pkcsslotd-log.o usr/sbin/pkcsslotd/usr_sbin_pkcsslotd_pkcsslotd-mutex.o -usr/sbin/pkcsslotd/usr_sbin_pkcsslotd_pkcsslotd-parser.o usr/sbin/pkcsslotd/usr_sbin_pkcsslotd_pkcsslotd-pkcsslotd_util.o usr/sbin/pkcsslotd/usr_sbin_pkcsslotd_pkcsslotd-shmem.o usr/sbin/pkcsslotd/usr_sbin_pkcsslotd_pkcsslotd-signal.o diff -Nru opencryptoki-3.16.0+dfsg/Makefile.am opencryptoki-3.17.0+dfsg+20220202.b40982e/Makefile.am --- opencryptoki-3.16.0+dfsg/Makefile.am 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/Makefile.am 2022-02-02 15:05:41.000000000 +0100 @@ -29,6 +29,8 @@ include man/man.mk include usr/usr.mk +include tools/tools.mk +include doc/doc.mk install-data-hook: if ENABLE_LIBRARY @@ -74,6 +76,10 @@ test -f $(DESTDIR)$(sysconfdir)/opencryptoki/ep11tok.conf || $(INSTALL) -m 644 $(srcdir)/usr/lib/ep11_stdll/ep11tok.conf $(DESTDIR)$(sysconfdir)/opencryptoki/ep11tok.conf || true test -f $(DESTDIR)$(sysconfdir)/opencryptoki/ep11cpfilter.conf || $(INSTALL) -m 644 $(srcdir)/usr/lib/ep11_stdll/ep11cpfilter.conf $(DESTDIR)$(sysconfdir)/opencryptoki/ep11cpfilter.conf || true endif +if ENABLE_P11SAK + test -f $(DESTDIR)$(sysconfdir)/opencryptoki || $(MKDIR_P) $(DESTDIR)$(sysconfdir)/opencryptoki || true + test -f $(DESTDIR)$(sysconfdir)/opencryptoki/p11sak_defined_attrs.conf || $(INSTALL) -g pkcs11 -m 0640 $(srcdir)/usr/sbin/p11sak/p11sak_defined_attrs.conf $(DESTDIR)$(sysconfdir)/opencryptoki/p11sak_defined_attrs.conf || true +endif if ENABLE_ICATOK cd $(DESTDIR)$(libdir)/opencryptoki/stdll && \ ln -fs libpkcs11_ica.so PKCS11_ICA.so @@ -123,6 +129,7 @@ if ENABLE_DAEMON test -f $(DESTDIR)$(sysconfdir)/opencryptoki || $(MKDIR_P) $(DESTDIR)$(sysconfdir)/opencryptoki || true test -f $(DESTDIR)$(sysconfdir)/opencryptoki/opencryptoki.conf || $(INSTALL) -m 644 $(srcdir)/usr/sbin/pkcsslotd/opencryptoki.conf $(DESTDIR)$(sysconfdir)/opencryptoki/opencryptoki.conf || true + test -f $(DESTDIR)$(sysconfdir)/opencryptoki/strength.conf || $(INSTALL) -m 640 -o root -g pkcs11 -T $(srcdir)/doc/strength-example.conf $(DESTDIR)$(sysconfdir)/opencryptoki/strength.conf || true if ENABLE_SYSTEMD mkdir -p $(DESTDIR)/usr/lib/tmpfiles.d cp $(srcdir)/misc/tmpfiles.conf $(DESTDIR)/usr/lib/tmpfiles.d/opencryptoki.conf @@ -201,6 +208,16 @@ if ENABLE_TESTCASES PKCS11_SO_PIN ?= 76543210 PKCS11_USER_PIN ?= 01234567 +PKCS11_VHSM_PIN ?= 1234567890 + +ci-prepare: + killall -HUP pkcsslotd || true + ${srcdir}/testcases/ciconfig.sh "$(sysconfdir)/opencryptoki" "$(sysconfdir)/opencryptoki" + @sbindir@/pkcsslotd + @sbindir@/pkcsstats --reset-all + for slot in `awk '/slot (.*)/ { print $$2; }' $(sysconfdir)/opencryptoki/opencryptoki.conf`; do @sbindir@/pkcsconf -c $$slot -t | grep "Flags:" | grep -q TOKEN_INITIALIZED || PKCS11_USER_PIN=$(PKCS11_USER_PIN) PKCS11_SO_PIN=$(PKCS11_SO_PIN) PKCSLIB=@libdir@/opencryptoki/libopencryptoki.so ${srcdir}/testcases/init_token.sh $$slot; done +# cd ${srcdir}/testcases && PKCS11_USER_PIN=$(PKCS11_USER_PIN) PKCS11_VHSM_PIN=$(PKCS11_VHSM_PIN) PKCSLIB=@libdir@/opencryptoki/libopencryptoki.so ./init_vhsm.exp 42 +# echo "VHSM_MODE" >> "$(sysconfdir)/opencryptoki/ep11tok42.conf" installcheck-local: all killall -HUP pkcsslotd || true @@ -208,18 +225,34 @@ if test ! -z ${PKCS11_TEST_USER}; then \ chmod 777 ${srcdir}/testcases && \ cd ${srcdir}/testcases && \ - su ${PKCS11_TEST_USER} -s /bin/bash -c "PKCS11_SO_PIN=$(PKCS11_SO_PIN) PKCS11_USER_PIN=$(PKCS11_USER_PIN) PKCSLIB=@libdir@/opencryptoki/libopencryptoki.so sh ./ock_tests.sh"; \ + su ${PKCS11_TEST_USER} -s /bin/bash -c "PKCS11_SO_PIN=$(PKCS11_SO_PIN) PKCS11_USER_PIN=$(PKCS11_USER_PIN) PKCSLIB=@libdir@/opencryptoki/libopencryptoki.so sh ./ock_tests.sh || true"; \ else \ cd ${srcdir}/testcases && \ - PKCS11_SO_PIN=$(PKCS11_SO_PIN) PKCS11_USER_PIN=$(PKCS11_USER_PIN) PKCSLIB=@libdir@/opencryptoki/libopencryptoki.so sh ./ock_tests.sh; \ + PKCS11_SO_PIN=$(PKCS11_SO_PIN) PKCS11_USER_PIN=$(PKCS11_USER_PIN) PKCSLIB=@libdir@/opencryptoki/libopencryptoki.so sh ./ock_tests.sh || true; \ fi killall -HUP pkcsslotd -ci-installcheck: installcheck +ci-installcheck: ci-prepare installcheck killall -HUP pkcsslotd || true @sbindir@/pkcsslotd cd ${srcdir}/testcases && export PKCSLIB=@libdir@/opencryptoki/libopencryptoki.so && export PKCS11_USER_PIN=$(PKCS11_USER_PIN) && ./misc_tests/p11sak_test.sh | tee log-p11sak.txt + @sbindir@/pkcsstats --all killall -HUP pkcsslotd @echo "done" + +ci-cleanup: + @sbindir@/pkcsstats --delete-all || true + killall -HUP pkcsslotd || true +# @sbindir@/pkcsslotd +# cd ${srcdir}/testcases && PKCS11_USER_PIN=$(PKCS11_USER_PIN) PKCSLIB=@libdir@/opencryptoki/libopencryptoki.so ./cleanup_vhsm.exp 42 +# killall -HUP pkcsslotd + +ci-uninstall: uninstall + rm -f $(sysconfdir)/opencryptoki/ep11tok*.conf + rm -rf $(localstatedir)/lib/opencryptoki/* + rm -rf $(lockdir)/* + rm -rf $(logdir)/* + +.PHONY: ci-prepare ci-installcheck ci-uninstall endif diff -Nru opencryptoki-3.16.0+dfsg/man/man1/man1.mk opencryptoki-3.17.0+dfsg+20220202.b40982e/man/man1/man1.mk --- opencryptoki-3.16.0+dfsg/man/man1/man1.mk 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/man/man1/man1.mk 2022-02-02 15:05:41.000000000 +0100 @@ -1,5 +1,9 @@ man1_MANS += man/man1/pkcsconf.1 man/man1/pkcsicsf.1 +if ENABLE_PKCSSTATS +man1_MANS += man/man1/pkcsstats.1 +endif + if ENABLE_PKCSTOK_MIGRATE man1_MANS += man/man1/pkcstok_migrate.1 endif diff -Nru opencryptoki-3.16.0+dfsg/man/man1/p11sak.1.in opencryptoki-3.17.0+dfsg+20220202.b40982e/man/man1/p11sak.1.in --- opencryptoki-3.16.0+dfsg/man/man1/p11sak.1.in 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/man/man1/p11sak.1.in 2022-02-02 15:05:41.000000000 +0100 @@ -59,7 +59,7 @@ option will show the arguments and options available. . .PP -.SS "list-key" +.SS "remove-key" .PP Use the .B remove-key|rm-key|rm @@ -84,7 +84,7 @@ .B \-\-label .IR LABEL .B \-\-attr -.IR [M R L S E D G V W U A X N T] +.IR [P M R L S E D G V W U A X N T] .B \-\-help | \-h .PP Use the @@ -105,7 +105,7 @@ .IR LABEL attribute of the key and .B \-\-attr -.IR [M R L S E D G V W U A X N T] +.IR [P M R L S E D G V W U A X N T] can be used to set the binary attributes of the key (see below for detailed description of the attributes). . .PP @@ -122,7 +122,7 @@ .B \-\-label .IR LABEL .B \-\-attr -.IR [M R L S E D G V W U A X N T] +.IR [P M R L S E D G V W U A X N T] .B \-\-help | \-h .PP Use the @@ -143,7 +143,7 @@ .IR LABEL attribute of the key and .B \-\-attr -.IR [M R L S E D G V W U A X N T] +.IR [P M R L S E D G V W U A X N T] can be used to set the binary attributes of the key (see below for detailed description of the attributes). . .PP @@ -162,7 +162,7 @@ .B \-\-exponent .IR EXP .B \-\-attr -.IR [M R L S E D G V W U A X N T] +.IR [P M R L S E D G V W U A X N T] .B \-\-help | \-h .PP Use the @@ -183,7 +183,7 @@ .IR LABEL attribute of the key and .B \-\-attr -.IR [M R L S E D G V W U A X N T] +.IR [P M R L S E D G V W U A X N T] can be used to set the binary attributes of the key (see below for detailed description of the attributes). Furthermore, the .B \-\-exponent .IR EXP @@ -203,7 +203,7 @@ .B \-\-label .IR LABEL .B \-\-attr -.IR [M R L S E D G V W U A X N T] +.IR [P M R L S E D G V W U A X N T] .B \-\-help | \-h .PP Use the @@ -234,7 +234,7 @@ .IR LABEL attribute of the key and .B \-\-attr -.IR [M R L S E D G V W U A X N T] +.IR [P M R L S E D G V W U A X N T] can be used to set the binary attributes of the key (see below for detailed description of the attributes). . .PP @@ -242,7 +242,7 @@ . .B p11sak .BR list-key | ls-key | ls -.BR des | 3des | aes | rsa | ec | public | private | secret +.BR des | 3des | aes | rsa | ec | public | private | secret | all .B \-\-slot .IR SLOTID .B \-\-pin @@ -252,7 +252,7 @@ .PP Use the .B list-key | ls-key | ls -command and key argument to list DES, 3DES, AES, RSA or EC keys, respectively. Public, private or secret keys can also be listed irrespective of key type. +command and key argument to list DES, 3DES, AES, RSA or EC keys, respectively. Public, private, secret, or all keys can also be listed irrespective of key type. . .PP .SS "Deleting symmetric and asymmetric keys" @@ -271,7 +271,7 @@ .PP Use the .B remove-key | rm-key | rm -command and key argument to delete DES, 3DES, AES, RSA or EC keys, respectively. All specified cipher keys will be promted to be deleted unless +command and key argument to delete DES, 3DES, AES, RSA, or EC keys, respectively. All specified cipher keys will be promted to be deleted unless a specific key with the .B \-\-label .IR LABEL @@ -285,13 +285,13 @@ . .SH ARGS . -.SS "des | 3des | aes | rsa | ec | public | private | secret" +.SS "des | 3des | aes | rsa | ec | public | private | secret | all" selects the respective symmetric or asymetric key to be generated or listed. The -.B public|private|secret +.B public|private|secret|all argument can only be used with the .B list-key -command to list either public, private or secret keys. +command to list either public, private, secret, or all keys. .PP . . @@ -352,7 +352,7 @@ . . . -.SS "\-\-attr [M R L S E D G V W U A X N T]" +.SS "\-\-attr [P M R L S E D G V W U A X N T]" sets the binary attributes of a key. .PP .B Note: @@ -365,6 +365,9 @@ when the letter that is associated with the given binary attribute is specified. The following letters are associated with the respective .B CK_ATTRIBUTE: .IP "\(bu" 2 +.B P +- CKA_PRIVATE +.IP "\(bu" 2 .B M - CKA_MODIFIABLE .IP "\(bu" 2 @@ -403,10 +406,22 @@ .IP "\(bu" 2 .B N - CKA_NEVER_EXTRACTABLE +.IP "\(bu" 2 +.B * +- if in p11sak_defined_attrs.conf additional attributes are defined. .PP CKA_TOKEN and CKA_PRIVATE are set by default to .B TRUE. -For multiple attributes, combine the letters in a string without white space, e. g. 'MLD'. +For multiple attributes, combine the letters in a string without white space, e. g. 'MlD'. +An uppercase letter means true, while an lowercase letter equals false. +From Example above: CKA_MODIFIABLE=true, CKA_LOCAL=false, CKA_DECRYPT=true +.PP +For asymmetric keys a user can set different custom attributes for the public and the private key. +The separator is the symbol ":". The defined attributes in front of the separator are set for the +public key and the attributes defined after the separator are set for the private key. When the +separator is not in the string, the defined attribute set is used for public and private key. To set +a configuration for only the public key, the string has to end with the separator and respectively, +to use a configuration for the private key only, the string has to start with the separator. .PP . . @@ -432,3 +447,51 @@ .B p11sak and/or the respective command. .PP +. +. +. +.SH "FILES" + +.SS "/usr/local/etc/opencryptoki/p11sak_defined_attrs.conf" +In the output config file a user can define additional attributes, which are not +mentioned in the PKCS#11 standard. A custom filepath can be set with an environment +variable. +.PP +. +. +. +.SH "ENVIRONMENT VARIABLES" + +.SS "P11SAK_DEFAULT_CONF_FILE" +A custom path for p11sak_defined_attrs.conf can be set with the environment variable +P11SAK_DEFAULT_CONF_FILE. If none is set p11sak will first look for the file in the user +directory, followed by the standard installation path. +.PP +. +. +. +.SH "EXIT STATUS" +p11sak returns various error codes on fail: +.SS CKR_ARGUMENTS_BAD (0x00000007): +The p11sak_defined_attrs.conf is not found. +.PP +. +. +. +.SS CKR_DATA_INVALID (0x00000020): +The p11sak_defined_attrs.conf cannot be parsed or syntax is invalid. +.PP +. +. +. +.SS CKR_ATTRIBUTE_TYPE_INVALID (0x00000012): +A given attribute type cannot be set for this key. +.PP +. +. +. +.SH "SEE ALSO" +.PD 0 +.TP +\fBp11sak_defined_attrs.conf\fP(5) +.PD diff -Nru opencryptoki-3.16.0+dfsg/man/man1/pkcsep11_session.1.in opencryptoki-3.17.0+dfsg+20220202.b40982e/man/man1/pkcsep11_session.1.in --- opencryptoki-3.16.0+dfsg/man/man1/pkcsep11_session.1.in 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/man/man1/pkcsep11_session.1.in 2022-02-02 15:05:41.000000000 +0100 @@ -5,8 +5,9 @@ .SH SYNOPSIS \fBpkcep11_session\fP [\fB-h\fP] -[\fBshow|logout|vhsmpin\fP \fB-slot\fP \fIslot-number\fP [\fB-id\fP \fIsession-ID\fP] -[\fB-pid\fP \fIprocess-ID\fP] [\fB-date\fP \fIyyyy/mm/dd\fP] [\fB-force\fP] ] +[\fBshow|logout|vhsmpin|status\fP [\fB-slot\fP \fIslot-number\fP] +[\fB-id\fP \fIsession-ID\fP] [\fB-pid\fP \fIprocess-ID\fP] +[\fB-date\fP \fIyyyy/mm/dd\fP] [\fB-force\fP] ] .SH DESCRIPTION Use pkcep11_session to list and logout leftover EP11 sessions. @@ -33,10 +34,14 @@ .br \fBNote:\fP When changing the VHSM PIN, all existing keys stored as token objects become unusable! +.IP "\fBstatus\fP" 10 +shows the maximum and currently available number of EP11 sessions for each +available EP11 APQN. .SH "OPTIONS" .IP "\fB-slot\fP \fIslot-number\fP" 10 -specifies the slot of the EP11 token +specifies the slot of the EP11 token. This option is required for all commands +except the \fBstatus\fP command. .IP "\fB-force\fP" 10 deletes a session even if logout fails on some adapters. .IP "\fB-id\fP \fIsession-ID\fP" 10 diff -Nru opencryptoki-3.16.0+dfsg/man/man1/pkcsicsf.1.in opencryptoki-3.17.0+dfsg+20220202.b40982e/man/man1/pkcsicsf.1.in --- opencryptoki-3.16.0+dfsg/man/man1/pkcsicsf.1.in 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/man/man1/pkcsicsf.1.in 2022-02-02 15:05:41.000000000 +0100 @@ -38,6 +38,9 @@ the user will be prompted for the racf password when listing or adding a token. +The \fBpkcsicsf\fP utility must be run as root when adding an ICSF token to +opencryptoki. + .SH "OPTIONS" .IP "\fB-a\fP \fItoken name\fp" 10 add the specified ICSF token to opencryptoki. diff -Nru opencryptoki-3.16.0+dfsg/man/man1/pkcsstats.1.in opencryptoki-3.17.0+dfsg+20220202.b40982e/man/man1/pkcsstats.1.in --- opencryptoki-3.16.0+dfsg/man/man1/pkcsstats.1.in 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/man/man1/pkcsstats.1.in 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,145 @@ +.\" pkcsstats.1 +.\" +.\" Copyright IBM Corp. 2021 +.\" See LICENSE for details. +.\" +.TH PKCSSTATS 1 "October 2021" "@PACKAGE_VERSION@" "openCryptoki" +.SH NAME +pkcsstats \- utility to display mechanism usage statistics for openCryptoki. + +.SH SYNOPSIS +.B pkcsstats +.RB [ OPTIONS ] +. +.PP +.B pkcsstats +.BR \-\-help | \-h +.br + +.SH DESCRIPTION +Displays mechanism usage statistics for openCryptoki. Usage statistics are +collected by openCryptoki on a per user basis. For each user, mechanism +usage is counted per configured slot and mechanism. For each mechanism a set of +counters exist, one for each cryptographic strength of the cryptographic +key used with the mechanism. +.PP +The available strengths are defined in the strength configuration file +\fB/etc/opencryptoki/strength.conf\fP. Supported strengths are 112, 128, 192, +and 256 representing the corresponding strength in bits. +The strength configuration file defines how the strength is determined for the +various key types. A strength of zero is used to count those mechanisms that +do not use a key, or where the key strength is less than 112 bits. +.PP +.B Note: +The strength does not specify the cryptographic strength of the mechanism, but +the cryptographic strength of the key used with the mechanism (if any). +For example, usage of mechanism CKM\_SHA256 is reported under strength 0, +because no key is used with this mechanism. However, usage of mechanism +CKM\_AES\_CBC is reported under strength 128, 192, or 256, dependent on the +cryptographic size of the AES key used with it (and the definitions in the +strength configuration file). +.PP +Statistics collection is enabled by default. It can be disabled and configured +in the openCryptoki configuration file +\fB/etc/opencryptoki/opencryptoki.conf\fP. +By default only explicit mechanism usage statistics from PKCS#11 applications +are collected. +.PP +Optionally, implicit mechanism usage statistics can be collected, where +additional mechanisms are specified in mechanism parameters. For example, +RSA\-PSS or RSA\-OAEP allows to specify a hash mechanism and a mask generation +function (MGF) in the mechanism parameter. ECDH allows to specify a key +derivation function (KDF) in the mechanism parameter. The PBKDF2 mechanism +allows to specify a pseudo random function (PRF) in the mechanism parameter. +.PP +Also optionally, opencryptoki\-internal mechanism usage statistics can be +collected. This collects usage statistics for crypto operations used internally +for pin handling and encryption of private token objects in the data store. +.PP +.B Note: +Implicit or internal mechanism usage can not be distinguished from explicit +mechanism usage of PKCS#11 applications in the displayed statistics. +.PP +Statistics are collected in a POSIX shared memory segment per user. This shared +memory segment contains all counters for all configured slots, mechanisms, and +strengths. The shared memory segments are named +\fBvar.lib.opencryptoki_stats_\fP, where \fBuid\fP is the numeric user\-id +of the user the statistics belong to. The shared memory segments are +automatically created for a user on the first attempt to collect statistics +(when not already existent). The shared memory segments can be deleted using +the \fBpkcsstats\fP command with the \fB\-\-delete\fP, or \fB\-\-delete\-all\fP +options. +.PP +The usage of a mechanism is counted once when the cryptographic operation is +sucessfully initialized, i.e. during \fBC_DigestInit\fP, \fBC_EncryptInit\fP, +\fBC_DecryptInit\fP, \fBC_SignInit\fP, \fBC_SignRecoverInit\fP, and +\fBC_VerifyInit\fP. Multi-part operations involving the update functions like +\fBC_DigestUpdate\fP, \fBC_EncryptUpdate\fP, \fBC_DecryptUpdate\fP, +\fBC_SignUpdate\fP, and \fBC_VerifyUpdate\fP, are not counted additionally. +.PP +Other operations such as key generation, key derivation, key wrapping and +unwrapping are counted during the respective functions like \fBC_GenerateKey\fP, +\fBC_GenerateKeyPair\fP, \fBC_DeriveKey\fP, \fBC_DeriveKey\fP, +\fBC_UnwrapKey\fP. + +.SH "OPTIONS" + +.TP +.BR \-U ", " \-\-user\~\fIuser\-id\fP +Specifies the user\-id of the user to display, reset, or delete statistics for. +If this option is omitted, the statistics of the current user are displayed, +resetted, or deleted. Only the \fBroot\fP user can display, reset, or delete +statistics of other users. +.TP +.BR \-S ", " \-\-summary +Shows the accumulated statistics from all users. Only the \fBroot\fP user can +display the accumulated statistics from other users. +.TP +.BR \-A ", " \-\-all +Shows the statistics from all users. Only the \fBroot\fP user can display +statistics from all users. +.TP +.BR \-a ", " \-\-all\-mechs +Shows the statistics for all mechanisms, also those with all\-zero counters. +If this option is omitted, only those mechanisms are displayed where at least +one counter is non\-zero. +.TP +.BR \-s ", " \-\-slot\~\fIslot\-id\fP +Specifies the slot\-id to display statistics for. If this option is omitted, +the statistics for all configured slots are displayed. +.TP +.BR \-r ", " \-\-reset +Resets the statistics counters for the current user, or for the user specified +with the \fB\-\-user\fP option. Only the \fBroot\fP user can reset the +statistics from other users. +.TP +.BR \-R ", " \-\-reset\-all +Resets the statistics counters for all users. Only the \fBroot\fP user +can reset the statistics from other users. +.TP +.BR \-d ", " \-\-delete +Deletes the shared memory segment containing the statistics counters for the +current user, or for the user specified with the \fB\-\-user\fP option. +Only the \fBroot\fP user can delete the statistics from other users. +.TP +.BR \-D ", " \-\-delete\-all +Deletes the shared memory segment containing the statistics counters for all +users. Only the \fBroot\fP user can delete the statistics from other users. +.TP +.BR \-j ", " \-\-json +Shows the statistics in JSON format. This is usefull to get the statistics in +a machine readable format. +.TP +.BR \-h ", " \-\-help +Displays help text and exits. + +.SH SEE ALSO +.PD 0 +.TP +\fBopencryptoki.conf\fP(5). +.TP +\fBstrength.conf\fP(5), +.TP +\fBopencryptoki\fP(7), + +.PD diff -Nru opencryptoki-3.16.0+dfsg/man/man1/pkcstok_migrate.1.in opencryptoki-3.17.0+dfsg+20220202.b40982e/man/man1/pkcstok_migrate.1.in --- opencryptoki-3.16.0+dfsg/man/man1/pkcstok_migrate.1.in 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/man/man1/pkcstok_migrate.1.in 2022-02-02 15:05:41.000000000 +0100 @@ -42,6 +42,8 @@ After an unsuccessful migration, the original repository is still available unchanged. +The \fBpkcstok_migrate\fP utility must be run as root. + .SH "OPTIONS SUMMARY" .IP "\fB--slotid -s\fP \fISLOT-NUMBER\fP" 10 specifies the token slot number of the token repository to be migrated diff -Nru opencryptoki-3.16.0+dfsg/man/man5/man5.mk opencryptoki-3.17.0+dfsg+20220202.b40982e/man/man5/man5.mk --- opencryptoki-3.16.0+dfsg/man/man5/man5.mk 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/man/man5/man5.mk 2022-02-02 15:05:41.000000000 +0100 @@ -1,4 +1,8 @@ -man5_MANS += man/man5/opencryptoki.conf.5 +man5_MANS += man/man5/opencryptoki.conf.5 man/man5/strength.conf.5 man/man5/policy.conf.5 + +if ENABLE_P11SAK +man5_MANS += man/man5/p11sak_defined_attrs.conf.5 +endif EXTRA_DIST += $(man5_MANS) CLEANFILES += $(man5_MANS) diff -Nru opencryptoki-3.16.0+dfsg/man/man5/opencryptoki.conf.5.in opencryptoki-3.17.0+dfsg+20220202.b40982e/man/man5/opencryptoki.conf.5.in --- opencryptoki-3.16.0+dfsg/man/man5/opencryptoki.conf.5.in 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/man/man5/opencryptoki.conf.5.in 2022-02-02 15:05:41.000000000 +0100 @@ -10,8 +10,39 @@ determine which slots will be made available. .SH SYNTAX -This file is made up of slot descriptions. Each slot description -is composed of a slot number, brackets and key-value pairs. +This file is made up of optional global definitions, and slot descriptions. + +The following global definitions are valid: + +.TP +.BR disable-event-support +If this keyword is specified the openCryptoki event support is disabled. + +.TP +.BR statistics\~(off | on [ ,implicit ][ ,internal ] ) +Enables or disables collection of statistics of mechanism usage. By default, +statistics collection is enabled. A value of \fB(off)\fP disables all statistics +collection. A value of \fB(on)\fP enables collection of mechanism usage. +The collected statistics can be displayed using the \fBpkcsstats\fP tool. + +In addition to enabling statistics collection for mechanisms used by PKCS#11 +applications, you can specify \fB(on,implicit)\fP to also enable collection +of implicit mechanism usage, where additional mechanisms are specified in +mechanism parameters. For example, RSA-PSS or RSA-OAEP allow to specify a hash +mechanism and a mask generation function (MGF) in the mechanism parameter. +ECDH allows to specify a key derivation function (KDF) in the mechanism +parameter. + +You can additionally enable statistics collection of mechanisms internally used +by Opencryptoki by specifying \fB(on,internal)\fP. This additionally collects +usage statistics for crypto operations used internally for pin handling and +encryption of private token objects in the data store. + +Implicit and internal statistics collection can also be combined: +\fB(on,implicit,internal)\fP + +.P +Each slot description is composed of a slot number, brackets and key-value pairs. slot number { @@ -80,4 +111,6 @@ \fBopencryptoki\fP(7), .TP \fBpkcsslotd\fP(8), +.TP +\fBpkcsstats\fP(1), .PD diff -Nru opencryptoki-3.16.0+dfsg/man/man5/p11sak_defined_attrs.conf.5.in opencryptoki-3.17.0+dfsg+20220202.b40982e/man/man5/p11sak_defined_attrs.conf.5.in --- opencryptoki-3.16.0+dfsg/man/man5/p11sak_defined_attrs.conf.5.in 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/man/man5/p11sak_defined_attrs.conf.5.in 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,57 @@ +.TH P11SAK_DEFINED_ATTRS.CONF 5 "September 2021" "@PACKAGE_VERSION@" "openCryptoki" +.SH NAME +p11sak_defined_attrs.conf \- Configuration file for p11sak list-key command. + +.SH DESCRIPTION +p11sak uses a configuration file at /etc/opencryptoki/p11sak_defined_attrs.conf. +This configuration file path can be overwritten by the user with the environment +variable P11SAK_DEFAULT_CONF_FILE. + +This is a text file that contains information used to configure +non standard attributes that shall be printed with the p11sak list-key command. + +.SH SYNTAX + +.P +Each attribute description is composed of the attribute title, brackets and three key-value pairs. +e.g.: + + attribute + { + name = CKA_IBM_RESTRICTABLE + id = 0x80010001 + type = CK_BBOOL + } + +All three keywords +.B name +, +.B id +, +.B type +are required to define an attribute. + +The +.B name +has to start with a letter followed by an arbitrary number of letters, numbers, underscores, dots, minuses, or slashes. +The +.B id +is defined in the PKCS#11 standard and can be +in decimal as well as in hexadecimal, when started with 0x, format. +The only valid values for +.B type +are +.B CK_BBOOL +, +.B CK_ULONG +or +.B CK_BYTE. + +.SH Notes +The pound sign ('#') is used to indicate a comment up to and including the end of line. + +.SH "SEE ALSO" +.PD 0 +.TP +\fBp11sak\fP(1), +.PD diff -Nru opencryptoki-3.16.0+dfsg/man/man5/policy.conf.5.in opencryptoki-3.17.0+dfsg+20220202.b40982e/man/man5/policy.conf.5.in --- opencryptoki-3.16.0+dfsg/man/man5/policy.conf.5.in 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/man/man5/policy.conf.5.in 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,238 @@ +.TH POLICY.CONF 5 "September 2021" "@PACKAGE_VERSION@" "openCryptoki" +.SH NAME +policy.conf \- Configuration file for openCryptoki policies. + +.SH DESCRIPTION +openCryptoki uses a policy configuration file at +/etc/opencryptoki/policy.conf + +This configuration file restricts the operations of openCryptoki to a +specific set of allowed operations. The policy allows users to +restrict keys to a minimal cryptographic strength, restrict supported +elliptic curves, mechanisms, MGFs, KDFs, or PRFs. + +.SH SYNTAX +This file starts with a version specification of the form +\fBversion policy-0\fR +followed by policy constraints. + +.P + +A policy constraint assigns a value to a configuration key. The +syntax depends of the value of the key: + +.TP +.BR strength + +This key defines the minimal required strength for keys, and digest +and signature sizes. It corresponds to the definition in +/etc/opencryptoki/strength.conf. Valid values are 0, 112, 128, 192, +and 256. The special value 0 allows every key and arbitrary size of +digests and signatures. The format is a simple assignment: + +strength = number + +If other values are used, they are rounded up to the next supported +value. Values greater than 256 are rounded down to 256. + +.TP +.BR allowedmechs + +This key specifies a list of mechanisms that are allowed by this +policy. The list should contain a comma-separated list of +.BR CKM_ +constants supported by openCryptoki. The list is placed inside +brackets: + +allowedmechs ( mech1, mech2 ) + +Note: This key is optional. If not present, all mechanisms are +allowed. If an empty list is provided, no mechanism would be allowed. +.TP +.BR allowedcurves + +This key specifies a list of allowed elliptic curves. Keys that do +not belong to any of the allowed curves cannot be created or used. +The list has the same format as the +.BR allowedmechs +key: + +allowedcurves ( curve1, curve2 ) + +Valid curve names are: + +.RS +.IP \(bu +BRAINPOOL_P160R1 +.IP \(bu +BRAINPOOL_P160T1 +.IP \(bu +BRAINPOOL_P192R1 +.IP \(bu +BRAINPOOL_P192T1 +.IP \(bu +BRAINPOOL_P224R1 +.IP \(bu +BRAINPOOL_P224T1 +.IP \(bu +BRAINPOOL_P256R1 +.IP \(bu +BRAINPOOL_P256T1 +.IP \(bu +BRAINPOOL_P320R1 +.IP \(bu +BRAINPOOL_P320T1 +.IP \(bu +BRAINPOOL_P384R1 +.IP \(bu +BRAINPOOL_P384T1 +.IP \(bu +BRAINPOOL_P512R1 +.IP \(bu +BRAINPOOL_P512T1 +.IP \(bu +PRIME192V1 +.IP \(bu +SECP224R1 +.IP \(bu +PRIME256V1 +.IP \(bu +SECP384R1 +.IP \(bu +SECP521R1 +.IP \(bu +SECP256K1 +.IP \(bu +CURVE25519 +.IP \(bu +CURVE448 +.IP \(bu +ED25519 +.IP \(bu +ED448 +.RE + +Note: This key is optional. If not present, all curves are allowed. +An empty list allows no curve. +.TP +.BR allowedmgfs + +This key specifies the allowed Message Generation Functions (MGFs) for +use in RSA OAEP and RSA PSS. The value is a list of +.BR CKG_ +constants supported by openCryptoki. The list has the same format as +the +.BR allowedmechs +key: + +allowedmgfs ( mgf1, mgf2 ) + +Note: This key is optional. If not present, all MGFs are allowed. An +empty list allows no MGF. +.TP +.BR allowedkdfs + +This key specifies the allowed Key Derivation Functions (KDFs) for use +in ECDH key derivation. The value is a list of +.BR CKD_ +constants supported by openCryptoki. This list has the same format as +the +.BR allowedmechs +key: + +allowedkdfs ( kdf1, kdf2 ) + +Note: This key is optional. If not present, all KDFs are allowed. An +empty list allows no KDF. +.TP +.BR allowedprfs + +This key specifies the allowed Pseudo-Random Functions (PRFs) for use +in PKCS #5 PBKDF. The value is a list of PRFs. Currently, the only +supported value is +.BR CKP_PKCS5_PBKD2_HMAC_SHA256 +.BR CKP_PKCS5_PBKD2_HMAC_SHA512 +which leads to the list + +allowedprfs ( CKP_PKCS5_PBKD2_HMAC_SHA512, CKP_PKCS5_PBKD2_HMAC_SHA256 ) + +Note: This key is optional. If not present, all PRFs are allowed. An +empty list allows no PRF. + +.SH NOTES + +The policy configuration file has to be owned by \fBroot:pkcs11\fP and +have mode 0640. Otherwise, openCryptoki will return +\fBCKR_FUNCTION_FAILED\fR on \fBC_Initialize\fR and log the reason +into syslog. + +.PP + +The pound sign ('#') is used to indicate a comment. Both the comment +character and any text after it, up to the end of the line, are +ignored. The comment character can be used at the beginning of a line +(including before the file version specification), after the strength +value, after a comma, and before and after the bracket. + +.PP +Since the policy indirectly refers to a strength configuration, a +strength configuration has to exist and be valid. If no strength +configuration exists, no policy will be enforced. If an existing +policy configuration is invalid, openCryptoki cannot be used. + +.PP + +openCryptoki uses some cryptographic operations to store token +objects. These operations have to be allowed by the policy. Which +operations are needed depends on the token store format and the token +(since the ICSF Token as a remote token uses different crypto +operations to store its management data): + +.RS +.IP "FIPS compliant format" +Token stores in the FIPS compliant format need the mechanisms +.BR CKM_AES_KEY_GEN, +.BR CKM_AES_KEY_WRAP, +.BR CKM_AES_GCM, +.BR CKM_PKCS5_PBKD2, +the PRF +.BR CKP_PKCS5_PBKD2_HMAC_SHA512, +and must allow 256 bit AES keys. +.IP "legacy format" +Token stores in legacy format need the mechanisms +.BR CKM_DES3_KEY_GEN, +.BR CKM_DES3_CBC, +.BR CKM_AES_KEY_GEN, +.BR CKM_AES_CBC, +.BR CKM_SHA1, +.BR CKM_MD5 +and must allow 2-key TDES keys (80 bit symmetric keys with 64 bit signatures). +.IP "ICSF Token store" +.BR CKM_AES_KEY_GEN, +.BR CKM_AES_CBC, +.BR CKM_SHA1, +.BR CKM_MD5 +.BR CKM_PKCS5_PBKD2, +the PRF +.BR CKP_PKCS5_PBKD2_HMAC_SHA256, +and must allow 256 bit AES keys. +.RE + +Tokens cannot be loaded if their token store format is not supported +by the policy. If a token cannot be loaded, a message is printed into +syslog detailing the policy violation. To fix this problem, make sure +the token format is allowed by your policy (either by satisfying above +constraints or by temporarily removing /etc/opencryptoki/policy.conf) +and migrate your token store, e.g., to the FIPS-compliant format. + +.SH "SEE ALSO" +.PD 0 +.TP +\fBstrength.conf\fP(5), +.TP +\fBopencryptoki\fP(7), +.TP +\fBpkcstok_migrate\fP(1), +.TP +/usr/share/doc/opencryptoki/policy-example.conf +.PD diff -Nru opencryptoki-3.16.0+dfsg/man/man5/strength.conf.5.in opencryptoki-3.17.0+dfsg+20220202.b40982e/man/man5/strength.conf.5.in --- opencryptoki-3.16.0+dfsg/man/man5/strength.conf.5.in 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/man/man5/strength.conf.5.in 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,105 @@ +.TH STRENGTH.CONF 5 "September 2021" "@PACKAGE_VERSION@" "openCryptoki" +.SH NAME +strength.conf \- Configuration file for openCryptoki strength configuration. + +.SH DESCRIPTION +openCryptoki uses a strength configuration file at +/etc/opencryptoki/strength.conf + +This configuration file allows users to configure openCryptoki +cryptographic key strength determination based on key attributes. +This file is required by openCryptoki. + +.SH SYNTAX +This file starts with a version specification of the form +\fBversion strength-0\fR +followed by the definition of various strengths. + +.P +Each strength definition is composed of a strength, brackets and key-value pairs. + + strength number + { + ... + } + +Supported numbers are 112, 128, 192, and 256 representing the +corresponding strength in bits. + +Note: These definitions are optional. If a definition is missing, no +key can have the strength. If no strength definition is present, all +keys will have strength 0. + +More than one key-value pair may be used within a strength description. + +A key-value pair is composed of +.B keyword = value +where +.B value +is an unsigned number. + +The following keywords are valid: + +.TP +.BR MOD_EXP +Specifies the minimum number of bits required for RSA moduli, and DH +and DSA primes such that the corresponding key is of the currently +defined strength. + +Note: This key-value pair is optional. If not present, no RSA, DH, or +DSA key can have the currently defined strength. +.TP +.BR ECC +Specifies the minimum number of bits in the prime field of the +elliptic curve such that the corresponding key is of the currently +defined strength. + +Note: This key-value pair is optional. If not present, no EC key can +have the currently defined strength. +.TP +.BR SYMMETRIC +Specifies the minimum number of bits required for symmetric keys such +that the corresponding key is of the currently defined strength. + +Note: This key-value pair is optional. If not present, no symmetric +key can have the currently defined strength. +.TP +.BR digest +Specifies the minimum size in bits of digest outputs required by the +currently defined strength. + +Note: This key-value pair is optional. If not present, this strength +definition does not constrain the size of digests. +.TP +.BR signature +Specifies the minimum size in bits of signatures required by the +currently defined strength. + +Note: This key-value pair is optional. If not present, this strength +definition does not constrain the size of signatures. + +.SH NOTES + +The strength configuration file has to be owned by \fBroot:pkcs11\fP, +have mode 0640, and be parsable. Otherwise, openCryptoki will return +\fBCKR_FUNCTION_FAILED\fR on \fBC_Initialize\fR and log a +corresponding message to syslog detailing the reason why the strength +configuration could not be used. In this case, fix the problem +described in syslog to be able to use openCryptoki again. + +.PP +The pound sign ('#') is used to indicate a comment. Both the comment +character and any text after it, up to the end of the line, are +ignored. The comment character can be used at the beginning of a line +(including before the file version specification), after a value, and +before and after the braces. + +.SH "SEE ALSO" +.PD 0 +.TP +\fBstrength.conf\fP(5), +.TP +\fBopencryptoki\fP(7), +.TP +/usr/share/doc/opencryptoki/strength-example.conf +.PD diff -Nru opencryptoki-3.16.0+dfsg/man/man7/opencryptoki.7.in opencryptoki-3.17.0+dfsg+20220202.b40982e/man/man7/opencryptoki.7.in --- opencryptoki-3.16.0+dfsg/man/man7/opencryptoki.7.in 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/man/man7/opencryptoki.7.in 2022-02-02 15:05:41.000000000 +0100 @@ -21,8 +21,7 @@ must be assigned to the \fIpkcs11\fP group to be able to communicate with the \fIpkcsslotd\fP daemon. Only fully trusted users should be granted membership in the group. Group members can block other openCryptoki users -from accessing PKCS#11 tokens, and execute arbitrary code with the -privileges of other openCryptoki users. +from accessing PKCS#11 tokens. .SH "SEE ALSO" .PD 0 diff -Nru opencryptoki-3.16.0+dfsg/misc/pkcsslotd.in opencryptoki-3.17.0+dfsg+20220202.b40982e/misc/pkcsslotd.in --- opencryptoki-3.16.0+dfsg/misc/pkcsslotd.in 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/misc/pkcsslotd.in 2022-02-02 15:05:41.000000000 +0100 @@ -12,7 +12,7 @@ . /etc/init.d/functions -PIDFILE=/var/run/pkcsslotd.pid +PIDFILE=/run/pkcsslotd.pid LOCKFILE=/var/lock/subsys/pkcsslotd SLOTDBIN=@sbindir@/pkcsslotd diff -Nru opencryptoki-3.16.0+dfsg/misc/pkcsslotd.service.in opencryptoki-3.17.0+dfsg+20220202.b40982e/misc/pkcsslotd.service.in --- opencryptoki-3.16.0+dfsg/misc/pkcsslotd.service.in 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/misc/pkcsslotd.service.in 2022-02-02 15:05:41.000000000 +0100 @@ -4,7 +4,7 @@ [Service] Type=forking -PIDFile=/var/run/pkcsslotd.pid +PIDFile=/run/pkcsslotd.pid ExecStart=@sbindir@/pkcsslotd [Install] diff -Nru opencryptoki-3.16.0+dfsg/README.md opencryptoki-3.17.0+dfsg+20220202.b40982e/README.md --- opencryptoki-3.16.0+dfsg/README.md 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/README.md 2022-02-02 15:05:41.000000000 +0100 @@ -1,15 +1,15 @@ -['![Travis CI Build Status](https://travis-ci.org/opencryptoki/opencryptoki.svg?branch=master)'](https://travis-ci.org/opencryptoki/opencryptoki) +[![Build Status](https://app.travis-ci.com/opencryptoki/opencryptoki.svg?branch=master)](https://app.travis-ci.com/opencryptoki/opencryptoki) ['![Coverity Scan Build Status](https://img.shields.io/coverity/scan/16802.svg)'](https://scan.coverity.com/projects/opencryptoki-opencryptoki) # openCryptoki -Package version 3.16 +Package version 3.17 Please see [ChangeLog](ChangeLog) for release specific information. ## OVERVIEW -openCryptoki version 3.16 implements the PKCS#11 specification version 3.0. +openCryptoki version 3.17 implements the PKCS#11 specification version 3.0. This package includes several cryptographic tokens: CCA, ICA, TPM , SWToken, ICSF and EP11. @@ -27,7 +27,7 @@ - TPM - requires a TPM, TPM tools, and TCG software stack. -- SWToken - The software token uses OpenSSL version 1.0.2 or higher. +- SWToken - The software token uses OpenSSL version 1.1.1 or higher. - ICSF - The Integrated Cryptographic Service Facility (ICSF) token requires openldap and openldap client software version 2.4.23 or higher. Lex and Yacc are diff -Nru opencryptoki-3.16.0+dfsg/rpm/opencryptoki.spec opencryptoki-3.17.0+dfsg+20220202.b40982e/rpm/opencryptoki.spec --- opencryptoki-3.16.0+dfsg/rpm/opencryptoki.spec 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/rpm/opencryptoki.spec 2022-02-02 15:05:41.000000000 +0100 @@ -2,7 +2,7 @@ Name: opencryptoki Summary: Implementation of the PKCS#11 (Cryptoki) specification v3.0 -Version: 3.16.0 +Version: 3.17.0 Release: 1%{?dist} License: CPL Group: System Environment/Base @@ -10,7 +10,7 @@ Source: https://github.com/%{name}/%{name}/archive/v%{version}.tar.gz#/%{name}-%{version}.tar.gz Requires(pre): coreutils -BuildRequires: openssl-devel >= 1.0.2 +BuildRequires: openssl-devel >= 1.1.1 BuildRequires: trousers-devel BuildRequires: openldap-devel BuildRequires: autoconf automake libtool diff -Nru opencryptoki-3.16.0+dfsg/testcases/ciconfig.sh opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/ciconfig.sh --- opencryptoki-3.16.0+dfsg/testcases/ciconfig.sh 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/ciconfig.sh 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,117 @@ +#!/bin/bash + +OCKCONFDIR="$1" +EPCONFDIR="$2" + +LATESTCEXP="CEX7P" + +USENEWFORMAT=/bin/false + +# Usage: addslot slot-num stdll slot-name [confname] +function addslot() { + cat <> "${OCKCONFDIR}/opencryptoki.conf" +slot $1 +{ +stdll = $2 +tokname = $3 +EOF + if $USENEWFORMAT; then + echo "tokversion = 3.12" >> "${OCKCONFDIR}/opencryptoki.conf" + fi + if [ "x$4" != "x" ]; then + echo "confname = $4" >> "${OCKCONFDIR}/opencryptoki.conf" + fi + echo "}" >> "${OCKCONFDIR}/opencryptoki.conf" +} + +# Usage: genep11cfg num configline +function genep11cfg() { + cat < "${EPCONFDIR}/ep11tok${1}.conf" +${2} +APQN_ANY +EOF +} + +# Usage: genlatestep11cfg num +# Return: 0 if successful +function genlatestep11cfg() { + local res=1 + + lszcrypt | grep "$LATESTCEXP" | perl -ne '/(\d+)\.(\d+)\s.*/ && print "0x$1 0x$2\n"' > tmp.apqns + if test -s tmp.apqns; then + echo "APQN_WHITELIST" > "${EPCONFDIR}/ep11tok${1}.conf" + cat tmp.apqns >> "${EPCONFDIR}/ep11tok${1}.conf" + echo "END" >> "${EPCONFDIR}/ep11tok${1}.conf" + res=0 + fi + rm -f tmp.apqns + return $res +} + +if test $(($(date +%j)%2)) == 1; then + USENEWFORMAT=/bin/true + echo "Using FIPS compliant token store" +else + echo "Using legacy token store" +fi + +# initialize opencryptoki.conf +echo "version opencryptoki-3.16" > "${OCKCONFDIR}/opencryptoki.conf" + +# enable full statistics +echo "statistics (on,implicit,internal)" >> "${OCKCONFDIR}/opencryptoki.conf" + +# ICA token +addslot 10 libpkcs11_ica.so ica0 +addslot 11 libpkcs11_ica.so ica1 + +# CCA token +addslot 20 libpkcs11_cca.so cca0 +addslot 21 libpkcs11_cca.so cca1 + +# SW token +addslot 30 libpkcs11_sw.so sw0 +addslot 31 libpkcs11_sw.so sw1 + +# EP11 token +# 0: +# APQN_ANY +genep11cfg 40 "" +addslot 40 libpkcs11_ep11.so ep0 ep11tok40.conf + +# 1: +# FORCE_SENSITIVE +# APQN_ANY +genep11cfg 41 "FORCE_SENSITIVE" +addslot 41 libpkcs11_ep11.so ep1 ep11tok41.conf + +# 2: +# STRICT_MODE +# APQN_ANY +# later appended: VHSM_MODE + +#genep11cfg 42 "STRICT_MODE" +#addslot 42 libpkcs11_ep11.so ep2 ep11tok42.conf + +# 3: +# OPTIMIZE_SINGLE_PART_OPERATIONS +# APQN_ANY +genep11cfg 43 "OPTIMIZE_SINGLE_PART_OPERATIONS" +addslot 43 libpkcs11_ep11.so ep3 ep11tok43.conf + +# 4: +# DIGEST_LIBICA OFF +# APQN_ANY +genep11cfg 44 "DIGEST_LIBICA OFF" +addslot 44 libpkcs11_ep11.so ep4 ep11tok44.conf + +# 5: +# PKEY_MODE ENABLE4NONEXTR +# APQN_ANY +genep11cfg 45 "PKEY_MODE ENABLE4NONEXTR" +addslot 45 libpkcs11_ep11.so ep5 ep11tok45.conf + +# 6: latest +if genlatestep11cfg 46; then + addslot 46 libpkcs11_ep11.so ep6 ep11tok46.conf +fi diff -Nru opencryptoki-3.16.0+dfsg/testcases/cleanup_vhsm.exp.in opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/cleanup_vhsm.exp.in --- opencryptoki-3.16.0+dfsg/testcases/cleanup_vhsm.exp.in 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/cleanup_vhsm.exp.in 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,25 @@ +#!/usr/bin/expect -f +# +# COPYRIGHT (c) International Business Machines Corp. 2001-2017 +# +# This program is provided under the terms of the Common Public License, +# version 1.0 (CPL-1.0). Any use, reproduction or distribution for this software +# constitutes recipient's acceptance of CPL-1.0 terms which can be found +# in the file LICENSE file or at https://opensource.org/licenses/cpl1.0.php +# + +spawn @sbindir@/pkcsep11_session logout -force -slot [lindex $argv 0] +expect { + "Enter the USER PIN:" { sleep .1; send $env(PKCS11_USER_PIN); send "\r"; } + eof { send_user "Unexpected EOF on user pin\n"; exit 1 } + timeout { send_user "Timeout on user pin\n"; exit 1 } +} +expect { + "EP11-Sessions logged out" {} + eof { send_user "Unexpected EOF at the end\n"; exit 1 } + timeout { send_user "Unexpected timeout at the end\n"; exit 1 } +} +expect { + eof {} + timeout { send_user "Unexpected timeout at the end\n"; exit 1 } +} diff -Nru opencryptoki-3.16.0+dfsg/testcases/common/common.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/common/common.c --- opencryptoki-3.16.0+dfsg/testcases/common/common.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/common/common.c 2022-02-02 15:05:41.000000000 +0100 @@ -16,6 +16,8 @@ #include "pkcs11types.h" #include "regress.h" +#define UNUSED(var) ((void)(var)) + CK_FUNCTION_LIST *funcs; CK_FUNCTION_LIST_3_0 *funcs3; CK_INTERFACE *ifs; @@ -51,7 +53,7 @@ static void unload_pkcslib(void) { if (pkcs11lib != NULL) { - dlclose(pkcs11lib); + dlclose(pkcs11lib); } } @@ -100,6 +102,10 @@ if (rc != CKR_OK) return FALSE; + /* min and max being zero indicate no key size limitation */ + if (mech_info.ulMinKeySize == 0 && mech_info.ulMaxKeySize == 0) + return TRUE; + return ((mech_info.ulMinKeySize <= keylen) && (keylen <= mech_info.ulMaxKeySize)); } @@ -138,10 +144,30 @@ return rc; } +/** + * Check if the last CKR_FUNCTION__FAILED error was due to policy restrictions + */ +int is_rejected_by_policy(CK_RV ret_code, CK_SESSION_HANDLE session) +{ + CK_SESSION_INFO info; + CK_RV rc; + + if (ret_code != CKR_FUNCTION_FAILED) + return 0; + + rc = funcs->C_GetSessionInfo(session, &info); + if (rc != CKR_OK) { + testcase_error("C_GetSessionInfo(), rc=%s.", p11_get_ckr(rc)); + return 0; + } + + return (info.ulDeviceError == CKR_POLICY_VIOLATION); +} + /** Create an AES key handle with given value **/ -int create_AESKey(CK_SESSION_HANDLE session, CK_BBOOL extractable, - unsigned char key[], unsigned char key_len, - CK_OBJECT_HANDLE * h_key) +CK_RV create_AESKey(CK_SESSION_HANDLE session, CK_BBOOL extractable, + unsigned char key[], unsigned char key_len, + CK_OBJECT_HANDLE * h_key) { CK_RV rc; CK_BBOOL true = TRUE; @@ -160,16 +186,19 @@ rc = funcs->C_CreateObject(session, keyTemplate, keyTemplate_len, h_key); if (rc != CKR_OK) { - testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); + if (is_rejected_by_policy(rc, session)) + rc = CKR_POLICY_VIOLATION; + else + testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); } return rc; } /** Generate an AES key handle **/ -int generate_AESKey(CK_SESSION_HANDLE session, - CK_ULONG key_len, CK_BBOOL extractable, - CK_MECHANISM * mechkey, CK_OBJECT_HANDLE * h_key) +CK_RV generate_AESKey(CK_SESSION_HANDLE session, + CK_ULONG key_len, CK_BBOOL extractable, + CK_MECHANISM * mechkey, CK_OBJECT_HANDLE * h_key) { CK_ATTRIBUTE key_gen_tmpl[] = { {CKA_EXTRACTABLE, &extractable, sizeof(CK_BBOOL)}, @@ -181,16 +210,19 @@ key_gen_tmpl, key_gen_tmpl_len, h_key); if (rc != CKR_OK) { - testcase_error("C_GenerateKey rc=%s", p11_get_ckr(rc)); + if (is_rejected_by_policy(rc, session)) + rc = CKR_POLICY_VIOLATION; + else + testcase_error("C_GenerateKey rc=%s", p11_get_ckr(rc)); } return rc; } /** Create a DES key handle with given value **/ -int create_DESKey(CK_SESSION_HANDLE session, - unsigned char key[], unsigned char klen, - CK_OBJECT_HANDLE * h_key) +CK_RV create_DESKey(CK_SESSION_HANDLE session, + unsigned char key[], unsigned char klen, + CK_OBJECT_HANDLE * h_key) { CK_RV rc; CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; @@ -211,16 +243,19 @@ memcpy(value, key, klen); rc = funcs->C_CreateObject(session, keyTemplate, 5, h_key); if (rc != CKR_OK) { - testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); + if (is_rejected_by_policy(rc, session)) + rc = CKR_POLICY_VIOLATION; + else + testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); } return rc; } /** Create DES2 key handle with given value **/ -int create_DES2Key(CK_SESSION_HANDLE session, - unsigned char key[], unsigned char klen, - CK_OBJECT_HANDLE * h_key) +CK_RV create_DES2Key(CK_SESSION_HANDLE session, + unsigned char key[], unsigned char klen, + CK_OBJECT_HANDLE * h_key) { CK_RV rc; CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; @@ -240,16 +275,19 @@ memcpy(value, key, klen); rc = funcs->C_CreateObject(session, keyTemplate, 5, h_key); if (rc != CKR_OK) { - testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); + if (is_rejected_by_policy(rc, session)) + rc = CKR_POLICY_VIOLATION; + else + testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); } return rc; } /** Create DES3 key handle with given value **/ -int create_DES3Key(CK_SESSION_HANDLE session, - unsigned char key[], unsigned char klen, - CK_OBJECT_HANDLE * h_key) +CK_RV create_DES3Key(CK_SESSION_HANDLE session, + unsigned char key[], unsigned char klen, + CK_OBJECT_HANDLE * h_key) { CK_RV rc; CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; @@ -269,14 +307,17 @@ memcpy(value, key, klen); rc = funcs->C_CreateObject(session, keyTemplate, 5, h_key); if (rc != CKR_OK) { - testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); + if (is_rejected_by_policy(rc, session)) + rc = CKR_POLICY_VIOLATION; + else + testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); } return rc; } /** Create Generic Secret key handle with given value **/ -int create_GenericSecretKey(CK_SESSION_HANDLE session, +CK_RV create_GenericSecretKey(CK_SESSION_HANDLE session, CK_BYTE key[], CK_ULONG key_len, CK_OBJECT_HANDLE * h_key) { @@ -293,7 +334,10 @@ rc = funcs->C_CreateObject(session, key_attribs, 4, h_key); if (rc != CKR_OK) { - testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); + if (is_rejected_by_policy(rc, session)) + rc = CKR_POLICY_VIOLATION; + else + testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); } return rc; @@ -352,7 +396,10 @@ // create key rc = funcs->C_CreateObject(session, template, 17, priv_key); if (rc != CKR_OK) { - testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); + if (is_rejected_by_policy(rc, session)) + rc = CKR_POLICY_VIOLATION; + else + testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); } return rc; @@ -386,7 +433,10 @@ // create key rc = funcs->C_CreateObject(session, template, 8, publ_key); if (rc != CKR_OK) { - testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); + if (is_rejected_by_policy(rc, session)) + rc = CKR_POLICY_VIOLATION; + else + testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); } return rc; @@ -429,6 +479,9 @@ publicKeyTemplate, 5, privateKeyTemplate, 8, publ_key, priv_key); + if (is_rejected_by_policy(rc, session)) + rc = CKR_POLICY_VIOLATION; + return rc; // no error checking due to // ICA Token + public exponent values + CKR_TEMPLATE_INCONSISTENT @@ -470,6 +523,9 @@ privateKeyTemplate, num_priv_attrs, publ_key, priv_key); + if (is_rejected_by_policy(rc, session)) + rc = CKR_POLICY_VIOLATION; + return rc; } @@ -515,6 +571,10 @@ rc = funcs->C_CreateObject(session, template, sizeof(template) / sizeof(CK_ATTRIBUTE), priv_key); + + if (is_rejected_by_policy(rc, session)) + rc = CKR_POLICY_VIOLATION; + return rc; } @@ -546,6 +606,10 @@ rc = funcs->C_CreateObject(session, template, sizeof(template) / sizeof(CK_ATTRIBUTE), publ_key); + + if (is_rejected_by_policy(rc, session)) + rc = CKR_POLICY_VIOLATION; + return rc; } @@ -594,7 +658,10 @@ sizeof(template) / sizeof(CK_ATTRIBUTE), priv_key); if (rc != CKR_OK) { - testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); + if (is_rejected_by_policy(rc, session)) + rc = CKR_POLICY_VIOLATION; + else + testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); } return rc; @@ -628,7 +695,10 @@ sizeof(template) / sizeof(CK_ATTRIBUTE), publ_key); if (rc != CKR_OK) { - testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); + if (is_rejected_by_policy(rc, session)) + rc = CKR_POLICY_VIOLATION; + else + testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); } return rc; @@ -675,7 +745,10 @@ sizeof(template) / sizeof(CK_ATTRIBUTE), priv_key); if (rc != CKR_OK) { - testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); + if (is_rejected_by_policy(rc, session)) + rc = CKR_POLICY_VIOLATION; + else + testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); } return rc; @@ -715,7 +788,10 @@ sizeof(template) / sizeof(CK_ATTRIBUTE), publ_key); if (rc != CKR_OK) { - testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); + if (is_rejected_by_policy(rc, session)) + rc = CKR_POLICY_VIOLATION; + else + testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); } return rc; @@ -760,7 +836,10 @@ sizeof(template) / sizeof(CK_ATTRIBUTE), priv_key); if (rc != CKR_OK) { - testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); + if (is_rejected_by_policy(rc, session)) + rc = CKR_POLICY_VIOLATION; + else + testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); } return rc; @@ -797,7 +876,10 @@ sizeof(template) / sizeof(CK_ATTRIBUTE), publ_key); if (rc != CKR_OK) { - testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); + if (is_rejected_by_policy(rc, session)) + rc = CKR_POLICY_VIOLATION; + else + testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); } return rc; @@ -817,7 +899,10 @@ rc = funcs->C_GenerateKey(session, mech, secret_tmpl, 2, secret_key); if (rc != CKR_OK) { - testcase_fail("C_GenerateKey, rc=%s", p11_get_ckr(rc)); + if (is_rejected_by_policy(rc, session)) + rc = CKR_POLICY_VIOLATION; + else + testcase_fail("C_GenerateKey, rc=%s", p11_get_ckr(rc)); } return rc; @@ -876,6 +961,15 @@ || (pubexp_len == 3 && (!memcmp(pubexp, exp65537, 3))); } +/** Returns true if pubexp is valid for Soft Tokens **/ +int is_valid_soft_pubexp(CK_BYTE pubexp[], CK_ULONG pubexp_len) +{ + UNUSED(pubexp); + UNUSED(pubexp_len); + + return TRUE; +} + /** Returns true if slot_id is an ICSF token ** ICSF token info is not necessarily hard-coded like the other tokens ** so there is no single identifying attribute. So, instead just diff -Nru opencryptoki-3.16.0+dfsg/testcases/common/common.mk opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/common/common.mk --- opencryptoki-3.16.0+dfsg/testcases/common/common.mk 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/common/common.mk 2022-02-02 15:05:41.000000000 +0100 @@ -1,6 +1,8 @@ noinst_LTLIBRARIES += testcases/common/libcommon.la testcases_common_libcommon_la_LIBADD = -lc -ldl -lpthread -testcases_common_libcommon_la_CFLAGS = -c ${testcases_inc} -testcases_common_libcommon_la_SOURCES = \ - usr/lib/common/p11util.c testcases/common/common.c +testcases_common_libcommon_la_CFLAGS = -c ${testcases_inc} \ + -I${top_builddir}/usr/lib/api +testcases_common_libcommon_la_SOURCES = usr/lib/common/p11util.c \ + testcases/common/common.c +nodist_testcases_common_libcommon_la_SOURCES = usr/lib/api/mechtable.c diff -Nru opencryptoki-3.16.0+dfsg/testcases/crypto/abfunc.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/crypto/abfunc.c --- opencryptoki-3.16.0+dfsg/testcases/crypto/abfunc.c 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/crypto/abfunc.c 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,1199 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2006-2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ + +#include +#include +#include +#include +#include + +#include "pkcs11types.h" +#include "common.c" +#include "regress.h" +#include "mech_to_str.h" +#include "ec_curves.h" + +#define NUMKEYS 15 + +struct keys { + union keysunion { + struct details { + // AB keys + CK_OBJECT_HANDLE aes; + CK_OBJECT_HANDLE des2; + CK_OBJECT_HANDLE des3; + CK_OBJECT_HANDLE generic; + CK_OBJECT_HANDLE rsapub; + CK_OBJECT_HANDLE rsapriv; + CK_OBJECT_HANDLE ecpub; + CK_OBJECT_HANDLE ecpriv; + CK_OBJECT_HANDLE dsapub; + CK_OBJECT_HANDLE dsapriv; + CK_OBJECT_HANDLE dhpub; + CK_OBJECT_HANDLE dhpriv; + // non-AB key + CK_OBJECT_HANDLE nonabpub; + CK_OBJECT_HANDLE nonabpriv; + CK_OBJECT_HANDLE nonabecpub; + CK_OBJECT_HANDLE nonabecpriv; + } d; + CK_OBJECT_HANDLE keys[NUMKEYS]; + } u; +} keys; + +CK_BYTE DSA_PUBL_PRIME[128] = { + 0xba, 0xa2, 0x5b, 0xd9, 0x77, 0xb3, 0xf0, 0x2d, 0xa1, 0x65, + 0xf1, 0x83, 0xa7, 0xc9, 0xf0, 0x8a, 0x51, 0x3f, 0x74, 0xe8, + 0xeb, 0x1f, 0xd7, 0x0a, 0xd5, 0x41, 0xfa, 0x52, 0x3c, 0x1f, + 0x79, 0x15, 0x55, 0x18, 0x45, 0x41, 0x29, 0x27, 0x12, 0x4a, + 0xb4, 0x32, 0xa6, 0xd2, 0xec, 0xe2, 0x82, 0x73, 0xf4, 0x30, + 0x66, 0x1a, 0x31, 0x06, 0x37, 0xd2, 0xb0, 0xe4, 0x26, 0x39, + 0x2a, 0x0e, 0x48, 0xf6, 0x77, 0x94, 0x47, 0xea, 0x7d, 0x99, + 0x22, 0xce, 0x65, 0x61, 0x82, 0xd5, 0xe3, 0xfc, 0x15, 0x3f, + 0xff, 0xff, 0xc8, 0xb9, 0x4f, 0x37, 0xbf, 0x7a, 0xa6, 0x6a, + 0xbe, 0xff, 0xa9, 0xdf, 0xfd, 0xed, 0x4a, 0xb6, 0x83, 0xd6, + 0x0f, 0xea, 0xf6, 0x90, 0x4f, 0x12, 0x8e, 0x09, 0x6e, 0x3c, + 0x0a, 0x6d, 0x2e, 0xfb, 0xb3, 0x79, 0x90, 0x8e, 0x39, 0xc0, + 0x86, 0x0e, 0x5d, 0xf0, 0x56, 0xcd, 0x26, 0x45 +}; + +CK_BYTE DSA_PUBL_SUBPRIME[20] = { + 0x9f, 0x3d, 0x47, 0x13, 0xa3, 0xff, 0x93, 0xbb, 0x4a, 0xa6, + 0xb0, 0xf1, 0x7e, 0x54, 0x1e, 0xba, 0xf0, 0x66, 0x03, 0x61 +}; + + +CK_BYTE DSA_PUBL_BASE[128] = { + 0x1a, 0x5b, 0xfe, 0x12, 0xba, 0x85, 0x8e, 0x9b, 0x08, 0x86, + 0xd1, 0x43, 0x9b, 0x4a, 0xaf, 0x44, 0x31, 0xdf, 0xa1, 0x57, + 0xd8, 0xe0, 0xec, 0x34, 0x07, 0x4b, 0x78, 0x8e, 0x3c, 0x62, + 0x47, 0x4c, 0x2f, 0x5d, 0xd3, 0x31, 0x2c, 0xe9, 0xdd, 0x59, + 0xc5, 0xe7, 0x2e, 0x06, 0x40, 0x6c, 0x72, 0x9c, 0x95, 0xc6, + 0xa4, 0x2a, 0x1c, 0x1c, 0x45, 0xb9, 0xf3, 0xdc, 0x83, 0xb6, + 0xc6, 0xdd, 0x94, 0x45, 0x4f, 0x74, 0xc6, 0x55, 0x36, 0x54, + 0xba, 0x20, 0xad, 0x9a, 0xb6, 0xe3, 0x20, 0xf2, 0xdd, 0xd3, + 0x66, 0x19, 0xeb, 0x53, 0xf5, 0x88, 0x35, 0xe1, 0xea, 0xe8, + 0xd4, 0x57, 0xe1, 0x3d, 0xea, 0xd5, 0x00, 0xc2, 0xa4, 0xf5, + 0xff, 0xfb, 0x0b, 0xfb, 0xa2, 0xb9, 0xf1, 0x49, 0x46, 0x9d, + 0x11, 0xa5, 0xb1, 0x94, 0x52, 0x47, 0x6e, 0x2e, 0x79, 0x4b, + 0xc5, 0x18, 0xe9, 0xbc, 0xff, 0xae, 0x34, 0x7f +}; + +CK_BYTE DH_PUBL_PRIME[128] = { + 0xd5, 0xb1, 0xaa, 0x6a, 0x3b, 0x85, 0x50, 0xf0, 0xe2, + 0xea, 0x6b, 0xec, 0x26, 0x3b, 0xe0, 0xbf, 0x7a, 0x82, + 0x45, 0x1b, 0xa8, 0x0a, 0x54, 0x2e, 0x14, 0x2c, 0xc2, + 0x58, 0xb1, 0xf5, 0x59, 0xec, 0x7d, 0x16, 0x9e, 0x00, + 0x62, 0xb3, 0xa7, 0xdc, 0x38, 0x6f, 0x64, 0x40, 0xfc, + 0x0d, 0x3e, 0x0b, 0x66, 0x13, 0x5e, 0xa5, 0x84, 0x90, + 0x26, 0x62, 0xcf, 0x5a, 0x14, 0x72, 0x2d, 0x1b, 0x37, + 0x7e, 0x8a, 0x4b, 0xc0, 0xb7, 0xf2, 0x63, 0xd1, 0xaa, + 0x51, 0x92, 0x96, 0x18, 0xae, 0xb9, 0xfd, 0x5f, 0x9d, + 0x5d, 0xdf, 0x75, 0xa9, 0x80, 0x3d, 0xaa, 0xc2, 0x54, + 0x00, 0xcc, 0xc1, 0x9e, 0x31, 0x4d, 0x22, 0x31, 0x44, + 0xe9, 0x69, 0x34, 0xae, 0xcf, 0xcd, 0x6d, 0xf6, 0xe9, + 0x37, 0x20, 0xa4, 0xd3, 0x85, 0x24, 0xff, 0x9f, 0x39, + 0xeb, 0x78, 0xf2, 0xd1, 0xc3, 0xf9, 0x66, 0xab, 0xbd, + 0x2d, 0xd3 +}; + + +CK_BYTE DH_PUBL_BASE[128] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02 +}; + +CK_BYTE AES_KEY_VAL[] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c +}; + +CK_BYTE DSA1024_BASE[128] = { + 0xf7, 0xe1, 0xa0, 0x85, 0xd6, 0x9b, 0x3d, 0xde, 0xcb, 0xbc, + 0xab, 0x5c, 0x36, 0xb8, 0x57, 0xb9, 0x79, 0x94, 0xaf, 0xbb, + 0xfa, 0x3a, 0xea, 0x82, 0xf9, 0x57, 0x4c, 0x0b, 0x3d, 0x07, + 0x82, 0x67, 0x51, 0x59, 0x57, 0x8e, 0xba, 0xd4, 0x59, 0x4f, + 0xe6, 0x71, 0x07, 0x10, 0x81, 0x80, 0xb4, 0x49, 0x16, 0x71, + 0x23, 0xe8, 0x4c, 0x28, 0x16, 0x13, 0xb7, 0xcf, 0x09, 0x32, + 0x8c, 0xc8, 0xa6, 0xe1, 0x3c, 0x16, 0x7a, 0x8b, 0x54, 0x7c, + 0x8d, 0x28, 0xe0, 0xa3, 0xae, 0x1e, 0x2b, 0xb3, 0xa6, 0x75, + 0x91, 0x6e, 0xa3, 0x7f, 0x0b, 0xfa, 0x21, 0x35, 0x62, 0xf1, + 0xfb, 0x62, 0x7a, 0x01, 0x24, 0x3b, 0xcc, 0xa4, 0xf1, 0xbe, + 0xa8, 0x51, 0x90, 0x89, 0xa8, 0x83, 0xdf, 0xe1, 0x5a, 0xe5, + 0x9f, 0x06, 0x92, 0x8b, 0x66, 0x5e, 0x80, 0x7b, 0x55, 0x25, + 0x64, 0x01, 0x4c, 0x3b, 0xfe, 0xcf, 0x49, 0x2a +}; + +CK_BYTE DSA1024_PRIME[128] = { + 0xfd, 0x7f, 0x53, 0x81, 0x1d, 0x75, 0x12, 0x29, 0x52, 0xdf, + 0x4a, 0x9c, 0x2e, 0xec, 0xe4, 0xe7, 0xf6, 0x11, 0xb7, 0x52, + 0x3c, 0xef, 0x44, 0x00, 0xc3, 0x1e, 0x3f, 0x80, 0xb6, 0x51, + 0x26, 0x69, 0x45, 0x5d, 0x40, 0x22, 0x51, 0xfb, 0x59, 0x3d, + 0x8d, 0x58, 0xfa, 0xbf, 0xc5, 0xf5, 0xba, 0x30, 0xf6, 0xcb, + 0x9b, 0x55, 0x6c, 0xd7, 0x81, 0x3b, 0x80, 0x1d, 0x34, 0x6f, + 0xf2, 0x66, 0x60, 0xb7, 0x6b, 0x99, 0x50, 0xa5, 0xa4, 0x9f, + 0x9f, 0xe8, 0x04, 0x7b, 0x10, 0x22, 0xc2, 0x4f, 0xbb, 0xa9, + 0xd7, 0xfe, 0xb7, 0xc6, 0x1b, 0xf8, 0x3b, 0x57, 0xe7, 0xc6, + 0xa8, 0xa6, 0x15, 0x0f, 0x04, 0xfb, 0x83, 0xf6, 0xd3, 0xc5, + 0x1e, 0xc3, 0x02, 0x35, 0x54, 0x13, 0x5a, 0x16, 0x91, 0x32, + 0xf6, 0x75, 0xf3, 0xae, 0x2b, 0x61, 0xd7, 0x2a, 0xef, 0xf2, + 0x22, 0x03, 0x19, 0x9d, 0xd1, 0x48, 0x01, 0xc7 +}; + +CK_BYTE DSA1024_SUBPRIME[20] = { + 0x97, 0x60, 0x50, 0x8f, 0x15, 0x23, 0x0b, 0xcc, 0xb2, 0x92, + 0xb9, 0x82, 0xa2, 0xeb, 0x84, 0x0b, 0xf0, 0x58, 0x1c, 0xf5 +}; + +CK_BYTE DSA1024_PUBLIC[128] = { + 0xa2, 0x8a, 0x43, 0xb9, 0x5d, 0x73, 0x6b, 0x5a, 0x5a, 0xfe, + 0xb5, 0xa0, 0x7d, 0x2c, 0x89, 0x65, 0xeb, 0xf3, 0x52, 0xa3, + 0xe2, 0x9b, 0xa7, 0xe3, 0x65, 0x11, 0x12, 0x0c, 0xcc, 0xa2, + 0xb7, 0x60, 0x51, 0xcd, 0xfb, 0x87, 0xfd, 0x9e, 0xe7, 0x58, + 0xe5, 0xb1, 0x15, 0x98, 0x66, 0x63, 0x18, 0x6f, 0x46, 0x83, + 0x27, 0xbf, 0x5a, 0xc5, 0x00, 0xf1, 0x89, 0xcb, 0x70, 0x6f, + 0x62, 0x16, 0xab, 0xbc, 0x4b, 0xb7, 0x25, 0x8f, 0x92, 0x15, + 0x06, 0x06, 0x5d, 0xb3, 0x36, 0x98, 0x3c, 0x31, 0x26, 0x7c, + 0xe7, 0x8c, 0x94, 0x27, 0xfa, 0xb8, 0xda, 0xd0, 0xc6, 0x4b, + 0x54, 0xf1, 0xef, 0xf6, 0x0e, 0xc6, 0x01, 0xdd, 0x1a, 0xbc, + 0x25, 0xd9, 0x56, 0x93, 0x80, 0x37, 0x94, 0xd9, 0x67, 0x33, + 0xd5, 0x65, 0x69, 0x93, 0x1f, 0x07, 0xc7, 0x72, 0xa5, 0x13, + 0x23, 0x83, 0xac, 0x6e, 0xab, 0xda, 0xfb, 0xc4 +}; + +CK_BYTE DSA1024_PRIVATE[20] = { + 0x87, 0xa0, 0x68, 0x97, 0x5e, 0xf2, 0x51, 0xb4, 0x50, 0x51, + 0x0d, 0xee, 0x08, 0x73, 0x41, 0x19, 0x5c, 0xa6, 0x8c, 0x16 +}; + +/// Helper functions +#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0])) + +static void dumpEP11Blob(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, + const char *fmt, ...) +{ + CK_ATTRIBUTE blobattr = { CKA_IBM_OPAQUE, NULL, 0 }; + unsigned char *blob = NULL; + char fname[1024]; + FILE *f = NULL; + va_list va; + int rc; + + va_start(va, fmt); + vsnprintf(fname, sizeof(fname), fmt, va); + va_end(va); + rc = funcs->C_GetAttributeValue(session, key, &blobattr, 1); + if (rc != CKR_OK) + return; + blob = (unsigned char *)malloc(blobattr.ulValueLen); + if (!blob) + return; + blobattr.pValue = blob; + rc = funcs->C_GetAttributeValue(session, key, &blobattr, 1); + if (rc != CKR_OK) + goto out; + f = fopen(fname, "wb"); + if (!f) + goto out; + fwrite(blob, blobattr.ulValueLen, 1, f); + out: + free(blob); + if (f) + fclose(f); +} + +static void dumpSPKI(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, + const char *fmt, ...) +{ + CK_ATTRIBUTE blobattr = { CKA_PUBLIC_KEY_INFO, NULL, 0 }; + unsigned char *blob = NULL; + char fname[1024]; + FILE *f = NULL; + va_list va; + int rc; + + va_start(va, fmt); + vsnprintf(fname, sizeof(fname), fmt, va); + va_end(va); + rc = funcs->C_GetAttributeValue(session, key, &blobattr, 1); + if (rc != CKR_OK) + return; + blob = (unsigned char *)malloc(blobattr.ulValueLen); + if (!blob) + return; + blobattr.pValue = blob; + rc = funcs->C_GetAttributeValue(session, key, &blobattr, 1); + if (rc != CKR_OK) + goto out; + f = fopen(fname, "wb"); + if (!f) + goto out; + fwrite(blob, blobattr.ulValueLen, 1, f); + out: + free(blob); + if (f) + fclose(f); +} + +CK_RV compareDESKeys(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE source, + CK_OBJECT_HANDLE dest) +{ + CK_BYTE data[16] = {0}; + CK_BYTE iv[] = {1,2,3,4,5,6,7,8}; + CK_MECHANISM mech = {CKM_DES3_CBC_PAD, iv, sizeof(iv)}; + CK_BYTE resultsource[24]; + CK_BYTE resultdest[24]; + CK_ULONG reslensource = 24; + CK_ULONG reslendest = 24; + CK_RV rc; + + rc = funcs->C_EncryptInit(session, &mech, source); + if (rc != CKR_OK) + return rc; + rc = funcs->C_Encrypt(session, data, sizeof(data), resultsource, &reslensource); + if (rc != CKR_OK) + return rc; + + rc = funcs->C_EncryptInit(session, &mech, dest); + if (rc != CKR_OK) + return rc; + rc = funcs->C_Encrypt(session, data, sizeof(data), resultdest, &reslendest); + if (rc != CKR_OK) + return rc; + + if (reslensource != reslendest || memcmp(resultsource, resultdest, reslendest)) + return CKR_FUNCTION_FAILED; + return CKR_OK; +} + +CK_RV compareECKeys(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE sign, + CK_OBJECT_HANDLE verify) +{ + CK_BYTE data[16] = {0}; + CK_BYTE *signature = NULL; + CK_MECHANISM signmech = {CKM_ECDSA, 0, 0}; + CK_MECHANISM verifymech = {CKM_ECDSA, 0, 0}; + CK_ULONG signaturelen = 0; + CK_RV rc; + + rc = funcs->C_SignInit(session, &signmech, sign); + if (rc != CKR_OK) + return rc; + rc = funcs->C_Sign(session, data, sizeof(data), signature, &signaturelen); + if (rc != CKR_OK) + return rc; + signature = calloc(1, signaturelen); + if (!signature) + return CKR_HOST_MEMORY; + rc = funcs->C_Sign(session, data, sizeof(data), signature, &signaturelen); + if (rc != CKR_OK) + goto out; + + rc = funcs->C_VerifyInit(session, &verifymech, verify); + if (rc != CKR_OK) + goto out; + rc = funcs->C_Verify(session, data, sizeof(data), signature, signaturelen); + out: + free(signature); + return rc; +} + +// expected to fail +CK_RV createABAESKey(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE *handle) +{ + CK_BBOOL true = TRUE; + CK_BBOOL false = FALSE; + CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; + CK_KEY_TYPE keyType = CKK_AES; + CK_ATTRIBUTE keyTemplate[] = { + {CKA_CLASS, &keyClass, sizeof(keyClass)}, + {CKA_KEY_TYPE, &keyType, sizeof(keyType)}, + {CKA_ENCRYPT, &true, sizeof(true)}, + {CKA_TOKEN, &false, sizeof(false)}, + {CKA_VALUE, AES_KEY_VAL, sizeof(AES_KEY_VAL)}, + {CKA_IBM_ATTRBOUND, &true, sizeof(true)}, + {CKA_SENSITIVE, &true, sizeof(true)} + }; + + return funcs->C_CreateObject(session, keyTemplate, + ARRAY_SIZE(keyTemplate), handle); +} + +CK_RV createABPublicDSAKey(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE *handle) +{ + CK_OBJECT_CLASS class = CKO_PUBLIC_KEY; + CK_KEY_TYPE keyType = CKK_DSA; + CK_UTF8CHAR label[] = "A DSA public key object"; + CK_BBOOL true = TRUE; + CK_ATTRIBUTE template[] = { + {CKA_CLASS, &class, sizeof(class)}, + {CKA_KEY_TYPE, &keyType, sizeof(keyType)}, + {CKA_TOKEN, &true, sizeof(true)}, + {CKA_LABEL, label, sizeof(label)}, + {CKA_ENCRYPT, &true, sizeof(true)}, + {CKA_VERIFY, &true, sizeof(true)}, + {CKA_PRIME, DSA1024_PRIME, sizeof(DSA1024_PRIME)}, + {CKA_SUBPRIME, DSA1024_SUBPRIME, sizeof(DSA1024_SUBPRIME)}, + {CKA_BASE, DSA1024_BASE, sizeof(DSA1024_BASE)}, + {CKA_VALUE, DSA1024_PUBLIC, sizeof(DSA1024_PUBLIC)}, + {CKA_IBM_ATTRBOUND, &true, sizeof(true)} + }; + + return funcs->C_CreateObject(session, template, + ARRAY_SIZE(template), handle); +} + +// expected to fail +CK_RV createABPrivateDSAKey(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE *handle) +{ + CK_OBJECT_CLASS class = CKO_PRIVATE_KEY; + CK_KEY_TYPE keyType = CKK_DSA; + CK_UTF8CHAR label[] = "An DSA private key object"; + CK_BYTE subject[] = {0}; + CK_BYTE id[] = { 123 }; + + CK_BBOOL true = TRUE; + CK_ATTRIBUTE template[] = { + {CKA_CLASS, &class, sizeof(class)}, + {CKA_KEY_TYPE, &keyType, sizeof(keyType)}, + {CKA_TOKEN, &true, sizeof(true)}, + {CKA_LABEL, label, sizeof(label)}, + {CKA_SUBJECT, subject, 0}, + {CKA_ID, id, sizeof(id)}, + {CKA_SENSITIVE, &true, sizeof(true)}, + {CKA_DECRYPT, &true, sizeof(true)}, + {CKA_SIGN, &true, sizeof(true)}, + {CKA_PRIME, DSA1024_PRIME, sizeof(DSA1024_PRIME)}, + {CKA_SUBPRIME, DSA1024_SUBPRIME, sizeof(DSA1024_SUBPRIME)}, + {CKA_BASE, DSA1024_BASE, sizeof(DSA1024_BASE)}, + {CKA_VALUE, DSA1024_PRIVATE, sizeof(DSA1024_PRIVATE)}, + {CKA_IBM_ATTRBOUND, &true, sizeof(true)}, + {CKA_SENSITIVE, &true, sizeof(true)} + }; + + return funcs->C_CreateObject(session, template, + ARRAY_SIZE(template), handle); +} + +CK_RV generateABAESKey(CK_SESSION_HANDLE session, CK_ULONG key_len, + CK_OBJECT_HANDLE *handle) +{ + CK_BBOOL cktrue = TRUE; + CK_ATTRIBUTE key_gen_tmpl[] = { + {CKA_VALUE_LEN, &key_len, sizeof(CK_ULONG)}, + {CKA_IBM_ATTRBOUND, &cktrue, sizeof(CK_BBOOL)}, + {CKA_SENSITIVE, &cktrue, sizeof(CK_BBOOL)} + }; + CK_MECHANISM mech = { + .mechanism = CKM_AES_KEY_GEN, + .ulParameterLen = 0, + .pParameter = NULL, + }; + + return funcs->C_GenerateKey(session, &mech, key_gen_tmpl, + ARRAY_SIZE(key_gen_tmpl), handle); +} + +CK_RV generateABDESKey(CK_SESSION_HANDLE session, CK_MECHANISM_TYPE type, + CK_OBJECT_HANDLE *handle) +{ + CK_MECHANISM mech = { type, NULL, 0 }; + CK_BBOOL true = TRUE; + CK_ATTRIBUTE tmpl[] = { + {CKA_IBM_ATTRBOUND, &true, sizeof(true)}, + {CKA_SENSITIVE, &true, sizeof(true)} + }; + + return funcs->C_GenerateKey(session, &mech, tmpl, ARRAY_SIZE(tmpl), handle); +} + +CK_RV generateABGenericSecret(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE *handle) +{ + CK_OBJECT_CLASS class = CKO_SECRET_KEY; + CK_BBOOL true = TRUE; + CK_ULONG keylen = 20; + CK_ATTRIBUTE tmpl[] = { + {CKA_CLASS, &class, sizeof(class)}, + {CKA_VALUE_LEN, &keylen, sizeof(keylen)}, + {CKA_IBM_ATTRBOUND, &true, sizeof(true)}, + {CKA_SENSITIVE, &true, sizeof(true)} + }; + CK_MECHANISM mech = { CKM_GENERIC_SECRET_KEY_GEN, NULL, 0 }; + + return funcs->C_GenerateKey(session, &mech, tmpl, ARRAY_SIZE(tmpl), handle); +} + +CK_RV generateABRSAKey(CK_SESSION_HANDLE session, + CK_BBOOL abpub, CK_BBOOL abpriv, CK_BBOOL sensitive, + CK_OBJECT_HANDLE *pubkey, CK_OBJECT_HANDLE *privkey) +{ + CK_MECHANISM mech = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL, 0 }; + CK_BYTE subject[] = {0}; + CK_BYTE id[] = {123}; + CK_BBOOL cktrue = TRUE; + CK_ULONG modulusBits = 4096; + CK_BYTE publicExponent[] = {0x01, 0x00, 0x01}; + CK_ATTRIBUTE pubkeyTemplate[] = { + {CKA_ENCRYPT, &cktrue, sizeof(cktrue)}, + {CKA_VERIFY, &cktrue, sizeof(cktrue)}, + {CKA_WRAP, &cktrue, sizeof(cktrue)}, + {CKA_MODULUS_BITS, &modulusBits, sizeof(modulusBits)}, + {CKA_PUBLIC_EXPONENT, publicExponent, sizeof(publicExponent)}, + {CKA_IBM_ATTRBOUND, &abpub, sizeof(abpub)} + }; + CK_ATTRIBUTE privkeyTemplate[] = { + {CKA_TOKEN, &cktrue, sizeof(cktrue)}, + {CKA_PRIVATE, &cktrue, sizeof(cktrue)}, + {CKA_SUBJECT, subject, 0}, + {CKA_ID, id, sizeof(id)}, + {CKA_DECRYPT, &cktrue, sizeof(cktrue)}, + {CKA_SIGN, &cktrue, sizeof(cktrue)}, + {CKA_UNWRAP, &cktrue, sizeof(cktrue)}, + {CKA_IBM_ATTRBOUND, &abpriv, sizeof(abpriv)}, + {CKA_SENSITIVE, &sensitive, sizeof(sensitive)} + }; + + return funcs->C_GenerateKeyPair(session, &mech, + pubkeyTemplate, ARRAY_SIZE(pubkeyTemplate), + privkeyTemplate, ARRAY_SIZE(privkeyTemplate), + pubkey, privkey); +} + +CK_RV generateABECKey(CK_SESSION_HANDLE session, CK_BBOOL ab, + CK_OBJECT_HANDLE *pubkey, CK_OBJECT_HANDLE *privkey) +{ + CK_BYTE prime256v1[] = OCK_PRIME256V1; + CK_MECHANISM mech = { CKM_EC_KEY_PAIR_GEN, NULL, 0 }; + CK_BYTE subject[] = {0}; + CK_BYTE id[] = { 123 }; + CK_BBOOL true = TRUE; + CK_ATTRIBUTE publicKeyTemplate[] = { + {CKA_VERIFY, &true, sizeof(true)}, + {CKA_EC_PARAMS, &prime256v1, sizeof(prime256v1)}, + {CKA_IBM_ATTRBOUND, &ab, sizeof(true)} + }; + CK_ATTRIBUTE privateKeyTemplate[] = { + {CKA_TOKEN, &true, sizeof(true)}, + {CKA_PRIVATE, &true, sizeof(true)}, + {CKA_SUBJECT, subject, 0}, + {CKA_ID, id, sizeof(id)}, + {CKA_SENSITIVE, &true, sizeof(true)}, + {CKA_SIGN, &true, sizeof(true)}, + {CKA_DERIVE, &true, sizeof(true)}, + {CKA_IBM_ATTRBOUND, &ab, sizeof(true)}, + {CKA_SENSITIVE, &true, sizeof(true)} + }; + + return funcs->C_GenerateKeyPair(session, &mech, + publicKeyTemplate, ARRAY_SIZE(publicKeyTemplate), + privateKeyTemplate, ARRAY_SIZE(privateKeyTemplate), + pubkey, privkey); +} + +CK_RV generateABDSAKey(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE *pubkey, CK_OBJECT_HANDLE *privkey) +{ + CK_MECHANISM mech = { CKM_DSA_KEY_PAIR_GEN, NULL, 0 }; + CK_BBOOL true = TRUE; + CK_ATTRIBUTE publ_tmpl[] = { + {CKA_PRIME, DSA_PUBL_PRIME, sizeof(DSA_PUBL_PRIME)}, + {CKA_SUBPRIME, DSA_PUBL_SUBPRIME, sizeof(DSA_PUBL_SUBPRIME)}, + {CKA_BASE, DSA_PUBL_BASE, sizeof(DSA_PUBL_BASE)}, + {CKA_IBM_ATTRBOUND, &true, sizeof(true)} + }; + CK_ATTRIBUTE priv_tmpl[] = { + {CKA_IBM_ATTRBOUND, &true, sizeof(true)}, + {CKA_SENSITIVE, &true, sizeof(true)} + }; + + return funcs->C_GenerateKeyPair(session, &mech, + publ_tmpl, ARRAY_SIZE(publ_tmpl), + priv_tmpl, ARRAY_SIZE(priv_tmpl), + pubkey, privkey); +} + +CK_RV generateABDHKey(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE *pubkey, CK_OBJECT_HANDLE *privkey) +{ + CK_MECHANISM mech = { CKM_DH_PKCS_KEY_PAIR_GEN, NULL, 0 }; + CK_BBOOL true = TRUE; + CK_OBJECT_CLASS pub_key_class = CKO_PUBLIC_KEY; + CK_KEY_TYPE key_type = CKK_DH; + CK_UTF8CHAR publ_label[] = "An AB DH public key object"; + CK_OBJECT_CLASS priv_key_class = CKO_PRIVATE_KEY; + CK_UTF8CHAR priv_label[] = "An AB DH private key object"; + CK_ATTRIBUTE publ_tmpl[] = { + {CKA_CLASS, &pub_key_class, sizeof(pub_key_class)}, + {CKA_KEY_TYPE, &key_type, sizeof(key_type)}, + {CKA_LABEL, publ_label, sizeof(publ_label) - 1}, + {CKA_PRIME, DH_PUBL_PRIME, sizeof(DH_PUBL_PRIME)}, + {CKA_BASE, DH_PUBL_BASE, sizeof(DH_PUBL_BASE)}, + {CKA_IBM_ATTRBOUND, &true, sizeof(true)} + }; + CK_ATTRIBUTE priv_tmpl[] = { + {CKA_CLASS, &priv_key_class, sizeof(priv_key_class)}, + {CKA_KEY_TYPE, &key_type, sizeof(key_type)}, + {CKA_LABEL, priv_label, sizeof(priv_label) - 1}, + {CKA_DERIVE, &true, sizeof(true)}, + {CKA_IBM_ATTRBOUND, &true, sizeof(true)}, + {CKA_SENSITIVE, &true, sizeof(true)} + }; + + return funcs->C_GenerateKeyPair(session, &mech, + publ_tmpl, ARRAY_SIZE(publ_tmpl), + priv_tmpl, ARRAY_SIZE(priv_tmpl), + pubkey, privkey); +} + +// Expected to fail +CK_RV generateABDilithiumKey(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE *pubkey, CK_OBJECT_HANDLE *privkey) +{ + CK_MECHANISM mech = { CKM_IBM_DILITHIUM, NULL, 0 }; + CK_BBOOL cktrue = TRUE; + CK_ATTRIBUTE pubkeyTemplate[] = { + {CKA_VERIFY, &cktrue, sizeof(cktrue)}, + {CKA_IBM_ATTRBOUND, &cktrue, sizeof(cktrue)} + }; + CK_ATTRIBUTE privkeyTemplate[] = { + {CKA_SIGN, &cktrue, sizeof(cktrue)}, + {CKA_IBM_ATTRBOUND, &cktrue, sizeof(cktrue)}, + {CKA_SENSITIVE, &cktrue, sizeof(cktrue)} + }; + + return funcs->C_GenerateKeyPair(session, &mech, + pubkeyTemplate, ARRAY_SIZE(pubkeyTemplate), + privkeyTemplate, ARRAY_SIZE(privkeyTemplate), + pubkey, privkey); +} + +void teardown(CK_SESSION_HANDLE session) { + int i; + + for (i = 0; i < NUMKEYS; ++i) + funcs->C_DestroyObject(session, keys.u.keys[i]); +} + +/// Test functions + +CK_RV do_CheckMechanismInfo() +{ + CK_IBM_ATTRIBUTEBOUND_WRAP_PARAMS params = { + .hSignVerifyKey = CK_INVALID_HANDLE + }; + CK_MECHANISM mech = { + .mechanism = CKM_IBM_ATTRIBUTEBOUND_WRAP, + .pParameter = ¶ms, + .ulParameterLen = sizeof(params) + }; + CK_RV res = CKR_OK; + + // begin testsuite + testsuite_begin("Check CKM_IBM_ATTRIBUTEBOUND_WRAP mechanism info."); + + // skip tests if the slot doesn't support this mechanism + if (!mech_supported(SLOT_ID, CKM_IBM_ATTRIBUTEBOUND_WRAP)) { + testsuite_skip(2, + "Slot %u doesn't support CKM_IBM_ATTRIBUTEBOUND_WRAP (0x%x)", + (unsigned int) SLOT_ID, + (unsigned int) CKM_IBM_ATTRIBUTEBOUND_WRAP); + res = CKR_FUNCTION_NOT_SUPPORTED; + goto testcase_cleanup; + } + testcase_new_assertion(); + testcase_begin("CKM_IBM_ATTRIBUTEBOUND_WRAP supported for wrapping"); + if (!wrap_supported(SLOT_ID, mech)) + testcase_fail("CKM_IBM_ATTRIBUTEBOUND_WRAP does NOT support wrapping"); + else + testcase_pass("CKM_IBM_ATTRIBUTEBOUND_WRAP does support wrapping"); + testcase_new_assertion(); + testcase_begin("CKM_IBM_ATTRIBUTEBOUND_WRAP supported for unwrapping"); + if (!unwrap_supported(SLOT_ID, mech)) + testcase_fail("CKM_IBM_ATTRIBUTEBOUND_WRAP does NOT support unwrapping"); + else + testcase_pass("CKM_IBM_ATTRIBUTEBOUND_WRAP does support unwrapping"); + testcase_cleanup: + return res; +} + +void do_TestInvalidKeys(CK_SESSION_HANDLE session) +{ + CK_OBJECT_HANDLE pubkey = CK_INVALID_HANDLE, privkey = CK_INVALID_HANDLE; + CK_RV rc; + + // Expected to fail with CKR_TEMPLATE_INCONSISTENT + testcase_begin("Create RSA AB key without CKA_SENSITIVE"); + testcase_new_assertion(); + rc = generateABRSAKey(session, TRUE, TRUE, FALSE, &pubkey, &privkey); + if (rc != CKR_TEMPLATE_INCONSISTENT) + testcase_fail("Create RSA AB key without CKA_SENSITIVE did not return CKR_TEMPLATE_INCONSISTENT but %s", p11_get_ckr(rc)); + else + testcase_pass("Create RSA AB key without CKA_SENSITIVE returned CKR_TEMPLATE_INCONSISTENT as expected"); + + if (pubkey != CK_INVALID_HANDLE) + funcs->C_DestroyObject(session, pubkey); + if (privkey != CK_INVALID_HANDLE) + funcs->C_DestroyObject(session, privkey); + + testcase_begin("Create RSA AB key with non-AB private key"); + testcase_new_assertion(); + rc = generateABRSAKey(session, FALSE, TRUE, TRUE, &pubkey, &privkey); + if (rc != CKR_TEMPLATE_INCONSISTENT) + testcase_fail("Create RSA AB key with non-AB private key did not return CKR_TEMPLATE_INCONSISTENT but %s", p11_get_ckr(rc)); + else + testcase_pass("Create RSA AB key with non-AB private key returned CKR_TEMPLATE_INCONSISTENT as expected"); + + if (pubkey != CK_INVALID_HANDLE) + funcs->C_DestroyObject(session, pubkey); + if (privkey != CK_INVALID_HANDLE) + funcs->C_DestroyObject(session, privkey); + + testcase_begin("Create RSA AB key with non-AB public key"); + testcase_new_assertion(); + rc = generateABRSAKey(session, TRUE, FALSE, TRUE, &pubkey, &privkey); + if (rc != CKR_TEMPLATE_INCONSISTENT) + testcase_fail("Create RSA AB key with non-AB public key did not return CKR_TEMPLATE_INCONSISTENT but %s", p11_get_ckr(rc)); + else + testcase_pass("Create RSA AB key with non-AB public key returned CKR_TEMPLATE_INCONSISTENT as expected"); + + if (pubkey != CK_INVALID_HANDLE) + funcs->C_DestroyObject(session, pubkey); + if (privkey != CK_INVALID_HANDLE) + funcs->C_DestroyObject(session, privkey); +} + +void do_CreateKeyObjects(CK_SESSION_HANDLE session) +{ + CK_RV rc; + CK_OBJECT_HANDLE handle = CK_INVALID_HANDLE; + + testcase_begin("Create AB AES key via C_CreateObject"); + testcase_new_assertion(); + rc = createABAESKey(session, &handle); + if (is_rejected_by_policy(rc, session)) + testcase_skip("Key import is not allowed by policy"); + else if (rc != CKR_ATTRIBUTE_VALUE_INVALID) + testcase_fail("C_CreateObject for AB AES key returned %s (expected CKR_ATTRIBUTE_VALUE_INVALID)", p11_get_ckr(rc)); + else + testcase_pass("C_CreateObject for AB AES key returned CKR_ATTRIBUTE_VALUE_INVALID as expected"); + if (handle != CK_INVALID_HANDLE) + funcs->C_DestroyObject(session, handle); + + testcase_begin("Create AB DSA private key via C_CreateObject"); + testcase_new_assertion(); + rc = createABPrivateDSAKey(session, &handle); + if (is_rejected_by_policy(rc, session)) + testcase_skip("Key import is not allowed by policy"); + else if (rc != CKR_ATTRIBUTE_VALUE_INVALID) + testcase_fail("C_CreateObject for AB DSA private key returned %s (expected CKR_ATTRIBUTE_VALUE_INVALID)", p11_get_ckr(rc)); + else + testcase_pass("C_CreateObject for AB DSA private key returned CKR_ATTRIBUTE_VALUE_INVALID as expected"); + if (handle != CK_INVALID_HANDLE) + funcs->C_DestroyObject(session, handle); + + testcase_begin("Create AB DSA public key via C_CreateObject"); + testcase_new_assertion(); + rc = createABPublicDSAKey(session, &handle); + if (is_rejected_by_policy(rc, session)) + testcase_skip("Key import is not allowed by policy"); + else if (rc != CKR_OK) + testcase_fail("C_CreateObject for AB DSA public key returned %s (expected CKR_OK)", p11_get_ckr(rc)); + else + testcase_pass("C_CreateObject for AB DSA public key returned CKR_OK as expected"); + if (handle != CK_INVALID_HANDLE) + funcs->C_DestroyObject(session, handle); +} + +CK_RV do_SetupKeys(CK_SESSION_HANDLE session) +{ + CK_RV rc; + int i; + + for (i = 0; i < NUMKEYS; ++i) + keys.u.keys[i] = CK_INVALID_HANDLE; + + testcase_begin("Create AB AES key"); + testcase_new_assertion(); + rc = generateABAESKey(session, 32, &keys.u.d.aes); + if (is_rejected_by_policy(rc, session)) + testcase_skip("Key generation is not allowed by policy"); + else if (rc != CKR_OK) + testcase_fail("Create AB AES key failed with rc=%s", p11_get_ckr(rc)); + else + testcase_pass("Successfully created AB AES key"); + testcase_begin("Create AB DES2 key"); + testcase_new_assertion(); + rc = generateABDESKey(session, CKM_DES2_KEY_GEN, &keys.u.d.des2); + if (is_rejected_by_policy(rc, session)) + testcase_skip("Key generation is not allowed by policy"); + else if (rc != CKR_OK) + testcase_fail("Create AB DES2 key failed with rc=%s", p11_get_ckr(rc)); + else + testcase_pass("Successfully created AB DES2 key"); + testcase_begin("Create AB DES3 key"); + testcase_new_assertion(); + rc = generateABDESKey(session, CKM_DES3_KEY_GEN, &keys.u.d.des3); + if (is_rejected_by_policy(rc, session)) + testcase_skip("Key generation is not allowed by policy"); + else if (rc != CKR_OK) + testcase_fail("Create AB DES3 key failed with rc=%s", p11_get_ckr(rc)); + else + testcase_pass("Successfully created AB DES3 key"); + testcase_begin("Create AB generic secret key"); + testcase_new_assertion(); + if (!mech_supported(SLOT_ID, CKM_GENERIC_SECRET_KEY_GEN)) { + testcase_skip("CKM_GENERIC_SECRET_KEY_GEN not supported"); + } else { + rc = generateABGenericSecret(session, &keys.u.d.generic); + if (is_rejected_by_policy(rc, session)) + testcase_skip("Key generation is not allowed by policy"); + else if (rc != CKR_OK) + testcase_fail("Create AB generic secret key failed with rc=%s", p11_get_ckr(rc)); + else + testcase_pass("Successfully created AB generic secret key"); + } + testcase_begin("Create AB RSA key"); + testcase_new_assertion(); + rc = generateABRSAKey(session, TRUE, TRUE, TRUE, &keys.u.d.rsapub, &keys.u.d.rsapriv); + if (is_rejected_by_policy(rc, session)) + testcase_skip("Key generation is not allowed by policy"); + else if (rc != CKR_OK) + testcase_fail("Create AB RSA key failed with rc=%s", p11_get_ckr(rc)); + else + testcase_pass("Successfully created AB RSA key"); + testcase_begin("Create AB EC key"); + testcase_new_assertion(); + rc = generateABECKey(session, TRUE, &keys.u.d.ecpub, &keys.u.d.ecpriv); + if (is_rejected_by_policy(rc, session)) + testcase_skip("Key generation is not allowed by policy"); + else if (rc != CKR_OK) + testcase_fail("Create AB EC key failed with rc=%s", p11_get_ckr(rc)); + else + testcase_pass("Successfully created AB EC key"); + testcase_begin("Create AB DSA key"); + testcase_new_assertion(); + rc = generateABDSAKey(session, &keys.u.d.dsapub, &keys.u.d.dsapriv); + if (is_rejected_by_policy(rc, session)) + testcase_skip("Key generation is not allowed by policy"); + else if (rc != CKR_OK) + testcase_fail("Create AB DSA key failed with rc=%s", p11_get_ckr(rc)); + else + testcase_pass("Successfully created AB DSA key"); + testcase_begin("Create AB DH key"); + testcase_new_assertion(); + rc = generateABDHKey(session, &keys.u.d.dhpub, &keys.u.d.dhpriv); + if (is_rejected_by_policy(rc, session)) + testcase_skip("Key generation is not allowed by policy"); + else if (rc != CKR_OK) + testcase_fail("Create AB DH key failed with rc=%s", p11_get_ckr(rc)); + else + testcase_pass("Successfully created AB DH key"); + // These are not a test in this suite since it is covered by other suites... + rc = generateABRSAKey(session, FALSE, FALSE, FALSE, &keys.u.d.nonabpub, &keys.u.d.nonabpriv); + if (is_rejected_by_policy(rc, session)) { + testcase_skip("Key generation is not allowed by policy"); + rc = CKR_POLICY_VIOLATION; + } + if (rc != CKR_OK) + return rc; + rc = generateABECKey(session, FALSE, &keys.u.d.nonabecpub, &keys.u.d.nonabecpriv); + if (is_rejected_by_policy(rc, session)) { + testcase_skip("Key generation is not allowed by policy"); + rc = CKR_POLICY_VIOLATION; + } + + for (i = 0; i < NUMKEYS; ++i) { + if (keys.u.keys[i] == CK_INVALID_HANDLE) + rc = CKR_POLICY_VIOLATION; + } + + return rc; +} + +void do_TestKeyWrappingUnwrapping(CK_SESSION_HANDLE session) +{ + CK_BYTE wrappedkey[16384]; + CK_ULONG wrappedkeylen; + CK_RV rc; + unsigned i; + static CK_KEY_TYPE deskt = CKK_DES3, eckt = CKK_EC; + static CK_OBJECT_CLASS secretoc = CKO_SECRET_KEY, privateoc = CKO_PRIVATE_KEY; + static CK_BBOOL cktrue = TRUE; + static CK_ATTRIBUTE desunwrapattrs[] = { + {CKA_CLASS, &secretoc, sizeof(CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, &deskt, sizeof(CK_KEY_TYPE)}, + {CKA_IBM_ATTRBOUND, &cktrue, sizeof(CK_BBOOL)} + }; + static CK_ATTRIBUTE ecprivunwrapattrs[] = { + {CKA_CLASS, &privateoc, sizeof(CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, &eckt, sizeof(CK_KEY_TYPE)}, + {CKA_IBM_ATTRBOUND, &cktrue, sizeof(CK_BBOOL)} + }; + static const struct { + CK_OBJECT_HANDLE *keytowrap; + CK_OBJECT_HANDLE *wrappingkey; + CK_OBJECT_HANDLE *signingkey; + CK_OBJECT_HANDLE *unwrappingkey; + CK_OBJECT_HANDLE *verificationkey; + CK_RV wrapres; + CK_RV unwrapres;// ignored if wrapres != CKR_OK + // ignored if wrapres != CKR_OK or unwrapres != CKR_OK + CK_RV (*compare)(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE source, + CK_OBJECT_HANDLE dest); + CK_OBJECT_HANDLE *comparedest; + CK_ATTRIBUTE *unwraptemplate; + CK_ULONG unwraptemplatesize; + } config[] = { + // symm, symm, symm + /*0*/{&keys.u.d.des3, &keys.u.d.aes, &keys.u.d.aes, &keys.u.d.aes, &keys.u.d.aes, CKR_OK, CKR_OK, compareDESKeys, &keys.u.d.des3, desunwrapattrs, ARRAY_SIZE(desunwrapattrs)}, + // symm, symm, asymm + /*1*/{&keys.u.d.des3, &keys.u.d.aes, &keys.u.d.ecpriv, &keys.u.d.aes, &keys.u.d.ecpub, CKR_OK, CKR_OK, compareDESKeys, &keys.u.d.des3, desunwrapattrs, ARRAY_SIZE(desunwrapattrs)}, + // symm, asymm, symm + /*2*/{&keys.u.d.des3, &keys.u.d.rsapub, &keys.u.d.ecpriv, &keys.u.d.rsapriv, &keys.u.d.ecpub, CKR_OK, CKR_OK, compareDESKeys, &keys.u.d.des3, desunwrapattrs, ARRAY_SIZE(desunwrapattrs)}, + // symm, asymm, asymm + /*3*/{&keys.u.d.des3, &keys.u.d.rsapub, &keys.u.d.ecpriv, &keys.u.d.rsapriv, &keys.u.d.ecpub, CKR_OK, CKR_OK, compareDESKeys, &keys.u.d.des3, desunwrapattrs, ARRAY_SIZE(desunwrapattrs)}, + // asymm, symm, symm + /*4*/{&keys.u.d.ecpriv, &keys.u.d.aes, &keys.u.d.aes, &keys.u.d.aes, &keys.u.d.aes, CKR_OK, CKR_OK, compareECKeys, &keys.u.d.ecpub, ecprivunwrapattrs, ARRAY_SIZE(ecprivunwrapattrs)}, + // asymm, symm, asymm + /*5*/{&keys.u.d.ecpriv, &keys.u.d.aes, &keys.u.d.ecpriv, &keys.u.d.aes, &keys.u.d.ecpub, CKR_OK, CKR_OK, compareECKeys, &keys.u.d.ecpub, ecprivunwrapattrs, ARRAY_SIZE(ecprivunwrapattrs)}, + // asymm, asymm, symm + /*6*/{&keys.u.d.ecpriv, &keys.u.d.rsapub, &keys.u.d.ecpriv, &keys.u.d.rsapriv, &keys.u.d.ecpub, CKR_OK, CKR_OK, compareECKeys, &keys.u.d.ecpub, ecprivunwrapattrs, ARRAY_SIZE(ecprivunwrapattrs)}, + // asymm, asymm, asymm + /*7*/{&keys.u.d.ecpriv, &keys.u.d.rsapub, &keys.u.d.ecpriv, &keys.u.d.rsapriv, &keys.u.d.ecpub, CKR_OK, CKR_OK, compareECKeys, &keys.u.d.ecpub, ecprivunwrapattrs, ARRAY_SIZE(ecprivunwrapattrs)}, + // kek unsupported + /*8*/{&keys.u.d.des3, &keys.u.d.ecpub, &keys.u.d.aes, &keys.u.d.ecpriv, &keys.u.d.aes, CKR_WRAPPING_KEY_TYPE_INCONSISTENT, CKR_OK, 0, 0, 0, 0}, + /*9*/{&keys.u.d.des3, &keys.u.d.rsapub, &keys.u.d.aes, &keys.u.d.dsapriv, &keys.u.d.aes, CKR_OK, CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT, 0, 0, desunwrapattrs, ARRAY_SIZE(desunwrapattrs)}, + // kek not ab + /*10*/{&keys.u.d.des3, &keys.u.d.nonabpub, &keys.u.d.aes, &keys.u.d.nonabpriv, &keys.u.d.aes, CKR_KEY_FUNCTION_NOT_PERMITTED, CKR_OK, 0, 0, 0, 0}, + /*11*/{&keys.u.d.des3, &keys.u.d.rsapub, &keys.u.d.aes, &keys.u.d.nonabpriv, &keys.u.d.aes, CKR_OK, CKR_KEY_FUNCTION_NOT_PERMITTED, 0, 0, desunwrapattrs, ARRAY_SIZE(desunwrapattrs)}, + // sign/verify key not ab + /*12*/{&keys.u.d.des3, &keys.u.d.rsapub, &keys.u.d.nonabpriv, &keys.u.d.rsapriv, &keys.u.d.aes, CKR_KEY_FUNCTION_NOT_PERMITTED, CKR_OK, 0, 0, 0, 0}, + /*13*/{&keys.u.d.des3, &keys.u.d.rsapub, &keys.u.d.aes, &keys.u.d.rsapriv, &keys.u.d.nonabpub, CKR_OK, CKR_KEY_FUNCTION_NOT_PERMITTED, 0, 0, desunwrapattrs, ARRAY_SIZE(desunwrapattrs)}, + // signing key not able to sign + /*14*/{&keys.u.d.des3, &keys.u.d.rsapub, &keys.u.d.ecpub, &keys.u.d.rsapriv, &keys.u.d.ecpub, CKR_KEY_FUNCTION_NOT_PERMITTED, CKR_OK, 0, 0, 0, 0}, + /*15*/{&keys.u.d.des3, &keys.u.d.rsapub, &keys.u.d.ecpriv, &keys.u.d.rsapriv, &keys.u.d.ecpriv, CKR_OK, CKR_KEY_FUNCTION_NOT_PERMITTED, 0, 0, desunwrapattrs, ARRAY_SIZE(desunwrapattrs)}, + // target non-ab + /*16*/{&keys.u.d.nonabpriv, &keys.u.d.rsapub, &keys.u.d.aes, &keys.u.d.rsapriv, &keys.u.d.aes, CKR_KEY_NOT_WRAPPABLE, CKR_OK, 0, 0, 0, 0}, + // Wrong key type in unwrap template + /*17*/{&keys.u.d.des3, &keys.u.d.aes, &keys.u.d.aes, &keys.u.d.aes, &keys.u.d.aes, CKR_OK, CKR_TEMPLATE_INCONSISTENT, 0, 0, ecprivunwrapattrs, ARRAY_SIZE(ecprivunwrapattrs)} + }; + + for (i = 0; i < ARRAY_SIZE(config); ++i) { + CK_OBJECT_HANDLE unwrapped; + CK_IBM_ATTRIBUTEBOUND_WRAP_PARAMS params; + CK_MECHANISM mech = {CKM_IBM_ATTRIBUTEBOUND_WRAP, ¶ms, sizeof(params)}; + params.hSignVerifyKey = *(config[i].signingkey); + testcase_begin("AB Wrap/Unwrap test %d", i); + testcase_new_assertion(); + wrappedkeylen = sizeof(wrappedkey); + rc = funcs->C_WrapKey(session, &mech, *(config[i].wrappingkey), + *(config[i].keytowrap), wrappedkey, &wrappedkeylen); + if (rc != config[i].wrapres) { + testcase_fail("Wrap/Unwrap test %u: wrapping: expected %s, got %s", + i, p11_get_ckr(config[i].wrapres), p11_get_ckr(rc)); + // Skip rest of the test + continue; + } else if (rc != CKR_OK) { + testcase_pass("Wrap/Unwrap test %u: wrapping failed as expected", i); + // Wrapping failed as expected. So skip unwrapping. + continue; + } + params.hSignVerifyKey = *(config[i].verificationkey); + rc = funcs->C_UnwrapKey(session, &mech, *(config[i].unwrappingkey), + wrappedkey, wrappedkeylen, config[i].unwraptemplate, + config[i].unwraptemplatesize, &unwrapped); + if (rc != config[i].unwrapres) { + testcase_fail("Wrap/Unwrap test %u: unwrapping: expected %s, got %s", + i, p11_get_ckr(config[i].unwrapres), p11_get_ckr(rc)); + // Skip rest of the test + continue; + } else if (rc != CKR_OK) { + testcase_pass("Wrap/Unwrap test %u: unwrapping failed as expected", i); + continue; + } + rc = config[i].compare(session, unwrapped, *(config[i].comparedest)); + if (rc != CKR_OK) { + dumpEP11Blob(session, *(config[i].wrappingkey), "dump-wrappingkey-%u", i); + dumpEP11Blob(session, *(config[i].keytowrap), "dump-keytowrap-%u", i); + dumpEP11Blob(session, *(config[i].signingkey), "dump-signingkey-%u", i); + dumpEP11Blob(session, unwrapped, "dump-unwrapped-%u", i); + dumpSPKI(session, *(config[i].keytowrap), "dump-keytowrap-spki-%u", i); + dumpSPKI(session, unwrapped, "dump-unwrapped-spki-%u", i); + testcase_fail("Wrap/Unwrap test %u: compare returned %s", i, p11_get_ckr(rc)); + } else { + testcase_pass("Wrap/Unwrap test %u: cycle passed", i); + } + funcs->C_DestroyObject(session, unwrapped); + } +} + +void do_TestAttributeChange(CK_SESSION_HANDLE session) +{ + CK_BBOOL cktrue = TRUE, ckfalse=FALSE; + CK_ATTRIBUTE attr = { + .type = CKA_IBM_ATTRBOUND, + .ulValueLen = sizeof(CK_BBOOL) + }; + CK_RV rc; + CK_OBJECT_HANDLE copyres = CK_INVALID_HANDLE; + + testcase_begin("Set CKA_IBM_ATTRBOUND to TRUE via C_SetAttributeValue"); + testcase_new_assertion(); + attr.pValue = &cktrue; + rc = funcs->C_SetAttributeValue(session, keys.u.d.nonabpub, &attr, 1); + if (rc != CKR_ATTRIBUTE_READ_ONLY) + testcase_fail("Changed CKA_IBM_ATTRBOUND via C_SetAttributeValue to TRUE"); + else + testcase_pass("Could not change CKA_IBM_ATTRBOUND via C_SetAttributeValue to TRUE"); + + testcase_begin("Set CKA_IBM_ATTRBOUND to TRUE via C_CopyObject"); + testcase_new_assertion(); + attr.pValue = &cktrue; + rc = funcs->C_CopyObject(session, keys.u.d.nonabpub, &attr, 1, ©res); + if (rc != CKR_ATTRIBUTE_READ_ONLY) + testcase_fail("Changed CKA_IBM_ATTRBOUND via C_CopyObject to TRUE"); + else + testcase_pass("Could not change CKA_IBM_ATTRBOUND via C_CopyObject to TRUE"); + if (copyres != CK_INVALID_HANDLE) + funcs->C_DestroyObject(session, copyres); + copyres = CK_INVALID_HANDLE; + + testcase_begin("Set CKA_IBM_ATTRBOUND to FALSE via C_SetAttributeValue"); + testcase_new_assertion(); + attr.pValue = &ckfalse; + rc = funcs->C_SetAttributeValue(session, keys.u.d.des2, &attr, 1); + if (rc != CKR_ATTRIBUTE_READ_ONLY) + testcase_fail("Changed CKA_IBM_ATTRBOUND via C_SetAttributeValue to FALSE"); + else + testcase_pass("Could not change CKA_IBM_ATTRBOUND via C_SetAttributeValue to FALSE"); + + testcase_begin("Set CKA_IBM_ATTRBOUND to FALSE via C_CopyObject"); + testcase_new_assertion(); + attr.pValue = &ckfalse; + rc = funcs->C_CopyObject(session, keys.u.d.des2, &attr, 1, ©res); + if (rc != CKR_ATTRIBUTE_READ_ONLY) + testcase_fail("Changed CKA_IBM_ATTRBOUND via C_CopyObject to FALSE"); + else + testcase_pass("Could not change CKA_IBM_ATTRBOUND via C_CopyObject to FALSE"); + if (copyres != CK_INVALID_HANDLE) + funcs->C_DestroyObject(session, copyres); +} + +void do_TestDerive(CK_SESSION_HANDLE session) +{ + CK_RV rc; + unsigned i; + CK_BBOOL val, checkval, true = TRUE; + CK_OBJECT_CLASS class = CKO_SECRET_KEY; + CK_KEY_TYPE key_type = CKK_GENERIC_SECRET; + CK_ULONG valuelen = 10; + // Cannot be static because of @val + CK_ATTRIBUTE derive_tmpl[] = { + {CKA_CLASS, &class, sizeof(class)}, + {CKA_KEY_TYPE, &key_type, sizeof(key_type)}, + {CKA_SENSITIVE, &true, sizeof(true)}, + {CKA_VALUE_LEN, &valuelen, sizeof(CK_ULONG)}, + {CKA_IBM_ATTRBOUND, &val, sizeof(CK_BBOOL)} + }; + CK_ATTRIBUTE derive_tmpl_noab[] = { + {CKA_CLASS, &class, sizeof(class)}, + {CKA_KEY_TYPE, &key_type, sizeof(key_type)}, + {CKA_SENSITIVE, &true, sizeof(true)}, + {CKA_VALUE_LEN, &valuelen, sizeof(CK_ULONG)} + }; + // Workaround since templates are not static + CK_ATTRIBUTE *tmpls[] = { + derive_tmpl, + derive_tmpl_noab + }; + CK_ULONG tmplsizes[] = { + ARRAY_SIZE(derive_tmpl), + ARRAY_SIZE(derive_tmpl_noab) + }; + CK_ATTRIBUTE checkattr = {CKA_IBM_ATTRBOUND, &checkval, sizeof(CK_BBOOL)}; + CK_ECDH1_DERIVE_PARAMS parm; + CK_MECHANISM mech = {CKM_ECDH1_DERIVE, &parm, sizeof(parm)}; + CK_BYTE pubkey_value[256]; + CK_ATTRIBUTE extr_tmpl = {CKA_EC_POINT, pubkey_value, sizeof(pubkey_value)}; + CK_OBJECT_HANDLE handle; + static const struct { + CK_OBJECT_HANDLE *basekey; + CK_OBJECT_HANDLE *pubkey; + CK_ULONG tmplidx; + CK_BBOOL abval; + CK_RV exprc; + CK_BBOOL expabval; + } config[] = { + // AB from AB with explicit template + /*0*/{&keys.u.d.ecpriv, &keys.u.d.ecpub, 0, TRUE, CKR_OK, TRUE}, + // AB from AB with implicit template + /*1*/{&keys.u.d.ecpriv, &keys.u.d.ecpub, 1, TRUE, CKR_OK, TRUE}, + // non-AB from AB + /*2*/{&keys.u.d.ecpriv, &keys.u.d.ecpub, 0, FALSE, CKR_OK, FALSE}, + // AB from non-AB (expected to fail) + /*3*/{&keys.u.d.nonabecpriv, &keys.u.d.nonabecpub, 0, TRUE, CKR_TEMPLATE_INCONSISTENT, FALSE} + }; + + for (i = 0; i < ARRAY_SIZE(config); ++i) { + handle = CK_INVALID_HANDLE; + val = config[i].abval; + testcase_begin("Derive Test %u", i); + testcase_new_assertion(); + rc = funcs->C_GetAttributeValue(session, *(config[i].pubkey), + &extr_tmpl, 1); + if (rc != CKR_OK) { + testcase_fail("Derive Test %u failed to extract EC point (rc=%s)", + i, p11_get_ckr(rc)); + continue; + } + parm.kdf = CKD_NULL; + parm.pSharedData = NULL; + parm.ulSharedDataLen = 0; + parm.pPublicData = extr_tmpl.pValue; + parm.ulPublicDataLen = extr_tmpl.ulValueLen; + rc = funcs->C_DeriveKey(session, &mech, *(config[i].basekey), + tmpls[config[i].tmplidx], + tmplsizes[config[i].tmplidx], + &handle); + if (rc == CKR_MECHANISM_INVALID) { + /* Special handling for bug in EP11: ECDH only supported for newer cards. */ + testcase_skip("Derive Test %u skipped due to bad card level\n", i); + continue; + }else if (rc != config[i].exprc) { + testcase_fail("Derive Test %u got unexpected derive result (got: %s; expected %s)", + i, p11_get_ckr(rc), p11_get_ckr(config[i].exprc)); + continue; + } + if (rc == CKR_OK) { + rc = funcs->C_GetAttributeValue(session, handle, &checkattr, 1); + if (rc == CKR_TEMPLATE_INCOMPLETE) { + // Treat this as okay, but non-AB + rc = CKR_OK; + checkval = FALSE; + } + if (rc != CKR_OK) { + testcase_fail("Derive Test %u failed to retrieve AB attribute (rc=%s)", + i, p11_get_ckr(rc)); + } else if (checkval == config[i].expabval) { + testcase_pass("Derive Test %u: cycle completed", i); + } else { + testcase_fail("Derive Test %u got wrong AB value (expected %s)", + i, config[i].expabval ? "TRUE" : "FALSE"); + } + } else { + testcase_pass("Derive Test %u failed as expected", i); + } + funcs->C_DestroyObject(session, handle); + } +} + +void testdriver() +{ + CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; + CK_ULONG user_pin_len; + CK_SESSION_HANDLE session; + CK_FLAGS flags; + CK_RV rc = CKR_OK; + + testsuite_begin("Attribute Bound Keys Tests"); + testcase_rw_session(); + testcase_user_login(); + + do_TestInvalidKeys(session); + + do_CreateKeyObjects(session); + + rc = do_SetupKeys(session); + if (rc == CKR_POLICY_VIOLATION) { + rc = CKR_OK; + goto testcase_cleanup; + } + if (rc != CKR_OK) { + testcase_error("Bail out since keys were not properly created!"); + goto testcase_cleanup; + } + do_TestKeyWrappingUnwrapping(session); + do_TestDerive(session); + do_TestAttributeChange(session); + testcase_cleanup: + teardown(session); + testcase_user_logout(); + testcase_close_session(); +} + +int main(int argc, char **argv) +{ + int rc; + CK_C_INITIALIZE_ARGS cinit_args; + + rc = do_ParseArgs(argc, argv); + if (rc != 1) { + return rc; + } + + printf("Using slot #%lu...\n\n", SLOT_ID); + printf("With option: no_stop: %d\n", no_stop); + + rc = do_GetFunctionList(); + if (!rc) { + PRINT_ERR("ERROR do_GetFunctionList() Failed, rx = 0x%0x\n", rc); + return rc; + } + + memset(&cinit_args, 0x0, sizeof(cinit_args)); + cinit_args.flags = CKF_OS_LOCKING_OK; + + funcs->C_Initialize(&cinit_args); + { + CK_SESSION_HANDLE hsess = 0; + rc = funcs->C_GetFunctionStatus(hsess); + if (rc != CKR_FUNCTION_NOT_PARALLEL) { + return rc; + } + + rc = funcs->C_CancelFunction(hsess); + if (rc != CKR_FUNCTION_NOT_PARALLEL) { + return rc; + } + } + + if (is_ep11_token(SLOT_ID)) { + testcase_setup(0); + rc = do_CheckMechanismInfo(); + if (rc != CKR_OK) { + // Skip, but don't crash the test executor + rc = 0; + } else { + testdriver(); + testcase_print_result(); + } + } else { + rc = 0; + } + + funcs->C_Finalize(NULL); + + return testcase_return(rc); +} diff -Nru opencryptoki-3.16.0+dfsg/testcases/crypto/aes_func.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/crypto/aes_func.c --- opencryptoki-3.16.0+dfsg/testcases/crypto/aes_func.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/crypto/aes_func.c 2022-02-02 15:05:41.000000000 +0100 @@ -17,6 +17,7 @@ #include "regress.h" #include "aes.h" #include "common.c" +#include "mechtable.h" #include "mech_to_str.h" CK_ULONG key_lens[] = { 16, 24, 32 }; @@ -61,7 +62,7 @@ /** skip tests if the slot doesn't support this mechanism **/ if (!mech_supported(slot_id, tsuite->mech.mechanism)) { testsuite_skip(3, - "Slot %u doesn't support %s (%u)", + "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); @@ -80,6 +81,11 @@ rc = generate_AESKey(session, key_lens[i], !pkey, &mechkey, &h_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("AES key generation is not allowed by policy"); + continue; + } + testcase_error("C_GenerateKey rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -201,7 +207,7 @@ /** skip test if the slot doesn't support this mechanism **/ if (!mech_supported(slot_id, tsuite->mech.mechanism)) { - testcase_skip("Slot %u doesn't support %s (%u)", + testcase_skip("Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); @@ -219,6 +225,11 @@ rc = generate_AESKey(session, key_lens[i], !pkey, &mechkey, &h_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("AES key generation is not allowed by policy"); + continue; + } + testcase_error("C_GenerateKey rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -427,7 +438,7 @@ /** skip test if the slot doesn't support this mechanism **/ if (!mech_supported(slot_id, tsuite->mech.mechanism)) { testsuite_skip(tsuite->tvcount, - "Slot %u doesn't support %s (%u)", + "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); @@ -446,6 +457,11 @@ tsuite->tv[i].key, tsuite->tv[i].klen, &h_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("AES key import is not allowed by policy"); + continue; + } + testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); goto error; } @@ -564,7 +580,7 @@ /** skip test if the slot doesn't support this mechanism **/ if (!mech_supported(slot_id, tsuite->mech.mechanism)) { testsuite_skip(tsuite->tvcount, - "Slot %u doesn't support %s (%u)", + "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); @@ -583,6 +599,11 @@ tsuite->tv[i].key, tsuite->tv[i].klen, &h_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("AES key import is not allowed by policy"); + continue; + } + testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); goto error; } @@ -742,7 +763,7 @@ /** skip test if the slot doesn't support this mechanism **/ if (!mech_supported(slot_id, tsuite->mech.mechanism)) { testsuite_skip(tsuite->tvcount, - "Slot %u doesn't support %s (%u)", + "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); @@ -761,6 +782,11 @@ tsuite->tv[i].key, tsuite->tv[i].klen, &h_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("AES key import is not allowed by policy"); + continue; + } + testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); goto error; } @@ -878,7 +904,7 @@ /** skip tests if the slot doesn't support this mechanism **/ if (!mech_supported(slot_id, tsuite->mech.mechanism)) { testsuite_skip(tsuite->tvcount, - "Slot %u doesn't support %s (%u)", + "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); @@ -895,6 +921,11 @@ tsuite->tv[i].key, tsuite->tv[i].klen, &h_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("AES key import is not allowed by policy"); + continue; + } + testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); goto error; } @@ -1062,7 +1093,7 @@ /** skip test if the slot doesn't support this mechanism **/ if (!mech_supported(slot_id, tsuite->mech.mechanism)) { testsuite_skip(3, - "Slot %u doesn't support %s (%u)", + "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); @@ -1070,7 +1101,7 @@ } if (!wrap_supported(slot_id, tsuite->mech)) { - testsuite_skip(3, "Slot %u doesn't support %s (%u)", + testsuite_skip(3, "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); @@ -1103,6 +1134,11 @@ /** generate crypto key (must be extractable) **/ rc = generate_AESKey(session, key_lens[i], CK_TRUE, &mechkey, &h_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("AES key generation is not allowed by policy"); + continue; + } + testcase_error("C_GenerateKey rc=%s", p11_get_ckr(rc)); goto error; } @@ -1336,7 +1372,7 @@ /** skip test if the slot doesn't support this mechanism **/ if (!mech_supported(slot_id, tsuite->mech.mechanism)) { testsuite_skip(3, - "Slot %u doesn't support %s (%u)", + "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); @@ -1344,13 +1380,29 @@ } if (!mech_supported(slot_id, CKM_RSA_PKCS)) { testsuite_skip(3, - "Slot %u doesn't support %s (%u)", + "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(CKM_RSA_PKCS), (unsigned int) CKM_RSA_PKCS); goto testcase_cleanup; } + if (!mech_supported(slot_id, CKM_RSA_PKCS_KEY_PAIR_GEN)) { + testsuite_skip(3, + "Slot %u doesn't support CKM_RSA_PKCS_KEY_PAIR_GEN", + (unsigned int) slot_id); + goto testcase_cleanup; + } + + rc = funcs->C_GetMechanismInfo(slot_id, CKM_RSA_PKCS_KEY_PAIR_GEN, &mech_info); + if (rc != CKR_OK) { + testcase_error("C_GetMechanismInfo rc=%s", p11_get_ckr(rc)); + goto testcase_cleanup; + } + + if (bits < mech_info.ulMinKeySize) + bits = mech_info.ulMinKeySize; + for (i = 0; i < 3; i++) { testcase_begin("%s wrap/unwrap of RSA key for key length=%ld and pkey=%X.", @@ -1374,6 +1426,11 @@ NULL, 0, &publ_key, &priv_key); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("RSA key generation is not allowed by policy"); + continue; + } + testcase_error("C_GenerateKeyPair rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -1384,6 +1441,11 @@ &w_key); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("AES key generation is not allowed by policy"); + continue; + } + testcase_error("C_GenerateKey rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -1555,12 +1617,41 @@ /** skip test if the slot doesn't support this mechanism **/ if (!mech_supported(slot_id, tsuite->mech.mechanism)) { - testsuite_skip(3, "Slot %u doesn't support %s (%u)", + testsuite_skip(3, "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); goto testcase_cleanup; } + if (!mech_supported(slot_id, CKM_AES_KEY_GEN)) { + testsuite_skip(3, + "Slot %u doesn't support CKM_AES_KEY_GEN)", + (unsigned int) slot_id); + goto testcase_cleanup; + } + if (mech_supported_flags(slot_id, tsuite->mech.mechanism, CKF_WRAP) && + !mech_supported(slot_id, CKM_AES_CBC_PAD)) { + testsuite_skip(3, + "Slot %u doesn't support CKM_AES_CBC_PAD)", + (unsigned int) slot_id); + goto testcase_cleanup; + } + + if (!mech_supported(slot_id, CKM_RSA_PKCS_KEY_PAIR_GEN)) { + testsuite_skip(3, + "Slot %u doesn't support CKM_RSA_PKCS_KEY_PAIR_GEN", + (unsigned int) slot_id); + goto testcase_cleanup; + } + + rc = funcs->C_GetMechanismInfo(slot_id, CKM_RSA_PKCS_KEY_PAIR_GEN, &mech_info); + if (rc != CKR_OK) { + testcase_error("C_GetMechanismInfo rc=%s", p11_get_ckr(rc)); + goto testcase_cleanup; + } + + if (bits < mech_info.ulMinKeySize) + bits = mech_info.ulMinKeySize; for (i = 0; i < 3; i++) { @@ -1585,6 +1676,11 @@ NULL, 0, &publ_key, &priv_key); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("RSA key generation is not allowed by policy"); + continue; + } + testcase_error("C_GenerateKeyPair rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -1594,6 +1690,11 @@ key_gen_tmpl, key_gen_tmpl_len, &w_key); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("AES key generation is not allowed by policy"); + continue; + } + testcase_error("C_GenerateKey rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -1710,12 +1811,41 @@ /** skip test if the slot doesn't support this mechanism **/ if (!mech_supported(slot_id, tsuite->mech.mechanism)) { testsuite_skip(3, - "Slot %u doesn't support %s (%u)", + "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); goto testcase_cleanup; } + if (!mech_supported(slot_id, CKM_AES_KEY_GEN)) { + testsuite_skip(3, + "Slot %u doesn't support CKM_AES_KEY_GEN)", + (unsigned int) slot_id); + goto testcase_cleanup; + } + if (mech_supported_flags(slot_id, tsuite->mech.mechanism, CKF_UNWRAP) && + !mech_supported(slot_id, CKM_AES_CBC_PAD)) { + testsuite_skip(3, + "Slot %u doesn't support CKM_AES_CBC_PAD)", + (unsigned int) slot_id); + goto testcase_cleanup; + } + + if (!mech_supported(slot_id, CKM_RSA_PKCS_KEY_PAIR_GEN)) { + testsuite_skip(3, + "Slot %u doesn't support CKM_RSA_PKCS_KEY_PAIR_GEN", + (unsigned int) slot_id); + goto testcase_cleanup; + } + + rc = funcs->C_GetMechanismInfo(slot_id, CKM_RSA_PKCS_KEY_PAIR_GEN, &mech_info); + if (rc != CKR_OK) { + testcase_error("C_GetMechanismInfo rc=%s", p11_get_ckr(rc)); + goto testcase_cleanup; + } + + if (bits < mech_info.ulMinKeySize) + bits = mech_info.ulMinKeySize; for (i = 0; i < 3; i++) { @@ -1740,6 +1870,11 @@ NULL, 0, &publ_key, &priv_key); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("RSA key generation is not allowed by policy"); + continue; + } + testcase_error("C_GenerateKeyPair rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -1749,6 +1884,11 @@ key_gen_tmpl, key_gen_tmpl_len, &w_key); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("AES key generation is not allowed by policy"); + continue; + } + testcase_error("C_GenerateKey rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -1849,7 +1989,7 @@ /** skip tests if the slot doesn't support this mechanism **/ if (!mech_supported(slot_id, tsuite->mech.mechanism)) { testsuite_skip(3, - "Slot %u doesn't support %s (%u)", + "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); @@ -1866,6 +2006,11 @@ tsuite->tv[i].key, tsuite->tv[i].klen, &h_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("AES key import is not allowed by policy"); + continue; + } + testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); goto error; } @@ -1889,13 +2034,19 @@ break; default: testcase_error("Invalid mechanism: %s", - p11_get_ckm(mech.mechanism)); + p11_get_ckm(&mechtable_funcs, mech.mechanism)); goto error; } /** initialize signing **/ rc = funcs->C_SignInit(session, &mech, h_key); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("C_SignInit with mech %s is not allowed by policy", + mech_to_str(mech.mechanism)); + goto error; + } + testcase_error("C_SignInit rc=%s", p11_get_ckr(rc)); goto error; } @@ -2042,6 +2193,11 @@ /* Generate a test key */ rc = generate_AESKey(session, 16, CK_FALSE, &keygen_mech, &h_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("AES key generation is not allowed by policy"); + goto testcase_cleanup; + } + testcase_fail("generate_AESKey rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -2152,6 +2308,11 @@ /* Generate token object */ rc = funcs->C_GenerateKey(session, &keygen_mech, keygen_tmpl, keygen_tmpl_len, &h_key); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("AES key generation is not allowed by policy"); + goto testcase_cleanup; + } + testcase_fail("C_GenerateKey rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -2421,6 +2582,5 @@ funcs->C_Finalize(NULL); - /* make sure we return non-zero if rv is non-zero */ - return ((rv == 0) || (rv % 256) ? (int)rv : -1); + return testcase_return(rv); } diff -Nru opencryptoki-3.16.0+dfsg/testcases/crypto/des3_func.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/crypto/des3_func.c --- opencryptoki-3.16.0+dfsg/testcases/crypto/des3_func.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/crypto/des3_func.c 2022-02-02 15:05:41.000000000 +0100 @@ -18,6 +18,7 @@ #include "des3.h" #include "common.c" #include "mech_to_str.h" +#include "mechtable.h" /** Tests triple DES encryption with published test vectors. **/ CK_RV do_EncryptDES3(struct published_test_suite_info *tsuite) @@ -45,7 +46,7 @@ /** skip testsuite if the slot does not support this mechanism **/ if (!mech_supported(slot_id, tsuite->mechanism)) { testsuite_skip(tsuite->tvcount, - "Slot %u doesn't support %s (%u)", + "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mechanism), (unsigned int) tsuite->mechanism); @@ -80,6 +81,11 @@ rc = create_DES3Key(session, tsuite->tv[i].key, tsuite->tv[i].klen, &h_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("DES3 key import is not allowed by policy"); + continue; + } + testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); goto error; } @@ -165,7 +171,7 @@ /** skip testuite if the slot does not support this mechanism **/ if (!mech_supported(slot_id, tsuite->mechanism)) { testsuite_skip(tsuite->tvcount, - "Slot %u doesn't support %s (%u)", + "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mechanism), (unsigned int) tsuite->mechanism); @@ -204,6 +210,11 @@ rc = create_DES3Key(session, tsuite->tv[i].key, tsuite->tv[i].klen, &h_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("DES3 key import is not allowed by policy"); + continue; + } + testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); goto error; } @@ -334,7 +345,7 @@ /** skip test if the slot does not support this mechanism **/ if (!mech_supported(slot_id, tsuite->mechanism)) { testsuite_skip(tsuite->tvcount, - "Slot %u doesn't support %s (%u)", + "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mechanism), (unsigned int) tsuite->mechanism); @@ -370,6 +381,11 @@ rc = create_DES3Key(session, tsuite->tv[i].key, tsuite->tv[i].klen, &h_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("DES3 key import is not allowed by policy"); + continue; + } + testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -455,7 +471,7 @@ /** skip test if the slot does not support this mechanism **/ if (!mech_supported(slot_id, tsuite->mechanism)) { testsuite_skip(tsuite->tvcount, - "Slot %u doesn't support %s (%u)", + "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mechanism), (unsigned int) tsuite->mechanism); @@ -494,6 +510,11 @@ rc = create_DES3Key(session, tsuite->tv[i].key, tsuite->tv[i].klen, &h_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("DES3 key import is not allowed by policy"); + continue; + } + testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -623,7 +644,7 @@ /** skip test if the slot does not support this mechanism **/ if (!mech_supported(slot_id, tsuite->mech.mechanism)) { - testcase_skip("Slot %u doesn't support %s (%u)", + testcase_skip("Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); @@ -749,7 +770,7 @@ /** skip test if the slot does not support this mechanism **/ if (!mech_supported(slot_id, tsuite->mech.mechanism)) { - testcase_skip("Slot %u doesn't support %s (%u)", + testcase_skip("Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); @@ -970,14 +991,14 @@ /** skip test if the slot does not support this mechanism **/ if (!mech_supported(SLOT_ID, tsuite->mech.mechanism)) { - testcase_skip("Slot %u doesn't support %s (%u)", + testcase_skip("Slot %u doesn't support %s (0x%x)", (unsigned int) SLOT_ID, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); goto testcase_cleanup; } if (!wrap_supported(SLOT_ID, tsuite->mech)) { - testcase_skip("Slot %u doesn't support %s (%u)", + testcase_skip("Slot %u doesn't support %s (0x%x)", (unsigned int) SLOT_ID, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); @@ -1133,7 +1154,7 @@ /** skip tests if the slot doesn't support this mechanism **/ if (!mech_supported(slot_id, tsuite->mech.mechanism)) { testsuite_skip(3, - "Slot %u doesn't support %s (%u)", + "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); @@ -1161,6 +1182,11 @@ else rc = CKR_KEY_TYPE_INCONSISTENT; if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("DES2/DES3 key import is not allowed by policy"); + continue; + } + testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); goto error; } @@ -1184,7 +1210,7 @@ break; default: testcase_error("Invalid mechanism: %s", - p11_get_ckm(mech.mechanism)); + p11_get_ckm(&mechtable_funcs, mech.mechanism)); goto error; } @@ -1391,5 +1417,5 @@ funcs->C_Finalize(NULL); - return rc; + return testcase_return(rc); } diff -Nru opencryptoki-3.16.0+dfsg/testcases/crypto/des_func.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/crypto/des_func.c --- opencryptoki-3.16.0+dfsg/testcases/crypto/des_func.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/crypto/des_func.c 2022-02-02 15:05:41.000000000 +0100 @@ -45,7 +45,7 @@ /** skip test if the slot doesn't support this mechanism **/ if (!mech_supported(slot_id, tsuite->mechanism)) { testsuite_skip(tsuite->tvcount, - "Slot %u doesn't support %s (%u)", + "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mechanism), (unsigned int) tsuite->mechanism); @@ -82,6 +82,11 @@ rc = create_DESKey(session, tsuite->tv[i].key, tsuite->tv[i].klen, &h_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("DES key import is not allowed by policy"); + continue; + } + testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -166,7 +171,7 @@ /** skip test if slot doesn't support this mechanism **/ if (!mech_supported(slot_id, tsuite->mechanism)) { testsuite_skip(tsuite->tvcount, - "Slot %u doesn't support %s (%u)", + "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mechanism), (unsigned int) tsuite->mechanism); @@ -205,6 +210,11 @@ rc = create_DESKey(session, tsuite->tv[i].key, tsuite->tv[i].klen, &h_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("DES key import is not allowed by policy"); + continue; + } + testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -336,7 +346,7 @@ /** query the slot to see if the mech is supported. **/ if (!mech_supported(slot_id, tsuite->mechanism)) { testsuite_skip(tsuite->tvcount, - "Slot %u doesn't support %s (%u)", + "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mechanism), (unsigned int) tsuite->mechanism); @@ -356,6 +366,11 @@ rc = create_DESKey(session, tsuite->tv[i].key, tsuite->tv[i].klen, &h_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("DES key import is not allowed by policy"); + continue; + } + testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -459,7 +474,7 @@ /** skip testsuite if the slot doesn't support this mechanism **/ if (!mech_supported(slot_id, tsuite->mechanism)) { testsuite_skip(tsuite->tvcount, - "Slot %u doesn't support %s (%u)", + "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mechanism), (unsigned int) tsuite->mechanism); @@ -497,6 +512,11 @@ rc = create_DESKey(session, tsuite->tv[i].key, tsuite->tv[i].klen, &h_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("DES key import is not allowed by policy"); + continue; + } + testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -628,7 +648,7 @@ /** skip test if the slot doesn't support this mechanism **/ if (!mech_supported(slot_id, tsuite->mech.mechanism)) { - testcase_skip("Slot %u doesn't support %s (%u)", + testcase_skip("Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); @@ -753,7 +773,7 @@ /** skip test if the slot doesn't support this mechanism **/ if (!mech_supported(slot_id, tsuite->mech.mechanism)) { - testcase_skip("Slot %u doesn't support %s (%u)", + testcase_skip("Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); @@ -931,14 +951,14 @@ /** skip test if the slot doesn't support this mechanism **/ if (!mech_supported(slot_id, tsuite->mech.mechanism)) { - testcase_skip("Slot %u doesn't support %s (%u)", + testcase_skip("Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); goto testcase_cleanup; } if (!wrap_supported(slot_id, tsuite->mech)) { - testcase_skip("Slot %u doesn't support %s (%u)", + testcase_skip("Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); @@ -1141,5 +1161,5 @@ funcs->C_Finalize(NULL); - return rc; + return testcase_return(rc); } diff -Nru opencryptoki-3.16.0+dfsg/testcases/crypto/dh_func.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/crypto/dh_func.c --- opencryptoki-3.16.0+dfsg/testcases/crypto/dh_func.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/crypto/dh_func.c 2022-02-02 15:05:41.000000000 +0100 @@ -239,6 +239,11 @@ rc = funcs->C_GenerateKeyPair(session, &mech, publ_tmpl, 5, priv_tmpl, 4, &publ_key, &priv_key); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("DH key generation is not allowed by policy"); + rc = CKR_OK; + goto testcase_cleanup; + } testcase_fail("C_GenerateKeyPair #1: rc = %s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -271,6 +276,11 @@ DH_PUBL_BASE, sizeof(DH_PUBL_BASE), DH_PRIVATE_A, sizeof(DH_PRIVATE_A), &priv_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("DH key import is not allowed by policy"); + rc = CKR_OK; + goto testcase_cleanup; + } testcase_fail("C_CreateObject (DH Private Key) failed rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; @@ -281,6 +291,11 @@ DH_PUBL_BASE, sizeof(DH_PUBL_BASE), DH_PUBLIC_A, sizeof(DH_PUBLIC_A), &publ_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("DH key import is not allowed by policy"); + rc = CKR_OK; + goto testcase_cleanup; + } testcase_fail("C_CreateObject (DH Public Key) failed rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; @@ -292,6 +307,11 @@ DH_PRIVATE_B, sizeof(DH_PRIVATE_B), &peer_priv_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("DH key import is not allowed by policy"); + rc = CKR_OK; + goto testcase_cleanup; + } testcase_fail("C_CreateObject (DH Private Key) failed rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; @@ -303,6 +323,11 @@ DH_PUBLIC_B, sizeof(DH_PUBLIC_B), &peer_publ_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("DH key import is not allowed by policy"); + rc = CKR_OK; + goto testcase_cleanup; + } testcase_fail("C_CreateObject (DH Public Key) failed rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; @@ -570,6 +595,5 @@ funcs->C_Finalize(NULL); - /* make sure we return non-zero if rv is non-zero */ - return ((rv == 0) || (rv % 256) ? (int)rv : -1); + return testcase_return(rv); } diff -Nru opencryptoki-3.16.0+dfsg/testcases/crypto/digest_func.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/crypto/digest_func.c --- opencryptoki-3.16.0+dfsg/testcases/crypto/digest_func.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/crypto/digest_func.c 2022-02-02 15:05:41.000000000 +0100 @@ -19,6 +19,7 @@ #include "regress.h" #include "digest.h" #include "common.c" +#include "mech_to_str.h" #define DIGEST_UPDATE_SIZE 32 @@ -314,6 +315,11 @@ /** create key object **/ rc = create_GenericSecretKey(session, key, key_len, &h_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("generic secret key generation is not allowed by policy"); + continue; + } + testcase_error("create_GenericSecretKey rc=%s", p11_get_ckr(rc)); goto error; } @@ -321,6 +327,12 @@ /** initialize signing **/ rc = funcs->C_SignInit(session, &mech, h_key); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("C_SignInit with mech %s is not allowed by policy", + mech_to_str(mech.mechanism)); + goto error; + } + testcase_error("C_SignInit rc=%s", p11_get_ckr(rc)); goto error; } @@ -429,6 +441,11 @@ /** create key object **/ rc = create_GenericSecretKey(session, key, key_len, &h_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("generic secret key generation is not allowed by policy"); + continue; + } + testcase_error("create_GenericSecretKey rc=%s", p11_get_ckr(rc)); goto error; } @@ -436,6 +453,12 @@ /** initilaize verification **/ rc = funcs->C_VerifyInit(session, &mech, h_key); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("C_VerifyInit with mech %s is not allowed by policy", + mech_to_str(mech.mechanism)); + goto error; + } + testcase_error("C_VerifyInit rc=%s", p11_get_ckr(rc)); goto error; } @@ -567,6 +590,11 @@ /** create key object **/ rc = create_GenericSecretKey(session, key, key_len, &h_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("generic secret key generation is not allowed by policy"); + continue; + } + testcase_error("create_GenericSecretKey rc=%s", p11_get_ckr(rc)); goto error; } @@ -711,6 +739,11 @@ /** create key object **/ rc = create_GenericSecretKey(session, key, key_len, &h_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("generic secret key generation is not allowed by policy"); + continue; + } + testcase_error("create_GenericSecretKey rc=%s", p11_get_ckr(rc)); goto error; } @@ -853,6 +886,11 @@ /** create key object **/ rc = create_GenericSecretKey(session, key, key_len, &h_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("generic secret key generation is not allowed by policy"); + continue; + } + testcase_error("create_GenericSecretKey rc=%s", p11_get_ckr(rc)); goto error; } @@ -1037,6 +1075,11 @@ /** create key object **/ rc = create_GenericSecretKey(session, key, key_len, &h_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("generic secret key generation is not allowed by policy"); + continue; + } + testcase_error("create_GenericSecretKey rc=%s", p11_get_ckr(rc)); goto error; } @@ -1184,6 +1227,11 @@ /** create key object **/ rc = create_GenericSecretKey(session, key, key_len, &h_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("generic secret key generation is not allowed by policy"); + continue; + } + testcase_error("create_GenericSecretKey rc=%s", p11_get_ckr(rc)); goto error; } @@ -1191,6 +1239,12 @@ /** initialize signing **/ rc = funcs->C_SignInit(session, &mech, h_key); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("C_SignInit with mech %s is not allowed by policy", + mech_to_str(mech.mechanism)); + goto error; + } + testcase_error("C_SignInit rc=%s", p11_get_ckr(rc)); goto error; } @@ -1326,6 +1380,11 @@ /** create key object **/ rc = create_GenericSecretKey(session, key, key_len, &h_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("generic secret key generation is not allowed by policy"); + continue; + } + testcase_error("create_GenericSecretKey rc=%s", p11_get_ckr(rc)); goto error; } @@ -1495,6 +1554,11 @@ /** generate key object **/ rc = generate_SecretKey(session, key_len, &secret_mech, &h_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testsuite_skip(1, "generic secret key generation is not allowed by policy"); + goto testcase_cleanup; + } + testcase_error("generate_SecretKey rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -1660,6 +1724,5 @@ funcs->C_Finalize(NULL); - /* make sure we return non-zero if rv is non-zero */ - return ((rv == 0) || (rv % 256) ? (int)rv : -1); + return testcase_return(rv); } diff -Nru opencryptoki-3.16.0+dfsg/testcases/crypto/dilithium_func.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/crypto/dilithium_func.c --- opencryptoki-3.16.0+dfsg/testcases/crypto/dilithium_func.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/crypto/dilithium_func.c 2022-02-02 15:05:41.000000000 +0100 @@ -20,6 +20,7 @@ #include "common.c" #include "defs.h" #include "dilithium.h" +#include "mechtable.h" /** * Experimental Support for Dilithium keys and signatures @@ -63,7 +64,8 @@ if (rc == CKR_MECHANISM_INVALID) { /* no support for Dilithium? skip */ testcase_skip("Slot %u doesn't support %s", - (unsigned int) SLOT_ID, p11_get_ckm(mechType)); + (unsigned int) SLOT_ID, + p11_get_ckm(&mechtable_funcs, mechType)); rc = CKR_OK; goto testcase_cleanup; } else { @@ -369,6 +371,10 @@ &priv_key); testcase_new_assertion(); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("Dilithium key import is not allowed by policy"); + continue; + } testcase_fail("C_CreateObject (Dilithium Private Key) failed at i=%lu, " "rc=%s", i, p11_get_ckr(rc)); goto testcase_cleanup; @@ -383,6 +389,10 @@ &publ_key); testcase_new_assertion(); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("Dilithium key import is not allowed by policy"); + goto testcase_cleanup; + } testcase_fail("C_CreateObject (Dilithium Public Key) failed at i=%lu, " "rc=%s", i, p11_get_ckr(rc)); goto testcase_cleanup; @@ -569,6 +579,10 @@ &priv_key); testcase_new_assertion(); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("Dilithium key import is not allowed by policy"); + continue; + } testcase_fail ("C_CreateObject (Dilithium Private Key) failed at i=%lu, rc=%s", i, p11_get_ckr(rc)); @@ -584,6 +598,10 @@ &publ_key); testcase_new_assertion(); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("Dilithium key import is not allowed by policy"); + goto testcase_cleanup; + } testcase_fail ("C_CreateObject (Dilithium Public Key) failed at i=%lu, rc=%s", i, p11_get_ckr(rc)); @@ -598,6 +616,11 @@ wkey_mech.ulParameterLen = 0; rc = generate_AESKey(session, 32, CK_TRUE, &wkey_mech, &secret_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("AES key generation is not allowed by policy"); + goto testcase_cleanup; + } + testcase_error("generate_AESKey, rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -734,6 +757,5 @@ funcs->C_Finalize(NULL); - /* make sure we return non-zero if rv is non-zero */ - return ((rv == 0) || (rv % 256) ? (int)rv : -1); + return testcase_return(rv); } diff -Nru opencryptoki-3.16.0+dfsg/testcases/crypto/dsa_func.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/crypto/dsa_func.c --- opencryptoki-3.16.0+dfsg/testcases/crypto/dsa_func.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/crypto/dsa_func.c 2022-02-02 15:05:41.000000000 +0100 @@ -66,7 +66,7 @@ CK_SLOT_ID slot_id = SLOT_ID; CK_SESSION_HANDLE session; CK_MECHANISM mech; - CK_OBJECT_HANDLE publ_key, priv_key; + CK_OBJECT_HANDLE publ_key = CK_INVALID_HANDLE, priv_key = CK_INVALID_HANDLE; CK_FLAGS flags; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_ULONG user_pin_len; @@ -90,12 +90,20 @@ rc = funcs->C_GenerateKeyPair(session, &mech, publ_tmpl, 3, NULL, 0, &publ_key, &priv_key); - if (rc != CKR_OK) - testcase_fail("C_GenerateKeyPair rc=%s", p11_get_ckr(rc)); - else + if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("DSA key generation is not allowed by policy"); + rc = CKR_OK; + } else { + testcase_fail("C_GenerateKeyPair rc=%s", p11_get_ckr(rc)); + } + } else { testcase_pass("GenerateDSAKeyPair passed"); + } testcase_cleanup: + funcs->C_DestroyObject(session, priv_key); + funcs->C_DestroyObject(session, publ_key); testcase_user_logout(); if (funcs->C_CloseAllSessions(slot_id) != CKR_OK) testcase_error("C_CloseAllSession failed."); @@ -114,7 +122,7 @@ CK_SLOT_ID slot_id = SLOT_ID; CK_SESSION_HANDLE session; CK_MECHANISM mech; - CK_OBJECT_HANDLE publ_key, priv_key; + CK_OBJECT_HANDLE publ_key = CK_INVALID_HANDLE, priv_key = CK_INVALID_HANDLE; CK_FLAGS flags; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_ULONG user_pin_len; @@ -141,6 +149,10 @@ rc = funcs->C_GenerateKeyPair(session, &mech, publ_tmpl, 3, NULL, 0, &publ_key, &priv_key); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("DSA key generation is not allowed by policy"); + goto testcase_cleanup; + } testcase_error("C_GenerateKeyPair rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -201,6 +213,8 @@ } testcase_cleanup: + funcs->C_DestroyObject(session, priv_key); + funcs->C_DestroyObject(session, publ_key); testcase_user_logout(); if (funcs->C_CloseAllSessions(slot_id) != CKR_OK) testcase_error("C_CloseAllSessions failed."); @@ -274,7 +288,7 @@ CK_SLOT_ID slot_id = SLOT_ID; CK_SESSION_HANDLE session; CK_FLAGS flags; - CK_OBJECT_HANDLE publ_key, priv_key; + CK_OBJECT_HANDLE publ_key = CK_INVALID_HANDLE, priv_key = CK_INVALID_HANDLE; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_ULONG user_pin_len; CK_MECHANISM mech; @@ -298,6 +312,10 @@ DSA1024_PRIVATE, sizeof(DSA1024_PRIVATE), &priv_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("DSA key import is not allowed by policy"); + goto testcase_cleanup; + } testcase_fail("C_CreateObject (DSA Private Key) failed rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; @@ -309,6 +327,10 @@ DSA1024_BASE, sizeof(DSA1024_BASE), DSA1024_PUBLIC, sizeof(DSA1024_PUBLIC), &publ_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("DSA key import is not allowed by policy"); + goto testcase_cleanup; + } testcase_fail("C_CreateObject (DSA Public Key) failed rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; @@ -353,6 +375,8 @@ testcase_pass("DSA Import KeyPair Sign/Verify"); testcase_cleanup: + funcs->C_DestroyObject(session, priv_key); + funcs->C_DestroyObject(session, publ_key); testcase_user_logout(); if (funcs->C_CloseAllSessions(slot_id) != CKR_OK) testcase_error("C_CloseAllSessions failed."); @@ -454,6 +478,5 @@ funcs->C_Finalize(NULL); - /* make sure we return non-zero if rv is non-zero */ - return ((rv == 0) || (rv % 256) ? (int)rv : -1); + return testcase_return(rv); } diff -Nru opencryptoki-3.16.0+dfsg/testcases/crypto/ec_func.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/crypto/ec_func.c --- opencryptoki-3.16.0+dfsg/testcases/crypto/ec_func.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/crypto/ec_func.c 2022-02-02 15:05:41.000000000 +0100 @@ -21,6 +21,7 @@ #include "ec.h" #include "defs.h" #include "ec_curves.h" +#include "mechtable.h" /* * Below is a list for the OIDs and DER encodings of the brainpool. @@ -313,6 +314,47 @@ } /* + * Perform a HMAC sign to verify that the key is usable. + */ +CK_RV run_HMACSign(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE h_key, + CK_ULONG key_len) +{ + CK_MECHANISM mech = { .mechanism = CKM_SHA_1_HMAC, + .pParameter = NULL, .ulParameterLen = 0 }; + CK_BYTE data[32] = { 0 }; + CK_BYTE mac[SHA1_HASH_SIZE] = { 0 }; + CK_ULONG mac_len = sizeof(mac); + CK_RV rc = CKR_OK; + + if (!mech_supported(SLOT_ID, CKM_SHA_1_HMAC)) { + testcase_notice("Mechanism CKM_SHA_1_HMAC is not supported with slot " + "%ld. Skipping key check", SLOT_ID); + return CKR_OK; + } + if (!check_supp_keysize(SLOT_ID, CKM_SHA_1_HMAC, key_len * 8)) { + testcase_notice("Mechanism CKM_SHA_1_HMAC can not be used with keys " + "of size %lu. Skipping key check", key_len); + return CKR_OK; + } + + rc = funcs->C_SignInit(session, &mech, h_key); + if (rc != CKR_OK) { + testcase_notice("C_SignInit rc=%s", p11_get_ckr(rc)); + goto error; + } + + /** do signing **/ + rc = funcs->C_Sign(session, data, sizeof(data), mac, &mac_len); + if (rc != CKR_OK) { + testcase_notice("C_Sign rc=%s", p11_get_ckr(rc)); + goto error; + } + +error: + return rc; +} + +/* * Generate EC key-pairs for parties A and B. * Derive shared secrets based on Diffie Hellman key agreement defined in PKCS#3 */ @@ -451,7 +493,8 @@ } if (!mech_supported(SLOT_ID, derive_mech_type)) { testcase_skip("Slot %u doesn't support %s\n", - (unsigned int) SLOT_ID, p11_get_ckm(derive_mech_type)); + (unsigned int) SLOT_ID, + p11_get_ckm(&mechtable_funcs, derive_mech_type)); goto testcase_cleanup; } @@ -467,6 +510,10 @@ prv_attr_gen, prv_attr_gen_len, &publ_keyA, &priv_keyA); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("EC key generation is not allowed by policy"); + continue; + } if (rc == CKR_MECHANISM_PARAM_INVALID || rc == CKR_ATTRIBUTE_VALUE_INVALID || rc == CKR_CURVE_NOT_SUPPORTED) { @@ -498,6 +545,10 @@ prv_attr_gen, prv_attr_gen_len, &publ_keyB, &priv_keyB); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("EC key generation is not allowed by policy"); + goto testcase_cleanup; + } testcase_fail("C_GenerateKeyPair with valid input failed at i=%lu " "(%s), rc=%s", i, der_ec_supported[i].name, p11_get_ckr(rc)); @@ -522,6 +573,45 @@ // Testcase #2 - Now derive the secrets... for (j=0; j < NUM_KDFS; j++) { + switch (kdfs[j]) { + case CKD_SHA1_KDF: + if (!mech_supported(SLOT_ID, CKM_SHA_1)) { + testcase_skip("Slot %u doesn't support CKD_SHA1_KDF\n", + (unsigned int) SLOT_ID); + continue; + } + break; + case CKD_SHA224_KDF: + if (!mech_supported(SLOT_ID, CKM_SHA224)) { + testcase_skip("Slot %u doesn't support CKD_SHA224_KDF\n", + (unsigned int) SLOT_ID); + continue; + } + break; + case CKD_SHA256_KDF: + if (!mech_supported(SLOT_ID, CKM_SHA256)) { + testcase_skip("Slot %u doesn't support CKD_SHA256_KDF\n", + (unsigned int) SLOT_ID); + continue; + } + break; + case CKD_SHA384_KDF: + if (!mech_supported(SLOT_ID, CKM_SHA384)) { + testcase_skip("Slot %u doesn't support CKD_SHA384_KDF\n", + (unsigned int) SLOT_ID); + continue; + } + break; + case CKD_SHA512_KDF: + if (!mech_supported(SLOT_ID, CKM_SHA512)) { + testcase_skip("Slot %u doesn't support CKD_SHA512_KDF\n", + (unsigned int) SLOT_ID); + continue; + } + break; + default: + break; + } for (k=0; k 0 && secret_key_len[k] <= 8) { + /* + * The CEX5P seems to have a firmware bug that hinders it + * from deriving a valid EP11 key blob for a derived key + * size <= 8. Skip this key sizes until the firmware bug + * has been fixed. + */ + testcase_skip("EP11 cannot provide %lu key bytes on a CEX5\n", + secret_key_len[k]); + continue; + } if (secret_key_len[k] == 0 && der_ec_supported[i].type == CURVE_MONTGOMERY) { testcase_skip("Curve %s can not be used without the " @@ -577,7 +679,8 @@ der_ec_supported[i].name, p11_get_ckd(kdfs[j]), secret_key_len[k], shared_data[m].length, - p11_get_ckm(derive_mech_type), pkey); + p11_get_ckm(&mechtable_funcs, derive_mech_type), + pkey); // Now, derive a generic secret key using party A's private // key and B's public key @@ -611,12 +714,25 @@ "versions\n"); continue; } + if (is_rejected_by_policy(rc, session)) { + testcase_skip("key derivation is not allowed by policy"); + continue; + } testcase_fail("C_DeriveKey #1: rc = %s", p11_get_ckr(rc)); goto testcase_cleanup; } + rc = run_HMACSign(session, secret_keyA, + secret_key_len[k] > 0 ? + secret_key_len[k] : curve_len(i)); + if (rc != CKR_OK) { + testcase_fail("Derived key #1 is not usable: %s", + p11_get_ckr(rc)); + goto testcase_cleanup; + } + // Now, derive a generic secret key using B's private key // and A's public key ecdh_parmB.kdf = kdfs[j]; @@ -651,12 +767,27 @@ funcs->C_DestroyObject(session, secret_keyA); continue; } + if (is_rejected_by_policy(rc, session)) { + testcase_skip("key derivation is not allowed by policy"); + if (secret_keyA != CK_INVALID_HANDLE) + funcs->C_DestroyObject(session, secret_keyA); + continue; + } testcase_fail("C_DeriveKey #2: rc = %s", p11_get_ckr(rc)); goto testcase_cleanup; } + rc = run_HMACSign(session, secret_keyB, + secret_key_len[k] > 0 ? + secret_key_len[k] : curve_len(i)); + if (rc != CKR_OK) { + testcase_fail("Derived key #2 is not usable: %s", + p11_get_ckr(rc)); + goto testcase_cleanup; + } + // Extract the derived secret A rc = funcs->C_GetAttributeValue(session, secret_keyA, secretA_tmpl, @@ -704,7 +835,7 @@ der_ec_supported[i].name, p11_get_ckd(kdfs[j]), secret_key_len[k], shared_data[m].length, - p11_get_ckm(derive_mech_type)); + p11_get_ckm(&mechtable_funcs, derive_mech_type)); if (secret_keyA != CK_INVALID_HANDLE) funcs->C_DestroyObject(session, secret_keyA); @@ -798,6 +929,46 @@ testcase_new_assertion(); testcase_begin("Starting with shared secret i=%lu, pkey=%X", i, pkey); + switch (ecdh_tv[i].kdf) { + case CKD_SHA1_KDF: + if (!mech_supported(SLOT_ID, CKM_SHA_1)) { + testcase_skip("Slot %u doesn't support CKD_SHA1_KDF\n", + (unsigned int) SLOT_ID); + continue; + } + break; + case CKD_SHA224_KDF: + if (!mech_supported(SLOT_ID, CKM_SHA224)) { + testcase_skip("Slot %u doesn't support CKD_SHA224_KDF\n", + (unsigned int) SLOT_ID); + continue; + } + break; + case CKD_SHA256_KDF: + if (!mech_supported(SLOT_ID, CKM_SHA256)) { + testcase_skip("Slot %u doesn't support CKD_SHA256_KDF\n", + (unsigned int) SLOT_ID); + continue; + } + break; + case CKD_SHA384_KDF: + if (!mech_supported(SLOT_ID, CKM_SHA384)) { + testcase_skip("Slot %u doesn't support CKD_SHA384_KDF\n", + (unsigned int) SLOT_ID); + continue; + } + break; + case CKD_SHA512_KDF: + if (!mech_supported(SLOT_ID, CKM_SHA512)) { + testcase_skip("Slot %u doesn't support CKD_SHA512_KDF\n", + (unsigned int) SLOT_ID); + continue; + } + break; + default: + break; + } + // First, import the EC key pair for party A rc = create_ECPrivateKey(session, ecdh_tv[i].params, ecdh_tv[i].params_len, @@ -805,6 +976,10 @@ ecdh_tv[i].pubkeyA, ecdh_tv[i].pubkey_len, &priv_keyA, !pkey); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("EC key import is not allowed by policy"); + continue; + } if (rc == CKR_CURVE_NOT_SUPPORTED) { testcase_skip("Slot %u doesn't support this curve: %s", (unsigned int) SLOT_ID, ecdh_tv[i].name); @@ -821,6 +996,11 @@ ecdh_tv[i].pubkeyA, ecdh_tv[i].pubkey_len, &publ_keyA); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("EC key import is not allowed by policy"); + funcs->C_DestroyObject(session, priv_keyA); + continue; + } if (rc == CKR_CURVE_NOT_SUPPORTED) { testcase_skip("Slot %u doesn't support this curve: %s", (unsigned int) SLOT_ID, ecdh_tv[i].name); @@ -911,7 +1091,11 @@ priv_keyA, derive_tmpl, derive_tmpl_len, &secret_keyA); if (rc != CKR_OK) { - if (is_ep11_token(SLOT_ID) && + if (rc == CKR_CURVE_NOT_SUPPORTED) { + testcase_skip("Slot %u doesn't support this curve: %s", + (unsigned int) SLOT_ID, ecdh_tv[i].name); + goto testcase_next; + } else if (is_ep11_token(SLOT_ID) && rc == CKR_MECHANISM_PARAM_INVALID && (ecdh_tv[i].kdf != CKD_NULL || ecdh_tv[i].shared_data_len > 0)) { @@ -1078,7 +1262,7 @@ CK_RV rc; testcase_begin("Starting with mechtype='%s', inputlen=%lu parts=%lu, pkey=%X", - p11_get_ckm(mechType), inputlen, parts, pkey); + p11_get_ckm(&mechtable_funcs, mechType), inputlen, parts, pkey); mech2.mechanism = mechType; mech2.ulParameterLen = 0; @@ -1090,7 +1274,8 @@ if (rc == CKR_MECHANISM_INVALID) { /* no support for EC key gen? skip */ testcase_skip("Slot %u doesn't support %s", - (unsigned int) SLOT_ID, p11_get_ckm(mechType)); + (unsigned int) SLOT_ID, + p11_get_ckm(&mechtable_funcs, mechType)); rc = CKR_OK; goto testcase_cleanup; } else { @@ -1103,7 +1288,7 @@ if (curve_type != CURVE_EDWARDS) { /* Mechanism does not match to curve type, skip */ testcase_skip("Mechanism %s can only be used with Edwards curves", - p11_get_ckm(mechType)); + p11_get_ckm(&mechtable_funcs, mechType)); rc = CKR_OK; goto testcase_cleanup; } @@ -1111,7 +1296,7 @@ memcmp(params, ed25519, MIN(params_len, sizeof(ed25519))) != 0) { /* Mechanism does not match to curve, skip */ testcase_skip("Mechanism %s can only be used with Ed25519 curve", - p11_get_ckm(mechType)); + p11_get_ckm(&mechtable_funcs, mechType)); rc = CKR_OK; goto testcase_cleanup; } @@ -1119,7 +1304,7 @@ memcmp(params, ed448, MIN(params_len, sizeof(ed448))) != 0) { /* Mechanism does not match to curve, skip */ testcase_skip("Mechanism %s can only be used with Ed448 curve", - p11_get_ckm(mechType)); + p11_get_ckm(&mechtable_funcs, mechType)); rc = CKR_OK; goto testcase_cleanup; } @@ -1127,7 +1312,7 @@ if (curve_type == CURVE_EDWARDS || curve_type == CURVE_MONTGOMERY) { /* Mechanism does not match to curve type, skip */ testcase_skip("Mechanism %s can not be used with Edwards/Montogmery curves", - p11_get_ckm(mechType)); + p11_get_ckm(&mechtable_funcs, mechType)); rc = CKR_OK; goto testcase_cleanup; } @@ -1385,6 +1570,10 @@ &publ_key, &priv_key); testcase_new_assertion(); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("EC key generation is not allowed by policy"); + continue; + } if (rc == CKR_MECHANISM_PARAM_INVALID || rc == CKR_ATTRIBUTE_VALUE_INVALID || rc == CKR_CURVE_NOT_SUPPORTED) { @@ -1507,6 +1696,10 @@ testcase_new_assertion(); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("EC key import is not allowed by policy"); + continue; + } if (rc == CKR_CURVE_NOT_SUPPORTED) { testcase_skip("Slot %u doesn't support this curve: %s", (unsigned int) SLOT_ID, ec_tv[i].name); @@ -1536,6 +1729,11 @@ testcase_new_assertion(); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("EC key import is not allowed by policy"); + funcs->C_DestroyObject(session, priv_key); + continue; + } if (rc == CKR_CURVE_NOT_SUPPORTED) { testcase_skip("Slot %u doesn't support this curve: %s", (unsigned int) SLOT_ID, ec_tv[i].name); @@ -1709,6 +1907,10 @@ testcase_new_assertion(); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("EC key import is not allowed by policy"); + continue; + } if (rc == CKR_CURVE_NOT_SUPPORTED) { testcase_skip("Slot %u doesn't support this curve: %s", (unsigned int) SLOT_ID, ec_tv[i].name); @@ -1739,6 +1941,11 @@ testcase_new_assertion(); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("EC key import is not allowed by policy"); + funcs->C_DestroyObject(session, priv_key); + continue; + } if (rc == CKR_CURVE_NOT_SUPPORTED) { testcase_skip("Slot %u doesn't support this curve: %s", (unsigned int) SLOT_ID, ec_tv[i].name); @@ -1772,6 +1979,8 @@ CK_ULONG keylen = 32; CK_BBOOL true = TRUE; CK_BBOOL false = FALSE; + CK_BBOOL sign = TRUE; + CK_BBOOL derive = TRUE; CK_BYTE wrap_key_label[] = "Wrap_Key"; CK_OBJECT_CLASS wclass = CKO_PRIVATE_KEY; CK_KEY_TYPE keyType = CKK_EC; @@ -1782,8 +1991,8 @@ }; CK_ATTRIBUTE cka_unwrap_tmpl[] = { {CKA_DECRYPT, &true, sizeof(true)}, - {CKA_SIGN, &true, sizeof(true)}, - {CKA_DERIVE, &true, sizeof(true)}, + {CKA_SIGN, &sign, sizeof(sign)}, + {CKA_DERIVE, &derive, sizeof(derive)}, {CKA_PRIVATE, &true, sizeof(true)}, {CKA_IBM_PROTKEY_EXTRACTABLE, &true, sizeof(true)}, {CKA_EXTRACTABLE, &false, sizeof(false)}, @@ -1799,6 +2008,11 @@ {CKA_UNWRAP_TEMPLATE, &cka_unwrap_tmpl, sizeof(cka_unwrap_tmpl)}, }; + if (ec_tv[i].curve_type == CURVE_EDWARDS) + derive = FALSE; + if (ec_tv[i].curve_type == CURVE_MONTGOMERY) + sign = FALSE; + rc = funcs->C_GenerateKey(session, &aes_keygen_mech, secret_tmpl, sizeof(secret_tmpl) / sizeof(CK_ATTRIBUTE), &secret_key); @@ -1851,8 +2065,8 @@ {CKA_SUBJECT, subject, sizeof(subject)}, {CKA_ID, id, sizeof(id)}, {CKA_SENSITIVE, &true, sizeof(true)}, - {CKA_DECRYPT, &true, sizeof(true)}, - {CKA_SIGN, &true, sizeof(true)}, + {CKA_DERIVE, &derive, sizeof(derive)}, + {CKA_SIGN, &sign, sizeof(sign)}, {CKA_IBM_PROTKEY_EXTRACTABLE, &true, sizeof(true)}, {CKA_EXTRACTABLE, &false, sizeof(false)}, }; @@ -2024,6 +2238,10 @@ sizeof(priv_tmpl) / sizeof(CK_ATTRIBUTE), &priv_key); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("EC key generation is not allowed by policy"); + continue; + } if (rc == CKR_CURVE_NOT_SUPPORTED) { testcase_skip("Slot %u doesn't support this curve: %s", (unsigned int) SLOT_ID, ec_tv[i].name); @@ -2038,6 +2256,10 @@ sizeof(publ_tmpl) / sizeof(CK_ATTRIBUTE), &publ_key); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("EC key generation is not allowed by policy"); + goto testcase_cleanup; + } testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -2184,6 +2406,5 @@ funcs->C_Finalize(NULL); - /* make sure we return non-zero if rv is non-zero */ - return ((rv == 0) || (rv % 256) ? (int)rv : -1); + return testcase_return(rv); } diff -Nru opencryptoki-3.16.0+dfsg/testcases/crypto/rsa_func.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/crypto/rsa_func.c --- opencryptoki-3.16.0+dfsg/testcases/crypto/rsa_func.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/crypto/rsa_func.c 2022-02-02 15:05:41.000000000 +0100 @@ -24,6 +24,7 @@ #include "pkcs11types.h" #include "common.c" #include "regress.h" +#include "mechtable.h" #include "mech_to_str.h" #include "rsa.h" @@ -75,7 +76,7 @@ // skip tests if the slot doesn't support this mechanism if (!mech_supported(slot_id, tsuite->mech.mechanism)) { testsuite_skip(tsuite->tvcount, - "Slot %u doesn't support %s (%u)", + "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); @@ -102,8 +103,8 @@ if (!keysize_supported(slot_id, tsuite->mech.mechanism, tsuite->tv[i].modbits)) { - testcase_skip("Token in slot %ld cannot be used with " - "modbits.='%ld'", SLOT_ID, tsuite->tv[i].modbits); + testcase_skip("Token in slot %ld cannot be used with modbits.='%ld'", + SLOT_ID, tsuite->tv[i].modbits); free(s); continue; } @@ -111,8 +112,7 @@ if (is_ep11_token(slot_id)) { if (!is_valid_ep11_pubexp(tsuite->tv[i].publ_exp, tsuite->tv[i].publ_exp_len)) { - testcase_skip("EP11 Token cannot " - "be used with publ_exp.='%s'", s); + testcase_skip("EP11 Token cannot be used with publ_exp.='%s'", s); free(s); continue; } @@ -124,8 +124,7 @@ if (is_cca_token(slot_id)) { if (!is_valid_cca_pubexp(tsuite->tv[i].publ_exp, tsuite->tv[i].publ_exp_len)) { - testcase_skip("CCA Token cannot " - "be used with publ_exp.='%s'", s); + testcase_skip("CCA Token cannot be used with publ_exp.='%s'", s); free(s); continue; } @@ -148,6 +147,16 @@ continue; } } + + if (is_soft_token(slot_id)) { + if (!is_valid_soft_pubexp(tsuite->tv[i].publ_exp, + tsuite->tv[i].publ_exp_len)) { + testcase_skip("Soft Token cannot be used with publ_exp.='%s'", + s); + free(s); + continue; + } + } // tpm special cases: // tpm token can only use public exponent 0x010001 (65537) // so skip test if invalid public exponent is used @@ -155,8 +164,7 @@ if ((!is_valid_tpm_pubexp(tsuite->tv[i].publ_exp, tsuite->tv[i].publ_exp_len)) || (!is_valid_tpm_modbits(tsuite->tv[i].modbits))) { - testcase_skip("TPM Token cannot " "be used with publ_exp.='%s'", - s); + testcase_skip("TPM Token cannot be used with publ_exp.='%s'", s); free(s); continue; } @@ -166,8 +174,7 @@ if (!is_valid_icsf_pubexp(tsuite->tv[i].publ_exp, tsuite->tv[i].publ_exp_len) || (tsuite->tv[i].modbits < 1024)) { - testcase_skip("ICSF Token cannot be used with " - "publ_exp='%s'.", s); + testcase_skip("ICSF Token cannot be used with publ_exp='%s'.", s); free(s); continue; } @@ -191,6 +198,11 @@ &publ_key, &priv_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("RSA key generation is not allowed by policy"); + continue; + } + testcase_error("generate_RSA_PKCS_KeyPair(), " "rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; @@ -349,7 +361,7 @@ // skip tests if the slot doesn't support this mechanism if (!mech_supported(slot_id, tsuite->mech.mechanism)) { testsuite_skip(tsuite->tvcount, - "Slot %u doesn't support %s (%u)", + "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); @@ -376,8 +388,8 @@ if (!keysize_supported(slot_id, tsuite->mech.mechanism, tsuite->tv[i].mod_len * 8)) { - testcase_skip("Token in slot %ld cannot be used with " - "modbits.='%ld'", SLOT_ID, tsuite->tv[i].mod_len * 8); + testcase_skip("Token in slot %ld cannot be used with modbits.='%ld'", + SLOT_ID, tsuite->tv[i].mod_len * 8); free(s); continue; } @@ -385,16 +397,14 @@ if (is_ep11_token(slot_id)) { if (!is_valid_ep11_pubexp(tsuite->tv[i].pub_exp, tsuite->tv[i].pubexp_len)) { - testcase_skip("EP11 Token cannot " - "be used with publ_exp.='%s'", s); + testcase_skip("EP11 Token cannot be used with publ_exp.='%s'", s); free(s); continue; } // modulus length must be multiple of 128 byte // skip test if modulus length has unsuported size if ((tsuite->tv[i].mod_len % 128) != 0) { - testcase_skip("EP11 Token cannot be used with " - "this test vector."); + testcase_skip("EP11 Token cannot be used with this test vector."); free(s); continue; } @@ -416,8 +426,7 @@ (tsuite->tv[i].exp2_len > (tsuite->tv[i].mod_len / 2)) || (tsuite->tv[i].coef_len > (tsuite->tv[i].mod_len / 2))) { - testcase_skip("ICA Token cannot be used with " - "this test vector."); + testcase_skip("ICA Token cannot be used with this test vector."); free(s); continue; } @@ -431,12 +440,21 @@ if (is_cca_token(slot_id)) { if (!is_valid_cca_pubexp(tsuite->tv[i].pub_exp, tsuite->tv[i].pubexp_len)) { - testcase_skip("CCA Token cannot " - "be used with publ_exp.='%s'", s); + testcase_skip("CCA Token cannot be used with publ_exp.='%s'", s); free(s); continue; } } + + if (is_soft_token(slot_id)) { + if (!is_valid_soft_pubexp(tsuite->tv[i].pub_exp, + tsuite->tv[i].pubexp_len)) { + testcase_skip("Soft Token cannot be used with publ_exp.='%s'", s); + free(s); + continue; + } + } + // tpm special cases: // tpm token can only use public exponent 0x010001 (65537) // so skip test if invalid public exponent is used @@ -444,8 +462,7 @@ if ((!is_valid_tpm_pubexp(tsuite->tv[i].pub_exp, tsuite->tv[i].pubexp_len)) || (!is_valid_tpm_modbits(tsuite->tv[i].mod_len * 8))) { - testcase_skip("TPM Token cannot " "be used with publ_exp.='%s'", - s); + testcase_skip("TPM Token cannot be used with publ_exp.='%s'", s); free(s); continue; } @@ -455,8 +472,7 @@ if (!is_valid_icsf_pubexp(tsuite->tv[i].pub_exp, tsuite->tv[i].pubexp_len) || (tsuite->tv[i].mod_len * 8 < 1024)) { - testcase_skip("ICSF Token cannot be used with " - "publ_exp='%s'.", s); + testcase_skip("ICSF Token cannot be used with publ_exp='%s'.", s); free(s); continue; } @@ -490,6 +506,11 @@ tsuite->tv[i].exp2_len, tsuite->tv[i].coef_len, &priv_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("RSA key import is not allowed by policy"); + continue; + } + testcase_error("create_RSAPrivateKey(), rc=%s", p11_get_ckr(rc)); goto error; } @@ -501,6 +522,12 @@ tsuite->tv[i].mod_len, tsuite->tv[i].pubexp_len, &publ_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("RSA key import is not allowed by policy"); + funcs->C_DestroyObject(session, priv_key); + continue; + } + testcase_error("create_RSAPublicKey(), rc=%s", p11_get_ckr(rc)); goto error; } @@ -655,7 +682,7 @@ // skip tests if the slot doesn't support this mechanism if (!mech_supported(slot_id, tsuite->mech.mechanism)) { testsuite_skip(tsuite->tvcount, - "Slot %u doesn't support %s (%u)", + "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); @@ -665,7 +692,7 @@ if (!mech_supported_flags(slot_id, tsuite->mech.mechanism, CKF_SIGN_RECOVER | CKF_VERIFY_RECOVER)) { testsuite_skip(tsuite->tvcount, - "Slot %u doesn't support Sign/VerifyRecover with %s (%u)", + "Slot %u doesn't support Sign/VerifyRecover with %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); @@ -691,8 +718,8 @@ if (!keysize_supported(slot_id, tsuite->mech.mechanism, tsuite->tv[i].modbits)) { - testcase_skip("Token in slot %ld cannot be used with " - "modbits.='%ld'", SLOT_ID, tsuite->tv[i].modbits); + testcase_skip("Token in slot %ld cannot be used with modbits.='%ld'", + SLOT_ID, tsuite->tv[i].modbits); free(s); continue; } @@ -700,8 +727,7 @@ if (is_ep11_token(slot_id)) { if (!is_valid_ep11_pubexp(tsuite->tv[i].publ_exp, tsuite->tv[i].publ_exp_len)) { - testcase_skip("EP11 Token cannot " - "be used with publ_exp.='%s'", s); + testcase_skip("EP11 Token cannot be used with publ_exp.='%s'", s); free(s); continue; } @@ -710,8 +736,16 @@ if (is_cca_token(slot_id)) { if (!is_valid_cca_pubexp(tsuite->tv[i].publ_exp, tsuite->tv[i].publ_exp_len)) { - testcase_skip("CCA Token cannot " - "be used with publ_exp='%s'.", s); + testcase_skip("CCA Token cannot be used with publ_exp='%s'.", s); + free(s); + continue; + } + } + + if (is_soft_token(slot_id)) { + if (!is_valid_soft_pubexp(tsuite->tv[i].publ_exp, + tsuite->tv[i].publ_exp_len)) { + testcase_skip("Soft Token cannot be used with publ_exp='%s'.", s); free(s); continue; } @@ -721,8 +755,7 @@ if ((!is_valid_tpm_pubexp(tsuite->tv[i].publ_exp, tsuite->tv[i].publ_exp_len)) || (!is_valid_tpm_modbits(tsuite->tv[i].modbits))) { - testcase_skip("TPM Token cannot " "be used with publ_exp='%s'.", - s); + testcase_skip("TPM Token cannot be used with publ_exp='%s'.", s); free(s); continue; } @@ -732,8 +765,7 @@ if (!is_valid_icsf_pubexp(tsuite->tv[i].publ_exp, tsuite->tv[i].publ_exp_len) || (tsuite->tv[i].modbits < 1024)) { - testcase_skip("ICSF Token cannot be used with " - "publ_exp='%s'.", s); + testcase_skip("ICSF Token cannot be used with publ_exp='%s'.", s); free(s); continue; } @@ -758,6 +790,11 @@ tsuite->tv[i].publ_exp_len, &publ_key, &priv_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("RSA key generation is not allowed by policy"); + continue; + } + testcase_error("generate_RSA_PKCS_KeyPair(), " "rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; @@ -920,7 +957,7 @@ // skip tests if the slot doesn't support this mechanism if (!mech_supported(slot_id, tsuite->mech.mechanism)) { testsuite_skip(tsuite->tvcount, - "Slot %u doesn't support %s (%u)", + "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); @@ -944,16 +981,23 @@ if (!keysize_supported(slot_id, tsuite->mech.mechanism, tsuite->tv[i].modbits)) { - testcase_skip("Token in slot %ld cannot be used with " - "modbits.='%ld'", SLOT_ID, tsuite->tv[i].modbits); + testcase_skip("Token in slot %ld cannot be used with modbits.='%ld'", + SLOT_ID, tsuite->tv[i].modbits); free(s); continue; } if (is_cca_token(slot_id)) { if (!is_valid_cca_pubexp(tsuite->tv[i].publ_exp, tsuite->tv[i].publ_exp_len)) { - testcase_skip("CCA Token cannot " - "be used with publ_exp='%s'.", s); + testcase_skip("CCA Token cannot be used with publ_exp='%s'.", s); + free(s); + continue; + } + } + if (is_soft_token(slot_id)) { + if (!is_valid_soft_pubexp(tsuite->tv[i].publ_exp, + tsuite->tv[i].publ_exp_len)) { + testcase_skip("Soft Token cannot be used with publ_exp='%s'.", s); free(s); continue; } @@ -976,6 +1020,11 @@ tsuite->tv[i].publ_exp_len, &publ_key, &priv_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("RSA key generation is not allowed by policy"); + continue; + } + testcase_error("generate_RSA_PKCS_KeyPair(), " "rc=%s", p11_get_ckr(rc)); goto error; @@ -993,6 +1042,14 @@ h_len = MAX_HASH_SIZE; + if (!mech_supported(slot_id, mech.mechanism)) { + testcase_skip("Slot %u doesn't support %s (0x%x)", + (unsigned int)slot_id, + mech_to_str(mech.mechanism), + (unsigned int)mech.mechanism); + goto cleanup; + } + rc = funcs->C_DigestInit(session, &mech); if (rc != CKR_OK) { testcase_error("C_DigestInit rc=%s", p11_get_ckr(rc)); @@ -1050,6 +1107,7 @@ else testcase_fail("C_Verify(), rc=%s", p11_get_ckr(rc)); +cleanup: // clean up rc = funcs->C_DestroyObject(session, publ_key); if (rc != CKR_OK) { @@ -1129,7 +1187,7 @@ // skip all tests if the slot doesn't support this mechanism if (!mech_supported(slot_id, tsuite->mech.mechanism)) { testsuite_skip(tsuite->tvcount, - "Slot %u doesn't support %s (%u)", + "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); @@ -1145,7 +1203,7 @@ for (i = 0; i < tsuite->tvcount; i++) { // skip if the slot doesn't support the keygen mechanism if (!mech_supported(slot_id, tsuite->tv[i].keytype.mechanism)) { - testcase_skip("Slot %u doesn't support %s (%u)", + testcase_skip("Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->tv[i].keytype.mechanism), (unsigned int) tsuite->tv[i].keytype.mechanism); @@ -1154,8 +1212,8 @@ if (!keysize_supported(slot_id, tsuite->mech.mechanism, tsuite->tv[i].modbits)) { - testcase_skip("Token in slot %ld cannot be used with " - "modbits.='%ld'", SLOT_ID, tsuite->tv[i].modbits); + testcase_skip("Token in slot %ld cannot be used with modbits.='%ld'", + SLOT_ID, tsuite->tv[i].modbits); continue; } // get public exponent from test vector @@ -1169,8 +1227,7 @@ if (is_ep11_token(slot_id)) { if (!is_valid_ep11_pubexp(tsuite->tv[i].publ_exp, tsuite->tv[i].publ_exp_len)) { - testcase_skip("EP11 Token cannot " - "be used with publ_exp.='%s'", s); + testcase_skip("EP11 Token cannot be used with publ_exp.='%s'", s); free(s); continue; } @@ -1179,8 +1236,7 @@ if (!is_valid_icsf_pubexp(tsuite->tv[i].publ_exp, tsuite->tv[i].publ_exp_len) || (tsuite->tv[i].modbits < 1024)) { - testcase_skip("ICSF Token cannot be used with " - "publ_exp='%s'.", s); + testcase_skip("ICSF Token cannot be used with publ_exp='%s'.", s); free(s); continue; } @@ -1189,8 +1245,7 @@ if ((!is_valid_tpm_pubexp(tsuite->tv[i].publ_exp, tsuite->tv[i].publ_exp_len)) || (!is_valid_tpm_modbits(tsuite->tv[i].modbits))) { - testcase_skip("TPM Token cannot " "be used with publ_exp.='%s'", - s); + testcase_skip("TPM Token cannot be used with publ_exp.='%s'", s); free(s); continue; } @@ -1198,8 +1253,7 @@ if (is_cca_token(slot_id)) { if (!is_valid_cca_pubexp(tsuite->tv[i].publ_exp, tsuite->tv[i].publ_exp_len)) { - testcase_skip("CCA Token cannot " - "be used with publ_exp='%s'.", s); + testcase_skip("CCA Token cannot be used with publ_exp='%s'.", s); free(s); continue; } @@ -1228,13 +1282,22 @@ continue; } } + if (is_soft_token(slot_id)) { + if (!is_valid_soft_pubexp(tsuite->tv[i].publ_exp, + tsuite->tv[i].publ_exp_len)) { + testcase_skip("Soft Token cannot be used with publ_exp='%s'.", s); + free(s); + continue; + } + } // begin test testcase_begin("%s Wrap Unwrap with test vector %d, " "\npubl_exp='%s', mod_bits='%lu', keylen='%lu', " "keytype='%s'", tsuite->name, i, s, tsuite->tv[i].modbits, tsuite->tv[i].keylen, - p11_get_ckm(tsuite->tv[i].keytype.mechanism)); + p11_get_ckm(&mechtable_funcs, + tsuite->tv[i].keytype.mechanism)); // free memory if (s) @@ -1243,6 +1306,13 @@ // get key gen mechanism keygen_mech = tsuite->tv[i].keytype; + if (!mech_supported(slot_id, keygen_mech.mechanism)) { + testcase_skip("Slot %u doesn't support %s (0x%x)", + (unsigned int)slot_id, + mech_to_str(keygen_mech.mechanism), + (unsigned int)keygen_mech.mechanism); + continue; + } // get wrapping mechanism wrap_mech = tsuite->mech; if (wrap_mech.mechanism == CKM_RSA_PKCS_OAEP) { @@ -1250,6 +1320,15 @@ wrap_mech.pParameter = &oaep_params; wrap_mech.ulParameterLen = sizeof(CK_RSA_PKCS_OAEP_PARAMS); } + + if (!mech_supported(slot_id, wrap_mech.mechanism)) { + testcase_skip("Slot %u doesn't support %s (0x%x)", + (unsigned int)slot_id, + mech_to_str(wrap_mech.mechanism), + (unsigned int)wrap_mech.mechanism); + continue; + } + // clear out buffers memset(cipher, 0, sizeof(cipher)); memset(re_cipher, 0, sizeof(re_cipher)); @@ -1263,6 +1342,11 @@ tsuite->tv[i].publ_exp_len, &publ_key, &priv_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("RSA key generation is not allowed by policy"); + continue; + } + testcase_error("C_GenerateKeyPair() rc = %s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -1270,6 +1354,11 @@ rc = generate_SecretKey(session, tsuite->tv[i].keylen, &keygen_mech, &secret_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("Generic secret key generation is not allowed by policy"); + funcs->C_DestroyObject(session, priv_key); + continue; + } testcase_error("generate_SecretKey(), rc=%s", p11_get_ckr(rc)); goto error; } @@ -1323,7 +1412,7 @@ } if (!mech_supported(slot_id, mech.mechanism)) { - testcase_skip("Slot %u doesn't support %s (%u)", + testcase_skip("Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(mech.mechanism), (unsigned int)mech.mechanism); @@ -1526,7 +1615,7 @@ // skip tests if the slot doesn't support this mechanism **/ if (!mech_supported(slot_id, tsuite->mech.mechanism)) { testsuite_skip(tsuite->tvcount, - "Slot %u doesn't support %s (%u)", + "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); @@ -1554,8 +1643,7 @@ (tsuite->tv[i].exp2_len > (tsuite->tv[i].mod_len / 2)) || (tsuite->tv[i].coef_len > (tsuite->tv[i].mod_len / 2))) { - testcase_skip("ICA Token cannot be used with " - "this test vector."); + testcase_skip("ICA Token cannot be used with this test vector."); continue; } @@ -1565,8 +1653,7 @@ // skip test if modulus length has unsuported size if (is_ep11_token(slot_id)) { if ((tsuite->tv[i].mod_len % 128) != 0) { - testcase_skip("EP11 Token cannot be used with " - "this test vector."); + testcase_skip("EP11 Token cannot be used with this test vector."); continue; } } @@ -1575,8 +1662,7 @@ if ((!is_valid_tpm_pubexp(tsuite->tv[i].pub_exp, tsuite->tv[i].pubexp_len)) || (!is_valid_tpm_modbits(tsuite->tv[i].mod_len))) { - testcase_skip("TPM Token cannot " - "be used with this test vector."); + testcase_skip("TPM Token cannot be used with this test vector."); continue; } } @@ -1584,8 +1670,15 @@ if (is_cca_token(slot_id)) { if (!is_valid_cca_pubexp(tsuite->tv[i].pub_exp, tsuite->tv[i].pubexp_len)) { - testcase_skip("CCA Token cannot " - "be used with this test vector."); + testcase_skip("CCA Token cannot be used with this test vector."); + continue; + } + } + + if (is_soft_token(slot_id)) { + if (!is_valid_soft_pubexp(tsuite->tv[i].pub_exp, + tsuite->tv[i].pubexp_len)) { + testcase_skip("Soft Token cannot be used with this test vector."); continue; } } @@ -1624,6 +1717,11 @@ tsuite->tv[i].exp2_len, tsuite->tv[i].coef_len, &priv_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("RSA key import is not allowed by policy"); + continue; + } + testcase_error("create_RSAPrivateKey(), rc=%s", p11_get_ckr(rc)); goto error; } @@ -1717,7 +1815,7 @@ // skip tests if the slot doesn't support this mechanism if (!mech_supported(slot_id, tsuite->mech.mechanism)) { testsuite_skip(tsuite->tvcount, - "Slot %u doesn't support %s (%u)", + "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); @@ -1735,8 +1833,7 @@ // skip test if modulus length has unsuported size if (is_ep11_token(slot_id)) { if ((tsuite->tv[i].mod_len % 128) != 0) { - testcase_skip("EP11 Token cannot be used with " - "this test vector."); + testcase_skip("EP11 Token cannot be used with this test vector."); continue; } } @@ -1745,8 +1842,7 @@ if ((!is_valid_tpm_pubexp(tsuite->tv[i].pub_exp, tsuite->tv[i].pubexp_len)) || (!is_valid_tpm_modbits(tsuite->tv[i].mod_len))) { - testcase_skip("TPM Token cannot " - "be used with this test vector."); + testcase_skip("TPM Token cannot be used with this test vector."); continue; } } @@ -1754,8 +1850,15 @@ if (is_cca_token(slot_id)) { if (!is_valid_cca_pubexp(tsuite->tv[i].pub_exp, tsuite->tv[i].pubexp_len)) { - testcase_skip("CCA Token cannot " - "be used with this test vector."); + testcase_skip("CCA Token cannot be used with this test vector."); + continue; + } + } + + if (is_soft_token(slot_id)) { + if (!is_valid_soft_pubexp(tsuite->tv[i].pub_exp, + tsuite->tv[i].pubexp_len)) { + testcase_skip("Soft Token cannot be used with this test vector."); continue; } } @@ -1781,6 +1884,11 @@ tsuite->tv[i].pubexp_len, &publ_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("RSA key import is not allowed by policy"); + continue; + } + testcase_error("create_RSAPublicKey(), rc=%s", p11_get_ckr(rc)); goto error; } @@ -1947,5 +2055,5 @@ funcs->C_Finalize(NULL); - return rv; + return testcase_return(rv); } diff -Nru opencryptoki-3.16.0+dfsg/testcases/crypto/rsaupdate_func.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/crypto/rsaupdate_func.c --- opencryptoki-3.16.0+dfsg/testcases/crypto/rsaupdate_func.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/crypto/rsaupdate_func.c 2022-02-02 15:05:41.000000000 +0100 @@ -71,7 +71,7 @@ // skip tests if the slot doesn't support this mechanism if (!mech_supported(slot_id, tsuite->mech.mechanism)) { testsuite_skip(tsuite->tvcount, - "Slot %u doesn't support %s (%u)", + "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); @@ -96,8 +96,8 @@ if (!keysize_supported(slot_id, tsuite->mech.mechanism, tsuite->tv[i].modbits)) { - testcase_skip("Token in slot %ld cannot be used with " - "modbits.='%ld'", SLOT_ID, tsuite->tv[i].modbits); + testcase_skip("Token in slot %ld cannot be used with modbits.='%ld'", + SLOT_ID, tsuite->tv[i].modbits); free(s); continue; } @@ -105,8 +105,7 @@ if (is_ep11_token(slot_id)) { if (!is_valid_ep11_pubexp(tsuite->tv[i].publ_exp, tsuite->tv[i].publ_exp_len)) { - testcase_skip("EP11 Token cannot " - "be used with publ_exp.='%s'", s); + testcase_skip("EP11 Token cannot be used with publ_exp.='%s'", s); free(s); continue; } @@ -115,19 +114,27 @@ if (is_cca_token(slot_id)) { if (!is_valid_cca_pubexp(tsuite->tv[i].publ_exp, tsuite->tv[i].publ_exp_len)) { - testcase_skip("CCA Token cannot " - "be used with publ_exp='%s'.", s); + testcase_skip("CCA Token cannot be used with publ_exp='%s'.", s); free(s); continue; } } + if (is_soft_token(slot_id)) { + if (!is_valid_soft_pubexp(tsuite->tv[i].publ_exp, + tsuite->tv[i].publ_exp_len)) { + testcase_skip("Soft Token cannot be used with publ_exp='%s'.", s); + free(s); + continue; + } + } + + if (is_tpm_token(slot_id)) { if ((!is_valid_tpm_pubexp(tsuite->tv[i].publ_exp, tsuite->tv[i].publ_exp_len)) || (!is_valid_tpm_modbits(tsuite->tv[i].modbits))) { - testcase_skip("TPM Token cannot " "be used with publ_exp='%s'.", - s); + testcase_skip("TPM Token cannot be used with publ_exp='%s'.", s); free(s); continue; } @@ -137,8 +144,7 @@ if (!is_valid_icsf_pubexp(tsuite->tv[i].publ_exp, tsuite->tv[i].publ_exp_len) || (tsuite->tv[i].modbits < 1024)) { - testcase_skip("ICSF Token cannot " - "be used with publ_exp='%s'.", s); + testcase_skip("ICSF Token cannot be used with publ_exp='%s'.", s); free(s); continue; } @@ -162,8 +168,12 @@ tsuite->tv[i].publ_exp_len, &publ_key, &priv_key); if (rc != CKR_OK) { - testcase_error("generate_RSA_PKCS_KeyPair(), " - "rc=%s", p11_get_ckr(rc)); + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("RSA key generation is not allowed by policy"); + continue; + } + + testcase_error("generate_RSA_PKCS_KeyPair(), rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -343,7 +353,7 @@ // skip tests if the slot doesn't support this mechanism if (!mech_supported(slot_id, tsuite->mech.mechanism)) { testsuite_skip(tsuite->tvcount, - "Slot %u doesn't support %s (%u)", + "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); @@ -367,8 +377,8 @@ if (!keysize_supported(slot_id, tsuite->mech.mechanism, tsuite->tv[i].modbits)) { - testcase_skip("Token in slot %ld cannot be used with " - "modbits.='%ld'", SLOT_ID, tsuite->tv[i].modbits); + testcase_skip("Token in slot %ld cannot be used with modbits.='%ld'", + SLOT_ID, tsuite->tv[i].modbits); free(s); continue; } @@ -376,8 +386,7 @@ if (is_ep11_token(slot_id)) { if (!is_valid_ep11_pubexp(tsuite->tv[i].publ_exp, tsuite->tv[i].publ_exp_len)) { - testcase_skip("EP11 Token cannot " - "be used with publ_exp.='%s'", s); + testcase_skip("EP11 Token cannot be used with publ_exp.='%s'", s); free(s); continue; } @@ -386,8 +395,16 @@ if (is_cca_token(slot_id)) { if (!is_valid_cca_pubexp(tsuite->tv[i].publ_exp, tsuite->tv[i].publ_exp_len)) { - testcase_skip("CCA Token cannot " - "be used with publ_exp='%s'.", s); + testcase_skip("CCA Token cannot be used with publ_exp='%s'.", s); + free(s); + continue; + } + } + + if (is_soft_token(slot_id)) { + if (!is_valid_soft_pubexp(tsuite->tv[i].publ_exp, + tsuite->tv[i].publ_exp_len)) { + testcase_skip("Soft Token cannot be used with publ_exp='%s'.", s); free(s); continue; } @@ -412,8 +429,12 @@ tsuite->tv[i].publ_exp_len, &publ_key, &priv_key); if (rc != CKR_OK) { - testcase_error("generate_RSA_PKCS_KeyPair(), " - "rc=%s", p11_get_ckr(rc)); + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("RSA key generation is not allowed by policy"); + continue; + } + + testcase_error("generate_RSA_PKCS_KeyPair(), rc=%s", p11_get_ckr(rc)); goto error; } // generate message @@ -606,7 +627,7 @@ // skip tests if the slot doesn't support this mechanism if (!mech_supported(slot_id, tsuite->mech.mechanism)) { testsuite_skip(tsuite->tvcount, - "Slot %u doesn't support %s (%u)", + "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); @@ -639,8 +660,7 @@ if (is_ep11_token(slot_id)) { if (!is_valid_ep11_pubexp(tsuite->tv[i].pub_exp, tsuite->tv[i].pubexp_len)) { - testcase_skip("EP11 Token cannot " - "be used with pub_exp.='%s'", s); + testcase_skip("EP11 Token cannot be used with pub_exp.='%s'", s); free(s); continue; } @@ -650,8 +670,7 @@ if ((!is_valid_tpm_pubexp(tsuite->tv[i].pub_exp, tsuite->tv[i].pubexp_len)) || (!is_valid_tpm_modbits(tsuite->tv[i].mod_len))) { - testcase_skip("TPM Token cannot " - "be used with pub_exp='%s'.", s); + testcase_skip("TPM Token cannot be used with pub_exp='%s'.", s); free(s); continue; } @@ -660,8 +679,16 @@ if (is_cca_token(slot_id)) { if (!is_valid_cca_pubexp(tsuite->tv[i].pub_exp, tsuite->tv[i].pubexp_len)) { - testcase_skip("CCA Token cannot " - "be used with publ_exp='%s'.", s); + testcase_skip("CCA Token cannot be used with publ_exp='%s'.", s); + free(s); + continue; + } + } + + if (is_soft_token(slot_id)) { + if (!is_valid_soft_pubexp(tsuite->tv[i].pub_exp, + tsuite->tv[i].pubexp_len)) { + testcase_skip("Soft Token cannot be used with publ_exp='%s'.", s); free(s); continue; } @@ -693,6 +720,11 @@ tsuite->tv[i].pubexp_len, &publ_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("RSA key import is not allowed by policy"); + continue; + } + testcase_error("create_RSAPublicKey(), rc=%s", p11_get_ckr(rc)); goto error; } @@ -794,7 +826,7 @@ // skip tests if the slot doesn't support this mechanism **/ if (!mech_supported(slot_id, tsuite->mech.mechanism)) { testsuite_skip(tsuite->tvcount, - "Slot %u doesn't support %s (%u)", + "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); @@ -826,8 +858,7 @@ (tsuite->tv[i].exp2_len > (tsuite->tv[i].mod_len / 2)) || (tsuite->tv[i].coef_len > (tsuite->tv[i].mod_len / 2))) { - testcase_skip("ICA Token cannot be used with " - "this test vector."); + testcase_skip("ICA Token cannot be used with this test vector."); free(s); continue; } @@ -848,8 +879,7 @@ if (is_ep11_token(slot_id)) { if (!is_valid_ep11_pubexp(tsuite->tv[i].pub_exp, tsuite->tv[i].pubexp_len)) { - testcase_skip("EP11 Token cannot " - "be used with publ_exp.='%s'", s); + testcase_skip("EP11 Token cannot be used with publ_exp.='%s'", s); free(s); continue; } @@ -859,8 +889,7 @@ if ((!is_valid_tpm_pubexp(tsuite->tv[i].pub_exp, tsuite->tv[i].pubexp_len)) || (!is_valid_tpm_modbits(tsuite->tv[i].mod_len))) { - testcase_skip("TPM Token cannot " - "be used with pub_exp='%s'.", s); + testcase_skip("TPM Token cannot be used with pub_exp='%s'.", s); free(s); continue; } @@ -869,8 +898,16 @@ if (is_cca_token(slot_id)) { if (!is_valid_cca_pubexp(tsuite->tv[i].pub_exp, tsuite->tv[i].pubexp_len)) { - testcase_skip("CCA Token cannot " - "be used with publ_exp='%s'.", s); + testcase_skip("CCA Token cannot be used with publ_exp='%s'.", s); + free(s); + continue; + } + } + + if (is_soft_token(slot_id)) { + if (!is_valid_soft_pubexp(tsuite->tv[i].pub_exp, + tsuite->tv[i].pubexp_len)) { + testcase_skip("Soft Token cannot be used with publ_exp='%s'.", s); free(s); continue; } @@ -916,6 +953,11 @@ tsuite->tv[i].exp2_len, tsuite->tv[i].coef_len, &priv_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("RSA key import is not allowed by policy"); + continue; + } + testcase_error("create_RSAPrivateKey(), rc=%s", p11_get_ckr(rc)); goto error; } @@ -1097,5 +1139,5 @@ funcs->C_Finalize(NULL); - return rv; + return testcase_return(rv); } diff -Nru opencryptoki-3.16.0+dfsg/testcases/crypto/ssl3_func.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/crypto/ssl3_func.c --- opencryptoki-3.16.0+dfsg/testcases/crypto/ssl3_func.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/crypto/ssl3_func.c 2022-02-02 15:05:41.000000000 +0100 @@ -61,7 +61,7 @@ /** skip test if the slot doesn't support this mechanism **/ if (!mech_supported(slot_id, mech.mechanism)) { - testsuite_skip(48, "Slot %u doesn't support %s (%u)", + testsuite_skip(48, "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(mech.mechanism), (unsigned int) mech.mechanism); @@ -76,6 +76,10 @@ rc = funcs->C_CreateObject(session, key_attribs, 4, &h_key); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("key import is not allowed by policy"); + return CKR_OK; + } testcase_error("C_CreateObject() rc = %s", p11_get_ckr(rc)); return rc; } @@ -230,7 +234,7 @@ /** skip test if the slot doesn't support this mechanism **/ if (!mech_supported(slot_id, mech.mechanism)) { - testsuite_skip(48, "Slot %u doesn't support %s (%u)", + testsuite_skip(48, "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(mech.mechanism), (unsigned int) mech.mechanism); @@ -245,6 +249,10 @@ rc = funcs->C_CreateObject(session, key_attribs, 4, &h_key); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("key import is not allowed by policy"); + return CKR_OK; + } testcase_error("C_CreateObject() rc = %s", p11_get_ckr(rc)); return rc; } @@ -313,7 +321,7 @@ /** skip test if the slot doesn't support this mechanism **/ if (!mech_supported(slot_id, mech.mechanism)) { - testsuite_skip(1, "Slot %u doesn't support %s (%u)", + testsuite_skip(1, "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(mech.mechanism), (unsigned int) mech.mechanism); @@ -322,10 +330,15 @@ testcase_new_assertion(); rc = funcs->C_GenerateKey(session, &mech, NULL, 0, &h_key); - if (rc != CKR_OK) + if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("key generation is not allowed by policy"); + return CKR_OK; + } testcase_fail("C_GenerateKey() rc = %s", p11_get_ckr(rc)); - else + } else { testcase_pass("Successfully generated a generic secret key."); + } if (funcs->C_DestroyObject(session, h_key) != CKR_OK) testcase_error("C_DestroyObject() failed"); @@ -378,7 +391,7 @@ /** skip test if the slot doesn't support this mechanism **/ if (!mech_supported(slot_id, mech.mechanism)) { - testsuite_skip(32, "Slot %u doesn't support %s (%u)", + testsuite_skip(32, "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(mech.mechanism), (unsigned int) mech.mechanism); @@ -388,6 +401,10 @@ testcase_new_assertion(); rc = funcs->C_GenerateKey(session, &mech, pm_tmpl, 2, &h_pm_secret); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("key generation is not allowed by policy"); + return CKR_OK; + } testcase_fail("C_GenerateKey() rc= %s", p11_get_ckr(rc)); goto done; } else { @@ -416,6 +433,10 @@ testcase_new_assertion(); rc = funcs->C_DeriveKey(session, &mech, h_pm_secret, m_tmpl, 2, &h_mk); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("Key derivation is not allowed by policy"); + goto done; + } testcase_fail("C_DeriveKey() rc= %s", p11_get_ckr(rc)); goto done; } else { @@ -530,7 +551,7 @@ /** skip test if the slot doesn't support this mechanism **/ if (!mech_supported(slot_id, mech.mechanism)) { - testsuite_skip(3, "Slot %u doesn't support %s (%u)", + testsuite_skip(3, "Slot %u doesn't support %s (0x%x)", (unsigned int) slot_id, mech_to_str(mech.mechanism), (unsigned int) mech.mechanism); @@ -541,6 +562,10 @@ rc = funcs->C_GenerateKey(session, &mech, pm_tmpl, sizeof(pm_tmpl) / sizeof(*pm_tmpl), &h_pm_secret); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("Key generation is not allowed by policy"); + goto done; + } testcase_fail("C_GenerateKey() rc= %s", p11_get_ckr(rc)); goto done; } else { @@ -563,6 +588,10 @@ rc = funcs->C_DeriveKey(session, &mech, h_pm_secret, incomplete_tmpl, sizeof(incomplete_tmpl) / sizeof(*incomplete_tmpl), NULL); + if (is_rejected_by_policy(rc, session)) { + testcase_skip("key derivation is not allowed by policy"); + goto done; + } if (rc != CKR_TEMPLATE_INCOMPLETE) { testcase_fail("C_DeriveKey did not recognize missing attributes."); goto done; @@ -580,6 +609,10 @@ sizeof(complete_tmpl) / sizeof(*complete_tmpl), NULL); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("key derivation is not allowed by policy"); + goto done; + } testcase_fail("C_DeriveKey() rc= %s", p11_get_ckr(rc)); goto done; } else { @@ -709,6 +742,5 @@ funcs->C_Finalize(NULL); - /* make sure we return non-zero if rv is non-zero */ - return ((rv == 0) || (rv % 256) ? (int)rv : -1); + return testcase_return(rv); } diff -Nru opencryptoki-3.16.0+dfsg/testcases/include/mech_to_str.h opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/include/mech_to_str.h --- opencryptoki-3.16.0+dfsg/testcases/include/mech_to_str.h 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/include/mech_to_str.h 2022-02-02 15:05:41.000000000 +0100 @@ -11,489 +11,14 @@ #ifndef _MECH_TO_STR_ #define _MECH_TO_STR_ #include "pkcs11types.h" +#include -/* - * List generate with: - * - * grep CKM_ ../../usr/include/pkcs11/pkcs11types.h | - * awk '/^#/ { printf("\tif (mech == %s)\n\t\treturn \"%s\";\n", $2, $2); }' - * - */ static inline const char *mech_to_str(CK_ULONG mech) { - if (mech == CKM_RSA_PKCS_KEY_PAIR_GEN) - return "CKM_RSA_PKCS_KEY_PAIR_GEN"; - if (mech == CKM_RSA_PKCS) - return "CKM_RSA_PKCS"; - if (mech == CKM_RSA_9796) - return "CKM_RSA_9796"; - if (mech == CKM_RSA_X_509) - return "CKM_RSA_X_509"; - if (mech == CKM_MD2_RSA_PKCS) - return "CKM_MD2_RSA_PKCS"; - if (mech == CKM_MD5_RSA_PKCS) - return "CKM_MD5_RSA_PKCS"; - if (mech == CKM_SHA1_RSA_PKCS) - return "CKM_SHA1_RSA_PKCS"; - if (mech == CKM_RIPEMD128_RSA_PKCS) - return "CKM_RIPEMD128_RSA_PKCS"; - if (mech == CKM_RIPEMD160_RSA_PKCS) - return "CKM_RIPEMD160_RSA_PKCS"; - if (mech == CKM_RSA_PKCS_OAEP) - return "CKM_RSA_PKCS_OAEP"; - if (mech == CKM_RSA_X9_31_KEY_PAIR_GEN) - return "CKM_RSA_X9_31_KEY_PAIR_GEN"; - if (mech == CKM_RSA_X9_31) - return "CKM_RSA_X9_31"; - if (mech == CKM_SHA1_RSA_X9_31) - return "CKM_SHA1_RSA_X9_31"; - if (mech == CKM_RSA_PKCS_PSS) - return "CKM_RSA_PKCS_PSS"; - if (mech == CKM_SHA1_RSA_PKCS_PSS) - return "CKM_SHA1_RSA_PKCS_PSS"; - if (mech == CKM_DSA_KEY_PAIR_GEN) - return "CKM_DSA_KEY_PAIR_GEN"; - if (mech == CKM_DSA) - return "CKM_DSA"; - if (mech == CKM_DSA_SHA1) - return "CKM_DSA_SHA1"; - if (mech == CKM_DH_PKCS_KEY_PAIR_GEN) - return "CKM_DH_PKCS_KEY_PAIR_GEN"; - if (mech == CKM_DH_PKCS_DERIVE) - return "CKM_DH_PKCS_DERIVE"; - if (mech == CKM_X9_42_DH_KEY_PAIR_GEN) - return "CKM_X9_42_DH_KEY_PAIR_GEN"; - if (mech == CKM_X9_42_DH_DERIVE) - return "CKM_X9_42_DH_DERIVE"; - if (mech == CKM_X9_42_DH_HYBRID_DERIVE) - return "CKM_X9_42_DH_HYBRID_DERIVE"; - if (mech == CKM_X9_42_MQV_DERIVE) - return "CKM_X9_42_MQV_DERIVE"; - if (mech == CKM_SHA224_RSA_PKCS) - return "CKM_SHA224_RSA_PKCS"; - if (mech == CKM_SHA256_RSA_PKCS) - return "CKM_SHA256_RSA_PKCS"; - if (mech == CKM_SHA384_RSA_PKCS) - return "CKM_SHA384_RSA_PKCS"; - if (mech == CKM_SHA512_RSA_PKCS) - return "CKM_SHA512_RSA_PKCS"; - if (mech == CKM_RC2_KEY_GEN) - return "CKM_RC2_KEY_GEN"; - if (mech == CKM_RC2_ECB) - return "CKM_RC2_ECB"; - if (mech == CKM_RC2_CBC) - return "CKM_RC2_CBC"; - if (mech == CKM_RC2_MAC) - return "CKM_RC2_MAC"; - if (mech == CKM_RC2_MAC_GENERAL) - return "CKM_RC2_MAC_GENERAL"; - if (mech == CKM_RC2_CBC_PAD) - return "CKM_RC2_CBC_PAD"; - if (mech == CKM_RC4_KEY_GEN) - return "CKM_RC4_KEY_GEN"; - if (mech == CKM_RC4) - return "CKM_RC4"; - if (mech == CKM_DES_KEY_GEN) - return "CKM_DES_KEY_GEN"; - if (mech == CKM_DES_ECB) - return "CKM_DES_ECB"; - if (mech == CKM_DES_CBC) - return "CKM_DES_CBC"; - if (mech == CKM_DES_MAC) - return "CKM_DES_MAC"; - if (mech == CKM_DES_MAC_GENERAL) - return "CKM_DES_MAC_GENERAL"; - if (mech == CKM_DES_CBC_PAD) - return "CKM_DES_CBC_PAD"; - if (mech == CKM_DES_OFB64) - return "CKM_DES_OFB64"; - if (mech == CKM_DES_CFB64) - return "CKM_DES_CFB64"; - if (mech == CKM_DES_CFB8) - return "CKM_DES_CFB8"; - if (mech == CKM_DES2_KEY_GEN) - return "CKM_DES2_KEY_GEN"; - if (mech == CKM_DES3_KEY_GEN) - return "CKM_DES3_KEY_GEN"; - if (mech == CKM_DES3_ECB) - return "CKM_DES3_ECB"; - if (mech == CKM_DES3_CBC) - return "CKM_DES3_CBC"; - if (mech == CKM_DES3_MAC) - return "CKM_DES3_MAC"; - if (mech == CKM_DES3_MAC_GENERAL) - return "CKM_DES3_MAC_GENERAL"; - if (mech == CKM_DES3_CBC_PAD) - return "CKM_DES3_CBC_PAD"; - if (mech == CKM_DES3_CMAC_GENERAL) - return "CKM_DES3_CMAC_GENERAL"; - if (mech == CKM_DES3_CMAC) - return "CKM_DES3_CMAC"; - if (mech == CKM_CDMF_KEY_GEN) - return "CKM_CDMF_KEY_GEN"; - if (mech == CKM_CDMF_ECB) - return "CKM_CDMF_ECB"; - if (mech == CKM_CDMF_CBC) - return "CKM_CDMF_CBC"; - if (mech == CKM_CDMF_MAC) - return "CKM_CDMF_MAC"; - if (mech == CKM_CDMF_MAC_GENERAL) - return "CKM_CDMF_MAC_GENERAL"; - if (mech == CKM_CDMF_CBC_PAD) - return "CKM_CDMF_CBC_PAD"; - if (mech == CKM_MD2) - return "CKM_MD2"; - if (mech == CKM_MD2_HMAC) - return "CKM_MD2_HMAC"; - if (mech == CKM_MD2_HMAC_GENERAL) - return "CKM_MD2_HMAC_GENERAL"; - if (mech == CKM_MD5) - return "CKM_MD5"; - if (mech == CKM_MD5_HMAC) - return "CKM_MD5_HMAC"; - if (mech == CKM_MD5_HMAC_GENERAL) - return "CKM_MD5_HMAC_GENERAL"; - if (mech == CKM_SHA_1) - return "CKM_SHA_1"; - if (mech == CKM_SHA_1_HMAC) - return "CKM_SHA_1_HMAC"; - if (mech == CKM_SHA_1_HMAC_GENERAL) - return "CKM_SHA_1_HMAC_GENERAL"; - if (mech == CKM_RIPEMD128) - return "CKM_RIPEMD128"; - if (mech == CKM_RIPEMD128_HMAC) - return "CKM_RIPEMD128_HMAC"; - if (mech == CKM_RIPEMD128_HMAC_GENERAL) - return "CKM_RIPEMD128_HMAC_GENERAL"; - if (mech == CKM_RIPEMD160) - return "CKM_RIPEMD160"; - if (mech == CKM_RIPEMD160_HMAC) - return "CKM_RIPEMD160_HMAC"; - if (mech == CKM_RIPEMD160_HMAC_GENERAL) - return "CKM_RIPEMD160_HMAC_GENERAL"; - if (mech == CKM_SHA224) - return "CKM_SHA224"; - if (mech == CKM_SHA224_HMAC) - return "CKM_SHA224_HMAC"; - if (mech == CKM_SHA224_HMAC_GENERAL) - return "CKM_SHA224_HMAC_GENERAL"; - if (mech == CKM_SHA256) - return "CKM_SHA256"; - if (mech == CKM_SHA256_HMAC) - return "CKM_SHA256_HMAC"; - if (mech == CKM_SHA256_HMAC_GENERAL) - return "CKM_SHA256_HMAC_GENERAL"; - if (mech == CKM_SHA384) - return "CKM_SHA384"; - if (mech == CKM_SHA384_HMAC) - return "CKM_SHA384_HMAC"; - if (mech == CKM_SHA384_HMAC_GENERAL) - return "CKM_SHA384_HMAC_GENERAL"; - if (mech == CKM_SHA512) - return "CKM_SHA512"; - if (mech == CKM_SHA512_HMAC) - return "CKM_SHA512_HMAC"; - if (mech == CKM_SHA512_HMAC_GENERAL) - return "CKM_SHA512_HMAC_GENERAL"; - if (mech == CKM_SHA512_224) - return "CKM_SHA512_224"; - if (mech == CKM_SHA512_224_HMAC) - return "CKM_SHA512_224_HMAC"; - if (mech == CKM_SHA512_224_HMAC_GENERAL) - return "CKM_SHA512_224_HMAC_GENERAL"; - if (mech == CKM_SHA512_256) - return "CKM_SHA512_256"; - if (mech == CKM_SHA512_256_HMAC) - return "CKM_SHA512_256_HMAC"; - if (mech == CKM_SHA512_256_HMAC_GENERAL) - return "CKM_SHA512_256_HMAC_GENERAL"; - if (mech == CKM_CAST_KEY_GEN) - return "CKM_CAST_KEY_GEN"; - if (mech == CKM_CAST_ECB) - return "CKM_CAST_ECB"; - if (mech == CKM_CAST_CBC) - return "CKM_CAST_CBC"; - if (mech == CKM_CAST_MAC) - return "CKM_CAST_MAC"; - if (mech == CKM_CAST_MAC_GENERAL) - return "CKM_CAST_MAC_GENERAL"; - if (mech == CKM_CAST_CBC_PAD) - return "CKM_CAST_CBC_PAD"; - if (mech == CKM_CAST3_KEY_GEN) - return "CKM_CAST3_KEY_GEN"; - if (mech == CKM_CAST3_ECB) - return "CKM_CAST3_ECB"; - if (mech == CKM_CAST3_CBC) - return "CKM_CAST3_CBC"; - if (mech == CKM_CAST3_MAC) - return "CKM_CAST3_MAC"; - if (mech == CKM_CAST3_MAC_GENERAL) - return "CKM_CAST3_MAC_GENERAL"; - if (mech == CKM_CAST3_CBC_PAD) - return "CKM_CAST3_CBC_PAD"; - if (mech == CKM_CAST5_KEY_GEN) - return "CKM_CAST5_KEY_GEN"; - if (mech == CKM_CAST128_KEY_GEN) - return "CKM_CAST128_KEY_GEN"; - if (mech == CKM_CAST5_ECB) - return "CKM_CAST5_ECB"; - if (mech == CKM_CAST128_ECB) - return "CKM_CAST128_ECB"; - if (mech == CKM_CAST5_CBC) - return "CKM_CAST5_CBC"; - if (mech == CKM_CAST128_CBC) - return "CKM_CAST128_CBC"; - if (mech == CKM_CAST5_MAC) - return "CKM_CAST5_MAC"; - if (mech == CKM_CAST128_MAC) - return "CKM_CAST128_MAC"; - if (mech == CKM_CAST5_MAC_GENERAL) - return "CKM_CAST5_MAC_GENERAL"; - if (mech == CKM_CAST128_MAC_GENERAL) - return "CKM_CAST128_MAC_GENERAL"; - if (mech == CKM_CAST5_CBC_PAD) - return "CKM_CAST5_CBC_PAD"; - if (mech == CKM_CAST128_CBC_PAD) - return "CKM_CAST128_CBC_PAD"; - if (mech == CKM_RC5_KEY_GEN) - return "CKM_RC5_KEY_GEN"; - if (mech == CKM_RC5_ECB) - return "CKM_RC5_ECB"; - if (mech == CKM_RC5_CBC) - return "CKM_RC5_CBC"; - if (mech == CKM_RC5_MAC) - return "CKM_RC5_MAC"; - if (mech == CKM_RC5_MAC_GENERAL) - return "CKM_RC5_MAC_GENERAL"; - if (mech == CKM_RC5_CBC_PAD) - return "CKM_RC5_CBC_PAD"; - if (mech == CKM_IDEA_KEY_GEN) - return "CKM_IDEA_KEY_GEN"; - if (mech == CKM_IDEA_ECB) - return "CKM_IDEA_ECB"; - if (mech == CKM_IDEA_CBC) - return "CKM_IDEA_CBC"; - if (mech == CKM_IDEA_MAC) - return "CKM_IDEA_MAC"; - if (mech == CKM_IDEA_MAC_GENERAL) - return "CKM_IDEA_MAC_GENERAL"; - if (mech == CKM_IDEA_CBC_PAD) - return "CKM_IDEA_CBC_PAD"; - if (mech == CKM_GENERIC_SECRET_KEY_GEN) - return "CKM_GENERIC_SECRET_KEY_GEN"; - if (mech == CKM_CONCATENATE_BASE_AND_KEY) - return "CKM_CONCATENATE_BASE_AND_KEY"; - if (mech == CKM_CONCATENATE_BASE_AND_DATA) - return "CKM_CONCATENATE_BASE_AND_DATA"; - if (mech == CKM_CONCATENATE_DATA_AND_BASE) - return "CKM_CONCATENATE_DATA_AND_BASE"; - if (mech == CKM_XOR_BASE_AND_DATA) - return "CKM_XOR_BASE_AND_DATA"; - if (mech == CKM_EXTRACT_KEY_FROM_KEY) - return "CKM_EXTRACT_KEY_FROM_KEY"; - if (mech == CKM_SSL3_PRE_MASTER_KEY_GEN) - return "CKM_SSL3_PRE_MASTER_KEY_GEN"; - if (mech == CKM_SSL3_MASTER_KEY_DERIVE) - return "CKM_SSL3_MASTER_KEY_DERIVE"; - if (mech == CKM_SSL3_KEY_AND_MAC_DERIVE) - return "CKM_SSL3_KEY_AND_MAC_DERIVE"; - if (mech == CKM_SSL3_MASTER_KEY_DERIVE_DH) - return "CKM_SSL3_MASTER_KEY_DERIVE_DH"; - if (mech == CKM_TLS_PRE_MASTER_KEY_GEN) - return "CKM_TLS_PRE_MASTER_KEY_GEN"; - if (mech == CKM_TLS_MASTER_KEY_DERIVE) - return "CKM_TLS_MASTER_KEY_DERIVE"; - if (mech == CKM_TLS_KEY_AND_MAC_DERIVE) - return "CKM_TLS_KEY_AND_MAC_DERIVE"; - if (mech == CKM_TLS_MASTER_KEY_DERIVE_DH) - return "CKM_TLS_MASTER_KEY_DERIVE_DH"; - if (mech == CKM_SSL3_MD5_MAC) - return "CKM_SSL3_MD5_MAC"; - if (mech == CKM_SSL3_SHA1_MAC) - return "CKM_SSL3_SHA1_MAC"; - if (mech == CKM_MD5_KEY_DERIVATION) - return "CKM_MD5_KEY_DERIVATION"; - if (mech == CKM_MD2_KEY_DERIVATION) - return "CKM_MD2_KEY_DERIVATION"; - if (mech == CKM_SHA1_KEY_DERIVATION) - return "CKM_SHA1_KEY_DERIVATION"; - if (mech == CKM_SHA224_KEY_DERIVATION) - return "CKM_SHA224_KEY_DERIVATION"; - if (mech == CKM_SHA256_KEY_DERIVATION) - return "CKM_SHA256_KEY_DERIVATION"; - if (mech == CKM_SHA384_KEY_DERIVATION) - return "CKM_SHA384_KEY_DERIVATION"; - if (mech == CKM_SHA512_KEY_DERIVATION) - return "CKM_SHA512_KEY_DERIVATION"; - if (mech == CKM_PBE_MD2_DES_CBC) - return "CKM_PBE_MD2_DES_CBC"; - if (mech == CKM_PBE_MD5_DES_CBC) - return "CKM_PBE_MD5_DES_CBC"; - if (mech == CKM_PBE_MD5_CAST_CBC) - return "CKM_PBE_MD5_CAST_CBC"; - if (mech == CKM_PBE_MD5_CAST3_CBC) - return "CKM_PBE_MD5_CAST3_CBC"; - if (mech == CKM_PBE_MD5_CAST5_CBC) - return "CKM_PBE_MD5_CAST5_CBC"; - if (mech == CKM_PBE_MD5_CAST128_CBC) - return "CKM_PBE_MD5_CAST128_CBC"; - if (mech == CKM_PBE_SHA1_CAST5_CBC) - return "CKM_PBE_SHA1_CAST5_CBC"; - if (mech == CKM_PBE_SHA1_CAST128_CBC) - return "CKM_PBE_SHA1_CAST128_CBC"; - if (mech == CKM_PBE_SHA1_RC4_128) - return "CKM_PBE_SHA1_RC4_128"; - if (mech == CKM_PBE_SHA1_RC4_40) - return "CKM_PBE_SHA1_RC4_40"; - if (mech == CKM_PBE_SHA1_DES3_EDE_CBC) - return "CKM_PBE_SHA1_DES3_EDE_CBC"; - if (mech == CKM_PBE_SHA1_DES2_EDE_CBC) - return "CKM_PBE_SHA1_DES2_EDE_CBC"; - if (mech == CKM_PBE_SHA1_RC2_128_CBC) - return "CKM_PBE_SHA1_RC2_128_CBC"; - if (mech == CKM_PBE_SHA1_RC2_40_CBC) - return "CKM_PBE_SHA1_RC2_40_CBC"; - if (mech == CKM_PKCS5_PBKD2) - return "CKM_PKCS5_PBKD2"; - if (mech == CKM_PBA_SHA1_WITH_SHA1_HMAC) - return "CKM_PBA_SHA1_WITH_SHA1_HMAC"; - if (mech == CKM_KEY_WRAP_LYNKS) - return "CKM_KEY_WRAP_LYNKS"; - if (mech == CKM_KEY_WRAP_SET_OAEP) - return "CKM_KEY_WRAP_SET_OAEP"; - if (mech == CKM_SKIPJACK_KEY_GEN) - return "CKM_SKIPJACK_KEY_GEN"; - if (mech == CKM_SKIPJACK_ECB64) - return "CKM_SKIPJACK_ECB64"; - if (mech == CKM_SKIPJACK_CBC64) - return "CKM_SKIPJACK_CBC64"; - if (mech == CKM_SKIPJACK_OFB64) - return "CKM_SKIPJACK_OFB64"; - if (mech == CKM_SKIPJACK_CFB64) - return "CKM_SKIPJACK_CFB64"; - if (mech == CKM_SKIPJACK_CFB32) - return "CKM_SKIPJACK_CFB32"; - if (mech == CKM_SKIPJACK_CFB16) - return "CKM_SKIPJACK_CFB16"; - if (mech == CKM_SKIPJACK_CFB8) - return "CKM_SKIPJACK_CFB8"; - if (mech == CKM_SKIPJACK_WRAP) - return "CKM_SKIPJACK_WRAP"; - if (mech == CKM_SKIPJACK_PRIVATE_WRAP) - return "CKM_SKIPJACK_PRIVATE_WRAP"; - if (mech == CKM_SKIPJACK_RELAYX) - return "CKM_SKIPJACK_RELAYX"; - if (mech == CKM_KEA_KEY_PAIR_GEN) - return "CKM_KEA_KEY_PAIR_GEN"; - if (mech == CKM_KEA_KEY_DERIVE) - return "CKM_KEA_KEY_DERIVE"; - if (mech == CKM_FORTEZZA_TIMESTAMP) - return "CKM_FORTEZZA_TIMESTAMP"; - if (mech == CKM_BATON_KEY_GEN) - return "CKM_BATON_KEY_GEN"; - if (mech == CKM_BATON_ECB128) - return "CKM_BATON_ECB128"; - if (mech == CKM_BATON_ECB96) - return "CKM_BATON_ECB96"; - if (mech == CKM_BATON_CBC128) - return "CKM_BATON_CBC128"; - if (mech == CKM_BATON_COUNTER) - return "CKM_BATON_COUNTER"; - if (mech == CKM_BATON_SHUFFLE) - return "CKM_BATON_SHUFFLE"; - if (mech == CKM_BATON_WRAP) - return "CKM_BATON_WRAP"; - if (mech == CKM_ECDSA_KEY_PAIR_GEN) - return "CKM_ECDSA_KEY_PAIR_GEN"; - if (mech == CKM_EC_KEY_PAIR_GEN) - return "CKM_EC_KEY_PAIR_GEN"; - if (mech == CKM_ECDSA) - return "CKM_ECDSA"; - if (mech == CKM_ECDSA_SHA1) - return "CKM_ECDSA_SHA1"; - if (mech == CKM_ECDSA_SHA224) - return "CKM_ECDSA_SHA224"; - if (mech == CKM_ECDSA_SHA256) - return "CKM_ECDSA_SHA256"; - if (mech == CKM_ECDSA_SHA384) - return "CKM_ECDSA_SHA384"; - if (mech == CKM_ECDSA_SHA512) - return "CKM_ECDSA_SHA512"; - if (mech == CKM_ECDH1_DERIVE) - return "CKM_ECDH1_DERIVE"; - if (mech == CKM_ECDH1_COFACTOR_DERIVE) - return "CKM_ECDH1_COFACTOR_DERIVE"; - if (mech == CKM_ECMQV_DERIVE) - return "CKM_ECMQV_DERIVE"; - if (mech == CKM_JUNIPER_KEY_GEN) - return "CKM_JUNIPER_KEY_GEN"; - if (mech == CKM_JUNIPER_ECB128) - return "CKM_JUNIPER_ECB128"; - if (mech == CKM_JUNIPER_CBC128) - return "CKM_JUNIPER_CBC128"; - if (mech == CKM_JUNIPER_COUNTER) - return "CKM_JUNIPER_COUNTER"; - if (mech == CKM_JUNIPER_SHUFFLE) - return "CKM_JUNIPER_SHUFFLE"; - if (mech == CKM_JUNIPER_WRAP) - return "CKM_JUNIPER_WRAP"; - if (mech == CKM_FASTHASH) - return "CKM_FASTHASH"; - if (mech == CKM_AES_KEY_GEN) - return "CKM_AES_KEY_GEN"; - if (mech == CKM_AES_ECB) - return "CKM_AES_ECB"; - if (mech == CKM_AES_CBC) - return "CKM_AES_CBC"; - if (mech == CKM_AES_MAC) - return "CKM_AES_MAC"; - if (mech == CKM_AES_MAC_GENERAL) - return "CKM_AES_MAC_GENERAL"; - if (mech == CKM_AES_CBC_PAD) - return "CKM_AES_CBC_PAD"; - if (mech == CKM_AES_CTR) - return "CKM_AES_CTR"; - if (mech == CKM_AES_GCM) - return "CKM_AES_GCM"; - if (mech == CKM_AES_OFB) - return "CKM_AES_OFB"; - if (mech == CKM_AES_CFB128) - return "CKM_AES_CFB128"; - if (mech == CKM_AES_CFB64) - return "CKM_AES_CFB64"; - if (mech == CKM_AES_CFB8) - return "CKM_AES_CFB8"; - if (mech == CKM_AES_CMAC_GENERAL) - return "CKM_AES_CMAC_GENERAL"; - if (mech == CKM_AES_CMAC) - return "CKM_AES_CMAC"; - if (mech == CKM_DSA_PARAMETER_GEN) - return "CKM_DSA_PARAMETER_GEN"; - if (mech == CKM_DH_PKCS_PARAMETER_GEN) - return "CKM_DH_PKCS_PARAMETER_GEN"; - if (mech == CKM_X9_42_DH_PARAMETER_GEN) - return "CKM_X9_42_DH_PARAMETER_GEN"; - if (mech == CKM_VENDOR_DEFINED) - return "CKM_VENDOR_DEFINED"; - if (mech == CKM_IBM_SHA3_224) - return "CKM_IBM_SHA3_224"; - if (mech == CKM_IBM_SHA3_256) - return "CKM_IBM_SHA3_256"; - if (mech == CKM_IBM_SHA3_384) - return "CKM_IBM_SHA3_384"; - if (mech == CKM_IBM_SHA3_512) - return "CKM_IBM_SHA3_512"; - if (mech == CKM_IBM_SHA3_224_HMAC) - return "CKM_IBM_SHA3_224_HMAC"; - if (mech == CKM_IBM_SHA3_256_HMAC) - return "CKM_IBM_SHA3_256_HMAC"; - if (mech == CKM_IBM_SHA3_384_HMAC) - return "CKM_IBM_SHA3_384_HMAC"; - if (mech == CKM_IBM_SHA3_512_HMAC) - return "CKM_IBM_SHA3_512_HMAC"; - if (mech == CKM_IBM_CMAC) - return "CKM_IBM_CMAC"; + const struct mechrow *row = mechrow_from_numeric(mech); + if (row) + return row->string; return "(unknown mech)"; } diff -Nru opencryptoki-3.16.0+dfsg/testcases/include/regress.h opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/include/regress.h --- opencryptoki-3.16.0+dfsg/testcases/include/regress.h 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/include/regress.h 2022-02-02 15:05:41.000000000 +0100 @@ -322,4 +322,7 @@ } \ } while (0) +#define testcase_return(rc) \ + (((rc) != 0 || t_failed != 0 || t_errors != 0) ? 1 : 0) + #endif diff -Nru opencryptoki-3.16.0+dfsg/testcases/init_token.sh.in opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/init_token.sh.in --- opencryptoki-3.16.0+dfsg/testcases/init_token.sh.in 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/init_token.sh.in 2022-02-02 15:05:41.000000000 +0100 @@ -8,64 +8,74 @@ # in the file LICENSE file or at https://opensource.org/licenses/cpl1.0.php # -set timeout 5 - spawn @sbindir@/pkcsconf -c [lindex $argv 0] -I -expect "Enter the SO PIN: " -sleep .1 -send "87654321\r" -sleep .1 -expect "label: " -sleep .1 -send "ibmtest\r" -sleep .1 -expect eof {} \ -"Incorrect PIN Entered." {exit 1} +expect { + "Enter the SO PIN: " { sleep .1; send "87654321\r"; } + default { send_user "Error sending SO PIN during initialization\n"; exit 1 } +} +expect { + "label: " { sleep .1; send "ibmtest\r"; } + default { send_user "Error sending label during initialization\n"; exit 1 } +} +expect { + eof {} + "Incorrect PIN Entered." { exit 1 } + timeout { send_user "Timeout during initialization\n"; exit 1 } +} spawn @sbindir@/pkcsconf -c [lindex $argv 0] -P -expect "Enter the SO PIN: " -sleep .1 -send "87654321\r" -sleep .1 -expect "Enter the new SO PIN: " -sleep .1 -send "76543210\r" -sleep .1 -expect "Re-enter the new SO PIN: " -sleep .1 -send "76543210\r" -sleep .1 -expect eof {} \ -"Incorrect PIN Entered." {exit 1} +expect { + "Enter the SO PIN: " { sleep .1; send "87654321\r"; } + default { send_user "Error sending SO PIN during SO PIN setting\n"; exit 1 } +} +expect { + "Enter the new SO PIN: " { sleep .1; send $env(PKCS11_SO_PIN); send "\r"; } + default { send_user "Error sending new SO PIN during SO PIN setting\n"; exit 1 } +} +expect { + "Re-enter the new SO PIN: " { sleep .1; send $env(PKCS11_SO_PIN); send "\r"; } + default { send_user "Error resending new SO PIN during SO PIN setting\n"; exit 1 } +} +expect { + eof {} + "Incorrect PIN Entered." { exit 1 } + timeout { send_user "Timeout during SO PIN setting\n"; exit 1 } +} spawn @sbindir@/pkcsconf -c [lindex $argv 0] -u -expect "Enter the SO PIN: " -sleep .1 -send "76543210\r" -sleep .1 -expect "Enter the new user PIN: " -sleep .1 -send "12345678\r" -sleep .1 -expect "Re-enter the new user PIN: " -sleep .1 -send "12345678\r" -sleep .1 -expect eof {} \ -"Incorrect PIN Entered." {exit 1} +expect { + "Enter the SO PIN: " { sleep .1; send $env(PKCS11_SO_PIN); send "\r"; } + default { send_user "Error sending SO PIN during user PIN initialization\n"; exit 1 } +} +expect { + "Enter the new user PIN: " { sleep .1; send "12345678\r"; } + default { send_user "Error sending new user PIN during user PIN initialization\n"; exit 1 } +} +expect { + "Re-enter the new user PIN: " { sleep .1; send "12345678\r"; } + default { send_user "Error resending new user during user PIN initialization\n"; exit 1 } +} +expect { + eof {} + "Incorrect PIN Entered." { exit 1 } + timeout { send_user "Timeout during user PIN initialization\n"; exit 1 } +} spawn @sbindir@/pkcsconf -c [lindex $argv 0] -p -expect "Enter user PIN: " -sleep .1 -send "12345678\r" -sleep .1 -expect "Enter the new user PIN: " -sleep .1 -send "01234567\r" -sleep .1 -expect "Re-enter the new user PIN: " -sleep .1 -send "01234567\r" -sleep .1 -expect eof {} \ -"Incorrect PIN Entered." {exit 1} +expect { + "Enter user PIN: " { sleep .1; send "12345678\r"; } + default { send_user "Error sending user PIN during user PIN setting\n"; exit 1 } +} +expect { + "Enter the new user PIN: " { sleep .1; send $env(PKCS11_USER_PIN); send "\r"; } + default { send_user "Error sending new user PIN during user PIN setting\n"; exit 1 } +} +expect { + "Re-enter the new user PIN: " { sleep .1; send $env(PKCS11_USER_PIN); send "\r"; } + default { send_user "Error resending new user PIN during user PIN setting\n"; exit 1 } +} +expect { + eof {} + "Incorrect PIN Entered." { exit 1 } + timeout { send_user "Timeout during user PIN setting\n"; exit 1 } +} diff -Nru opencryptoki-3.16.0+dfsg/testcases/init_vhsm.exp.in opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/init_vhsm.exp.in --- opencryptoki-3.16.0+dfsg/testcases/init_vhsm.exp.in 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/init_vhsm.exp.in 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,30 @@ +#!/usr/bin/expect -f +# +# COPYRIGHT (c) International Business Machines Corp. 2001-2017 +# +# This program is provided under the terms of the Common Public License, +# version 1.0 (CPL-1.0). Any use, reproduction or distribution for this software +# constitutes recipient's acceptance of CPL-1.0 terms which can be found +# in the file LICENSE file or at https://opensource.org/licenses/cpl1.0.php +# + +spawn @sbindir@/pkcsep11_session vhsmpin -slot [lindex $argv 0] +expect { + "Enter the USER PIN:" { sleep .1; send $env(PKCS11_USER_PIN); send "\r"; } + eof { send_user "Unexpected EOF on user pin\n"; exit 1 } + timeout { send_user "Timeout on user pin\n"; exit 1 } +} +expect { + "Enter the new VHSM PIN:" { sleep .1; send $env(PKCS11_VHSM_PIN); send "\r"; } + eof { send_user "Unexpected EOF on VHSM pin\n"; exit 1 } + timeout { send_user "Timeout on VHSM pin\n"; exit 1 } +} +expect { + "VHSM-pin successfully set." {} + eof { send_user "Unexpected EOF at the end\n"; exit 1 } + timeout { send_user "Unexpected timeout at the end\n"; exit 1 } +} +expect { + eof {} + timeout { send_user "Unexpected timeout at the end\n"; exit 1 } +} diff -Nru opencryptoki-3.16.0+dfsg/testcases/misc_tests/cca_export_import_test.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/misc_tests/cca_export_import_test.c --- opencryptoki-3.16.0+dfsg/testcases/misc_tests/cca_export_import_test.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/misc_tests/cca_export_import_test.c 2022-02-02 15:05:41.000000000 +0100 @@ -379,6 +379,11 @@ rc = create_DESKey(session, key, sizeof(key), &hkey); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("DES key generation is not allowed by policy"); + goto testcase_cleanup; + } + testcase_error("create_DESKey() rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -488,6 +493,11 @@ rc = create_DES3Key(session, key, sizeof(key), &hkey); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("DES3 key generation is not allowed by policy"); + goto testcase_cleanup; + } + testcase_error("create_DES3Key() rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -601,6 +611,11 @@ rc = create_AESKey(session, CK_TRUE, key, keylen, &hkey); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("AES key generation is not allowed by policy"); + continue; + } + testcase_error("create_AESKey() rc=%s", p11_get_ckr(rc)); goto error; } @@ -793,6 +808,11 @@ goto out; } + if (!mech_supported(SLOT_ID, mech.mechanism)) { + testcase_skip("this slot does not support CKM_SHA_1_HMAC"); + goto out; + } + testcase_rw_session(); testcase_user_login(); @@ -804,6 +824,11 @@ rc = create_GenericSecretKey(session, key, keybits[i] / 8, &hkey); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("Generic Secret key import is not allowed by policy"); + continue; + } + testcase_error("create_GenericSecretKey() rc=%s", p11_get_ckr(rc)); goto error; } @@ -909,6 +934,14 @@ testcase_skip("this slot is not a CCA token"); goto out; } + if (!mech_supported(SLOT_ID, CKM_RSA_PKCS_KEY_PAIR_GEN)) { + testcase_skip("this slot does not support CKM_RSA_PKCS_KEY_PAIR_GEN"); + goto out; + } + if (!mech_supported(SLOT_ID, mech.mechanism)) { + testcase_skip("this slot does not support CKM_RSA_PKCS"); + goto out; + } testcase_rw_session(); testcase_user_login(); @@ -924,6 +957,11 @@ exp, sizeof(exp), &publ_key, &priv_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("RSA key generation is not allowed by policy"); + goto error; + } + testcase_error("generate_RSA_PKCS_KeyPair() rc=%s", p11_get_ckr(rc)); goto error; } @@ -1190,6 +1228,11 @@ goto error; } if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("ECC key generation is not allowed by policy"); + goto error; + } + testcase_error("generate_EC_KeyPair() rc=%s", p11_get_ckr(rc)); goto error; } @@ -1444,6 +1487,5 @@ funcs->C_Finalize(NULL); - /* make sure we return non-zero if rv is non-zero */ - return ((rv == 0) || (rv % 256) ? (int)rv : -1); + return testcase_return(rv); } diff -Nru opencryptoki-3.16.0+dfsg/testcases/misc_tests/events.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/misc_tests/events.c --- opencryptoki-3.16.0+dfsg/testcases/misc_tests/events.c 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/misc_tests/events.c 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,191 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ + + +#include +#include +#include + +#include "event_client.h" +#include "regress.h" +#include "defs.h" + +const char payload[20] = "12345678901234567890"; + +static inline void init_event_destination(struct event_destination *dest, + unsigned int token_type, + const char *label, + pid_t process_id) +{ + size_t len; + + dest->token_type = token_type; + dest->process_id = process_id; + + memset(dest->token_label, ' ', sizeof(dest->token_label)); + if (label != NULL) { + len = strlen(label); + memcpy(dest->token_label, label, len > sizeof(dest->token_label) ? + sizeof(dest->token_label) : len); + } +} + +int main(int argc, char **argv) +{ + CK_C_INITIALIZE_ARGS cinit_args; + int rc, fd = -1, ret = 1; + struct event_destination dest; + struct event_reply reply; + + UNUSED(argc); + UNUSED(argv); + + rc = do_GetFunctionList(); + if (!rc) { + testcase_error("do_getFunctionList(), rc=%s", p11_get_ckr(rc)); + return rc; + } + + /* + * Initialize Opencryptoki in this process, so that at least one + * process is receiving the events. + */ + memset(&cinit_args, 0x0, sizeof(cinit_args)); + cinit_args.flags = CKF_OS_LOCKING_OK; + funcs->C_Initialize(&cinit_args); + + testcase_setup(0); + testcase_begin("Starting event tests"); + + // Test fork before C_Initialize + testcase_new_assertion(); + + rc = send_event(-1, 0x12345, EVENT_FLAGS_NONE, 0, NULL, NULL, NULL); + if (rc != 0) { + testcase_fail("send_event (simple, one-shot) rc = %d (%s)", rc, + strerror(-rc)); + goto out; + } + testcase_pass("send_event (simple, one-shot)"); + + rc = send_event(-1, 0x12345, EVENT_FLAGS_NONE, sizeof(payload), payload, + NULL, NULL); + if (rc != 0) { + testcase_fail("send_event (payload, one-shot) rc = %d (%s)", rc, + strerror(-rc)); + goto out; + } + testcase_pass("send_event (payload, one-shot)"); + + init_event_destination(&dest, EVENT_TOK_TYPE_CCA, NULL, 0); + + rc = send_event(-1, 0x12345, EVENT_FLAGS_NONE, 0, NULL, &dest, NULL); + if (rc != 0) { + testcase_fail("send_event (token-type, one-shot) rc = %d (%s)", rc, + strerror(-rc)); + goto out; + } + testcase_pass("send_event (token-type, one-shot)"); + + init_event_destination(&dest, EVENT_TOK_TYPE_ALL, "cca", 0); + + rc = send_event(-1, 0x12345, EVENT_FLAGS_NONE, 0, NULL, &dest, NULL); + if (rc != 0) { + testcase_fail("send_event (token-label, one-shot) rc = %d (%s)", rc, + strerror(-rc)); + goto out; + } + testcase_pass("send_event (token-label, one-shot)"); + + init_event_destination(&dest, EVENT_TOK_TYPE_ALL, NULL, 12345); + + rc = send_event(-1, 0x12345, EVENT_FLAGS_NONE, 0, NULL, &dest, NULL); + if (rc != 0) { + testcase_fail("send_event (pid, one-shot) rc = %d (%s)", rc, + strerror(-rc)); + goto out; + } + testcase_pass("send_event (pid, one-shot)"); + + memset(&reply, 0, sizeof(reply)); + + rc = send_event(-1, 0x12345, EVENT_FLAGS_REPLY_REQ, 0, NULL, NULL, &reply); + if (rc != 0) { + testcase_fail("send_event (reply, one-shot) rc = %d (%s)", rc, + strerror(-rc)); + goto out; + } + printf("Reply: positive_replies: %lu\n", reply.positive_replies); + printf(" negative_replies: %lu\n", reply.negative_replies); + printf(" nothandled_replies: %lu\n", reply.nothandled_replies); + if (reply.positive_replies + reply.negative_replies + + reply.nothandled_replies == 0) { + testcase_fail("send_event (reply, one-shot) replies all zero"); + goto out; + } + testcase_pass("send_event (reply, one-shot)"); + + + fd = init_event_client(); + if (fd < 0) { + testcase_fail("init_event_client rc = %d (%s)", fd, strerror(-fd)); + goto out; + } + testcase_pass("init_event_client()"); + + rc = send_event(fd, 0x12345, EVENT_FLAGS_NONE, 0, NULL, NULL, NULL); + if (rc != 0) { + testcase_fail("send_event (simple) rc = %d (%s)", rc, strerror(-rc)); + goto out; + } + testcase_pass("send_event (simple)"); + + rc = send_event(fd, 0x12345, EVENT_FLAGS_NONE, sizeof(payload), payload, + NULL, NULL); + if (rc != 0) { + testcase_fail("send_event (payload) rc = %d (%s)", rc, + strerror(-rc)); + goto out; + } + testcase_pass("send_event (payload)"); + + memset(&reply, 0, sizeof(reply)); + + rc = send_event(-1, 0x12345, EVENT_FLAGS_REPLY_REQ, 0, NULL, NULL, &reply); + if (rc != 0) { + testcase_fail("send_event (reply) rc = %d (%s)", rc, + strerror(-rc)); + goto out; + } + printf("Reply: positive_replies: %lu\n", reply.positive_replies); + printf(" negative_replies: %lu\n", reply.negative_replies); + printf(" nothandled_replies: %lu\n", reply.nothandled_replies); + if (reply.positive_replies + reply.negative_replies + + reply.nothandled_replies == 0) { + testcase_fail("send_event (reply) replies all zero"); + goto out; + } + testcase_pass("send_event (reply)"); + + term_event_client(fd); + fd = -1; + + ret = 0; + +out: + if (fd >= 0) + term_event_client(fd); + + funcs->C_Finalize(NULL); + + testcase_print_result(); + + return testcase_return(ret); +} diff -Nru opencryptoki-3.16.0+dfsg/testcases/misc_tests/fork.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/misc_tests/fork.c --- opencryptoki-3.16.0+dfsg/testcases/misc_tests/fork.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/misc_tests/fork.c 2022-02-02 15:05:41.000000000 +0100 @@ -25,6 +25,7 @@ #include "pkcs11types.h" #include "regress.h" +#include "common.c" CK_BYTE user_pin[128]; CK_ULONG user_pin_len; @@ -53,8 +54,12 @@ rv = funcs->C_GetMechanismInfo(slot_id, CKM_RSA_PKCS_KEY_PAIR_GEN, &rsakeygeninfo); if (rv != CKR_OK) { + if (rv == CKR_MECHANISM_INVALID) { + testcase_skip("Mechanism CKM_RSA_PKCS_KEY_PAIR_GEN not supported"); + return CKR_POLICY_VIOLATION; + } testcase_fail("C_GetMechanismInfo(CKM_RSA_PKCS_KEY_PAIR_GEN) rc = %s", p11_get_ckr(rv)); - return rv;; + return rv; } mech.mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN; @@ -64,6 +69,11 @@ rv = funcs->C_GenerateKeyPair(sess, &mech, pub_tmpl, 4, priv_tmpl, 2, hPubKey, hPrivKey); if (rv != CKR_OK) { + if (is_rejected_by_policy(rv, sess)) { + testcase_skip("Key generation is not allowed by policy"); + return CKR_POLICY_VIOLATION; + } + testcase_fail("C_GenerateKeyPair rc = %s", p11_get_ckr(rv)); return rv; } @@ -154,6 +164,10 @@ rv = do_GenerateTokenRSAKeyPair(session, (CK_BYTE *)"RSA-1024-CLIENT", 1024, &hPubKey, &hPrivKey); if (rv != CKR_OK) { + if (rv == CKR_POLICY_VIOLATION) { + rv = 0; + goto close_session; + } testcase_fail("do_GenerateTokenRSAKeyPair (client) rc = %s", p11_get_ckr(rv)); goto close_session; } @@ -185,7 +199,7 @@ out: testcase_print_result(); - exit(rv); + exit(testcase_return(rv)); } int main(int argc, char **argv) @@ -282,6 +296,10 @@ rv = do_GenerateTokenRSAKeyPair(session, (CK_BYTE *)"RSA-1024-PARENT", 1024, &hPubKey, &hPrivKey); if (rv != CKR_OK) { + if (rv == CKR_POLICY_VIOLATION) { + ret = 0; + goto close_session; + } testcase_fail("do_GenerateTokenRSAKeyPair (parent) rc = %s", p11_get_ckr(rv)); goto close_session; } @@ -354,5 +372,5 @@ } out: testcase_print_result(); - return ret; + return testcase_return(ret); } diff -Nru opencryptoki-3.16.0+dfsg/testcases/misc_tests/misc_tests.mk opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/misc_tests/misc_tests.mk --- opencryptoki-3.16.0+dfsg/testcases/misc_tests/misc_tests.mk 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/misc_tests/misc_tests.mk 2022-02-02 15:05:41.000000000 +0100 @@ -7,7 +7,8 @@ testcases/misc_tests/fork testcases/misc_tests/multi_instance \ testcases/misc_tests/obj_lock testcases/misc_tests/tok2tok_transport \ testcases/misc_tests/obj_lock testcases/misc_tests/reencrypt \ - testcases/misc_tests/cca_export_import_test + testcases/misc_tests/cca_export_import_test \ + testcases/misc_tests/events testcases_misc_tests_obj_mgmt_tests_CFLAGS = ${testcases_inc} testcases_misc_tests_obj_mgmt_tests_LDADD = \ @@ -73,3 +74,8 @@ testcases/common/libcommon.la testcases_misc_tests_cca_export_import_test_SOURCES = \ testcases/misc_tests/cca_export_import_test.c + +testcases_misc_tests_events_CFLAGS = ${testcases_inc} +testcases_misc_tests_events_LDADD = testcases/common/libcommon.la +testcases_misc_tests_events_SOURCES = testcases/misc_tests/events.c \ + usr/lib/common/event_client.c diff -Nru opencryptoki-3.16.0+dfsg/testcases/misc_tests/multi_instance.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/misc_tests/multi_instance.c --- opencryptoki-3.16.0+dfsg/testcases/misc_tests/multi_instance.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/misc_tests/multi_instance.c 2022-02-02 15:05:41.000000000 +0100 @@ -410,5 +410,5 @@ } out: testcase_print_result(); - return ret; + return testcase_return(ret); } diff -Nru opencryptoki-3.16.0+dfsg/testcases/misc_tests/obj_lock.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/misc_tests/obj_lock.c --- opencryptoki-3.16.0+dfsg/testcases/misc_tests/obj_lock.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/misc_tests/obj_lock.c 2022-02-02 15:05:41.000000000 +0100 @@ -427,5 +427,5 @@ out: testcase_print_result(); - return 0; + return testcase_return(rv); } diff -Nru opencryptoki-3.16.0+dfsg/testcases/misc_tests/obj_mgmt.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/misc_tests/obj_mgmt.c --- opencryptoki-3.16.0+dfsg/testcases/misc_tests/obj_mgmt.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/misc_tests/obj_mgmt.c 2022-02-02 15:05:41.000000000 +0100 @@ -129,18 +129,33 @@ // now, create the objects rc = funcs->C_CreateObject(h_session, data_attribs, 4, &h_data); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + funcs->C_CloseAllSessions(slot_id); + return CKR_OK; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); return rc; } rc = funcs->C_CreateObject(h_session, cert_attribs, 6, &h_cert); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + funcs->C_CloseAllSessions(slot_id); + return CKR_OK; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); return rc; } rc = funcs->C_CreateObject(h_session, key_attribs, 5, &h_key); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + funcs->C_CloseAllSessions(slot_id); + return CKR_OK; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); return rc; } @@ -266,6 +281,10 @@ /* create the object */ rc = funcs->C_CreateObject(h_session, data_attribs, 3, &h_data); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + return CKR_OK; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); return rc; } @@ -273,6 +292,10 @@ /* try to create invalid object */ rc = funcs->C_CreateObject(h_session, data_attribs2, 4, &h_data2); if (rc != CKR_ATTRIBUTE_READ_ONLY) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + return CKR_OK; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); return rc; } @@ -489,6 +512,10 @@ /* create the object */ rc = funcs->C_CreateObject(h_session, cert_attribs, 6, &h_cert); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + return CKR_OK; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); return rc; } @@ -727,18 +754,30 @@ /* create the objects */ rc = funcs->C_CreateObject(h_session, cert1_attribs, 6, &h_cert1); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + return CKR_OK; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); return rc; } rc = funcs->C_CreateObject(h_session, cert2_attribs, 6, &h_cert2); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + return CKR_OK; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); return rc; } rc = funcs->C_CreateObject(h_session, cert3_attribs, 6, &h_cert3); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + return CKR_OK; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); return rc; } @@ -972,18 +1011,30 @@ /* create the token objects */ rc = funcs->C_CreateObject(h_session, cert1_attribs, 7, &h_cert1); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + return CKR_OK; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); return rc; } rc = funcs->C_CreateObject(h_session, cert2_attribs, 7, &h_cert2); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + return CKR_OK; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); return rc; } rc = funcs->C_CreateObject(h_session, cert3_attribs, 7, &h_cert3); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + return CKR_OK; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); return rc; } @@ -1339,12 +1390,20 @@ /* Create the 4 test objects */ rc = funcs->C_CreateObject(h_session, obj1_template, 4, &h_obj1); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + return CKR_OK; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); return rc; } rc = funcs->C_CreateObject(h_session, obj2_template, 5, &h_obj2); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + return CKR_OK; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto destroy_1; } @@ -1354,12 +1413,20 @@ */ rc = funcs->C_CreateObject(h_session, counter1_template, 6, &h_counter1); if (rc != CKR_ATTRIBUTE_READ_ONLY) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + return CKR_OK; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto destroy_2; } rc = funcs->C_CreateObject(h_session, clock_template, 4, &h_clock); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + return CKR_OK; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto destroy_2; } @@ -1546,11 +1613,19 @@ /* Create the 2 test objects */ rc = funcs->C_CreateObject(h_session, profile1_template, 2, &h_obj1); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + return CKR_OK; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); return rc; } rc = funcs->C_CreateObject(h_session, profile2_template, 1, &h_obj2); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + return CKR_OK; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto destroy_1; } @@ -1718,6 +1793,5 @@ rv = obj_mgmt_functions(); testcase_print_result(); - /* make sure we return non-zero if rv is non-zero */ - return ((rv == 0) || (rv % 256) ? (int)rv : -1); + return testcase_return(rv); } diff -Nru opencryptoki-3.16.0+dfsg/testcases/misc_tests/obj_mgmt_lock.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/misc_tests/obj_mgmt_lock.c --- opencryptoki-3.16.0+dfsg/testcases/misc_tests/obj_mgmt_lock.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/misc_tests/obj_mgmt_lock.c 2022-02-02 15:05:41.000000000 +0100 @@ -97,12 +97,22 @@ // now, create the objects rc = funcs->C_CreateObject(h_session, data_attribs, 4, &h_data); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + rc = CKR_OK; + goto done; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto done; } rc = funcs->C_CreateObject(h_session, cert_attribs, 6, &h_cert); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + rc = CKR_OK; + goto done; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto done; } @@ -209,6 +219,11 @@ /* create the object */ rc = funcs->C_CreateObject(h_session, data_attribs, 3, &h_data); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + rc = CKR_OK; + goto done; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto done; } @@ -383,6 +398,11 @@ /* create the object */ rc = funcs->C_CreateObject(h_session, cert_attribs, 6, &h_cert); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + rc = CKR_OK; + goto done; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto error; } @@ -595,18 +615,33 @@ /* create the objects */ rc = funcs->C_CreateObject(h_session, cert1_attribs, 6, &h_cert1); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + rc = CKR_OK; + goto done; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto done; } rc = funcs->C_CreateObject(h_session, cert2_attribs, 6, &h_cert2); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + rc = CKR_OK; + goto done; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto destroy_1; } rc = funcs->C_CreateObject(h_session, cert3_attribs, 6, &h_cert3); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + rc = CKR_OK; + goto done; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto destroy_2; } @@ -825,18 +860,33 @@ /* create the token objects */ rc = funcs->C_CreateObject(h_session, cert1_attribs, 7, &h_cert1); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + rc = CKR_OK; + goto done; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto done; } rc = funcs->C_CreateObject(h_session, cert2_attribs, 7, &h_cert2); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + rc = CKR_OK; + goto done; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto destroy_1; } rc = funcs->C_CreateObject(h_session, cert3_attribs, 7, &h_cert3); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + rc = CKR_OK; + goto done; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto destroy_2; } @@ -1113,12 +1163,22 @@ /* Create the 3 test objects */ if ((rc = funcs->C_CreateObject(h_session, obj1_template, 4, &h_obj1)) != CKR_OK) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + rc = CKR_OK; + goto session_close; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto session_close; } if ((rc = funcs->C_CreateObject(h_session, obj2_template, 5, &h_obj2)) != CKR_OK) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + rc = CKR_OK; + goto destroy_1; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto destroy_1; } @@ -1128,12 +1188,22 @@ */ if ((rc = funcs->C_CreateObject(h_session, counter1_template, 6, &h_counter1)) != CKR_ATTRIBUTE_READ_ONLY) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + rc = CKR_OK; + goto destroy_2; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto destroy_2; } if ((rc = funcs->C_CreateObject(h_session, clock_template, 4, &h_clock)) != CKR_OK) { + if (is_rejected_by_policy(rc, h_session)) { + testcase_skip("Key import is not allowed by policy"); + rc = CKR_OK; + goto destroy_2; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto destroy_2; } @@ -1277,6 +1347,5 @@ rv = obj_mgmt_functions(); testcase_print_result(); - /* make sure we return non-zero if rv is non-zero */ - return ((rv == 0) || (rv % 256) ? (int)rv : -1); + return testcase_return(rv); } diff -Nru opencryptoki-3.16.0+dfsg/testcases/misc_tests/p11sak_test.sh opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/misc_tests/p11sak_test.sh --- opencryptoki-3.16.0+dfsg/testcases/misc_tests/p11sak_test.sh 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/misc_tests/p11sak_test.sh 2022-02-02 15:05:41.000000000 +0100 @@ -20,23 +20,28 @@ # tmp files P11SAK_DES_PRE=p11sak-des-pre.out +P11SAK_DES_LONG=p11sak-des-long.out P11SAK_DES_POST=p11sak-des-post.out P11SAK_3DES_PRE=p11sak-3des-pre.out +P11SAK_3DES_LONG=p11sak-3des-long.out P11SAK_3DES_POST=p11sak-3des-post.out P11SAK_AES_PRE=p11sak-aes-pre.out +P11SAK_AES_LONG=p11sak-aes-long.out P11SAK_AES_POST=p11sak-aes-post.out P11SAK_RSA_PRE=p11sak-rsa-pre.out +P11SAK_RSA_LONG=p11sak-rsa-long.out P11SAK_RSA_POST=p11sak-rsa-post.out P11SAK_EC_PRE=p11sak-ec-pre.out +P11SAK_EC_LONG=p11sak-ec-long.out P11SAK_EC_POST=p11sak-ec-post.out -echo "** Setting SLOT=3 to the Softtoken unless otherwise set - 'p11sak_test.sh'" +echo "** Setting SLOT=30 to the Softtoken unless otherwise set - 'p11sak_test.sh'" -# setting SLOT=3 to the Softtoken +# setting SLOT=30 to the Softtoken -SLOT=${SLOT:-3} +SLOT=${SLOT:-30} echo "** Using Slot $SLOT with PKCS11_USER_PIN $PKCS11_USER_PIN and PKCSLIB $PKCSLIB - 'p11sak_test.sh'" @@ -73,6 +78,11 @@ p11sak list-key rsa --slot $SLOT --pin $PKCS11_USER_PIN &> $P11SAK_RSA_PRE p11sak list-key ec --slot $SLOT --pin $PKCS11_USER_PIN &> $P11SAK_EC_PRE +p11sak list-key des --slot $SLOT --pin $PKCS11_USER_PIN --long &> $P11SAK_DES_LONG +p11sak list-key 3des --slot $SLOT --pin $PKCS11_USER_PIN --long &> $P11SAK_3DES_LONG +p11sak list-key aes --slot $SLOT --pin $PKCS11_USER_PIN --long &> $P11SAK_AES_LONG +p11sak list-key rsa --slot $SLOT --pin $PKCS11_USER_PIN --long &> $P11SAK_RSA_LONG +p11sak list-key ec --slot $SLOT --pin $PKCS11_USER_PIN --long &> $P11SAK_EC_LONG echo "** Now remove keys - 'p11sak_test.sh'" @@ -137,6 +147,26 @@ fi +# CK_BBOOL +if [[ $(grep -A 19 'p11sak-des' $P11SAK_DES_LONG | grep -c 'CKA_IBM_PROTKEY_EXTRACTABLE: CK_FALSE') == "1" ]]; then +echo "* TESTCASE list-key des PASS Listed random des public keys CK_BBOOL attribute" +else +echo "* TESTCASE list-key des FAIL Failed to list des public keys CK_BBOOL attribute" +fi +# CK_ULONG +if [[ $(grep -A 19 'p11sak-des' $P11SAK_DES_LONG | grep -c 'CKA_MODULUS_BITS:') == "0" ]]; then +echo "* TESTCASE list-key des PASS Listed random des public keys CK_ULONG attribute" +else +echo "* TESTCASE list-key des FAIL Failed to list des public keys CK_ULONG attribute" +fi +# CK_BYTE +if [[ $(grep -A 19 'p11sak-des' $P11SAK_DES_LONG | grep -c 'CKA_MODULUS:') == "0" ]]; then +echo "* TESTCASE list-key des PASS Listed random des public keys CK_BYTE attribute" +else +echo "* TESTCASE list-key des FAIL Failed to list des public keys CK_BYTE attribute" +fi + + # check 3DES grep -q 'p11sak-3des' $P11SAK_3DES_PRE rc=$? @@ -154,6 +184,26 @@ fi +# CK_BBOOL +if [[ $(grep -A 19 'p11sak-3des' $P11SAK_3DES_LONG | grep -c 'CKA_IBM_PROTKEY_EXTRACTABLE: CK_FALSE') == "1" ]]; then +echo "* TESTCASE list-key 3des PASS Listed random 3des public keys CK_BBOOL attribute" +else +echo "* TESTCASE list-key 3des FAIL Failed to list 3des public keys CK_BBOOL attribute" +fi +# CK_ULONG +if [[ $(grep -A 19 'p11sak-3des' $P11SAK_3DES_LONG | grep -c 'CKA_MODULUS_BITS:') == "0" ]]; then +echo "* TESTCASE list-key 3des PASS Listed random 3des public keys CK_ULONG attribute" +else +echo "* TESTCASE list-key 3des FAIL Failed to list 3des public keys CK_ULONG attribute" +fi +# CK_BYTE +if [[ $(grep -A 19 'p11sak-3des' $P11SAK_3DES_LONG | grep -c 'CKA_MODULUS:') == "0" ]]; then +echo "* TESTCASE list-key 3des PASS Listed random 3des public keys CK_BYTE attribute" +else +echo "* TESTCASE list-key 3des FAIL Failed to list 3des public keys CK_BYTE attribute" +fi + + # check AES 128 grep -q 'p11sak-aes-128' $P11SAK_AES_PRE rc=$? @@ -205,6 +255,26 @@ fi +# CK_BBOOL +if [[ $(grep -A 57 'p11sak-aes-128' $P11SAK_AES_LONG | grep -c 'CKA_IBM_PROTKEY_EXTRACTABLE: CK_FALSE') == "3" ]]; then +echo "* TESTCASE list-key aes PASS Listed random aes public keys CK_BBOOL attribute" +else +echo "* TESTCASE list-key aes FAIL Failed to list aes public keys CK_BBOOL attribute" +fi +# CK_ULONG +if [[ $(grep -A 57 'p11sak-aes-128' $P11SAK_AES_LONG | grep -c 'CKA_MODULUS_BITS:') == "0" ]]; then +echo "* TESTCASE list-key aes PASS Listed random aes public keys CK_ULONG attribute" +else +echo "* TESTCASE list-key aes FAIL Failed to list aes public keys CK_ULONG attribute" +fi +# CK_BYTE +if [[ $(grep -A 57 'p11sak-aes-128' $P11SAK_AES_LONG | grep -c 'CKA_MODULUS:') == "0" ]]; then +echo "* TESTCASE list-key aes PASS Listed random aes public keys CK_BYTE attribute" +else +echo "* TESTCASE list-key aes FAIL Failed to list aes public keys CK_BYTE attribute" +fi + + # check RSA 1024 public key grep -q 'p11sak-rsa-1024:pub' $P11SAK_RSA_PRE rc=$? @@ -307,6 +377,26 @@ fi +# CK_BBOOL +if [[ $(grep -A 205 'p11sak-rsa-1024:pub' $P11SAK_RSA_LONG | grep -c 'CKA_IBM_PROTKEY_EXTRACTABLE: CK_FALSE') == "6" ]]; then +echo "* TESTCASE list-key rsa PASS Listed random rsa public keys CK_BBOOL attribute" +else +echo "* TESTCASE list-key rsa FAIL Failed to list rsa public keys CK_BBOOL attribute" +fi +# CK_ULONG +if [[ $(grep -A 205 'p11sak-rsa-1024:pub' $P11SAK_RSA_LONG | grep -c 'CKA_MODULUS_BITS:') == "3" ]]; then +echo "* TESTCASE list-key rsa PASS Listed random rsa public keys CK_ULONG attribute" +else +echo "* TESTCASE list-key rsa FAIL Failed to list rsa public keys CK_ULONG attribute" +fi +# CK_BYTE +if [[ $(grep -A 205 'p11sak-rsa-1024:pub' $P11SAK_RSA_LONG | grep -c 'CKA_MODULUS:') == "6" ]]; then +echo "* TESTCASE list-key rsa PASS Listed random rsa public keys CK_BYTE attribute" +else +echo "* TESTCASE list-key rsa FAIL Failed to list rsa public keys CK_BYTE attribute" +fi + + # check EC prime256v1 public key grep -q 'p11sak-ec-prime256v1:pub' $P11SAK_EC_PRE rc=$? @@ -409,18 +499,43 @@ fi +# CK_BBOOL +if [[ $(grep -A 84 'p11sak-ec-prime256v1:pub' $P11SAK_EC_LONG | grep -c 'CKA_IBM_PROTKEY_EXTRACTABLE: CK_FALSE') == "6" ]]; then +echo "* TESTCASE list-key ec PASS Listed random ec public keys CK_BBOOL attribute" +else +echo "* TESTCASE list-key ec FAIL Failed to list ec public keys CK_BBOOL attribute" +fi +# CK_ULONG +if [[ $(grep -A 84 'p11sak-ec-prime256v1:pub' $P11SAK_EC_LONG | grep -c 'CKA_MODULUS_BITS:') == "0" ]]; then +echo "* TESTCASE list-key ec PASS Listed random ec public keys CK_ULONG attribute" +else +echo "* TESTCASE list-key ec FAIL Failed to list ec public keys CK_ULONG attribute" +fi +# CK_BYTE +if [[ $(grep -A 84 'p11sak-ec-prime256v1:pub' $P11SAK_EC_LONG | grep -c 'CKA_MODULUS:') == "0" ]]; then +echo "* TESTCASE list-key ec PASS Listed random ec public keys CK_BYTE attribute" +else +echo "* TESTCASE list-key ec FAIL Failed to list ec public keys CK_BYTE attribute" +fi + + echo "** Now remove temporary output files - 'p11sak_test.sh'" rm -f $P11SAK_DES_PRE +rm -f $P11SAK_DES_LONG rm -f $P11SAK_DES_POST rm -f $P11SAK_3DES_PRE +rm -f $P11SAK_3DES_LONG rm -f $P11SAK_3DES_POST rm -f $P11SAK_AES_PRE +rm -f $P11SAK_AES_LONG rm -f $P11SAK_AES_POST rm -f $P11SAK_RSA_PRE +rm -f $P11SAK_RSA_LONG rm -f $P11SAK_RSA_POST rm -f $P11SAK_EC_PRE +rm -f $P11SAK_EC_LONG rm -f $P11SAK_EC_POST echo "** Now DONE testing - 'p11sak_test.sh'" diff -Nru opencryptoki-3.16.0+dfsg/testcases/misc_tests/reencrypt.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/misc_tests/reencrypt.c --- opencryptoki-3.16.0+dfsg/testcases/misc_tests/reencrypt.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/misc_tests/reencrypt.c 2022-02-02 15:05:41.000000000 +0100 @@ -280,14 +280,14 @@ testcase_begin("Reencrypt from '%s' to '%s'", mech1->name, mech2->name); if (!mech_supported(slot_id, mech2->key_gen_mech.mechanism)) { - testcase_skip("Slot %u doesn't support %s (%u)", + testcase_skip("Slot %u doesn't support %s (0x%x)", (unsigned int)slot_id, mech_to_str(mech2->key_gen_mech.mechanism), (unsigned int)mech2->key_gen_mech.mechanism); goto testcase_cleanup; } if (!mech_supported(slot_id, mech2->mech.mechanism)) { - testcase_skip("Slot %u doesn't support %s (%u)", + testcase_skip("Slot %u doesn't support %s (0x%x)", (unsigned int)slot_id, mech_to_str(mech2->mech.mechanism), (unsigned int)mech2->mech.mechanism); @@ -361,24 +361,29 @@ if (!keysize_supported(slot_id, mech2->key_gen_mech.mechanism, mech2->rsa_modbits)) { - testcase_skip("Token in slot %ld cannot be used with " - "modbits.='%ld'", slot_id, mech2->rsa_modbits); + testcase_skip("Token in slot %ld cannot be used with modbits.='%ld'", + slot_id, mech2->rsa_modbits); goto testcase_cleanup; } if (is_ep11_token(slot_id)) { if (!is_valid_ep11_pubexp(mech2->rsa_publ_exp, mech2->rsa_publ_exp_len)) { - testcase_skip("EP11 Token in cannot be used with " - "publ_exp.='%s'", s); + testcase_skip("EP11 Token in cannot be used with publ_exp.='%s'", s); goto testcase_cleanup; } } if (is_cca_token(slot_id)) { if (!is_valid_cca_pubexp(mech2->rsa_publ_exp, mech2->rsa_publ_exp_len)) { - testcase_skip("CCA Token in cannot be used with " - " publ_exp.='%s'", s); + testcase_skip("CCA Token in cannot be used with publ_exp.='%s'", s); + goto testcase_cleanup; + } + } + if (is_soft_token(slot_id)) { + if (!is_valid_soft_pubexp(mech2->rsa_publ_exp, + mech2->rsa_publ_exp_len)) { + testcase_skip("Soft Token in cannot be used with publ_exp.='%s'", s); goto testcase_cleanup; } } @@ -386,8 +391,7 @@ if (!is_valid_tpm_pubexp(mech2->rsa_publ_exp, mech2->rsa_publ_exp_len) || !is_valid_tpm_modbits(mech2->rsa_modbits)) { - testcase_skip("TPM Token cannot be used with " - "publ_exp.='%s'", s); + testcase_skip("TPM Token cannot be used with publ_exp.='%s'", s); goto testcase_cleanup; } } @@ -395,8 +399,7 @@ if (!is_valid_icsf_pubexp(mech2->rsa_publ_exp, mech2->rsa_publ_exp_len) || mech2->rsa_modbits < 1024) { - testcase_skip("ICSF Token cannot be used with " - "publ_exp='%s'.", s); + testcase_skip("ICSF Token cannot be used with publ_exp='%s'.", s); goto testcase_cleanup; } } @@ -426,6 +429,15 @@ } if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("generate key-2 with mech %s (%u) in slot %lu " + "is not allowed by policy", + mech_to_str(mech2->key_gen_mech.mechanism), + (unsigned int)mech2->key_gen_mech.mechanism, + slot_id); + goto testcase_cleanup; + } + testcase_error("generate key-2 with mech %s (%u) in slot %lu " "failed, rc=%s", mech_to_str(mech2->key_gen_mech.mechanism), @@ -539,14 +551,14 @@ testsuite_begin("with '%s'", mech1->name); if (!mech_supported(slot_id, mech1->key_gen_mech.mechanism)) { - testsuite_skip(NUM_REENCRYPT_TESTS, "Slot %u doesn't support %s (%u)", + testsuite_skip(NUM_REENCRYPT_TESTS, "Slot %u doesn't support %s (0x%x)", (unsigned int)slot_id, mech_to_str(mech1->key_gen_mech.mechanism), (unsigned int)mech1->key_gen_mech.mechanism); goto testcase_cleanup; } if (!mech_supported(slot_id, mech1->mech.mechanism)) { - testsuite_skip(NUM_REENCRYPT_TESTS, "Slot %u doesn't support %s (%u)", + testsuite_skip(NUM_REENCRYPT_TESTS, "Slot %u doesn't support %s (0x%x)", (unsigned int)slot_id, mech_to_str(mech1->mech.mechanism), (unsigned int)mech1->mech.mechanism); @@ -619,6 +631,14 @@ goto testcase_cleanup; } } + if (is_soft_token(slot_id)) { + if (!is_valid_soft_pubexp(mech1->rsa_publ_exp, + mech1->rsa_publ_exp_len)) { + testsuite_skip(NUM_REENCRYPT_TESTS, "Soft Token cannot be " + "used with publ_exp.='%s'", s); + goto testcase_cleanup; + } + } if (is_tpm_token(slot_id) ) { if (!is_valid_tpm_pubexp(mech1->rsa_publ_exp, mech1->rsa_publ_exp_len) || @@ -663,6 +683,15 @@ } if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("generate key-1 with mech %s (%u) in slot %lu " + "is not allowed by policy", + mech_to_str(mech1->key_gen_mech.mechanism), + (unsigned int)mech1->key_gen_mech.mechanism, + slot_id); + goto testcase_cleanup; + } + testcase_error("generate key-1 with mech %s (%u) in slot %lu " "failed, rc=%s", mech_to_str(mech1->key_gen_mech.mechanism), @@ -848,5 +877,5 @@ } out: testcase_print_result(); - return ret; + return testcase_return(ret); } diff -Nru opencryptoki-3.16.0+dfsg/testcases/misc_tests/speed.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/misc_tests/speed.c --- opencryptoki-3.16.0+dfsg/testcases/misc_tests/speed.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/misc_tests/speed.c 2022-02-02 15:05:41.000000000 +0100 @@ -66,13 +66,12 @@ // keylength: 512, 1024, 2048, 4096 int do_RSA_PKCS_EncryptDecrypt(int keylength) { - CK_SLOT_ID slot_id; CK_SESSION_HANDLE session; CK_MECHANISM mech; CK_FLAGS flags; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_ULONG user_pin_len; - CK_RV rv, rc; + CK_RV rc; CK_OBJECT_HANDLE publ_key, priv_key; CK_BYTE data1[100]; @@ -96,7 +95,18 @@ testcase_begin("RSA PKCS Encrypt with keylen=%d datalen=%d", keylength, (int) sizeof(data1)); - slot_id = SLOT_ID; + if (!mech_supported(SLOT_ID, CKM_RSA_PKCS_KEY_PAIR_GEN)) { + testcase_skip("Slot %lu doesn't support CKM_RSA_PKCS_KEY_PAIR_GEN (0x%x)", + SLOT_ID, CKM_RSA_PKCS_KEY_PAIR_GEN); + return TRUE; + } + if (!mech_supported(SLOT_ID, CKM_RSA_PKCS)) { + testcase_skip("Slot %lu doesn't support CKM_RSA_PKCS (0x%x)", + SLOT_ID, CKM_RSA_PKCS); + return TRUE; + } + + testcase_new_assertion(); testcase_rw_session(); testcase_user_login(); @@ -165,11 +175,15 @@ avg_time /= 1000; printf("%ld iterations: total=%ldms min=%ldms max=%ldms avg=%ldms " - "op/s=%.3f\n\n", iterations, tot_time, min_time, max_time, + "op/s=%.3f\n", iterations, tot_time, min_time, max_time, avg_time, (double) (iterations * 1000) / (double) tot_time); - printf("RSA PKCS Decrypt with keylen=%d datalen=%d\n", - keylength, (int) encdata_len); + testcase_pass("RSA PKCS Encrypt with keylen=%d datalen=%d", + keylength, (int) sizeof(data1)); + + testcase_begin("RSA PKCS Decrypt with keylen=%d datalen=%d", + keylength, (int) encdata_len); + testcase_new_assertion(); tot_time = 0; max_time = 0; @@ -222,15 +236,16 @@ avg_time /= 1000; printf("%ld iterations: total=%ldms min=%ldms max=%ldms avg=%ldms " - "op/s=%.3f\n\n", iterations, tot_time, min_time, max_time, + "op/s=%.3f\n", iterations, tot_time, min_time, max_time, avg_time, (double) (iterations * 1000) / (double) tot_time); + testcase_pass("RSA PKCS Decrypt with keylen=%d datalen=%d", + keylength, (int) encdata_len); + testcase_cleanup: - rv = funcs->C_CloseAllSessions(slot_id); - if (rv != CKR_OK) { - testcase_error("C_CloseAllSessions rv=%s", p11_get_ckr(rv)); + testcase_closeall_session(); + if (rc != CKR_OK) return FALSE; - } return TRUE; } @@ -243,7 +258,7 @@ CK_FLAGS flags; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_ULONG user_pin_len; - CK_RV rv, rc; + CK_RV rc; CK_ULONG iterations = 10; SYSTEMTIME t1, t2; @@ -259,6 +274,14 @@ testcase_begin("RSA KeyGen with keylen=%d", keylength); + if (!mech_supported(SLOT_ID, CKM_RSA_PKCS_KEY_PAIR_GEN)) { + testcase_skip("Slot %lu doesn't support CKM_RSA_PKCS_KEY_PAIR_GEN (0x%x)", + SLOT_ID, CKM_RSA_PKCS_KEY_PAIR_GEN); + return TRUE; + } + + testcase_new_assertion(); + testcase_rw_session(); testcase_user_login(); @@ -305,15 +328,15 @@ avg_time /= 1000; printf("%ld iterations: total=%ldms min=%ldms max=%ldms avg=%ldms " - "op/s=%.3f\n\n", iterations, tot_time, min_time, max_time, + "op/s=%.3f\n", iterations, tot_time, min_time, max_time, avg_time, (double) (iterations * 1000) / (double) tot_time); + testcase_pass("RSA KeyGen with keylen=%d", keylength); + testcase_cleanup: - rv = funcs->C_CloseSession(session); - if (rv != CKR_OK) { - testcase_error("C_CloseSession rv=%s", p11_get_ckr(rv)); + testcase_closeall_session(); + if (rc != CKR_OK) return FALSE; - } return TRUE; } @@ -321,13 +344,12 @@ // keylength: 512, 1024, 2048, 4096 int do_RSA_PKCS_SignVerify(int keylength) { - CK_SLOT_ID slot_id; CK_SESSION_HANDLE session; CK_MECHANISM mech; CK_FLAGS flags; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_ULONG user_pin_len; - CK_RV rv, rc; + CK_RV rc; CK_ULONG i, len1, sig_len; CK_BYTE signature[512]; @@ -345,11 +367,22 @@ {CKA_PUBLIC_EXPONENT, &pub_exp, sizeof(pub_exp)} }; - slot_id = SLOT_ID; - testcase_begin("RSA PKCS Sign with keylen=%d datalen=%d", keylength, (int) sizeof(data1)); + if (!mech_supported(SLOT_ID, CKM_RSA_PKCS_KEY_PAIR_GEN)) { + testcase_skip("Slot %lu doesn't support CKM_RSA_PKCS_KEY_PAIR_GEN (0x%x)", + SLOT_ID, CKM_RSA_PKCS_KEY_PAIR_GEN); + return TRUE; + } + if (!mech_supported(SLOT_ID, CKM_RSA_PKCS)) { + testcase_skip("Slot %lu doesn't support CKM_RSA_PKCS (0x%x)", + SLOT_ID, CKM_RSA_PKCS); + return TRUE; + } + + testcase_new_assertion(); + testcase_rw_session(); testcase_user_login(); @@ -414,11 +447,15 @@ avg_time /= 1000; printf("%ld iterations: total=%ldms min=%ldms max=%ldms avg=%ldms " - "op/s=%.3f\n\n", iterations, tot_time, min_time, max_time, + "op/s=%.3f\n", iterations, tot_time, min_time, max_time, avg_time, (double) (iterations * 1000) / (double) tot_time); - printf("RSA PKCS Verify with keylen=%d datalen=%d\n", - keylength, (int) sizeof(data1)); + testcase_pass("RSA PKCS Sign with keylen=%d datalen=%d", + keylength, (int) sizeof(data1)); + + testcase_begin("RSA PKCS Verify with keylen=%d datalen=%d", + keylength, (int) sizeof(data1)); + testcase_new_assertion(); tot_time = 0; max_time = 0; @@ -458,15 +495,16 @@ avg_time /= 1000; printf("%ld iterations: total=%ldms min=%ldms max=%ldms avg=%ldms " - "op/s=%.3f\n\n", iterations, tot_time, min_time, max_time, + "op/s=%.3f\n", iterations, tot_time, min_time, max_time, avg_time, (double) (iterations * 1000) / (double) tot_time); + testcase_pass("RSA PKCS Verify with keylen=%d datalen=%d", + keylength, (int) sizeof(data1)); + testcase_cleanup: - rv = funcs->C_CloseAllSessions(slot_id); - if (rv != CKR_OK) { - testcase_error("C_CloseAllSession rv=%s", p11_get_ckr(rv)); + testcase_closeall_session(); + if (rc != CKR_OK) return FALSE; - } return TRUE; } @@ -474,13 +512,12 @@ // mode: ECB CBC int do_DES3_EncrDecr(const char *mode) { - CK_SLOT_ID slot_id; CK_SESSION_HANDLE session; CK_MECHANISM mech; CK_FLAGS flags; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_ULONG user_pin_len; - CK_RV rv, rc; + CK_RV rc; CK_OBJECT_HANDLE h_key; CK_BYTE original[BIG_REQUEST]; @@ -493,15 +530,25 @@ CK_ULONG i, iterations = 10000; CK_ULONG avg_time, tot_time, min_time, max_time, diff; - slot_id = SLOT_ID; + testcase_begin("DES3 Encrypt with mode=%s datalen=%d", mode, BIG_REQUEST); - testcase_begin("DES3 Encrypt with mode=%s datalen=%d\n", mode, BIG_REQUEST); - - if (is_cca_token(SLOT_ID) && strcmp(mode, "ECB") == 0) { - testcase_skip("Slot %u doesn't support DES3 ECB En/Decrypt\n", - (unsigned) SLOT_ID); + if (!mech_supported(SLOT_ID, CKM_DES3_KEY_GEN)) { + testcase_skip("Slot %lu doesn't support CKM_DES3_KEY_GEN (0x%x)", + SLOT_ID, CKM_DES3_KEY_GEN); + return TRUE; + } + if (strcmp(mode, "ECB") == 0 && !mech_supported(SLOT_ID, CKM_DES3_ECB)) { + testcase_skip("Slot %lu doesn't support CKM_DES3_ECB (0x%x)", + SLOT_ID, CKM_DES3_ECB); return TRUE; } + if (strcmp(mode, "CBC") == 0 && !mech_supported(SLOT_ID, CKM_DES3_CBC)) { + testcase_skip("Slot %lu doesn't support CKM_DES3_CBC (0x%x)", + SLOT_ID, CKM_DES3_CBC); + return TRUE; + } + + testcase_new_assertion(); testcase_rw_session(); testcase_user_login(); @@ -580,12 +627,15 @@ tot_time /= 1000; printf("%ld iterations: total=%ldms min=%ldus max=%ldus avg=%ldus " - "op/s=%.3f %.3fMB/s\n\n", iterations, tot_time, min_time, max_time, + "op/s=%.3f %.3fMB/s\n", iterations, tot_time, min_time, max_time, avg_time, (double) (iterations * 1000) / (double) tot_time, (((double) (iterations * 1000) / (double) (1024 * 1024)) * BIG_REQUEST) / (double) tot_time); - printf("DES3 Decrypt with mode=%s datalen=%d\n", mode, BIG_REQUEST); + testcase_pass("DES3 Encrypt with mode=%s datalen=%d", mode, BIG_REQUEST); + + testcase_begin("DES3 Decrypt with mode=%s datalen=%d", mode, BIG_REQUEST); + testcase_new_assertion(); tot_time = 0; max_time = 0; @@ -628,17 +678,17 @@ tot_time /= 1000; printf("%ld iterations: total=%ldms min=%ldus max=%ldus avg=%ldus " - "op/s=%.3f %.3fMB/s\n\n", iterations, tot_time, min_time, max_time, + "op/s=%.3f %.3fMB/s\n", iterations, tot_time, min_time, max_time, avg_time, (double) (iterations * 1000) / (double) tot_time, (((double) (iterations * 1000) / (double) (1024 * 1024)) * BIG_REQUEST) / (double) tot_time); + testcase_pass("DES3 Decrypt with mode=%s datalen=%d", mode, BIG_REQUEST); + testcase_cleanup: - rv = funcs->C_CloseAllSessions(slot_id); - if (rv != CKR_OK) { - testcase_error("C_CloseAllSessions rc=%s", p11_get_ckr(rv)); + testcase_closeall_session(); + if (rc != CKR_OK) return FALSE; - } return TRUE; } @@ -647,13 +697,12 @@ // mode: ECB CBC int do_AES_EncrDecr(int keylength, const char *mode) { - CK_SLOT_ID slot_id; CK_SESSION_HANDLE session; CK_MECHANISM mech; CK_FLAGS flags; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_ULONG user_pin_len; - CK_RV rv, rc; + CK_RV rc; CK_OBJECT_HANDLE h_key; CK_BYTE original[BIG_REQUEST]; @@ -673,10 +722,26 @@ SYSTEMTIME t1, t2; CK_ULONG avg_time, tot_time, min_time, max_time, diff; - testcase_begin("AES Encrypt with mode=%s keylen=%ld datalen=%d\n", + testcase_begin("AES Encrypt with mode=%s keylen=%ld datalen=%d", mode, key_len * 8, BIG_REQUEST); - slot_id = SLOT_ID; + if (!mech_supported(SLOT_ID, CKM_AES_KEY_GEN)) { + testcase_skip("Slot %lu doesn't support CKM_AES_KEY_GEN (0x%x)", + SLOT_ID, CKM_AES_KEY_GEN); + return TRUE; + } + if (strcmp(mode, "ECB") == 0 && !mech_supported(SLOT_ID, CKM_AES_ECB)) { + testcase_skip("Slot %lu doesn't support CKM_AES_ECB (0x%x)", + SLOT_ID, CKM_AES_ECB); + return TRUE; + } + if (strcmp(mode, "CBC") == 0 && !mech_supported(SLOT_ID, CKM_AES_CBC)) { + testcase_skip("Slot %lu doesn't support CKM_AES_CBC (0x%x)", + SLOT_ID, CKM_AES_CBC); + return TRUE; + } + + testcase_new_assertion(); testcase_rw_session(); testcase_user_login(); @@ -687,6 +752,10 @@ rc = generate_AESKey(session, key_len, CK_TRUE, &mech, &h_key); if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("AES key generation is not allowed by policy"); + goto testcase_cleanup; + } testcase_error("C_GenerateKey rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -751,13 +820,17 @@ tot_time /= 1000; printf("%ld iterations: total=%ldms min=%ldus max=%ldus avg=%ldus " - "op/s=%.3f %.3fMB/s\n\n", iterations, tot_time, min_time, max_time, + "op/s=%.3f %.3fMB/s\n", iterations, tot_time, min_time, max_time, avg_time, (double) (iterations * 1000) / (double) tot_time, (((double) (iterations * 1000) / (double) (1024 * 1024)) * BIG_REQUEST) / (double) tot_time); - printf("AES Decrypt with mode=%s keylen=%ld datalen=%d\n", - mode, key_len * 8, BIG_REQUEST); + testcase_pass("AES Encrypt with mode=%s keylen=%ld datalen=%d", + mode, key_len * 8, BIG_REQUEST); + + testcase_begin("AES Decrypt with mode=%s keylen=%ld datalen=%d", + mode, key_len * 8, BIG_REQUEST); + testcase_new_assertion(); tot_time = 0; max_time = 0; @@ -797,29 +870,28 @@ tot_time /= 1000; printf("%ld iterations: total=%ldms min=%ldus max=%ldus avg=%ldus " - "op/s=%.3f %.3fMB/s\n\n", iterations, tot_time, min_time, max_time, + "op/s=%.3f %.3fMB/s\n", iterations, tot_time, min_time, max_time, avg_time, (double) (iterations * 1000) / (double) tot_time, (((double) (iterations * 1000) / (double) (1024 * 1024)) * BIG_REQUEST) / (double) tot_time); + testcase_pass("AES Decrypt with mode=%s keylen=%ld datalen=%d", + mode, key_len * 8, BIG_REQUEST); testcase_cleanup: - rv = funcs->C_CloseAllSessions(slot_id); - if (rv != CKR_OK) { - testcase_error("C_CloseAllSessions rc=%s", p11_get_ckr(rv)); + testcase_closeall_session(); + if (rc != CKR_OK) return FALSE; - } return TRUE; } int do_SHA(const char *mode) { - CK_SLOT_ID slot_id; CK_SESSION_HANDLE session; CK_MECHANISM mech; CK_FLAGS flags; - CK_RV rc, rv; + CK_RV rc; CK_BYTE data[BIG_REQUEST]; CK_BYTE hash[MAX_HASH_LEN]; @@ -829,9 +901,25 @@ CK_ULONG diff, avg_time, tot_time, min_time, max_time; CK_ULONG i, iterations = 20000; - printf("SHA (%s) with datalen=%d\n", mode, BIG_REQUEST); + testcase_begin("SHA (%s) with datalen=%d", mode, BIG_REQUEST); - slot_id = SLOT_ID; + if (strcmp(mode, "SHA1") == 0 && !mech_supported(SLOT_ID, CKM_SHA_1)) { + testcase_skip("Slot %lu doesn't support CKM_SHA_1 (0x%x)", + SLOT_ID, CKM_SHA_1); + return TRUE; + } + if (strcmp(mode, "SHA256") == 0 && !mech_supported(SLOT_ID, CKM_SHA256)) { + testcase_skip("Slot %lu doesn't support CKM_SHA256 (0x%x)", + SLOT_ID, CKM_SHA256); + return TRUE; + } + if (strcmp(mode, "SHA512") == 0 && !mech_supported(SLOT_ID, CKM_SHA512)) { + testcase_skip("Slot %lu doesn't support CKM_SHA512 (0x%x)", + SLOT_ID, CKM_SHA512); + return TRUE; + } + + testcase_new_assertion(); testcase_rw_session(); @@ -906,67 +994,17 @@ tot_time /= 1000; printf("%ld iterations: total=%ldms min=%ldus max=%ldus avg=%ldus " - "op/s=%.3f %.3fMB/s\n\n", iterations, tot_time, min_time, max_time, + "op/s=%.3f %.3fMB/s\n", iterations, tot_time, min_time, max_time, avg_time, (double) (iterations * 1000) / (double) tot_time, (((double) (iterations * 1000) / (double) (1024 * 1024)) * BIG_REQUEST) / (double) tot_time); + testcase_pass("SHA (%s) with datalen=%d", mode, BIG_REQUEST); + testcase_cleanup: - rv = funcs->C_CloseAllSessions(slot_id); - if (rv != CKR_OK) { - testcase_error("C_CloseAllSessions rv=%s", p11_get_ckr(rv)); + testcase_closeall_session(); + if (rc != CKR_OK) return FALSE; - } - - return TRUE; -} - - -int do_DummyFunction(void) -{ -#if DUMMY - CK_SLOT_ID slot_id; - CK_ULONG i, diff, avg_time, min_time, max_time; - CK_ULONG iterations = 1000; - SYSTEMTIME t1, t2; - - testcase_begin("do_DummyFunction..."); - - slot_id = SLOT_ID; - - tot_time = 0; - max_time = 0; - min_time = 0xFFFFFFFF; - - for (i = 0; i < iterations + 2; i++) { - GetSystemTime(&t1); - DummyFunction(slot_id); - - GetSystemTime(&t2); - - diff = delta_time_us(&t1, &t2); - tot_time += diff; - - if (diff < min_time) - min_time = diff; - - if (diff > max_time) - max_time = diff; - } - - tot_time -= min_time; - tot_time -= max_time; - avg_time = tot_time / iterations; - - // us -> ms - tot_time /= 1000; - min_time /= 1000; - max_time /= 1000; - - printf("%ld iterations: total=%ldms min=%ldms max=%ldms avg=%ldms " - "op/s=%.3f\n\n", iterations, tot_time, min_time, max_time, - avg_time, (double) (iterations * 1000) / (double) tot_time); -#endif return TRUE; } @@ -1054,85 +1092,96 @@ funcs->C_Initialize(&cinit_args); + testcase_setup(0); + if (do_rsa_keygen) { + testsuite_begin("RSA Keygen."); rc = do_RSA_KeyGen(1024); if (!rc) - return rc; + goto out; rc = do_RSA_KeyGen(2048); if (!rc) - return rc; + goto out; rc = do_RSA_KeyGen(4096); if (!rc) - return rc; + goto out; } if (do_rsa_signverify) { + testsuite_begin("RSA Sign/Verify."); rc = do_RSA_PKCS_SignVerify(1024); if (!rc) - return rc; + goto out; rc = do_RSA_PKCS_SignVerify(2048); if (!rc) - return rc; + goto out; rc = do_RSA_PKCS_SignVerify(4096); if (!rc) - return rc; + goto out; } if (do_rsa_endecrypt) { + testsuite_begin("RSA Encrypt/Decrypt."); rc = do_RSA_PKCS_EncryptDecrypt(1024); if (!rc) - return rc; + goto out; rc = do_RSA_PKCS_EncryptDecrypt(2048); if (!rc) - return rc; + goto out; rc = do_RSA_PKCS_EncryptDecrypt(4096); if (!rc) - return rc; + goto out; } if (do_des3_endecrypt) { + testsuite_begin("DES3 Encrypt/Decrypt."); rc = do_DES3_EncrDecr("ECB"); if (!rc) - return rc; + goto out; rc = do_DES3_EncrDecr("CBC"); if (!rc) - return rc; + goto out; } if (do_aes_endecrypt) { + testsuite_begin("AES Encrypt/Decrypt."); rc = do_AES_EncrDecr(128, "ECB"); if (!rc) - return rc; + goto out; rc = do_AES_EncrDecr(128, "CBC"); if (!rc) - return rc; + goto out; rc = do_AES_EncrDecr(192, "ECB"); if (!rc) - return rc; + goto out; rc = do_AES_EncrDecr(192, "CBC"); if (!rc) - return rc; + goto out; rc = do_AES_EncrDecr(256, "ECB"); if (!rc) - return rc; + goto out; rc = do_AES_EncrDecr(256, "CBC"); if (!rc) - return rc; + goto out; } if (do_sha) { + testsuite_begin("SHA Digest."); rc = do_SHA("SHA1"); if (!rc) - return rc; + goto out; rc = do_SHA("SHA256"); if (!rc) - return rc; + goto out; rc = do_SHA("SHA512"); if (!rc) - return rc; + goto out; } +out: + testcase_print_result(); + funcs->C_Finalize(NULL); - return 0; + return testcase_return(rc); } diff -Nru opencryptoki-3.16.0+dfsg/testcases/misc_tests/tok2tok_transport.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/misc_tests/tok2tok_transport.c --- opencryptoki-3.16.0+dfsg/testcases/misc_tests/tok2tok_transport.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/misc_tests/tok2tok_transport.c 2022-02-02 15:05:41.000000000 +0100 @@ -531,14 +531,14 @@ mech_to_str(wrap_mech->mechanism)); if (!mech_supported(slot_id1, tsuite->wrapped_key_gen_mech.mechanism)) { - testcase_skip("Slot %u doesn't support %s (%u)", + testcase_skip("Slot %u doesn't support %s (0x%x)", (unsigned int)slot_id1, mech_to_str(tsuite->wrapped_key_gen_mech.mechanism), (unsigned int)tsuite->wrapped_key_gen_mech.mechanism); goto testcase_cleanup; } if (!mech_supported(slot_id2, tsuite->wrapped_key_gen_mech.mechanism)) { - testcase_skip("Slot %u doesn't support %s (%u)", + testcase_skip("Slot %u doesn't support %s (0x%x)", (unsigned int)slot_id2, mech_to_str(tsuite->wrapped_key_gen_mech.mechanism), (unsigned int)tsuite->wrapped_key_gen_mech.mechanism); @@ -546,14 +546,14 @@ } if (!mech_supported(slot_id1, tsuite->operation_mech.mechanism)) { - testcase_skip("Slot %u doesn't support %s (%u)", + testcase_skip("Slot %u doesn't support %s (0x%x)", (unsigned int)slot_id1, mech_to_str(tsuite->operation_mech.mechanism), (unsigned int)tsuite->operation_mech.mechanism); goto testcase_cleanup; } if (!mech_supported(slot_id2, tsuite->operation_mech.mechanism)) { - testcase_skip("Slot %u doesn't support %s (%u)", + testcase_skip("Slot %u doesn't support %s (0x%x)", (unsigned int)slot_id2, mech_to_str(tsuite->operation_mech.mechanism), (unsigned int)tsuite->operation_mech.mechanism); @@ -581,30 +581,35 @@ if (!keysize_supported(slot_id1, tsuite->wrapped_key_gen_mech.mechanism, tsuite->rsa_modbits)) { - testcase_skip("Token in slot %lu cannot be used with " - "modbits.='%ld'", slot_id1, tsuite->rsa_modbits); + testcase_skip("Token in slot %lu cannot be used with modbits.='%ld'", + slot_id1, tsuite->rsa_modbits); goto testcase_cleanup; } if (!keysize_supported(slot_id2, tsuite->wrapped_key_gen_mech.mechanism, tsuite->rsa_modbits)) { - testcase_skip("Token in slot %lu cannot be used with " - "modbits.='%ld'", slot_id2, tsuite->rsa_modbits); + testcase_skip("Token in slot %lu cannot be used with modbits.='%ld'", + slot_id2, tsuite->rsa_modbits); goto testcase_cleanup; } if (is_ep11_token(slot_id1) || is_ep11_token(slot_id2)) { if (!is_valid_ep11_pubexp(tsuite->rsa_publ_exp, tsuite->rsa_publ_exp_len)) { - testcase_skip("EP11 Token in cannot be used with " - "publ_exp.='%s'", s); + testcase_skip("EP11 Token in cannot be used with publ_exp.='%s'", s); goto testcase_cleanup; } } if (is_cca_token(slot_id1) || is_cca_token(slot_id2)) { if (!is_valid_cca_pubexp(tsuite->rsa_publ_exp, tsuite->rsa_publ_exp_len)) { - testcase_skip("CCA Token in scannot be used with " - "publ_exp.='%s'", s); + testcase_skip("CCA Token in scannot be used with publ_exp.='%s'", s); + goto testcase_cleanup; + } + } + if (is_soft_token(slot_id1) || is_cca_token(slot_id2)) { + if (!is_valid_soft_pubexp(tsuite->rsa_publ_exp, + tsuite->rsa_publ_exp_len)) { + testcase_skip("Soft Token in scannot be used with publ_exp.='%s'", s); goto testcase_cleanup; } } @@ -612,8 +617,7 @@ if (!is_valid_tpm_pubexp(tsuite->rsa_publ_exp, tsuite->rsa_publ_exp_len) || !is_valid_tpm_modbits(tsuite->rsa_modbits)) { - testcase_skip("TPM Token cannot " "be used with " - "publ_exp.='%s'", s); + testcase_skip("TPM Token cannot " "be used with publ_exp.='%s'", s); goto testcase_cleanup; } } @@ -621,8 +625,7 @@ if (!is_valid_icsf_pubexp(tsuite->rsa_publ_exp, tsuite->rsa_publ_exp_len) || tsuite->rsa_modbits < 1024) { - testcase_skip("ICSF Token cannot be used with " - "publ_exp='%s'.", s); + testcase_skip("ICSF Token cannot be used with publ_exp='%s'.", s); goto testcase_cleanup; } } @@ -663,6 +666,16 @@ } if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("generate to be wrapped key with mech %s (%u) in slot " + "%lu is not allowed by policy", + mech_to_str(tsuite->wrapped_key_gen_mech.mechanism), + (unsigned int)tsuite->wrapped_key_gen_mech.mechanism, + slot_id1); + rc = CKR_OK; + goto testcase_cleanup; + } + testcase_error("generate to be wrapped key with mech %s (%u) in slot " "%lu failed, rc=%s", mech_to_str(tsuite->wrapped_key_gen_mech.mechanism), @@ -807,8 +820,8 @@ } if ((rc == CKR_MECHANISM_INVALID || rc == CKR_KEY_TYPE_INCONSISTENT) && is_ep11_token(slot_id2) && wrap_mech->mechanism == CKM_DES3_CBC && - key_type == CKK_EC) { - testcase_skip("EP11 does not support unwrap of EC keys with DES3 CBC"); + (key_type == CKK_EC || key_type == CKK_RSA)) { + testcase_skip("EP11 does not support unwrap of EC or RSA keys with DES3 CBC"); rc = CKR_OK; goto testcase_cleanup; } @@ -903,7 +916,7 @@ testsuite_begin("%s", tsuite->name); if (!mech_supported(slot_id1, tsuite->wrapping_key_gen_mech.mechanism)) { - testsuite_skip(NUM_WRAPPED_KEY_TESTS, "Slot %u doesn't support %s (%u)", + testsuite_skip(NUM_WRAPPED_KEY_TESTS, "Slot %u doesn't support %s (0x%x)", (unsigned int)slot_id1, mech_to_str(tsuite->wrapping_key_gen_mech.mechanism), (unsigned int)tsuite->wrapping_key_gen_mech.mechanism); @@ -911,7 +924,7 @@ } if (!mech_supported(slot_id2, tsuite->wrapping_key_gen_mech.mechanism)) { - testsuite_skip(NUM_WRAPPED_KEY_TESTS, "Slot %u doesn't support %s (%u)", + testsuite_skip(NUM_WRAPPED_KEY_TESTS, "Slot %u doesn't support %s (0x%x)", (unsigned int)slot_id2, mech_to_str(tsuite->wrapping_key_gen_mech.mechanism), (unsigned int)tsuite->wrapping_key_gen_mech.mechanism); @@ -919,7 +932,7 @@ } if (!mech_supported(slot_id1, tsuite->wrapping_mech.mechanism)) { - testsuite_skip(NUM_WRAPPED_KEY_TESTS, "Slot %u doesn't support %s (%u)", + testsuite_skip(NUM_WRAPPED_KEY_TESTS, "Slot %u doesn't support %s (0x%x)", (unsigned int)slot_id1, mech_to_str(tsuite->wrapping_mech.mechanism), (unsigned int)tsuite->wrapping_mech.mechanism); @@ -927,14 +940,14 @@ } if (!wrap_supported(slot_id1, tsuite->wrapping_mech)) { testsuite_skip(NUM_WRAPPED_KEY_TESTS, "Slot %u doesn't support key " - "wrapping with %s (%u)", (unsigned int)slot_id1, + "wrapping with %s (0x%x)", (unsigned int)slot_id1, mech_to_str(tsuite->wrapping_mech.mechanism), (unsigned int)tsuite->wrapping_mech.mechanism); goto testcase_cleanup; } if (!mech_supported(slot_id2, tsuite->wrapping_mech.mechanism)) { - testsuite_skip(NUM_WRAPPED_KEY_TESTS, "Slot %u doesn't support %s (%u)", + testsuite_skip(NUM_WRAPPED_KEY_TESTS, "Slot %u doesn't support %s (0x%x)", (unsigned int)slot_id2, mech_to_str(tsuite->wrapping_mech.mechanism), (unsigned int)tsuite->wrapping_mech.mechanism); @@ -942,7 +955,7 @@ } if (!unwrap_supported(slot_id2, tsuite->wrapping_mech)) { testsuite_skip(NUM_WRAPPED_KEY_TESTS, "Slot %u doesn't support key " - "wrapping with %s (%u)", (unsigned int)slot_id2, + "wrapping with %s (0x%x)", (unsigned int)slot_id2, mech_to_str(tsuite->wrapping_mech.mechanism), (unsigned int)tsuite->wrapping_mech.mechanism); goto testcase_cleanup; @@ -967,31 +980,36 @@ if (!keysize_supported(slot_id1, tsuite->wrapping_key_gen_mech.mechanism, tsuite->rsa_modbits)) { - testcase_skip("Token in slot %ld cannot be used with " - "modbits.='%ld'", slot_id1, tsuite->rsa_modbits); + testcase_skip("Token in slot %ld cannot be used with modbits.='%ld'", + slot_id1, tsuite->rsa_modbits); goto testcase_cleanup; } if (!keysize_supported(slot_id2, tsuite->wrapping_key_gen_mech.mechanism, tsuite->rsa_modbits)) { - testcase_skip("Token in slot %ld cannot be used with " - "modbits.='%ld'", slot_id2, tsuite->rsa_modbits); + testcase_skip("Token in slot %ld cannot be used with modbits.='%ld'", + slot_id2, tsuite->rsa_modbits); goto testcase_cleanup; } if (is_ep11_token(slot_id1) || is_ep11_token(slot_id2)) { if (!is_valid_ep11_pubexp(tsuite->rsa_publ_exp, tsuite->rsa_publ_exp_len)) { - testcase_skip("EP11 Token in cannot be used with " - "publ_exp.='%s'", s); + testcase_skip("EP11 Token in cannot be used with publ_exp.='%s'", s); goto testcase_cleanup; } } if (is_cca_token(slot_id1) || is_cca_token(slot_id2)) { if (!is_valid_cca_pubexp(tsuite->rsa_publ_exp, tsuite->rsa_publ_exp_len)) { - testcase_skip("CCA Token in scannot be used with " - "publ_exp.='%s'", s); + testcase_skip("CCA Token in scannot be used with publ_exp.='%s'", s); + goto testcase_cleanup; + } + } + if (is_soft_token(slot_id1) || is_soft_token(slot_id2)) { + if (!is_valid_soft_pubexp(tsuite->rsa_publ_exp, + tsuite->rsa_publ_exp_len)) { + testcase_skip("Soft Token in scannot be used with publ_exp.='%s'", s); goto testcase_cleanup; } } @@ -999,8 +1017,7 @@ if (!is_valid_tpm_pubexp(tsuite->rsa_publ_exp, tsuite->rsa_publ_exp_len) || !is_valid_tpm_modbits(tsuite->rsa_modbits)) { - testcase_skip("TPM Token cannot " "be used with " - "publ_exp.='%s'", s); + testcase_skip("TPM Token cannot " "be used with publ_exp.='%s'", s); goto testcase_cleanup; } } @@ -1008,8 +1025,7 @@ if (!is_valid_icsf_pubexp(tsuite->rsa_publ_exp, tsuite->rsa_publ_exp_len) || tsuite->rsa_modbits < 1024) { - testcase_skip("ICSF Token cannot be used with " - "publ_exp='%s'.", s); + testcase_skip("ICSF Token cannot be used with publ_exp='%s'.", s); goto testcase_cleanup; } } @@ -1028,6 +1044,11 @@ } rc = create_AESKey(session2, CK_TRUE, key, key_size, &sym_wrap_key2); + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("AES key import is not allowed by policy"); + rc = CKR_OK; + goto testcase_cleanup; + } break; case CKM_DES3_KEY_GEN: @@ -1071,6 +1092,16 @@ } if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("generate wrapping key with mech %s (%u) in slot %lu " + "is not allowed by policy", + mech_to_str(tsuite->wrapping_key_gen_mech.mechanism), + (unsigned int)tsuite->wrapping_key_gen_mech.mechanism, + slot_id2); + rc = CKR_OK; + goto testcase_cleanup; + } + testcase_error("generate wrapping key with mech %s (%u) in slot %lu " "failed, rc=%s", mech_to_str(tsuite->wrapping_key_gen_mech.mechanism), @@ -1135,6 +1166,13 @@ } if (rc != CKR_OK) { + if (rc == CKR_POLICY_VIOLATION) { + testcase_skip("import wrapping key in slot %lu is not allowed by policy", + slot_id1); + rc = CKR_OK; + goto testcase_cleanup; + } + testcase_error("import wrapping key in slot %lu failed, rc=%s", slot_id1, p11_get_ckr(rc)); goto testcase_cleanup; @@ -1327,5 +1365,5 @@ } out: testcase_print_result(); - return ret; + return testcase_return(ret); } diff -Nru opencryptoki-3.16.0+dfsg/testcases/ock_tests.sh.in opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/ock_tests.sh.in --- opencryptoki-3.16.0+dfsg/testcases/ock_tests.sh.in 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/ock_tests.sh.in 2022-02-02 15:05:41.000000000 +0100 @@ -53,6 +53,7 @@ OCK_TESTS+=" pkcs11/get_interface pkcs11/getobjectsize pkcs11/sess_opstate" OCK_TESTS+=" misc_tests/fork misc_tests/obj_mgmt_tests" OCK_TESTS+=" misc_tests/obj_mgmt_lock_tests misc_tests/reencrypt" +OCK_TESTS+=" misc_tests/events misc_tests/cca_export_import_test" OCK_TEST="" OCK_BENCHS="pkcs11/*bench" @@ -174,7 +175,7 @@ return 1 esac - # Check if Tokem is initialized and set $NONEED_TOKEN_INIT if so + # Check if token is initialized and set $NONEED_TOKEN_INIT if so NONEED_TOKEN_INIT=`echo "$TOKDESCR" | grep "Flags:" | grep TOKEN_INITIALIZED | wc -l` } @@ -248,15 +249,18 @@ OCK_TESTS="$OCK_TEST" fi echo "***** Will run the following tests for slot $1: $(ls -U $OCK_TESTS)" + ALLRES=0 for j in $( ls -U $OCK_TESTS ); do echo "** Now executing '$j'" $j -slot $1 $NO_STOP 2>&1 RES=$? - if [ $RES -ne 0 ]; then - echo "ERROR: Testcase $j failed to execute." - exit $RES - fi + if [ $RES -ne 0 ]; then + ALLRES=$RES + echo "ERROR: Testcase $j failed to execute, rc: $RES" + echo "ERROR: Testcase $j failed to execute for slot $1, rc: $RES" >> error_file.$1 + fi done + return $ALLRES } ### @@ -267,10 +271,18 @@ run_benchs() { echo "***** Will run the following benchmarks for slot $1: $(ls -U $OCK_BENCHS)" + ALLRES=0 for i in $( ls -U $OCK_BENCHS ); do echo "** Now executing '$i" $i -slot $1 $NO_STOP 2>&1 + RES=$? + if [ $RES -ne 0 ]; then + ALLRES=$RES + echo "ERROR: Benchmark $i failed to execute, rc: $RES" + echo "ERROR: Benchmark $i failed to execute for slot $1, rc: $RES" >> error_file.$1 + fi done + return $ALLRES } @@ -283,30 +295,49 @@ # where to run if [ -z $SLOT ]; then - NUMSLOT=$(grep '^slot' $PKCONF | wc -l) - for ((i=0; i<$NUMSLOT; i++)); do - SLOT="$SLOT $i" - LOGFILE=1 - done + SLOT="`awk '/slot (.*)/ { print $2; }' $PKCONF`" + LOGFILE=1 fi + # Turn space separated list into array + totrace=($OCK_TRACE_TOKENS) + + rm -f error_file.* + for i in $SLOT; do ( echo "********** Testing Slot $i **********" check_slot $i || { echo "SKIPPING slot $i"; exit; } if [ $NONEED_TOKEN_INIT -eq 0 ]; then init_slot $i || { echo "SKIPPING slot $i"; exit; } fi + for item in "${totrace[@]}"; do + [[ "$i" == "$item" ]] && export OPENCRYPTOKI_TRACE_LEVEL=4 + done if [ "$LOGFILE" = "1" ]; then echo "test output for slot $i stored in log-slot_$i.txt" run_tests $i > "log-slot_$i.txt" 2>&1 else run_tests $i fi - [ -n "$BENCHMARK" ] && run_benchs $i - echo "********** Finished Testing Slot $i **********" + RC=$? + if [ -n "$BENCHMARK" ]; then + run_benchs $i + RC2=$? + if [ $RC2 -ne 0 ]; then + RC=RC2 + fi + fi + echo "********** Finished Testing Slot $i with RC=$RC **********" ) & done wait + ls error_file.* &>/dev/null + if [ $? -eq 0 ]; then + echo "********** At least one slot finished with error **********" + cat error_file.* + rm -f error_file.* + exit 1 + fi } while getopts s:f:l:hc:n arg; do diff -Nru opencryptoki-3.16.0+dfsg/testcases/pkcs11/attribute.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/pkcs11/attribute.c --- opencryptoki-3.16.0+dfsg/testcases/pkcs11/attribute.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/pkcs11/attribute.c 2022-02-02 15:05:41.000000000 +0100 @@ -169,6 +169,10 @@ /* create a public key object */ rc = funcs->C_CreateObject(session, pub_template, 6, &obj_handle); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("Key generation is not allowed by policy"); + goto testcase_cleanup; + } testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -452,13 +456,17 @@ testcase_pass("Successfully verified attribute-array elements."); testcase_cleanup: - rv = funcs->C_DestroyObject(session, obj_handle); - if (rv != CKR_OK) - testcase_error("C_DestroyObject rv=%s", p11_get_ckr(rv)); + if (obj_handle != CK_INVALID_HANDLE) { + rv = funcs->C_DestroyObject(session, obj_handle); + if (rv != CKR_OK) + testcase_error("C_DestroyObject rv=%s", p11_get_ckr(rv)); + } - rv = funcs->C_DestroyObject(session, obj_handle_no_mod); - if (rv != CKR_OK) - testcase_error("C_DestroyObject rv=%s", p11_get_ckr(rv)); + if (obj_handle_no_mod != CK_INVALID_HANDLE) { + rv = funcs->C_DestroyObject(session, obj_handle_no_mod); + if (rv != CKR_OK) + testcase_error("C_DestroyObject rv=%s", p11_get_ckr(rv)); + } testcase_user_logout(); rv = funcs->C_CloseSession(session); @@ -495,13 +503,13 @@ { CK_SESSION_HANDLE hsess = 0; - rc = funcs->C_GetFunctionStatus(hsess); - if (rc != CKR_FUNCTION_NOT_PARALLEL) - return rc; - - rc = funcs->C_CancelFunction(hsess); - if (rc != CKR_FUNCTION_NOT_PARALLEL) - return rc; + rv = funcs->C_GetFunctionStatus(hsess); + if (rv != CKR_FUNCTION_NOT_PARALLEL) + return rv; + + rv = funcs->C_CancelFunction(hsess); + if (rv != CKR_FUNCTION_NOT_PARALLEL) + return rv; } testcase_setup(0); @@ -510,6 +518,5 @@ funcs->C_Finalize(NULL); - /* make sure we return non-zero if rv is non-zero */ - return ((rv == 0) || (rv % 256) ? (int)rv : -1); + return testcase_return(rc); } diff -Nru opencryptoki-3.16.0+dfsg/testcases/pkcs11/copyobjects.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/pkcs11/copyobjects.c --- opencryptoki-3.16.0+dfsg/testcases/pkcs11/copyobjects.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/pkcs11/copyobjects.c 2022-02-02 15:05:41.000000000 +0100 @@ -113,18 +113,30 @@ // Create an AES Key Object. rc = funcs->C_CreateObject(session, aes_tmpl, 4, &keyobj); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("Key import is not allowed by policy"); + goto testcase_cleanup; + } testcase_error("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto testcase_cleanup; } rc = funcs->C_CreateObject(session, aes_tmpl_no_copy, 5, &keyobj_no_copy); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("Key import is not allowed by policy"); + goto testcase_cleanup; + } testcase_error("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto testcase_cleanup; } rc = funcs->C_CreateObject(session, aes_tmpl_copy, 5, &keyobj_copy); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("Key import is not allowed by policy"); + goto testcase_cleanup; + } testcase_error("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -357,13 +369,13 @@ { CK_SESSION_HANDLE hsess = 0; - rc = funcs->C_GetFunctionStatus(hsess); - if (rc != CKR_FUNCTION_NOT_PARALLEL) - return rc; + rv = funcs->C_GetFunctionStatus(hsess); + if (rv != CKR_FUNCTION_NOT_PARALLEL) + return rv; rc = funcs->C_CancelFunction(hsess); - if (rc != CKR_FUNCTION_NOT_PARALLEL) - return rc; + if (rv != CKR_FUNCTION_NOT_PARALLEL) + return rv; } testcase_setup(0); @@ -372,6 +384,5 @@ funcs->C_Finalize(NULL); - /* make sure we return non-zero if rv is non-zero */ - return ((rv == 0) || (rv % 256) ? (int)rv : -1); + return testcase_return(rc); } diff -Nru opencryptoki-3.16.0+dfsg/testcases/pkcs11/destroyobjects.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/pkcs11/destroyobjects.c --- opencryptoki-3.16.0+dfsg/testcases/pkcs11/destroyobjects.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/pkcs11/destroyobjects.c 2022-02-02 15:05:41.000000000 +0100 @@ -85,6 +85,10 @@ for (i = 0; i < 4; i++) { rc = funcs->C_CreateObject(session, aes_tmpl, 4, &keyobj[num_objs]); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("Key generation is not allowed by policy"); + goto testcase_cleanup; + } testcase_error("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -100,6 +104,10 @@ rc = funcs->C_GenerateKey(session, &mech, aesgen_tmpl, 5, &keyobj[num_objs]); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("Key generation is not allowed by policy"); + goto testcase_cleanup; + } testcase_error("C_GenerateObject() rc = %s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -288,13 +296,13 @@ { CK_SESSION_HANDLE hsess = 0; - rc = funcs->C_GetFunctionStatus(hsess); - if (rc != CKR_FUNCTION_NOT_PARALLEL) - return rc; - - rc = funcs->C_CancelFunction(hsess); - if (rc != CKR_FUNCTION_NOT_PARALLEL) - return rc; + rv = funcs->C_GetFunctionStatus(hsess); + if (rv != CKR_FUNCTION_NOT_PARALLEL) + return rv; + + rv = funcs->C_CancelFunction(hsess); + if (rv != CKR_FUNCTION_NOT_PARALLEL) + return rv; } testcase_setup(0); @@ -303,6 +311,5 @@ funcs->C_Finalize(NULL); - /* make sure we return non-zero if rv is non-zero */ - return ((rv == 0) || (rv % 256) ? (int)rv : -1); + return testcase_return(rc); } diff -Nru opencryptoki-3.16.0+dfsg/testcases/pkcs11/findobjects.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/pkcs11/findobjects.c --- opencryptoki-3.16.0+dfsg/testcases/pkcs11/findobjects.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/pkcs11/findobjects.c 2022-02-02 15:05:41.000000000 +0100 @@ -86,6 +86,10 @@ /* Create 2 des3 session key objects */ rc = funcs->C_CreateObject(session, des3_tmpl, 4, &keyobj[num_objs]); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("key import is not allowed by policy"); + return CKR_OK; + } testcase_error("C_CreateObject() rc = %s", p11_get_ckr(rc)); return rc; } @@ -93,6 +97,10 @@ rc = funcs->C_CreateObject(session, des3_tmpl, 4, &keyobj[num_objs]); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("EC key generation is not allowed by policy"); + goto testcase_cleanup; + } testcase_error("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -101,6 +109,10 @@ /* Create 2 aes private session key objects */ rc = funcs->C_CreateObject(session, aes_tmpl, 5, &keyobj[num_objs]); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("EC key generation is not allowed by policy"); + goto testcase_cleanup; + } testcase_error("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -108,6 +120,10 @@ rc = funcs->C_CreateObject(session, aes_tmpl, 5, &keyobj[num_objs]); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("EC key generation is not allowed by policy"); + goto testcase_cleanup; + } testcase_error("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -275,13 +291,13 @@ { CK_SESSION_HANDLE hsess = 0; - rc = funcs->C_GetFunctionStatus(hsess); - if (rc != CKR_FUNCTION_NOT_PARALLEL) - return rc; - - rc = funcs->C_CancelFunction(hsess); - if (rc != CKR_FUNCTION_NOT_PARALLEL) - return rc; + rv = funcs->C_GetFunctionStatus(hsess); + if (rv != CKR_FUNCTION_NOT_PARALLEL) + return rv; + + rv = funcs->C_CancelFunction(hsess); + if (rv != CKR_FUNCTION_NOT_PARALLEL) + return rv; } testcase_setup(0); @@ -290,6 +306,5 @@ funcs->C_Finalize(NULL); - /* make sure we return non-zero if rv is non-zero */ - return ((rv == 0) || (rv % 256) ? (int)rv : -1); + return testcase_return(rc); } diff -Nru opencryptoki-3.16.0+dfsg/testcases/pkcs11/generate_keypair.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/pkcs11/generate_keypair.c --- opencryptoki-3.16.0+dfsg/testcases/pkcs11/generate_keypair.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/pkcs11/generate_keypair.c 2022-02-02 15:05:41.000000000 +0100 @@ -101,12 +101,22 @@ mech.ulParameterLen = 0; mech.pParameter = NULL; + if (!mech_supported(SLOT_ID, CKM_RSA_PKCS_KEY_PAIR_GEN)) { + testcase_skip("Mechanism CKM_RSA_PKCS_KEY_PAIR_GEN is not supported with slot " + "%ld. Skipping key check", SLOT_ID); + goto testcase_cleanup; + } + /* Assertion #1: generate an RSA key pair. */ testcase_new_assertion(); rc = funcs->C_GenerateKeyPair(session, &mech, publ_tmpl, 3, NULL, 0, &publ_key, &priv_key); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("Key generation is not allowed by policy"); + goto testcase_cleanup; + } testcase_fail("C_GenerateKeyPair() rc = %s", p11_get_ckr(rc)); goto testcase_cleanup; } @@ -236,19 +246,18 @@ { CK_SESSION_HANDLE hsess = 0; - rc = funcs->C_GetFunctionStatus(hsess); - if (rc != CKR_FUNCTION_NOT_PARALLEL) - return rc; - - rc = funcs->C_CancelFunction(hsess); - if (rc != CKR_FUNCTION_NOT_PARALLEL) - return rc; + rv = funcs->C_GetFunctionStatus(hsess); + if (rv != CKR_FUNCTION_NOT_PARALLEL) + return rv; + + rv = funcs->C_CancelFunction(hsess); + if (rv != CKR_FUNCTION_NOT_PARALLEL) + return rv; } testcase_setup(0); rc = do_GenerateKeyPairRSA(); testcase_print_result(); - /* make sure we return non-zero if rv is non-zero */ - return ((rv == 0) || (rv % 256) ? (int)rv : -1); + return testcase_return(rc); } diff -Nru opencryptoki-3.16.0+dfsg/testcases/pkcs11/gen_purpose.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/pkcs11/gen_purpose.c --- opencryptoki-3.16.0+dfsg/testcases/pkcs11/gen_purpose.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/pkcs11/gen_purpose.c 2022-02-02 15:05:41.000000000 +0100 @@ -740,13 +740,13 @@ { CK_SESSION_HANDLE hsess = 0; - rc = funcs->C_GetFunctionStatus(hsess); - if (rc != CKR_FUNCTION_NOT_PARALLEL) - return rc; + rv = funcs->C_GetFunctionStatus(hsess); + if (rv != CKR_FUNCTION_NOT_PARALLEL) + return rv; - rc = funcs->C_CancelFunction(hsess); - if (rc != CKR_FUNCTION_NOT_PARALLEL) - return rc; + rv = funcs->C_CancelFunction(hsess); + if (rv != CKR_FUNCTION_NOT_PARALLEL) + return rv; } testcase_setup(0); @@ -755,6 +755,5 @@ funcs->C_Finalize(NULL_PTR); - /* make sure we return non-zero if rv is non-zero */ - return ((rv == 0) || (rv % 256) ? (int)rv : -1); + return testcase_return(rv); } diff -Nru opencryptoki-3.16.0+dfsg/testcases/pkcs11/get_interface.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/pkcs11/get_interface.c --- opencryptoki-3.16.0+dfsg/testcases/pkcs11/get_interface.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/pkcs11/get_interface.c 2022-02-02 15:05:41.000000000 +0100 @@ -462,6 +462,5 @@ ret: testcase_print_result(); - /* make sure we return non-zero if rc is non-zero */ - return ((rc == 0) || (rc % 256) ? (int)rc : -1); + return testcase_return(rc); } diff -Nru opencryptoki-3.16.0+dfsg/testcases/pkcs11/getobjectsize.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/pkcs11/getobjectsize.c --- opencryptoki-3.16.0+dfsg/testcases/pkcs11/getobjectsize.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/pkcs11/getobjectsize.c 2022-02-02 15:05:41.000000000 +0100 @@ -61,6 +61,10 @@ // Create an AES Key Object. rc = funcs->C_CreateObject(session, aes_tmpl, 4, &keyobj); if (rc != CKR_OK) { + if (is_rejected_by_policy(rc, session)) { + testcase_skip("Key import is not allowed by policy"); + goto testcase_cleanup; + } testcase_error("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto testcase_cleanup; } diff -Nru opencryptoki-3.16.0+dfsg/testcases/pkcs11/sess_opstate.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/pkcs11/sess_opstate.c --- opencryptoki-3.16.0+dfsg/testcases/pkcs11/sess_opstate.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/pkcs11/sess_opstate.c 2022-02-02 15:05:41.000000000 +0100 @@ -59,6 +59,8 @@ CK_ULONG opstatelen; CK_BYTE *opstate = NULL; + testcase_begin("Get/SetOperationState digest test"); + // open 2 sessions flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; rc = funcs->C_OpenSession(slot_id, flags, NULL, NULL, &s1); @@ -73,6 +75,12 @@ goto out; } + if (!mech_supported(SLOT_ID, mech1.mechanism)) { + testcase_skip("Mechanism CKM_SHA256 is not supported with slot " + "%ld. Skipping key check", SLOT_ID); + goto out; + } + // init digest for both sessions rc = funcs->C_DigestInit(s1, &mech1); if (rc != CKR_OK) { @@ -123,6 +131,10 @@ opstatelen = 0; rc = funcs->C_GetOperationState(s2, NULL, &opstatelen); if (rc != CKR_OK) { + if (rc == CKR_STATE_UNSAVEABLE) { + testcase_skip("Get/SetOperationState digest test: state unsavable"); + goto out; + } testcase_error("C_GetOperationState rc=%s", p11_get_ckr(rc)); goto out; } @@ -135,6 +147,10 @@ rc = funcs->C_GetOperationState(s2, opstate, &opstatelen); if (rc != CKR_OK) { + if (rc == CKR_STATE_UNSAVEABLE) { + testcase_skip("Get/SetOperationState digest test: state unsavable"); + goto out; + } testcase_error("C_GetOperationState rc=%s", p11_get_ckr(rc)); goto out; } @@ -151,6 +167,12 @@ goto out; } + if (!mech_supported(SLOT_ID, mech2.mechanism)) { + testcase_skip("Mechanism CKM_SHA_1 is not supported with slot " + "%ld. Skipping key check", SLOT_ID); + continue; + } + // so now let's do a digest init/update/finish // to randomize the memory a little rc = funcs->C_DigestInit(s2, &mech2); @@ -214,6 +236,7 @@ goto out; } + testcase_new_assertion(); testcase_pass("Get/SetOperationState digest test"); out: @@ -271,17 +294,17 @@ { CK_SESSION_HANDLE hsess = 0; - rc = funcs->C_GetFunctionStatus(hsess); - if (rc != CKR_FUNCTION_NOT_PARALLEL) - return rc; - - rc = funcs->C_CancelFunction(hsess); - if (rc != CKR_FUNCTION_NOT_PARALLEL) - return rc; - } - - rv = sess_opstate_funcs(loops); + rv = funcs->C_GetFunctionStatus(hsess); + if (rv != CKR_FUNCTION_NOT_PARALLEL) + return rv; + + rv = funcs->C_CancelFunction(hsess); + if (rv != CKR_FUNCTION_NOT_PARALLEL) + return rv; + } + testcase_setup(0); + rc = sess_opstate_funcs(loops); + testcase_print_result(); - /* make sure we return non-zero if rv is non-zero */ - return ((rv == 0) || (rv % 256) ? (int)rv : -1); + return testcase_return(rc); } diff -Nru opencryptoki-3.16.0+dfsg/testcases/policy/policy.mk opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/policy/policy.mk --- opencryptoki-3.16.0+dfsg/testcases/policy/policy.mk 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/policy/policy.mk 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,16 @@ +noinst_PROGRAMS += testcases/policy/policytest + +testcases_policy_policytest_CFLAGS = ${testcases_inc} +testcases_policy_policytest_LDFLAGS = -ldl +testcases_policy_policytest_SOURCES = testcases/policy/policytest.c + +noinst_SCRIPTS += testcases/policy/policytest.sh +CLEANFILES += testcases/policy/policytest.sh +EXTRA_DIST += testcases/policy/policytest.sh + +testcases/policy/policytest.sh: testcases/policy/policytest.sh.in + $(AM_V_GEN)@SED@ -e s!\@sysconfdir\@!"@sysconfdir@"!g \ + -e s!\@sbindir\@!"@sbindir@"!g \ + -e s!\@libdir\@!"@libdir@"!g < $< > $@-t && \ + @CHMOD@ a+x $@-t && \ + $(am__mv) $@-t $@ diff -Nru opencryptoki-3.16.0+dfsg/testcases/policy/policytest.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/policy/policytest.c --- opencryptoki-3.16.0+dfsg/testcases/policy/policytest.c 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/policy/policytest.c 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,1072 @@ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pkcs11types.h" +#include "ec_curves.h" + +#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0])) + +#define PKCS11_MAX_PIN_LEN 128 +#define PKCS11_SO_PIN_ENV_VAR "PKCS11_SO_PIN" +#define PKCS11_USER_PIN_ENV_VAR "PKCS11_USER_PIN" + +#define POLICY_TEST_RSA_SIZE 4096 +#define POLICY_TEST_EC_SIZE 384 +#define POLICY_TEST_AES_SIZE 256 + +/* Tests implemented (Bit indices) */ +#define TEST_RSA 1u +#define TEST_EC 2u +#define TEST_AESWRAP 3u +#define TEST_DIGEST 4u +#define TEST_DH 5u + +static CK_FUNCTION_LIST *funcs; +static void *pkcs11lib; +static CK_SESSION_HANDLE session; + +static const char rsamessage[POLICY_TEST_RSA_SIZE / 8 - 11] = {0}; +static const char ecmessage[POLICY_TEST_EC_SIZE / 8] = {0}; + +static const CK_UTF8CHAR poltestlabel[] = "policytest key"; +static const CK_UTF8CHAR poltestdhlabelA[] = "policytest key A"; +static const CK_UTF8CHAR poltestdhlabelB[] = "policytest key B"; + +static CK_BBOOL tokenkeys = CK_FALSE; + +static struct { + CK_OBJECT_HANDLE rsapub; + CK_OBJECT_HANDLE rsapriv; + CK_OBJECT_HANDLE ecpub; + CK_OBJECT_HANDLE ecpriv; + CK_OBJECT_HANDLE aes; + CK_OBJECT_HANDLE dhpubA; + CK_OBJECT_HANDLE dhprivA; + CK_OBJECT_HANDLE dhpubB; + CK_OBJECT_HANDLE dhprivB; +} keys; + +/* copied from testcases/crypto/dh_func.c */ +CK_BYTE DH_PUBL_PRIME[128] = { + 0xd5, 0xb1, 0xaa, 0x6a, 0x3b, 0x85, 0x50, 0xf0, 0xe2, + 0xea, 0x6b, 0xec, 0x26, 0x3b, 0xe0, 0xbf, 0x7a, 0x82, + 0x45, 0x1b, 0xa8, 0x0a, 0x54, 0x2e, 0x14, 0x2c, 0xc2, + 0x58, 0xb1, 0xf5, 0x59, 0xec, 0x7d, 0x16, 0x9e, 0x00, + 0x62, 0xb3, 0xa7, 0xdc, 0x38, 0x6f, 0x64, 0x40, 0xfc, + 0x0d, 0x3e, 0x0b, 0x66, 0x13, 0x5e, 0xa5, 0x84, 0x90, + 0x26, 0x62, 0xcf, 0x5a, 0x14, 0x72, 0x2d, 0x1b, 0x37, + 0x7e, 0x8a, 0x4b, 0xc0, 0xb7, 0xf2, 0x63, 0xd1, 0xaa, + 0x51, 0x92, 0x96, 0x18, 0xae, 0xb9, 0xfd, 0x5f, 0x9d, + 0x5d, 0xdf, 0x75, 0xa9, 0x80, 0x3d, 0xaa, 0xc2, 0x54, + 0x00, 0xcc, 0xc1, 0x9e, 0x31, 0x4d, 0x22, 0x31, 0x44, + 0xe9, 0x69, 0x34, 0xae, 0xcf, 0xcd, 0x6d, 0xf6, 0xe9, + 0x37, 0x20, 0xa4, 0xd3, 0x85, 0x24, 0xff, 0x9f, 0x39, + 0xeb, 0x78, 0xf2, 0xd1, 0xc3, 0xf9, 0x66, 0xab, 0xbd, + 0x2d, 0xd3 +}; + + +CK_BYTE DH_PUBL_BASE[128] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02 +}; + + +static void unloadLib(void) +{ + if (pkcs11lib) + dlclose(pkcs11lib); +} + +static void finalizeLib(void) +{ + funcs->C_Finalize(NULL); +} + +static void closeSession(void) +{ + funcs->C_CloseSession(session); +} + +static void logoutUser(void) +{ + funcs->C_Logout(session); +} + +static int doLoadLib(void) +{ + const char *lib = "libopencryptoki.so"; + const char *envlib; + CK_RV (*pGetFuncList)(CK_FUNCTION_LIST **); + CK_RV rc; + + if ((envlib = getenv("PKCSLIB")) != NULL) + lib = envlib; + pkcs11lib = dlopen(lib, RTLD_NOW); + if (pkcs11lib == NULL) { + fprintf(stderr, "Failed to open %s: %s\n", lib, dlerror()); + return -1; + } + atexit(unloadLib); + *(void**)(&pGetFuncList) = dlsym(pkcs11lib, "C_GetFunctionList"); + if (pGetFuncList == NULL) { + fprintf(stderr, "Failed to find C_GetFunctionList symbol in %s\n", lib); + return -1; + } + rc = pGetFuncList(&funcs); + if (rc != CKR_OK) { + fprintf(stderr, "C_GetFunctionList failed with 0x%lx\n", rc); + return -1; + } + return 0; +} + +static int doInitLib(void) +{ + CK_C_INITIALIZE_ARGS cinit_args; + CK_RV rc; + + memset(&cinit_args, 0x0, sizeof(cinit_args)); + cinit_args.flags = CKF_OS_LOCKING_OK; + rc = funcs->C_Initialize(&cinit_args); + if (rc != CKR_OK) { + fprintf(stderr, "C_Initialize failed with 0x%lx\n", rc); + return -1; + } + atexit(finalizeLib); + return 0; +} + +static int doOpenSession(CK_SLOT_ID slot) +{ + CK_RV rc; + CK_FLAGS flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + + rc = funcs->C_OpenSession(slot, flags, NULL, NULL, &session); + if (rc != CKR_OK) { + fprintf(stderr, "Failed to open r/w session (rc = 0x%lx)\n", rc); + return -1; + } + atexit(closeSession); + return 0; +} + +static int doLoginUser(unsigned char *pin) +{ + CK_RV rc; + + rc = funcs->C_Login(session, CKU_USER, pin, strlen((char *)pin)); + if (rc != CKR_OK) { + fprintf(stderr, "Failed to log in to token (rc = 0x%lx)\n", rc); + return -1; + } + atexit(logoutUser); + return 0; +} + +static int is_cca_token(CK_SLOT_ID slot_id) +{ + CK_RV rc; + CK_TOKEN_INFO tokinfo; + + rc = funcs->C_GetTokenInfo(slot_id, &tokinfo); + if (rc != CKR_OK) + return FALSE; + + return strstr((const char *) tokinfo.model, "CCA") != NULL; +} + +static CK_RV generateRSAKey(void) +{ + CK_OBJECT_HANDLE pubkey, privkey; + CK_MECHANISM mech = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL, 0 }; + CK_BYTE subject[] = {0}; + CK_BYTE id[] = {123}; + CK_BBOOL cktrue = TRUE; + CK_ULONG modulusBits = POLICY_TEST_RSA_SIZE; + CK_BYTE publicExponent[] = {0x01, 0x00, 0x01}; + CK_ATTRIBUTE pubkeyTemplate[] = { + {CKA_ENCRYPT, &cktrue, sizeof(cktrue)}, + {CKA_VERIFY, &cktrue, sizeof(cktrue)}, + {CKA_WRAP, &cktrue, sizeof(cktrue)}, + {CKA_MODULUS_BITS, &modulusBits, sizeof(modulusBits)}, + {CKA_PUBLIC_EXPONENT, publicExponent, sizeof(publicExponent)}, + {CKA_TOKEN, &tokenkeys, sizeof(tokenkeys)}, + {CKA_LABEL, (void *)poltestlabel, sizeof(poltestlabel)} + }; + CK_ATTRIBUTE privkeyTemplate[] = { + {CKA_TOKEN, &cktrue, sizeof(cktrue)}, + {CKA_PRIVATE, &cktrue, sizeof(cktrue)}, + {CKA_SUBJECT, subject, 0}, + {CKA_ID, id, sizeof(id)}, + {CKA_DECRYPT, &cktrue, sizeof(cktrue)}, + {CKA_SIGN, &cktrue, sizeof(cktrue)}, + {CKA_UNWRAP, &cktrue, sizeof(cktrue)}, + {CKA_TOKEN, &tokenkeys, sizeof(tokenkeys)}, + {CKA_LABEL, (void *)poltestlabel, sizeof(poltestlabel)} + }; + + return funcs->C_GenerateKeyPair(session, &mech, + pubkeyTemplate, ARRAY_SIZE(pubkeyTemplate), + privkeyTemplate, ARRAY_SIZE(privkeyTemplate), + &pubkey, &privkey); +} + +static CK_RV generateECKey(void) +{ + CK_OBJECT_HANDLE pubkey, privkey; + CK_BYTE secp384r1[] = OCK_SECP384R1; + CK_MECHANISM mech = { CKM_EC_KEY_PAIR_GEN, NULL, 0 }; + CK_BYTE subject[] = {0}; + CK_BYTE id[] = { 123 }; + CK_BBOOL true = TRUE; + CK_ATTRIBUTE publicKeyTemplate[] = { + {CKA_VERIFY, &true, sizeof(true)}, + {CKA_EC_PARAMS, &secp384r1, sizeof(secp384r1)}, + {CKA_TOKEN, &tokenkeys, sizeof(tokenkeys)}, + {CKA_LABEL, (void *)poltestlabel, sizeof(poltestlabel)} + }; + CK_ATTRIBUTE privateKeyTemplate[] = { + {CKA_PRIVATE, &true, sizeof(true)}, + {CKA_SUBJECT, subject, 0}, + {CKA_ID, id, sizeof(id)}, + {CKA_SIGN, &true, sizeof(true)}, + {CKA_DERIVE, &true, sizeof(true)}, + {CKA_TOKEN, &tokenkeys, sizeof(tokenkeys)}, + {CKA_LABEL, (void *)poltestlabel, sizeof(poltestlabel)} + }; + + return funcs->C_GenerateKeyPair(session, &mech, + publicKeyTemplate, ARRAY_SIZE(publicKeyTemplate), + privateKeyTemplate, ARRAY_SIZE(privateKeyTemplate), + &pubkey, &privkey); +} + +static CK_RV generateAESKey() +{ + CK_OBJECT_HANDLE key; + CK_ULONG keylen = POLICY_TEST_AES_SIZE / 8; + CK_ATTRIBUTE key_gen_tmpl[] = { + {CKA_VALUE_LEN, &keylen, sizeof(CK_ULONG)}, + {CKA_TOKEN, &tokenkeys, sizeof(tokenkeys)}, + {CKA_LABEL, (void *)poltestlabel, sizeof(poltestlabel)} + }; + CK_MECHANISM mech = { + .mechanism = CKM_AES_KEY_GEN, + .ulParameterLen = 0, + .pParameter = NULL, + }; + + return funcs->C_GenerateKey(session, &mech, key_gen_tmpl, + ARRAY_SIZE(key_gen_tmpl), &key); +} + +static CK_RV generateDHKeys(void) +{ + CK_OBJECT_HANDLE pubkeyA, privkeyA, pubkeyB, privkeyB; + CK_OBJECT_CLASS pub_key_class = CKO_PUBLIC_KEY; + CK_KEY_TYPE key_type = CKK_DH; + CK_OBJECT_CLASS priv_key_class = CKO_PRIVATE_KEY; + CK_BBOOL ltrue = CK_TRUE; + CK_ATTRIBUTE publA_tmpl[] = { + {CKA_CLASS, &pub_key_class, sizeof(pub_key_class)}, + {CKA_KEY_TYPE, &key_type, sizeof(key_type)}, + {CKA_PRIME, DH_PUBL_PRIME, sizeof(DH_PUBL_PRIME)}, + {CKA_BASE, DH_PUBL_BASE, sizeof(DH_PUBL_BASE)}, + {CKA_TOKEN, &tokenkeys, sizeof(tokenkeys)}, + {CKA_LABEL, (void *)poltestdhlabelA, sizeof(poltestdhlabelA)} + }; + CK_ATTRIBUTE privA_tmpl[] = { + {CKA_CLASS, &priv_key_class, sizeof(priv_key_class)}, + {CKA_KEY_TYPE, &key_type, sizeof(key_type)}, + {CKA_DERIVE, <rue, sizeof(ltrue)}, + {CKA_TOKEN, &tokenkeys, sizeof(tokenkeys)}, + {CKA_LABEL, (void *)poltestdhlabelA, sizeof(poltestdhlabelA)} + }; + CK_ATTRIBUTE publB_tmpl[] = { + {CKA_CLASS, &pub_key_class, sizeof(pub_key_class)}, + {CKA_KEY_TYPE, &key_type, sizeof(key_type)}, + {CKA_PRIME, DH_PUBL_PRIME, sizeof(DH_PUBL_PRIME)}, + {CKA_BASE, DH_PUBL_BASE, sizeof(DH_PUBL_BASE)}, + {CKA_TOKEN, &tokenkeys, sizeof(tokenkeys)}, + {CKA_LABEL, (void *)poltestdhlabelB, sizeof(poltestdhlabelB)} + }; + CK_ATTRIBUTE privB_tmpl[] = { + {CKA_CLASS, &priv_key_class, sizeof(priv_key_class)}, + {CKA_KEY_TYPE, &key_type, sizeof(key_type)}, + {CKA_DERIVE, <rue, sizeof(ltrue)}, + {CKA_TOKEN, &tokenkeys, sizeof(tokenkeys)}, + {CKA_LABEL, (void *)poltestdhlabelB, sizeof(poltestdhlabelB)} + }; + CK_MECHANISM mech = { CKM_DH_PKCS_KEY_PAIR_GEN, NULL, 0 }; + CK_RV rc; + + rc = funcs->C_GenerateKeyPair(session, &mech, + publA_tmpl, ARRAY_SIZE(publA_tmpl), + privA_tmpl, ARRAY_SIZE(privA_tmpl), + &pubkeyA, &privkeyA); + if (rc != CKR_OK) + return rc; + rc = funcs->C_GenerateKeyPair(session, &mech, + publB_tmpl, ARRAY_SIZE(publB_tmpl), + privB_tmpl, ARRAY_SIZE(privB_tmpl), + &pubkeyB, &privkeyB); + if (rc != CKR_OK) { + funcs->C_DestroyObject(session, pubkeyA); + funcs->C_DestroyObject(session, privkeyA); + } + return rc; +} + +static CK_RV encryptRSA(CK_OBJECT_HANDLE key, CK_BYTE *res, CK_ULONG *reslen) +{ + CK_MECHANISM mech = { .mechanism = CKM_RSA_PKCS, + .pParameter = NULL, + .ulParameterLen = 0 }; + CK_RV rc; + + rc = funcs->C_EncryptInit(session, &mech, key); + if (rc != CKR_OK) + return rc; + rc = funcs->C_Encrypt(session, (CK_BYTE *)rsamessage, sizeof(rsamessage), + res, reslen); + return rc; +} + +static CK_RV decryptRSA(CK_OBJECT_HANDLE key, CK_BYTE *enc, CK_ULONG len) +{ + CK_MECHANISM mech = { .mechanism = CKM_RSA_PKCS, + .pParameter = NULL, + .ulParameterLen = 0 }; + CK_BYTE dec[POLICY_TEST_RSA_SIZE / 8]; + CK_ULONG declen = sizeof(dec); + CK_RV rc; + + rc = funcs->C_DecryptInit(session, &mech, key); + if (rc != CKR_OK) + return rc; + rc = funcs->C_Decrypt(session, enc, len, dec, &declen); + if (rc != CKR_OK) + return rc; + if (memcmp(rsamessage, dec, declen)) + return CKR_GENERAL_ERROR; + return rc; +} + +static int runRSATest(void) +{ + CK_BYTE enc[POLICY_TEST_RSA_SIZE / 8]; + CK_ULONG enclen = sizeof(enc); + CK_RV rc; + + rc = encryptRSA(keys.rsapub, enc, &enclen); + if (rc != CKR_OK) { + fprintf(stderr, "WARN: RSA public key usage failed with 0x%lx\n", rc); + return -1; + } + rc = decryptRSA(keys.rsapriv, enc, enclen); + if (rc != CKR_OK) { + fprintf(stderr, "WARN: RSA private key usage failed with 0x%lx\n", rc); + return -1; + } + return 0; +} + + +static CK_RV signEC(CK_OBJECT_HANDLE key, CK_BYTE *sig, CK_ULONG *siglen) +{ + CK_MECHANISM mech = { CKM_ECDSA, NULL, 0 }; + CK_RV rc; + + rc = funcs->C_SignInit(session, &mech, key); + if (rc != CKR_OK) + return rc; + rc = funcs->C_Sign(session, (CK_BYTE *)ecmessage, sizeof(ecmessage), + sig, siglen); + return rc; +} + +static CK_RV verifyEC(CK_OBJECT_HANDLE key, CK_BYTE *sig, CK_ULONG siglen) +{ + CK_MECHANISM mech = { CKM_ECDSA, NULL, 0 }; + CK_RV rc; + + rc = funcs->C_VerifyInit(session, &mech, key); + if (rc != CKR_OK) + return rc; + rc = funcs->C_Verify(session, (CK_BYTE *)ecmessage, sizeof(ecmessage), + sig, siglen); + return rc; +} + +static int runECTest(void) +{ + CK_BYTE sig[2 * POLICY_TEST_EC_SIZE / 8]; + CK_ULONG siglen = sizeof(sig); + CK_RV rc; + + rc = signEC(keys.ecpriv, sig, &siglen); + if (rc != CKR_OK) { + fprintf(stderr, "WARN: EC private key usage failed with 0x%lx\n", rc); + return -1; + } + rc = verifyEC(keys.ecpub, sig, siglen); + if (rc != CKR_OK) { + fprintf(stderr, "WARN: EC public key usage failed with 0x%lx\n", rc); + return -1; + } + return 0; +} + +static CK_RV wrapAESKey(CK_OBJECT_HANDLE key, CK_BYTE **wrapped, CK_ULONG *len) +{ + CK_BYTE iv[16] = {0}; + CK_MECHANISM mech = { CKM_AES_CBC_PAD, iv, sizeof(iv) }; + CK_RV rc; + CK_BYTE *res; + + rc = funcs->C_WrapKey(session, &mech, key, key, NULL, len); + if (rc != CKR_OK) + return rc; + res = calloc(1, *len); + if (!res) + return CKR_HOST_MEMORY; + rc = funcs->C_WrapKey(session, &mech, key, key, res, len); + if (rc != CKR_OK) { + free(res); + return rc; + } + *wrapped = res; + return rc; +} + +static CK_RV unwrapAESKey(CK_OBJECT_HANDLE key, CK_BYTE *wrapped, CK_ULONG len, + CK_OBJECT_HANDLE_PTR unwrapped, int iscca) +{ + CK_BYTE iv[16] = {0}; + CK_MECHANISM mech = { CKM_AES_CBC_PAD, iv, sizeof(iv) }; + CK_RV rc; + CK_OBJECT_CLASS key_class = CKO_SECRET_KEY; + CK_KEY_TYPE key_type = CKK_AES; + CK_ULONG key_size = POLICY_TEST_AES_SIZE / 8; + CK_ATTRIBUTE template[] = { + {CKA_CLASS, &key_class, sizeof(key_class)}, + {CKA_KEY_TYPE, &key_type, sizeof(key_type)}, + {CKA_VALUE_LEN, &key_size, sizeof(key_size)} /* For CCA only */ + }; + CK_ULONG templatecount = 2 + iscca; + + rc = funcs->C_UnwrapKey(session, &mech, key, wrapped, len, + template, templatecount, unwrapped); + free(wrapped); + return rc; +} + +static int runAESWrapTest(CK_SLOT_ID slot) +{ + CK_OBJECT_HANDLE unwrapped = CK_INVALID_HANDLE; + CK_BYTE *wrapped; + CK_ULONG wrappedlen; + CK_RV rc; + + rc = wrapAESKey(keys.aes, &wrapped, &wrappedlen); + if (rc != CKR_OK) { + fprintf(stderr, "WARN: AES wrapping failed with 0x%lx\n", rc); + return -1; + } + rc = unwrapAESKey(keys.aes, wrapped, wrappedlen, &unwrapped, + is_cca_token(slot)); + funcs->C_DestroyObject(session, unwrapped); + if (rc != CKR_OK) { + fprintf(stderr, "WARN: AES unwrapping failed with 0x%lx\n", rc); + return -1; + } + return 0; +} + +static int runDIGESTTest(void) +{ + CK_BYTE digest[64]; + CK_MECHANISM mech = { CKM_SHA512, NULL, 0 }; + CK_RV rc; + CK_ULONG len = sizeof(digest); + + rc = funcs->C_DigestInit(session, &mech); + if (rc != CKR_OK) { + fprintf(stderr, "WARN: Digest initialization failed with 0x%lx\n", rc); + return -1; + } + rc = funcs->C_Digest(session, (CK_BYTE *)rsamessage, sizeof(rsamessage), + digest, &len); + if (rc != CKR_OK) { + /* No policy checking done in C_Digest... */ + fprintf(stderr, "WARN: Digest failed with 0x%lx\n", rc); + return -1; + } + return 0; +} + + +static int runDHTest(void) +{ + CK_BYTE key_value[sizeof(DH_PUBL_PRIME) * 2]; + CK_ATTRIBUTE extr_tmpl = {CKA_VALUE, key_value, sizeof(key_value)}; + CK_ULONG secret_key_size = sizeof(DH_PUBL_PRIME); + CK_OBJECT_CLASS secret_key_class = CKO_SECRET_KEY; + CK_KEY_TYPE secret_key_type = CKK_GENERIC_SECRET; + CK_ATTRIBUTE secret_tmpl[] = { + {CKA_CLASS, &secret_key_class, sizeof(secret_key_class)}, + {CKA_KEY_TYPE, &secret_key_type, sizeof(secret_key_type)}, + {CKA_VALUE_LEN, &secret_key_size, sizeof(secret_key_size)} + }; + CK_MECHANISM mech = { CKM_DH_PKCS_DERIVE, key_value, 0 }; + CK_OBJECT_HANDLE derived = CK_INVALID_HANDLE; + CK_RV rc; + + // Extract the peer's public key + rc = funcs->C_GetAttributeValue(session, keys.dhpubB, &extr_tmpl, 1); + if (rc != CKR_OK) { + fprintf(stderr, + "WARN: Getting CKA_VALUE for DH peer pub key failed with 0x%lx!\n", + rc); + return -1; + } + mech.ulParameterLen = extr_tmpl.ulValueLen; + rc = funcs->C_DeriveKey(session, &mech, keys.dhprivA, secret_tmpl, ARRAY_SIZE(secret_tmpl), &derived); + funcs->C_DestroyObject(session, derived); + if (rc != CKR_OK) { + fprintf(stderr, "WARN: DH key derivation failed with 0x%lx\n", rc); + return -1; + } + return 0; +} + +static int generateKeys(void) +{ + int res = 0; + + if (generateRSAKey() != CKR_OK) + res = -1; + if (generateECKey() != CKR_OK) + res = -1; + if (generateAESKey() != CKR_OK) + res = -1; + if (generateDHKeys() != CKR_OK) + res = -1; + return res; +} + +static int loadKeys(void) +{ + static const CK_KEY_TYPE rsakt = CKK_RSA; + static const CK_KEY_TYPE eckt = CKK_EC; + static const CK_KEY_TYPE aeskt = CKK_AES; + static const CK_KEY_TYPE dhkt = CKK_DH; + static const CK_OBJECT_CLASS publickey = CKO_PUBLIC_KEY; + static const CK_OBJECT_CLASS privatekey = CKO_PRIVATE_KEY; + static const CK_ATTRIBUTE rsapubtmpl[] = { + {CKA_KEY_TYPE, (void *)&rsakt, sizeof(rsakt)}, + {CKA_CLASS, (void *)&publickey, sizeof(publickey)}, + {CKA_LABEL, (void *)poltestlabel, sizeof(poltestlabel)} + }; + static const CK_ATTRIBUTE rsaprivtmpl[] = { + {CKA_KEY_TYPE, (void *)&rsakt, sizeof(rsakt)}, + {CKA_CLASS, (void *)&privatekey, sizeof(privatekey)}, + {CKA_LABEL, (void *)poltestlabel, sizeof(poltestlabel)} + }; + static const CK_ATTRIBUTE ecpubtmpl[] = { + {CKA_KEY_TYPE, (void *)&eckt, sizeof(eckt)}, + {CKA_CLASS, (void *)&publickey, sizeof(publickey)}, + {CKA_LABEL, (void *)poltestlabel, sizeof(poltestlabel)} + }; + static const CK_ATTRIBUTE ecprivtmpl[] = { + {CKA_KEY_TYPE, (void *)&eckt, sizeof(eckt)}, + {CKA_CLASS, (void *)&privatekey, sizeof(privatekey)}, + {CKA_LABEL, (void *)poltestlabel, sizeof(poltestlabel)} + }; + static const CK_ATTRIBUTE aestmpl[] = { + {CKA_KEY_TYPE, (void *)&aeskt, sizeof(aeskt)}, + {CKA_LABEL, (void *)poltestlabel, sizeof(poltestlabel)} + }; + static const CK_ATTRIBUTE dhApubtmpl[] = { + {CKA_KEY_TYPE, (void *)&dhkt, sizeof(dhkt)}, + {CKA_CLASS, (void *)&publickey, sizeof(publickey)}, + {CKA_LABEL, (void *)poltestdhlabelA, sizeof(poltestdhlabelA)} + }; + static const CK_ATTRIBUTE dhAprivtmpl[] = { + {CKA_KEY_TYPE, (void *)&dhkt, sizeof(dhkt)}, + {CKA_CLASS, (void *)&privatekey, sizeof(privatekey)}, + {CKA_LABEL, (void *)poltestdhlabelA, sizeof(poltestdhlabelA)} + }; + static const CK_ATTRIBUTE dhBpubtmpl[] = { + {CKA_KEY_TYPE, (void *)&dhkt, sizeof(dhkt)}, + {CKA_CLASS, (void *)&publickey, sizeof(publickey)}, + {CKA_LABEL, (void *)poltestdhlabelB, sizeof(poltestdhlabelB)} + }; + static const CK_ATTRIBUTE dhBprivtmpl[] = { + {CKA_KEY_TYPE, (void *)&dhkt, sizeof(dhkt)}, + {CKA_CLASS, (void *)&privatekey, sizeof(privatekey)}, + {CKA_LABEL, (void *)poltestdhlabelB, sizeof(poltestdhlabelB)} + }; + CK_OBJECT_HANDLE handle; + CK_ULONG count; + CK_RV rc; + int res = 0; + + // Find RSA pubkey + rc = funcs->C_FindObjectsInit(session, (CK_ATTRIBUTE *)rsapubtmpl, + ARRAY_SIZE(rsapubtmpl)); + if (rc != CKR_OK) { + res = -1; + } else { + rc = funcs->C_FindObjects(session, &handle, 1, &count); + funcs->C_FindObjectsFinal(session); + if (rc != CKR_OK || count != 1u) + res = -1; + else + keys.rsapub = handle; + } + // Find RSA privkey + rc = funcs->C_FindObjectsInit(session, (CK_ATTRIBUTE *)rsaprivtmpl, + ARRAY_SIZE(rsaprivtmpl)); + if (rc != CKR_OK) { + res = -1; + } else { + rc = funcs->C_FindObjects(session, &handle, 1, &count); + funcs->C_FindObjectsFinal(session); + if (rc != CKR_OK || count != 1u) + res = -1; + else + keys.rsapriv = handle; + } + // Find EC pubkey + rc = funcs->C_FindObjectsInit(session, (CK_ATTRIBUTE *)ecpubtmpl, + ARRAY_SIZE(ecpubtmpl)); + if (rc != CKR_OK) { + res = -1; + } else { + rc = funcs->C_FindObjects(session, &handle, 1, &count); + funcs->C_FindObjectsFinal(session); + if (rc != CKR_OK || count != 1u) + res = -1; + else + keys.ecpub = handle; + } + // Find EC privkey + rc = funcs->C_FindObjectsInit(session, (CK_ATTRIBUTE *)ecprivtmpl, + ARRAY_SIZE(ecprivtmpl)); + if (rc != CKR_OK) { + res = -1; + } else { + rc = funcs->C_FindObjects(session, &handle, 1, &count); + funcs->C_FindObjectsFinal(session); + if (rc != CKR_OK || count != 1u) + res = -1; + else + keys.ecpriv = handle; + } + // Find AES pubkey + rc = funcs->C_FindObjectsInit(session, (CK_ATTRIBUTE *)aestmpl, + ARRAY_SIZE(aestmpl)); + if (rc != CKR_OK) { + res = -1; + } else { + rc = funcs->C_FindObjects(session, &handle, 1, &count); + funcs->C_FindObjectsFinal(session); + if (rc != CKR_OK || count != 1u) + res = -1; + else + keys.aes = handle; + } + // Find DH pubkey A + rc = funcs->C_FindObjectsInit(session, (CK_ATTRIBUTE *)dhApubtmpl, + ARRAY_SIZE(dhApubtmpl)); + if (rc != CKR_OK) { + res = -1; + } else { + rc = funcs->C_FindObjects(session, &handle, 1, &count); + funcs->C_FindObjectsFinal(session); + if (rc != CKR_OK || count != 1u) + res = -1; + else + keys.dhpubA = handle; + } + // Find DH privkey A + rc = funcs->C_FindObjectsInit(session, (CK_ATTRIBUTE *)dhAprivtmpl, + ARRAY_SIZE(dhAprivtmpl)); + if (rc != CKR_OK) { + res = -1; + } else { + rc = funcs->C_FindObjects(session, &handle, 1, &count); + funcs->C_FindObjectsFinal(session); + if (rc != CKR_OK || count != 1u) + res = -1; + else + keys.dhprivA = handle; + } + // Find DH pubkey B + rc = funcs->C_FindObjectsInit(session, (CK_ATTRIBUTE *)dhBpubtmpl, + ARRAY_SIZE(dhBpubtmpl)); + if (rc != CKR_OK) { + res = -1; + } else { + rc = funcs->C_FindObjects(session, &handle, 1, &count); + funcs->C_FindObjectsFinal(session); + if (rc != CKR_OK || count != 1u) + res = -1; + else + keys.dhpubB = handle; + } + // Find DH privkey B + rc = funcs->C_FindObjectsInit(session, (CK_ATTRIBUTE *)dhBprivtmpl, + ARRAY_SIZE(dhBprivtmpl)); + if (rc != CKR_OK) { + res = -1; + } else { + rc = funcs->C_FindObjects(session, &handle, 1, &count); + funcs->C_FindObjectsFinal(session); + if (rc != CKR_OK || count != 1u) + res = -1; + else + keys.dhprivB = handle; + } + return res; +} + +static void deleteKeys(void) +{ + funcs->C_DestroyObject(session, keys.rsapub); + funcs->C_DestroyObject(session, keys.rsapriv); + funcs->C_DestroyObject(session, keys.ecpub); + funcs->C_DestroyObject(session, keys.ecpriv); + funcs->C_DestroyObject(session, keys.aes); + funcs->C_DestroyObject(session, keys.dhpubA); + funcs->C_DestroyObject(session, keys.dhprivA); + funcs->C_DestroyObject(session, keys.dhpubB); + funcs->C_DestroyObject(session, keys.dhprivB); +} + +static void dumpKeyInfo(void) +{ +#define KEY_TO_STR(X) ((X) == CK_INVALID_HANDLE ? "UNAVAILABLE" : "ok") + fprintf(stderr, "RSA public key: %s\n", KEY_TO_STR(keys.rsapub)); + fprintf(stderr, "RSA private key: %s\n", KEY_TO_STR(keys.rsapriv)); + fprintf(stderr, "EC public key: %s\n", KEY_TO_STR(keys.ecpub)); + fprintf(stderr, "EC private key: %s\n", KEY_TO_STR(keys.ecpriv)); + fprintf(stderr, "AES key: %s\n", KEY_TO_STR(keys.aes)); + fprintf(stderr, "DH public key A: %s\n", KEY_TO_STR(keys.dhpubA)); + fprintf(stderr, "DH private key A: %s\n", KEY_TO_STR(keys.dhprivA)); + fprintf(stderr, "DH public key B: %s\n", KEY_TO_STR(keys.dhpubB)); + fprintf(stderr, "DH private key B: %s\n", KEY_TO_STR(keys.dhprivB)); +#undef KEY_TO_STR +} + +static inline void initializeKeys(void) +{ + keys.rsapub = keys.rsapriv = + keys.ecpub = keys.ecpriv = + keys.aes = + keys.dhpubA = keys.dhprivA = + keys.dhpubB = keys.dhprivB = CK_INVALID_HANDLE; +} + +static int runTests(CK_SLOT_ID slot, uint32_t tests, uint32_t expfail) +{ + int res = 0, tmpres, shouldfail; + + tmpres = 0; + if (tests & (1u << TEST_RSA)) { + shouldfail = expfail & (1u << TEST_RSA); + if (keys.rsapub == CK_INVALID_HANDLE || + keys.rsapriv == CK_INVALID_HANDLE) { + fprintf(stderr, "WARN: RSA test requested, but RSA keys unavailable!\n"); + tmpres = -1; + } else { + tmpres = runRSATest(); + } + if (tmpres && shouldfail == 0) { + fprintf(stderr, "ERROR: RSA test failed unexpectedly!\n"); + res = -1; + } else if (tmpres == 0 && shouldfail) { + fprintf(stderr, "ERROR: RSA test did not fail as expected!\n"); + res = -1; + } + } + tmpres = 0; + if (tests & (1u << TEST_EC)) { + shouldfail = expfail & (1u << TEST_EC); + if (keys.ecpub == CK_INVALID_HANDLE || + keys.ecpriv == CK_INVALID_HANDLE) { + fprintf(stderr, "WARN: EC test requested, but EC keys unavailable!\n"); + tmpres = -1; + } else { + tmpres = runECTest(); + } + if (tmpres && shouldfail == 0) { + fprintf(stderr, "ERROR: EC test failed unexpectedly!\n"); + res = -1; + } else if (tmpres == 0 && shouldfail) { + fprintf(stderr, "ERROR: EC test did not fail as expected!\n"); + res = -1; + } + } + tmpres = 0; + if (tests & (1u << TEST_AESWRAP)) { + shouldfail = expfail & (1u << TEST_AESWRAP); + if (keys.aes == CK_INVALID_HANDLE) { + fprintf(stderr, "WARN: AES test requested, but AES key unavailable!\n"); + tmpres = -1; + } else { + tmpres = runAESWrapTest(slot); + } + if (tmpres && shouldfail == 0) { + fprintf(stderr, "ERROR: AES Wrap test failed unexpectedly!\n"); + res = -1; + } else if (tmpres == 0 && shouldfail) { + fprintf(stderr, "ERROR: AES Wrap test did not fail as expected!\n"); + res = -1; + } + } + if (tests & (1u << TEST_DIGEST)) { + shouldfail = expfail & (1u << TEST_DIGEST); + tmpres = runDIGESTTest(); + if (tmpres && shouldfail == 0) { + fprintf(stderr, "ERROR: Digest test failed unexpectedly!\n"); + res = -1; + } else if (tmpres == 0 && shouldfail) { + fprintf(stderr, "ERROR: Digest test did not fail as expected!\n"); + res = -1; + } + } + tmpres = 0; + if (tests & (1u << TEST_DH)) { + shouldfail = expfail & (1u << TEST_DH); + if (keys.dhpubA == CK_INVALID_HANDLE || + keys.dhprivA == CK_INVALID_HANDLE || + keys.dhpubB == CK_INVALID_HANDLE || + keys.dhprivB == CK_INVALID_HANDLE) { + fprintf(stderr, "WARN: DH test requested, but DH key unavailable!\n"); + tmpres = -1; + } else { + tmpres = runDHTest(); + } + if (tmpres && shouldfail == 0) { + fprintf(stderr, "ERROR: DH test failed unexpectedly!\n"); + res = -1; + } else if (tmpres == 0 && shouldfail) { + fprintf(stderr, "ERROR: DH test did not fail as expected!\n"); + res = -1; + } + } + return res; +} + +static void usage(char *prgname) +{ + printf("USAGE: %s -s|--slot [-g|--generate] [-t|--tests] [-d|--delete] [-k|--token] [-r|--restrict ] [-f|--fail ]\n", + prgname); + printf("where:\n"); + printf("\t-s or --slot specifies the PKCS #11 slot to use\n"); + printf("\t-g or --generate specifies to generate keys for testing\n"); + printf("\t-t or --tests specifies to run tests\n"); + printf("\t-d or --delete specifies to delete the keys at the end\n"); + printf("\t-k or --token specifies to use token keys (only useful with key generation)\n"); + printf("\t-r or --restrict specifies which tests to run\n"); + printf("\t-f or --fail specifies which tests are expected to fail\n"); + printf("\nvalid tests are:\n"); + printf("RSA - Encrypt/Decrypt test with 4k RSA key and CKM_RSA_PKCS\n"); + printf("EC - CKM_ECDSA sign/verify with secp384r1 key\n"); + printf("AESWRAP - CKM_AES_CBC_PAD key wrapping with 256bit key\n"); + printf("DIGEST - CKM_SHA512\n"); + printf("DH - CKM_DH_PKCS_DERIVE with 128 byte prime\n"); + printf(" is a CSV of the keys above.\n"); +} + +static int getslotid(CK_SLOT_ID *slotid, char *arg) +{ + char *endptr; + unsigned long res; + + errno = 0; + res = strtoul(arg, &endptr, 0); + if (*endptr || endptr == arg || (res == ULONG_MAX && errno == ERANGE)) { + fprintf(stderr, "Failed to parse slot id %s\n", arg); + return -1; + } + *slotid = res; + return 0; +} + + +static int get_user_pin(CK_BYTE * dest) +{ + char *val; + + val = getenv(PKCS11_USER_PIN_ENV_VAR); + if (val == NULL) { + fprintf(stderr, "The environment variable %s must be set " + "before this testcase is run.\n", PKCS11_USER_PIN_ENV_VAR); + return -1; + } + + if ((strlen(val) + 1) > PKCS11_MAX_PIN_LEN) { + fprintf(stderr, "The environment variable %s must hold a " + "value less than %d chars in length.\n", + PKCS11_SO_PIN_ENV_VAR, (int) PKCS11_MAX_PIN_LEN); + return -1; + } + + memcpy(dest, val, strlen(val) + 1); + + return 0; +} + +static int parsecsv(uint32_t *mask, const char *carg) +{ + char *arg = strdup(carg); + char *s, *tok; + int res = 0; + + if (!arg) + return -1; + s = arg; + while ((tok = strtok(s, ",")) != NULL) { + if (strcmp(tok, "RSA") == 0) + *mask |= (1u << TEST_RSA); + else if (strcmp(tok, "EC") == 0) + *mask |= (1u << TEST_EC); + else if (strcmp(tok, "AESWRAP") == 0) + *mask |= (1u << TEST_AESWRAP); + else if (strcmp(tok, "DIGEST") == 0) + *mask |= (1u << TEST_DIGEST); + else if (strcmp(tok, "DH") == 0) + *mask |= (1u << TEST_DH); + else + res = -1; + s = NULL; + } + free(arg); + return res; +} + +static int parseArgs(int argc, char **argv, CK_SLOT_ID *slot, + int *keygen, int *test, int *delete, + uint32_t *tests, uint32_t *fail) +{ + static struct option long_options[] = + { + {"slot", required_argument, 0, 's'}, + {"generate", no_argument, 0, 'g'}, + {"tests", no_argument, 0, 't'}, + {"delete", no_argument, 0, 'd'}, + {"restrict", required_argument, 0, 'r'}, + {"fail", required_argument, 0, 'f'}, + {"token", no_argument, 0, 'k'}, + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0 } + }; + int c, slotunspecified = -1; + + *keygen = *test = *delete = 0; + *tests = ~0u; + *fail = 0; + while (1) { + c = getopt_long(argc, argv, "s:gtdr:f:kh", long_options, 0); + if (c == -1) + break; + switch (c) { + case 's': + if (getslotid(slot, optarg)) + return -1; + slotunspecified = 0; + break; + case 'g': + *keygen = 1; + break; + case 't': + *test = 1; + break; + case 'd': + *delete = 1; + break; + case 'r': + *tests = 0; + if (parsecsv(tests, optarg)) + return -1; + break; + case 'f': + if (parsecsv(fail, optarg)) + return -1; + break; + case 'k': + tokenkeys = CK_TRUE; + break; + case 'h': + usage(argv[0]); + return 0; + default: + usage(argv[0]); + return -1; + } + } + if (slotunspecified) + usage(argv[0]); + return slotunspecified; +} + +int main(int argc, char **argv) +{ + + CK_BYTE userpin[PKCS11_MAX_PIN_LEN]; + int keygen, test, delete; + uint32_t tests, fail; + CK_SLOT_ID slot = 0; + int res = 0; + + initializeKeys(); + if (parseArgs(argc, argv, &slot, &keygen, &test, &delete, &tests, &fail)) + return 1; + if (get_user_pin(userpin)) + return 2; + if (doLoadLib()) + return 3; + if (doInitLib()) + return 4; + if (doOpenSession(slot)) + return 5; + if (doLoginUser(userpin)) + return 6; + if (keygen && generateKeys()) + fprintf(stderr, "WARN: Could not generate all keys\n"); + if (loadKeys()) { + fprintf(stderr, "WARN: Could not load all keys\n"); + dumpKeyInfo(); + } + if (test && runTests(slot, tests, fail)) + res = 7; + if (delete) + deleteKeys(); + return res; +} diff -Nru opencryptoki-3.16.0+dfsg/testcases/policy/policytest.sh.in opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/policy/policytest.sh.in --- opencryptoki-3.16.0+dfsg/testcases/policy/policytest.sh.in 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/policy/policytest.sh.in 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,221 @@ +#!/bin/bash + +# Get script directory as source directory for all other files +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink + DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )" + SOURCE="$(readlink "$SOURCE")" + [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located +done +DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )" + +restoreconfig() { + if test -e @sysconfdir@/opencryptoki/strength.conf.ptbak; then + rm -f @sysconfdir@/opencryptoki/strength.conf + mv @sysconfdir@/opencryptoki/strength.conf.ptbak @sysconfdir@/opencryptoki/strength.conf + chown root:pkcs11 @sysconfdir@/opencryptoki/strength.conf + chmod 0640 @sysconfdir@/opencryptoki/strength.conf + fi + if test -e @sysconfdir@/opencryptoki/policy.conf.ptbak; then + rm -f @sysconfdir@/opencryptoki/policy.conf + mv @sysconfdir@/opencryptoki/policy.conf.ptbak @sysconfdir@/opencryptoki/policy.conf + chown root:pkcs11 @sysconfdir@/opencryptoki/policy.conf + chmod 0640 @sysconfdir@/opencryptoki/policy.conf + fi +} + +backupconfig() { + if test -e @sysconfdir@/opencryptoki/strength.conf; then + mv @sysconfdir@/opencryptoki/strength.conf @sysconfdir@/opencryptoki/strength.conf.ptbak + fi + if test -e @sysconfdir@/opencryptoki/policy.conf; then + mv @sysconfdir@/opencryptoki/policy.conf @sysconfdir@/opencryptoki/policy.conf.ptbak + fi + trap restoreconfig EXIT +} + +initstrength() { + cat < @sysconfdir@/opencryptoki/strength.conf +version strength-0 + +strength 112 { + MOD_EXP = 2048 + ECC = 224 + SYMMETRIC = 112 + digest = 224 + signature = 112 +} +strength 128 { + MOD_EXP = 3072 + ECC = 256 + SYMMETRIC = 128 + digest = 256 + signature = 128 +} +strength 192 { + MOD_EXP = 7680 + ECC = 384 + SYMMETRIC = 192 + digest = 384 + signature = 192 +} +strength 256 { + MOD_EXP = 15360 + ECC = 512 + SYMMETRIC = 256 + digest = 512 + signature = 256 +} +EOF + chown root:pkcs11 @sysconfdir@/opencryptoki/strength.conf + chmod 0640 @sysconfdir@/opencryptoki/strength.conf +} + +# Usage: genpolicy +genpolicy() { + cat < @sysconfdir@/opencryptoki/policy.conf +version policy-0 +strength = $1 +EOF + chown root:pkcs11 @sysconfdir@/opencryptoki/policy.conf + chmod 0640 @sysconfdir@/opencryptoki/policy.conf +} + +if test $# -ne 1; then + echo "USAGE: policytest " + exit 1; +fi + +SLOT=$1 +FAILED=/bin/false + +# basic initialization +backupconfig +initstrength + +# start with strength of 0 +genpolicy 0 + +# check which tests we can run +TESTS="" +SEP="" + +if pkcsconf -m -c $SLOT | grep -q "(CKM_RSA_PKCS)"; then + TESTS="${TESTS}${SEP}RSA" + SEP="," +fi +if pkcsconf -m -c $SLOT | grep -q "(CKM_ECDSA)"; then + TESTS="${TESTS}${SEP}EC" + SEP="," +fi +if pkcsconf -m -c $SLOT | grep -q "(CKM_AES_CBC_PAD)" &&\ + pkcsconf -m -c $SLOT | grep -A 2 "(CKM_AES_CBC_PAD)" | grep -q CKF_WRAP; then + TESTS="${TESTS}${SEP}AESWRAP" + SEP="," +fi +if pkcsconf -m -c $SLOT | grep -q "(CKM_SHA512)"; then + TESTS="${TESTS}${SEP}DIGEST" + SEP="," +fi +if pkcsconf -m -c $SLOT | grep -q "(CKM_DH_PKCS_DERIVE)"; then + TESTS="${TESTS}${SEP}DH" + SEP="," +fi + +if test "x$TESTS" == "x"; then + echo "Cannot run any tests on this slot" + exit 0 +fi + +echo "Using test mask $TESTS" + +echo "Running tests with session keys..." + +${DIR}/policytest -s $SLOT -g -t -d -r $TESTS || { + echo "Failed with session keys for strength 0" + FAILED=/bin/true +} + +genpolicy 112 + +${DIR}/policytest -s $SLOT -g -t -d -r $TESTS -f DH || { + echo "Failed with session keys for strength 112" + FAILED=/bin/true +} + +genpolicy 128 + +${DIR}/policytest -s $SLOT -g -t -d -r $TESTS -f DH || { + echo "Failed with session keys for strength 128" + FAILED=/bin/true +} + +genpolicy 192 + +${DIR}/policytest -s $SLOT -g -t -d -r $TESTS -f DH,RSA || { + echo "Failed with session keys for strength 192" + FAILED=/bin/true +} + +genpolicy 256 + +${DIR}/policytest -s $SLOT -g -t -d -r $TESTS -f DH,RSA,EC || { + echo "Failed with session keys for strength 256" + FAILED=/bin/true +} + +echo "...now generating token keys..." + +genpolicy 0 + +${DIR}/policytest -s $SLOT -g -k || { + echo "Failed to generate token keys" + exit 1 +} + +echo "...now running tests with token keys..." + +${DIR}/policytest -s $SLOT -t -r $TESTS || { + echo "Failed with token keys from strength 0" + FAILED=/bin/true +} + +genpolicy 112 + +${DIR}/policytest -s $SLOT -t -r $TESTS -f DH || { + echo "Failed with token keys from strength 112" + FAILED=/bin/true +} + +genpolicy 128 + +${DIR}/policytest -s $SLOT -t -r $TESTS -f DH || { + echo "Failed with token keys from strength 128" + FAILED=/bin/true +} + +genpolicy 192 + +${DIR}/policytest -s $SLOT -t -r $TESTS -f DH,RSA || { + echo "Failed with token keys from strength 192" + FAILED=/bin/true +} + +genpolicy 256 + +${DIR}/policytest -s $SLOT -t -r $TESTS -f DH,RSA,EC || { + echo "Failed with token keys from strength 256" + FAILED=/bin/true +} + +echo "...now deleting token keys" + +genpolicy 0 + ${DIR}/policytest -s $SLOT -d || echo "Could not delete all generated tokens keys" + +if $FAILED; then + echo "Some tests have failed" + exit 1 +fi + +exit 0 diff -Nru opencryptoki-3.16.0+dfsg/testcases/testcases.mk opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/testcases.mk --- opencryptoki-3.16.0+dfsg/testcases/testcases.mk 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/testcases.mk 2022-02-02 15:05:41.000000000 +0100 @@ -1,8 +1,8 @@ -testcases_inc = \ - -I${srcdir}/usr/include -I${srcdir}/usr/lib/common \ +testcases_inc = -I${srcdir}/usr/include -I${srcdir}/usr/lib/common \ -I${srcdir}/testcases/include -I${srcdir}/testcases/common \ -I${srcdir}/testcases/login -I${srcdir}/testcases/crypto \ - -I${srcdir}/testcases/misc_tests -I${srcdir}/testcases/pkcs11 + -I${srcdir}/testcases/misc_tests -I${srcdir}/testcases/pkcs11 \ + -I${srcdir}/usr/lib/api -I${top_builddir}/usr/lib/api include testcases/include/include.mk include testcases/common/common.mk @@ -11,21 +11,37 @@ include testcases/misc_tests/misc_tests.mk include testcases/pkcs11/pkcs11.mk include testcases/build/build.mk +include testcases/unit/unit.mk +include testcases/policy/policy.mk -noinst_SCRIPTS += testcases/ock_tests.sh testcases/init_token.sh -CLEANFILES += testcases/ock_tests.sh testcases/init_token.sh -EXTRA_DIST += testcases/ock_tests.sh.in testcases/init_token.sh.in +noinst_SCRIPTS += testcases/ock_tests.sh testcases/init_token.sh testcases/init_vhsm.exp testcases/cleanup_vhsm.exp +CLEANFILES += testcases/ock_tests.sh testcases/init_token.sh testcases/init_vhsm.exp testcases/cleanup_vhsm.exp +EXTRA_DIST += testcases/ock_tests.sh.in testcases/init_token.sh.in testcases/init_vhsm.exp.in testcases/cleanup_vhsm.exp.in testcases/ock_tests.sh: testcases/ock_tests.sh.in - @SED@ -e s!\@sysconfdir\@!"@sysconfdir@"!g \ + $(AM_V_GEN)@SED@ -e s!\@sysconfdir\@!"@sysconfdir@"!g \ -e s!\@sbindir\@!"@sbindir@"!g \ - -e s!\@libdir\@!"@libdir@"!g < $< > $@-t - @CHMOD@ a+x $@-t - mv $@-t $@ + -e s!\@libdir\@!"@libdir@"!g < $< > $@-t && \ + @CHMOD@ a+x $@-t && \ + $(am__mv) $@-t $@ testcases/init_token.sh: testcases/init_token.sh.in - @SED@ -e s!\@localstatedir\@!"@localstatedir@"!g \ + $(AM_V_GEN)@SED@ -e s!\@localstatedir\@!"@localstatedir@"!g \ -e s!\@sbindir\@!"@sbindir@"!g \ - -e s!\@libdir\@!"@libdir@"!g < $< > $@-t - @CHMOD@ a+x $@-t - mv $@-t $@ + -e s!\@libdir\@!"@libdir@"!g < $< > $@-t && \ + @CHMOD@ a+x $@-t && \ + $(am__mv) $@-t $@ + +testcases/init_vhsm.exp: testcases/init_vhsm.exp.in + $(AM_V_GEN)@SED@ -e s!\@localstatedir\@!"@localstatedir@"!g \ + -e s!\@sbindir\@!"@sbindir@"!g \ + -e s!\@libdir\@!"@libdir@"!g < $< > $@-t && \ + @CHMOD@ a+x $@-t && \ + $(am__mv) $@-t $@ + +testcases/cleanup_vhsm.exp: testcases/cleanup_vhsm.exp.in + $(AM_V_GEN)@SED@ -e s!\@localstatedir\@!"@localstatedir@"!g \ + -e s!\@sbindir\@!"@sbindir@"!g \ + -e s!\@libdir\@!"@libdir@"!g < $< > $@-t && \ + @CHMOD@ a+x $@-t && \ + $(am__mv) $@-t $@ diff -Nru opencryptoki-3.16.0+dfsg/testcases/unit/configdump.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/unit/configdump.c --- opencryptoki-3.16.0+dfsg/testcases/unit/configdump.c 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/unit/configdump.c 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,78 @@ +#include "unittest.h" +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif +#include +#include +#include +#include +#include + +static const char test1[] = "foo = 1\nbar = 2\n"; +static const char test2[] = "foo = 1 bar = 2\n"; +static const char test3[] = "foo {\n bar = 1\n buzz = 2\n}\n"; +static const char test4[] = "foo {\n bar = 1 buzz = 2\n}\n"; +static const char test5[] = "foo ( bar, buzz )\n"; +static const char test6[] = "foo (\n bar,\n buzz\n )\n"; +static const char test7[] = "foo\n(\n bar,\n buzz\n)\n"; +static const char nested1[] = "nested {\n foo (\n bar,\n buzz\n )\n}\n"; +static const char nested2[] = "nested {\n foo\n (\n bar,\n buzz\n )\n}\n"; +static char outbuf[1024]; + +static const char *curtest; + +static FILE *opentest(const char *test) +{ + FILE *res = fmemopen((char *)test, strlen(test), "r"); + if (!res) + err(TEST_FAIL, "Could not fmemopen test string \"%s\"", test); + return res; +} + +static FILE *openout(void) +{ + FILE *res = fmemopen(outbuf, sizeof(outbuf), "w"); + if (!res) + err(TEST_FAIL, "Could not fmemopen output"); + return res; +} + +static void parse_error(int line, int col, const char *msg) +{ + errx(TEST_FAIL, "Parsing \"%s\", line %d, col %d: %s\n", + curtest, line, col, msg); +} + +static void runparsedumptest(const char *test) +{ + struct ConfigBaseNode *config; + FILE *in, *out; + int ret; + + curtest = test; + in = opentest(test); + out = openout(); + ret = parse_configlib_file(in, &config, parse_error, 1); + fclose(in); + if (ret) + errx(TEST_FAIL, "Failed to parse \"%s\"", test); + confignode_dump(out, config, NULL, 2); + fclose(out); + confignode_deepfree(config); + if (strcmp(test, outbuf)) + errx(TEST_FAIL, "Expected \"%s\", but got \"%s\"!", test, outbuf); +} + +int main(void) +{ + runparsedumptest(test1); + runparsedumptest(test2); + runparsedumptest(test3); + runparsedumptest(test4); + runparsedumptest(test5); + runparsedumptest(test6); + runparsedumptest(test7); + runparsedumptest(nested1); + runparsedumptest(nested2); + return TEST_PASS; +} diff -Nru opencryptoki-3.16.0+dfsg/testcases/unit/hashmaptest.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/unit/hashmaptest.c --- opencryptoki-3.16.0+dfsg/testcases/unit/hashmaptest.c 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/unit/hashmaptest.c 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,207 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ +#define _GNU_SOURCE +#include "hashmap.h" +#include "unittest.h" +#include +#include +#include +#include +#include +#include + +static int testhashcollisionexpansion(void) +{ + CK_ULONG values[] = + { + /* First 12 values that should end up in the same bucket if + simplest hash function is used. Make sure they also end + up in the same bucket after the first expansion. */ + 0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x700, 0x800, 0x900, + 0xa00, 0xb00, + /* Next 12 values that should also end up in the same bucket + after the expansion. */ + 0x1100, 0x1200, 0x1300, 0x1400, 0x1500, 0x1600, 0x1700, 0x1800, + 0x1900, 0x0a00, 0x1b00 + }; + union hashmap_value val = { .ulVal = 0 }; + struct hashmap *h; + unsigned long i; + int res = 0; + + h = hashmap_new(); + if (!h) { + fprintf(stderr, "Failed to allocate mesh hash\n"); + return -1; + } + for (i = 0; i < ARRAYSIZE(values) / 2; ++i) { + if (hashmap_add(h, values[i], val, NULL)) { + fprintf(stderr, "Failed to add element %lu to meshhash\n", i); + res = -1; + goto out; + } + } + for (i = 0; i < ARRAYSIZE(values) / 2; ++i) { + if (!hashmap_find(h, values[i], NULL)) { + fprintf(stderr, "Lost element %lu (%lu) in hashmap\n", + i, values[i]); + res = -1; + goto out; + } + } + for ( ; i < ARRAYSIZE(values); ++i) { + if (hashmap_add(h, values[i], val, NULL)) { + fprintf(stderr, "Failed to add element %lu to meshhash\n", i); + res = -1; + goto out; + } + } + for (i = 0; i < ARRAYSIZE(values); ++i) { + if (!hashmap_find(h, values[i], NULL)) { + fprintf(stderr, + "Lost element %lu (%lu) in hashmap after expansion\n", + i, values[i]); + res = -1; + goto out; + } + } + out: + hashmap_free(h, NULL); + return res; +} + +static int compareulong(const void *a, const void *b) +{ + unsigned long la = *(const unsigned long *)a; + unsigned long lb = *(const unsigned long *)b; + + if (la < lb) + return -1; + if (la == lb) + return 0; + return 1; +} + +static int testhashrandom(unsigned long seed, unsigned long iterations) +{ + unsigned long i, *arr, mid, unsucccnt; + union hashmap_value val = { .ulVal = 0}; + struct hashmap *h; + int res = 0; + + h = hashmap_new(); + if (!h) { + fprintf(stderr, "Could not allocate hashmap\n"); + return -1; + } + arr = calloc(iterations, sizeof(unsigned long)); + if (!arr) { + fprintf(stderr, "Failed to allocate data array\n"); + res = -1; + goto out; + } + srandom(seed); + for (i = 0; i < iterations; ++i) + arr[i] = random(); + for (i = 0; i < iterations; ++i) { + if (hashmap_add(h, arr[i], val, NULL)) { + fprintf(stderr, "Failed to add %lu to hash\n", arr[i]); + res = -1; + goto out; + } + } + /* successful searches */ + for (i = 0; i < iterations; ++i) { + if (!hashmap_find(h, arr[i], NULL)) { + fprintf(stderr, "Failed to find %lu in hash\n", arr[i]); + res = -1; + goto out; + } + } + /* unsuccessful searches */ + unsucccnt = 0; + qsort(arr, iterations, sizeof(unsigned long), compareulong); + for (i = 0; i < iterations - 1; ++i) { + mid = arr[i] + (arr[i + 1] - arr[i]) / 2; + if (mid != arr[i]) { + ++unsucccnt; + if (hashmap_find(h, mid, NULL)) { + fprintf(stderr, "Found non-existing element %lu in hash\n", + mid); + res = -1; + goto out; + } + } + } + fprintf(stderr, "Performed %lu (expected) unsuccessful searches\n", + unsucccnt); + out: + free(arr); + hashmap_free(h, NULL); + return res; +} + +static int parseulong(const char *str, unsigned long *res) +{ + unsigned long tmp; + char *endptr; + + errno = 0; + tmp = strtoul(str, &endptr, 0); + if (*endptr || (tmp == ULONG_MAX && errno == ERANGE)) + return 1; + *res = tmp; + return 0; +} + +int main(int argc, char **argv) +{ + unsigned long seed = 0, iterations = 100; + static struct option long_options[] = + { + {"seed", required_argument, 0, 's'}, + {"iterations", required_argument, 0, 'i'}, + {0, 0, 0, 0 } + }; + int c; + + while (1) { + c = getopt_long(argc, argv, "s:i:", long_options, NULL); + if (c == -1) + break; + switch(c) { + case 's': + if (parseulong(optarg, &seed)) { + fprintf(stderr, "Seed could not be parsed!\n"); + return TEST_SKIP; + } + break; + case 'i': + if (parseulong(optarg, &iterations)) { + fprintf(stderr, "Iterations could not be parsed!\n"); + return TEST_SKIP; + } + break; + default: + printf("USAGE: %s [-s|--seed ] [-i|--iterations ]\n", + argv[0]); + printf("where the parameters configure the random hash test:\n"); + printf("-s or --seed specifies the random seed\n"); + printf("-i or --iterations specifies the number of iterations to perform\n"); + return TEST_SKIP; + } + } + if (testhashcollisionexpansion()) + return TEST_FAIL; + if (testhashrandom(seed, iterations)) + return TEST_FAIL; + /* hashmap_delete function is untested since it is unused so far */ + return TEST_PASS; +} diff -Nru opencryptoki-3.16.0+dfsg/testcases/unit/mechtabletest.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/unit/mechtabletest.c --- opencryptoki-3.16.0+dfsg/testcases/unit/mechtabletest.c 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/unit/mechtabletest.c 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,88 @@ +#include +#include + +#include "unittest.h" + +#include + +int checkstring(void) +{ + unsigned int i; + int idx, res = 0; + + for (i = 0; i < MECHTABLE_NUM_ELEMS; ++i) { + idx = mechtable_idx_from_string(mechtable_rows[i].string); + if (idx < 0) { + fprintf(stderr, "Mechanism %s not found in table!\n", + mechtable_rows[i].string); + res = -1; + } else if ((unsigned int) idx != i) { + fprintf(stderr, "Expected mechanism %s at index %u, but query returned %d!\n", + mechtable_rows[i].string, i, idx); + res = -1; + } + if (mechrow_from_string(mechtable_rows[i].string) == NULL) { + fprintf(stderr, "Unable to get row reference for mechanism %s!\n", + mechtable_rows[i].string); + res = -1; + } + } + return res; +} + +int checknumeric(void) +{ + unsigned int i; + int idx, res = 0; + + for (i = 0; i < MECHTABLE_NUM_ELEMS; ++i) { + idx = mechtable_idx_from_numeric(mechtable_rows[i].numeric); + if (idx < 0) { + fprintf(stderr, "Mechanism %lu not found in table!\n", + mechtable_rows[i].numeric); + res = -1; + } else if ((unsigned int) idx != i) { + fprintf(stderr, "Expected mechanism %lu at index %u, but query returned %d!\n", + mechtable_rows[i].numeric, i, idx); + res = -1; + } + if (mechrow_from_numeric(mechtable_rows[i].numeric) == NULL) { + fprintf(stderr, "Unable to get row reference for mechanism %lu!\n", + mechtable_rows[i].numeric); + res = -1; + } + } + return res; +} + +int checkalias(void) +{ + const struct mechrow *row = mechrow_from_string("CKM_ECDSA_KEY_PAIR_GEN"); + if (row) + return strcmp(row->string, "CKM_EC_KEY_PAIR_GEN"); + return -1; +} + +int checkfailure(void) +{ + int idxnum = mechtable_idx_from_numeric(0xffffffffu); + int idxstr = mechtable_idx_from_string("CKM_DOES_NOT_EXIST"); + int res = 0; + + if (idxnum != -1) { + fprintf(stderr, "Did find 0xffffffff which should not be a valid mechanism!\n"); + res = -1; + } + if (idxstr != -1) { + fprintf(stderr, "Did find mechanism CKM_DOES_NOT_EXIST!\n"); + res = -1; + } + return res; +} + +int main(void) +{ + if (checkstring() || checknumeric() || checkalias() || checkfailure()) + return TEST_FAIL; + return TEST_PASS; +} diff -Nru opencryptoki-3.16.0+dfsg/testcases/unit/policytest.c opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/unit/policytest.c --- opencryptoki-3.16.0+dfsg/testcases/unit/policytest.c 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/unit/policytest.c 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,994 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ +#define _GNU_SOURCE +#include "policy.h" +#include "ec_defs.h" +#include "unittest.h" +#include +#include +#include + +/* Inlined strength definitions */ +static const char niststrength[] = + "version strength-0\n" + "strength 112 {\n" + " MOD_EXP = 2048\n" + " ECC = 224\n" + " SYMMETRIC = 112\n" + " digest = 224\n" + " signature = 112\n" + "}\n" + "strength 128 {\n" + " MOD_EXP = 3072\n" + " ECC = 256\n" + " SYMMETRIC = 128\n" + " digest = 256\n" + " signature = 128\n" + "}\n" + "strength 192 {\n" + " MOD_EXP = 7680\n" + " ECC = 384\n" + " SYMMETRIC = 192\n" + " digest = 384\n" + " signature = 192\n" + "}\n" + "strength 256 {\n" + " MOD_EXP = 15360\n" + " ECC = 512\n" + " SYMMETRIC = 256\n" + " digest = 512\n" + " signature = 256\n" + "}\n"; + +static const char quantum112[] = + "version strength-0\n" + "strength 112 {\n" + " SYMMETRIC = 224\n" + " digest = 448\n" + " signature = 224\n" + "}\n"; + +static const char emptystrength[] = + "version strength-0\n"; + +/* Inlined policies */ +static const char policysecponly[] = + "version policy-0\n" + "strength = 0\n" + "allowedcurves ( SECP224R1, SECP384R1, SECP521R1, SECP256K1 )\n"; + +static const char policynocurves[] = + "version policy-0\n" + "strength = 0\n" + "allowedcurves ( )\n"; + +static const char policystrength256[] = + "version policy-0\n" + "strength = 256\n"; + +static const char policystrength192[] = + "version policy-0\n" + "strength = 192\n"; + +static const char policystrength128[] = + "version policy-0\n" + "strength = 128\n"; + +static const char policystrength112[] = + "version policy-0\n" + "strength = 112\n"; + +static const char policyempty[] = + "version policy-0\n" + "strength = 0\n"; + +static const char policynomechs[] = + "version policy-0\n" + "strength = 0\n" + "allowedmechs ()\n"; + +static const char policyfixedmechs[] = + "version policy-0\n" + "strength = 0\n" + "allowedmechs ( CKM_RSA_PKCS, CKM_ECDSA )\n"; + +static const char policymgfstandard[] = + "version policy-0\n" + "strength = 0\n" + "allowedmgfs ( CKG_MGF1_SHA1, CKG_MGF1_SHA224, CKG_MGF1_SHA256,\n" + "CKG_MGF1_SHA384, CKG_MGF1_SHA512 )\n"; + +static const char policymgfibm[] = + "version policy-0\n" + "strength = 0\n" + "allowedmgfs ( CKG_IBM_MGF1_SHA3_224, CKG_IBM_MGF1_SHA3_256,\n" + "CKG_IBM_MGF1_SHA3_384, CKG_IBM_MGF1_SHA3_512 )\n"; + +static const char policymgfoneeach[] = + "version policy-0\n" + "strength = 0\n" + "allowedmgfs ( CKG_MGF1_SHA512, CKG_IBM_MGF1_SHA3_224 )\n"; + +static const char policymgfnone[] = + "version policy-0\n" + "strength = 0\n" + "allowedmgfs ()\n"; + +static const char policykdfnosha1[] = + "version policy-0\n" + "strength = 0\n" + "allowedkdfs ( CKD_SHA224_KDF, CKD_SHA256_KDF, CKD_SHA384_KDF,\n" + "CKD_SHA512_KDF )\n"; + +static const char policykdfnone[] = + "version policy-0\n" + "strength = 0\n" + "allowedkdfs ()\n"; + +/* Loading functions (in usr/lib/api/policy.c) */ +struct policy_private; +extern void policy_init_policy(struct policy *p); +extern CK_RV policy_load_strength_cfg(struct policy_private *pp, + FILE *fp); +extern CK_RV policy_load_policy_cfg(struct policy_private *pp, + FILE *fp, CK_BBOOL *restricting); +extern struct policy_private *policy_private_alloc(void); +extern struct policy_private *policy_private_free(struct policy_private *pp); +extern void policy_private_deactivate(struct policy_private *pp); + +struct keytest { + CK_ULONG keytype; + union { + CK_ULONG value; + int nid; + } strengthattr; + CK_ULONG sigattr; + CK_ULONG expstrength;/* Index: 0=256; 1=192; 2=128; 3=112; 4=0 */ + CK_ULONG expsiglen; + CK_BBOOL expallowed; + CK_RV exprc; +}; + +#define STRENGTH_256 0 +#define STRENGTH_192 1 +#define STRENGTH_128 2 +#define STRENGTH_112 3 +#define STRENGTH_0 4 + +#define NUM_KEYTESTS_STRENGTHDET 4 + +static const struct strengthdettest { + const char *definition; + size_t definitionsize; + struct keytest tests[NUM_KEYTESTS_STRENGTHDET]; +} strengthdettests[] = + { + /* 0: NIST strength definition */ + { + niststrength, + sizeof(niststrength), + { + { CKK_RSA, { .value = 7680 }, 0, STRENGTH_192, 7680, CK_TRUE, CKR_OK }, + { CKK_DSA, { .value = 1024 }, 512, STRENGTH_0, 512 * 2, CK_TRUE, CKR_OK }, + { CKK_EC, { .nid = NID_secp224r1 }, 0, STRENGTH_112, 224 * 2, CK_TRUE, CKR_OK }, + { CKK_AES, { .value = 156 / 8 }, 0, STRENGTH_128, 128, CK_TRUE, CKR_OK }, + } + }, + /* 1: PQ strength definition */ + { + quantum112, + sizeof(quantum112), + { + { CKK_RSA, { .value = 7680 }, 0, STRENGTH_0, 7680, CK_TRUE, CKR_OK }, + { CKK_DSA, { .value = 1024 }, 512, STRENGTH_0, 512 * 2, CK_TRUE, CKR_OK }, + /* allowed is CK_TRUE since no policy is active */ + { CKK_EC, { .nid = NID_secp224r1 }, 0, STRENGTH_0, 224 * 2, CK_TRUE, CKR_OK }, + { CKK_AES, { .value = 256 / 8 }, 0, STRENGTH_112, 128, CK_TRUE, CKR_OK }, + } + }, + /* 2: empty */ + { + emptystrength, + sizeof(emptystrength), + { + { CKK_RSA, { .value = 7680 }, 0, STRENGTH_0, 7680, CK_TRUE, CKR_OK }, + { CKK_DSA, { .value = 1024 }, 512, STRENGTH_0, 512 * 2, CK_TRUE, CKR_OK }, + { CKK_EC, { .nid = NID_secp224r1 }, 0, STRENGTH_0, 224 * 2, CK_TRUE, CKR_OK }, + { CKK_AES, { .value = 156 / 8 }, 0, STRENGTH_0, 128, CK_TRUE, CKR_OK }, + } + } + }; + +#define NUM_KEYTESTS_STRENGTHENFORCE 4 + +static const struct strengthenforcetest { + const char *strength; + size_t strengthsize; + const char *policy; + size_t policysize; + struct keytest tests[NUM_KEYTESTS_STRENGTHENFORCE]; +} strengthenforcetests[] = + { + /* 0: NIST strength, require 0 and only secp curves */ + { + niststrength, + sizeof(niststrength), + policysecponly, + sizeof(policysecponly), + { + /* MOD_EXP */ + { CKK_RSA, { .value = 3072 }, 0, STRENGTH_128, 3072, CK_TRUE, CKR_OK }, + /* ECC (Test 0) */ + { CKK_EC, { .nid = NID_secp224r1 }, 0, STRENGTH_112, 448, CK_TRUE, CKR_OK }, + /* ECC (Test 1) */ + { CKK_EC, { .nid = NID_brainpoolP512t1 }, 0, STRENGTH_256, 1024, CK_FALSE, CKR_FUNCTION_FAILED }, + /* SYMMETRIC */ + { CKK_AES, { .value = 200 / 8 }, 0, STRENGTH_192, 128, CK_TRUE, CKR_OK } + } + }, + /* 1: NIST strength, require 0 and no curves */ + { + niststrength, + sizeof(niststrength), + policynocurves, + sizeof(policynocurves), + { + /* MOD_EXP */ + { CKK_RSA, { .value = 3072 }, 0, STRENGTH_128, 3072, CK_TRUE, CKR_OK }, + /* ECC (Test 0) */ + { CKK_EC, { .nid = NID_secp224r1 }, 0, STRENGTH_112, 448, CK_FALSE, CKR_FUNCTION_FAILED }, + /* ECC (Test 1) */ + { CKK_EC, { .nid = NID_brainpoolP512t1 }, 0, STRENGTH_256, 1024, CK_FALSE, CKR_FUNCTION_FAILED }, + /* SYMMETRIC */ + { CKK_AES, { .value = 200 / 8 }, 0, STRENGTH_192, 128, CK_TRUE, CKR_OK } + } + }, + /* 2: NIST strength, require 256 */ + { + niststrength, + sizeof(niststrength), + policystrength256, + sizeof(policystrength256), + { + /* MOD_EXP */ + { CKK_RSA, { .value = 3072 }, 0, STRENGTH_128, 3072, CK_TRUE, CKR_FUNCTION_FAILED }, + /* ECC (Test 0) */ + { CKK_EC, { .nid = NID_secp224r1 }, 0, STRENGTH_112, 448, CK_TRUE, CKR_FUNCTION_FAILED }, + /* ECC (Test 1) */ + { CKK_EC, { .nid = NID_brainpoolP512t1 }, 0, STRENGTH_256, 1024, CK_TRUE, CKR_OK }, + /* SYMMETRIC */ + { CKK_AES, { .value = 200 / 8 }, 0, STRENGTH_192, 128, CK_TRUE, CKR_FUNCTION_FAILED } + } + }, + /* 3: NIST strength, require 192 */ + { + niststrength, + sizeof(niststrength), + policystrength192, + sizeof(policystrength192), + { + /* MOD_EXP */ + { CKK_RSA, { .value = 3072 }, 0, STRENGTH_128, 3072, CK_TRUE, CKR_FUNCTION_FAILED }, + /* ECC (Test 0) */ + { CKK_EC, { .nid = NID_secp224r1 }, 0, STRENGTH_112, 448, CK_TRUE, CKR_FUNCTION_FAILED }, + /* ECC (Test 1) */ + { CKK_EC, { .nid = NID_brainpoolP512t1 }, 0, STRENGTH_256, 1024, CK_TRUE, CKR_OK }, + /* SYMMETRIC */ + { CKK_AES, { .value = 200 / 8 }, 0, STRENGTH_192, 128, CK_TRUE, CKR_OK } + } + }, + /* 4: NIST strength, require 128 */ + { + niststrength, + sizeof(niststrength), + policystrength128, + sizeof(policystrength128), + { + /* MOD_EXP */ + { CKK_RSA, { .value = 3072 }, 0, STRENGTH_128, 3072, CK_TRUE, CKR_OK }, + /* ECC (Test 0) */ + { CKK_EC, { .nid = NID_secp224r1 }, 0, STRENGTH_112, 448, CK_TRUE, CKR_FUNCTION_FAILED }, + /* ECC (Test 1) */ + { CKK_EC, { .nid = NID_brainpoolP512t1 }, 0, STRENGTH_256, 1024, CK_TRUE, CKR_OK }, + /* SYMMETRIC */ + { CKK_AES, { .value = 200 / 8 }, 0, STRENGTH_192, 128, CK_TRUE, CKR_OK } + } + }, + /* 5: NIST strength, require 112 */ + { + niststrength, + sizeof(niststrength), + policystrength112, + sizeof(policystrength112), + { + /* MOD_EXP */ + { CKK_RSA, { .value = 3072 }, 0, STRENGTH_128, 3072, CK_TRUE, CKR_OK }, + /* ECC (Test 0) */ + { CKK_EC, { .nid = NID_secp224r1 }, 0, STRENGTH_112, 448, CK_TRUE, CKR_OK }, + /* ECC (Test 1) */ + { CKK_EC, { .nid = NID_brainpoolP512t1 }, 0, STRENGTH_256, 1024, CK_TRUE, CKR_OK }, + /* SYMMETRIC */ + { CKK_AES, { .value = 200 / 8 }, 0, STRENGTH_192, 128, CK_TRUE, CKR_OK } + } + }, + /* 6: NIST strength, require 0 */ + { + niststrength, + sizeof(niststrength), + policyempty, + sizeof(policyempty), + { + /* MOD_EXP */ + { CKK_RSA, { .value = 3072 }, 0, STRENGTH_128, 3072, CK_TRUE, CKR_OK }, + /* ECC (Test 0) */ + { CKK_EC, { .nid = NID_secp224r1 }, 0, STRENGTH_112, 448, CK_TRUE, CKR_OK }, + /* ECC (Test 1) */ + { CKK_EC, { .nid = NID_brainpoolP512t1 }, 0, STRENGTH_256, 1024, CK_TRUE, CKR_OK }, + /* SYMMETRIC */ + { CKK_AES, { .value = 200 / 8 }, 0, STRENGTH_192, 128, CK_TRUE, CKR_OK } + } + } + }; + +/* These tests run with niststrength and policystrength128 */ +static const struct policyenforcetest { + CK_ULONG strength; + CK_ULONG siglen; + CK_ULONG mech; + int check; + CK_RV exprc; +} policyenforcetests[] = + { + { STRENGTH_0, 0, CKM_SHA_1, POLICY_CHECK_DIGEST, CKR_FUNCTION_FAILED }, + { STRENGTH_0, 0, CKM_SHA256, POLICY_CHECK_DIGEST, CKR_OK }, + { STRENGTH_112, 0, CKM_RSA_PKCS, POLICY_CHECK_ENCRYPT, CKR_FUNCTION_FAILED }, + { STRENGTH_128, 0, CKM_RSA_PKCS, POLICY_CHECK_ENCRYPT, CKR_OK }, + { STRENGTH_128, 112, CKM_RSA_PKCS, POLICY_CHECK_SIGNATURE, CKR_FUNCTION_FAILED }, + { STRENGTH_128, 128, CKM_RSA_PKCS, POLICY_CHECK_SIGNATURE, CKR_OK }, + }; + +static const CK_ULONG testhashmechs[] = + { CKM_RSA_PKCS, CKM_SHA1_RSA_PKCS, CKM_ECDSA, CKM_ECDSA_SHA1 }; + +static const CK_RV testhashempty[] = { CKR_OK, CKR_OK, CKR_OK, CKR_OK }; +static const CK_RV testhashnomechs[] = + { CKR_FUNCTION_FAILED, CKR_FUNCTION_FAILED, CKR_FUNCTION_FAILED, + CKR_FUNCTION_FAILED }; +static const CK_RV testhashfixed[] = + { CKR_OK, CKR_FUNCTION_FAILED, CKR_OK, CKR_FUNCTION_FAILED }; + +static const struct policyhashtest { + const char *policy; + size_t policysize; + const CK_ULONG *mechs; + const CK_RV *exprcs; + size_t nummechs; +} policyhashtests[] = + { + { + policyempty, + sizeof(policyempty), + testhashmechs, + testhashempty, + ARRAYSIZE(testhashmechs) + }, + { + policynomechs, + sizeof(policynomechs), + testhashmechs, + testhashnomechs, + ARRAYSIZE(testhashmechs) + }, + { + policyfixedmechs, + sizeof(policyfixedmechs), + testhashmechs, + testhashfixed, + ARRAYSIZE(testhashmechs) + } + }; + +/* Helper functions for strength determination */ +static CK_RV build_ulong_attr(CK_ATTRIBUTE_TYPE type, CK_ULONG value, + CK_ATTRIBUTE **attr) +{ + CK_ATTRIBUTE *a; + + a = malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG)); + if (a == NULL) + return CKR_HOST_MEMORY; + a->type = type; + a->pValue = ((char *)a) + sizeof(CK_ATTRIBUTE); + a->ulValueLen = sizeof(CK_ULONG); + *(CK_ULONG *)a->pValue = value; + *attr = a; + return CKR_OK; +} + +static CK_RV build_bigint_attr(CK_ATTRIBUTE_TYPE type, CK_ULONG numbits, + CK_ATTRIBUTE **attr) +{ + CK_ATTRIBUTE *a; + CK_ULONG numbytes = numbits / 8u; + + a = malloc(sizeof(CK_ATTRIBUTE) + numbytes); + if (a == NULL) + return CKR_HOST_MEMORY; + a->type = type; + a->pValue = ((char *)a) + sizeof(CK_ATTRIBUTE); + a->ulValueLen = numbytes; + *attr = a; + return CKR_OK; +} + +static CK_RV build_oid_attr(CK_ATTRIBUTE_TYPE type, const CK_BYTE *data, + CK_ULONG datasize, CK_ATTRIBUTE **attr) +{ + CK_ATTRIBUTE *a; + + a = malloc(sizeof(CK_ATTRIBUTE)); + if (a == NULL) + return CKR_HOST_MEMORY; + a->type = type; + a->pValue = (void *)data; + a->ulValueLen = datasize; + *attr = a; + return CKR_OK; +} + +static int attrcalls; + +static CK_RV getdetattr(void *d, CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE **attr) +{ + struct keytest *t = d; + int i; + + ++attrcalls; + switch (type) { + case CKA_KEY_TYPE: + return build_ulong_attr(type, t->keytype, attr); + case CKA_VALUE_LEN: + return build_ulong_attr(type, t->strengthattr.value, attr); + case CKA_MODULUS: + case CKA_PRIME: + return build_bigint_attr(type, t->strengthattr.value, attr); + case CKA_SUBPRIME: + return build_bigint_attr(type, t->sigattr, attr); + case CKA_EC_PARAMS: + for (i = 0; i < NUMEC; ++i) { + if (der_ec_supported[i].nid == t->strengthattr.nid) + return build_oid_attr(type, der_ec_supported[i].data, + der_ec_supported[i].data_size, attr); + + } + // Fallthrough + default: + return CKR_FUNCTION_FAILED; + } +} + +static void freedetattr(CK_ATTRIBUTE *a) +{ + --attrcalls; + free(a); +} + +static int test_load_strength_cfg(struct policy_private *pp, + void *cfg, size_t size) +{ + FILE *fp; + CK_RV rc; + + fp = fmemopen(cfg, size, "r"); + if (fp == NULL) { + fprintf(stderr, "Failed to memopen strength configuration\n"); + return -1; + } + rc = policy_load_strength_cfg(pp, fp); + fclose(fp); + if (rc != CKR_OK) { + fprintf(stderr, "Strength configuration could not be loaded\n"); + return -1; + } + return 0; +} + +static int test_load_policy_cfg(struct policy_private *pp, + void *cfg, size_t size) +{ + FILE *fp; + CK_RV rc; + CK_BBOOL ignored; + + fp = fmemopen(cfg, size, "r"); + if (fp == NULL) { + fprintf(stderr, "Failed to memopen policy\n"); + return -1; + } + rc = policy_load_policy_cfg(pp, fp, &ignored); + fclose(fp); + if (rc != CKR_OK) { + fprintf(stderr, "Policy configuration could not be loaded\n"); + return -1; + } + return 0; +} + +static int runstrengthdettests(void) +{ + struct objstrength strength; + struct policy_private *pp; + const struct keytest *t; + struct policy p; + unsigned int o; + CK_RV rc; + int res; + int i; + + fprintf(stderr, "Running strengthdettests\n"); + res = 0; + policy_init_policy(&p); + for (o = 0; o < ARRAYSIZE(strengthdettests); ++o) { + pp = policy_private_alloc(); + if (pp == NULL) { + fprintf(stderr, "Failed to allocate policy_private\n"); + return -1; + } + policy_private_deactivate(pp); + p.priv = pp; + if (test_load_strength_cfg(pp, (void *)strengthdettests[o].definition, + strengthdettests[o].definitionsize)) { + fprintf(stderr, "Test %u: Failed to load strength configuration\n", o); + return -1; + } + for (i = 0; i < NUM_KEYTESTS_STRENGTHDET; ++i) { + attrcalls = 0; + t = &(strengthdettests[o].tests[i]); + rc = p.store_object_strength(&p, &strength, getdetattr, (void *)t, + freedetattr, NULL); + if (rc != CKR_OK) { + res = -1; + fprintf(stderr, "Test %u, case %i: Could not store object strength\n", + o, i); + break; + } + if (strength.strength != t->expstrength) { + res = -1; + fprintf(stderr, "Test %u, case %i: Unexpected strength:\nexpected: %lu\nis: %lu\n", + o, i, t->expstrength, strength.strength); + break; + } + if (strength.siglen != t->expsiglen) { + res = -1; + fprintf(stderr, "Test %u, case %i: Unexpected siglen:\nexpected: %lu\nis: %lu\n", + o, i, t->expsiglen, strength.siglen); + break; + } + if (t->keytype == CKK_EC && strength.allowed != t->expallowed) { + res = -1; + fprintf(stderr, "Test %u, case %i: Unexpected EC allowed flag\n", + o, i); + break; + } + if (attrcalls != 0) { + res = -1; + fprintf(stderr, "Unbalanced attribute calls. Count shows %i!\n", + attrcalls); + break; + } + } + p.priv = policy_private_free(pp); + if (res != 0) + break; + } + return res; +} + +static int runstrengthenforcetests(void) +{ + struct objstrength strength; + struct policy_private *pp; + const struct keytest *t; + struct policy p; + unsigned int o; + CK_RV rc; + int res; + int i; + + fprintf(stderr, "Running strengthenforcetests\n"); + res = 0; + policy_init_policy(&p); + for (o = 0; o < ARRAYSIZE(strengthenforcetests); ++o) { + pp = policy_private_alloc(); + if (pp == NULL) { + fprintf(stderr, "Test %u: Failed to allocate policy_private\n", o); + return -1; + } + p.priv = pp; + if (test_load_strength_cfg(pp,(void *)strengthenforcetests[o].strength, + strengthenforcetests[o].strengthsize)) { + policy_private_free(pp); + fprintf(stderr, "Test %u: Failed to load strength configuration\n", + o); + return -1; + } + if (test_load_policy_cfg(pp, (void *)strengthenforcetests[o].policy, + strengthenforcetests[o].policysize)) { + policy_private_free(pp); + fprintf(stderr, "Test %u: Failed to load policy configuration\n", + o); + return -1; + } + for (i = 0; i < NUM_KEYTESTS_STRENGTHENFORCE; ++i) { + attrcalls = 0; + t = &(strengthenforcetests[o].tests[i]); + rc = p.store_object_strength(&p, &strength, getdetattr, (void *)t, + freedetattr, NULL); + if (rc != t->exprc) { + res = -1; + fprintf(stderr, "Test %u, case %i: Wrong result on strength determination: expected %lu, got %lu\n", + o, i, t->exprc, rc); + break; + } + /* Even if we get CKR_FUNCTION_FAILED, the policy should + have stored the correct strength information. */ + if (strength.strength != t->expstrength) { + res = -1; + fprintf(stderr, "Test %u, case %i: Unexpected strength:\nexpected: %lu\nis: %lu\n", + o, i, t->expstrength, strength.strength); + break; + } + if (strength.siglen != t->expsiglen) { + res = -1; + fprintf(stderr, "Test %u, case %i: Unexpected siglen:\nexpected: %lu\nis: %lu\n", + o, i, t->expsiglen, strength.siglen); + break; + } + if (t->keytype == CKK_EC && strength.allowed != t->expallowed) { + res = -1; + fprintf(stderr, "Test %u, case %i: Unexpected EC allowed flag\n", + o, i); + break; + } + if (attrcalls != 0) { + res = -1; + fprintf(stderr, "Unbalanced attribute calls. Count shows %i!\n", + attrcalls); + break; + } + } + p.priv = policy_private_free(pp); + if (res != 0) + break; + } + return res; +} + +static int runpolicyenforcetests(void) +{ + struct objstrength strength, *s; + struct policy_private *pp; + CK_MECHANISM mech; + struct policy p; + unsigned int i; + CK_RV rc; + int res; + + fprintf(stderr, "Running policyenforcetests\n"); + res = 0; + mech.pParameter = NULL; + mech.ulParameterLen = 0; + strength.allowed = CK_TRUE; + policy_init_policy(&p); + pp = policy_private_alloc(); + if (pp == NULL) { + fprintf(stderr, "Failed to allocate policy_private\n"); + return -1; + } + p.priv = pp; + if (test_load_strength_cfg(pp, (void *)niststrength, sizeof(niststrength))) { + policy_private_free(pp); + fprintf(stderr, "Failed to load NIST strength configuration\n"); + return -1; + } + if (test_load_policy_cfg(pp, (void *)policystrength128, + sizeof(policystrength128))) { + policy_private_free(pp); + fprintf(stderr, "Failed to load policy with strength 128\n"); + return -1; + } + for (i = 0; i < ARRAYSIZE(policyenforcetests); ++i) { + strength.strength = policyenforcetests[i].strength; + strength.siglen = policyenforcetests[i].siglen; + s = policyenforcetests[i].check == POLICY_CHECK_DIGEST ? + NULL : &strength; + mech.mechanism = policyenforcetests[i].mech; + rc = p.is_mech_allowed(&p, &mech, s, policyenforcetests[i].check, NULL); + if (rc != policyenforcetests[i].exprc) { + fprintf(stderr, + "Test %u: Unexpected result: 0x%lx (expected 0x%lx)\n", + i, rc, policyenforcetests[i].exprc); + res = -1; + } + } + policy_private_free(pp); + return res; +} + +static int runpolicyhashtests(void) +{ + struct objstrength strength; + struct policy_private *pp; + CK_MECHANISM mech; + struct policy p; + unsigned int o, i; + CK_RV rc; + int res; + + fprintf(stderr, "Running policyhashtests\n"); + res = 0; + policy_init_policy(&p); + mech.pParameter = NULL; + mech.ulParameterLen = 0; + strength.strength = 0; + strength.siglen = 0; + strength.allowed = CK_TRUE; + for (o = 0; o < ARRAYSIZE(policyhashtests); ++o) { + pp = policy_private_alloc(); + if (pp == NULL) { + fprintf(stderr, "Test %u: Failed to allocate policy_private\n", o); + return -1; + } + p.priv = pp; + if (test_load_strength_cfg(pp,(void *)niststrength, + sizeof(niststrength))) { + policy_private_free(pp); + fprintf(stderr, "Test %u: Failed to load strength configuration\n", + o); + return -1; + } + if (test_load_policy_cfg(pp, (void *)policyhashtests[o].policy, + policyhashtests[o].policysize)) { + policy_private_free(pp); + fprintf(stderr, "Test %u: Failed to load policy configuration\n", + o); + return -1; + } + for (i = 0; i < policyhashtests[o].nummechs; ++i) { + mech.mechanism = policyhashtests[o].mechs[i]; + /* check is wrong for most, but is chosen to not perform + any additional size checking. */ + rc = p.is_mech_allowed(&p, &mech, &strength, POLICY_CHECK_ENCRYPT, + NULL); + if (rc != policyhashtests[o].exprcs[i]) { + fprintf(stderr, "Test %u case %u: Wrong result: 0x%lx (expected 0x%lx)\n", + o, i, rc, policyhashtests[o].exprcs[i]); + res = -1; + } + } + policy_private_free(pp); + } + return res; +} + +#define POLICYDEEPCHECKMGFNUM 4 + +static int runpolicydeepcheckmgftests(void) +{ + static const CK_ULONG mgfs[POLICYDEEPCHECKMGFNUM] = + { CKG_MGF1_SHA1, CKG_MGF1_SHA512, + CKG_IBM_MGF1_SHA3_224, CKG_IBM_MGF1_SHA3_384 }; + static const struct { + const char *policy; + size_t policylen; + CK_RV exprc[POLICYDEEPCHECKMGFNUM]; + } policies[] = + { + { policyempty, sizeof(policyempty), + {CKR_OK, CKR_OK, CKR_OK, CKR_OK} }, + { policymgfstandard, sizeof(policymgfstandard), + {CKR_OK, CKR_OK, CKR_FUNCTION_FAILED, CKR_FUNCTION_FAILED} }, + { policymgfibm, sizeof(policymgfibm), + { CKR_FUNCTION_FAILED, CKR_FUNCTION_FAILED, CKR_OK, CKR_OK} }, + { policymgfoneeach, sizeof(policymgfoneeach), + { CKR_FUNCTION_FAILED, CKR_OK, CKR_OK, CKR_FUNCTION_FAILED} }, + { policymgfnone, sizeof(policymgfnone), + { CKR_FUNCTION_FAILED, CKR_FUNCTION_FAILED, + CKR_FUNCTION_FAILED, CKR_FUNCTION_FAILED } } + }; + struct objstrength strength; + struct policy_private *pp; + CK_MECHANISM oaepmech, pssmech; + struct policy p; + unsigned int i, o; + CK_RV rc; + int res; + CK_RSA_PKCS_OAEP_PARAMS oaepparams; + CK_RSA_PKCS_PSS_PARAMS pssparams; + + fprintf(stderr, "Running policydeepcheckmgftests\n"); + res = 0; + policy_init_policy(&p); + oaepparams.hashAlg = CKM_SHA_1; + oaepparams.source = CKZ_DATA_SPECIFIED; + oaepparams.pSourceData = NULL; + oaepparams.ulSourceDataLen = 0; + pssparams.hashAlg = CKM_SHA_1; + pssparams.sLen = 0; + strength.strength = 0; + strength.siglen = 0; + strength.allowed = CK_TRUE; + oaepmech.mechanism = CKM_RSA_PKCS_OAEP; + oaepmech.pParameter = &oaepparams; + oaepmech.ulParameterLen = sizeof(oaepparams); + pssmech.mechanism = CKM_RSA_PKCS_PSS; + pssmech.pParameter = &pssparams; + pssmech.ulParameterLen = sizeof(pssparams); + + for (o = 0; o < ARRAYSIZE(policies); ++o) { + pp = policy_private_alloc(); + if (pp == NULL) { + fprintf(stderr, "Test %u: Failed to allocate policy_private\n", o); + return -1; + } + p.priv = pp; + if (test_load_strength_cfg(pp,(void *)niststrength, + sizeof(niststrength))) { + policy_private_free(pp); + fprintf(stderr, "Test %u: Failed to load strength configuration\n", + o); + return -1; + } + if (test_load_policy_cfg(pp, (void *)policies[o].policy, + policies[o].policylen)) { + policy_private_free(pp); + fprintf(stderr, "Test %u: Failed to load policy configuration\n", + o); + return -1; + } + for (i = 0; i < ARRAYSIZE(mgfs); ++i) { + oaepparams.mgf = pssparams.mgf = mgfs[i]; + /* Checking encrypt prevents output size checking here + which is not the goal of this test. */ + rc = p.is_mech_allowed(&p, &oaepmech, &strength, + POLICY_CHECK_ENCRYPT, + NULL); + if (rc != policies[o].exprc[i]) { + fprintf(stderr, + "Test %u, case %u, OAEP: unexpected result 0x%lx (expected 0x%lx)\n", + o, i, rc, policies[o].exprc[i]); + res = -1; + } + rc = p.is_mech_allowed(&p, &pssmech, &strength, + POLICY_CHECK_ENCRYPT, + NULL); + if (rc != policies[o].exprc[i]) { + fprintf(stderr, + "Test %u, case %u, PSS: unexpected result 0x%lx (expected 0x%lx)\n", + o, i, rc, policies[o].exprc[i]); + res = -1; + } + } + p.priv = pp = policy_private_free(pp); + } + return res; +} + +#define POLICYDEEPCHECKKDFNUM 4 + +static int runpolicydeepcheckkdftests(void) +{ + static const CK_ULONG kdfs[POLICYDEEPCHECKKDFNUM] = + { CKD_NULL, CKD_SHA1_KDF_ASN1, CKD_SHA256_KDF, CKD_SHA512_KDF }; + static const struct { + const char *policy; + size_t policylen; + CK_RV exprc[POLICYDEEPCHECKKDFNUM]; + } policies[] = + { + { + policyempty, sizeof(policyempty), + { CKR_OK, CKR_OK, CKR_OK, CKR_OK } + }, + { + policykdfnosha1, sizeof(policykdfnosha1), + { CKR_FUNCTION_FAILED, CKR_FUNCTION_FAILED, CKR_OK, CKR_OK } + }, + { + policykdfnone, sizeof(policykdfnone), + { CKR_FUNCTION_FAILED, CKR_FUNCTION_FAILED, + CKR_FUNCTION_FAILED, CKR_FUNCTION_FAILED } + } + }; + CK_ECDH1_DERIVE_PARAMS ecdhparams; + struct objstrength strength; + struct policy_private *pp; + CK_MECHANISM mech; + struct policy p; + unsigned int i, o; + CK_RV rc; + int res; + + fprintf(stderr, "Running policydeepcheckkdftests\n"); + res = 0; + policy_init_policy(&p); + strength.strength = 0; + strength.siglen = 0; + strength.allowed = CK_TRUE; + ecdhparams.ulSharedDataLen = 0; + ecdhparams.pSharedData = NULL; + ecdhparams.ulPublicDataLen = 0; + ecdhparams.pPublicData = NULL; + mech.mechanism = CKM_ECDH1_DERIVE; + mech.pParameter = &ecdhparams; + mech.ulParameterLen = sizeof(ecdhparams); + for (o = 0; o < ARRAYSIZE(policies); ++o) { + fprintf(stderr, "Test %u\n", o); + pp = policy_private_alloc(); + if (pp == NULL) { + fprintf(stderr, "Test %u: Failed to allocate policy_private\n", o); + return -1; + } + p.priv = pp; + if (test_load_strength_cfg(pp,(void *)niststrength, + sizeof(niststrength))) { + policy_private_free(pp); + fprintf(stderr, "Test %u: Failed to load strength configuration\n", + o); + return -1; + } + if (test_load_policy_cfg(pp, (void *)policies[o].policy, + policies[o].policylen)) { + policy_private_free(pp); + fprintf(stderr, "Test %u: Failed to load policy configuration\n", + o); + return -1; + } + for (i = 0; i < ARRAYSIZE(kdfs); ++i) { + fprintf(stderr, "Case %u\n", i); + ecdhparams.kdf = kdfs[i]; + rc = p.is_mech_allowed(&p, &mech, &strength, POLICY_CHECK_DERIVE, + NULL); + if (rc != policies[o].exprc[i]) { + fprintf(stderr, + "Test %u, case %u: unexpected result 0x%lx (expected 0x%lx)\n", + o, i, rc, policies[o].exprc[i]); + res = -1; + } + } + p.priv = pp = policy_private_free(pp); + } + return res; +} + +static int runpolicydeepchecktests(void) +{ + return runpolicydeepcheckmgftests() | runpolicydeepcheckkdftests(); +} + +static int runstrengthtests(void) +{ + return runstrengthdettests() | runstrengthenforcetests(); +} + +static int runpolicytests(void) +{ + return runpolicyenforcetests() | runpolicyhashtests() | + runpolicydeepchecktests(); +} + +int main(void) +{ + if (runstrengthtests()) + return TEST_FAIL; + if (runpolicytests()) + return TEST_FAIL; + return TEST_PASS; +} diff -Nru opencryptoki-3.16.0+dfsg/testcases/unit/unit.mk opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/unit/unit.mk --- opencryptoki-3.16.0+dfsg/testcases/unit/unit.mk 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/unit/unit.mk 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,44 @@ +check_PROGRAMS = testcases/unit/policytest testcases/unit/hashmaptest \ + testcases/unit/mechtabletest testcases/unit/configdump + +TESTS = testcases/unit/policytest testcases/unit/hashmaptest \ + testcases/unit/mechtabletest testcases/unit/configdump + +testcases_unit_policytest_CFLAGS=-I${top_srcdir}/usr/lib/common \ + -I${top_srcdir}/usr/lib/api -I${top_srcdir}/usr/include \ + -DSTDLL_NAME=\"policytest\" -I${top_srcdir}/usr/lib/config \ + -I${top_builddir}/usr/lib/config -I${top_builddir}/usr/lib/api + +testcases_unit_policytest_SOURCES=testcases/unit/policytest.c \ + usr/lib/api/policy.c usr/lib/api/hashmap.c \ + usr/lib/common/ec_supported.c usr/lib/common/trace.c \ + usr/lib/common/utility_common.c \ + usr/lib/config/configuration.c \ + usr/lib/common/ec_curve_translation.c \ + usr/lib/common/kdf_translation.c \ + usr/lib/common/mgf_translation.c \ + usr/lib/api/supportedstrengths.c \ + usr/lib/config/cfgparse.y usr/lib/config/cfglex.l + +nodist_testcases_unit_policytest_SOURCES=usr/lib/api/mechtable.c + +testcases_unit_hashmaptest_CFLAGS=-I${top_srcdir}/usr/lib/api \ + -I${top_srcdir}/usr/include + +testcases_unit_hashmaptest_SOURCES = testcases/unit/hashmaptest.c \ + usr/lib/api/hashmap.c + +testcases_unit_mechtabletest_CFLAGS=-I${top_srcdir}/usr/lib/api \ + -I${top_srcdir}/usr/include -I${top_builddir}/usr/lib/api \ + -I${top_srcdir}/usr/include + +testcases_unit_mechtabletest_SOURCES=testcases/unit/mechtabletest.c + +nodist_testcases_unit_mechtabletest_SOURCES=usr/lib/api/mechtable.c + +testcases_unit_configdump_SOURCES = testcases/unit/configdump.c \ + usr/lib/config/cfglex.l usr/lib/config/cfgparse.y \ + usr/lib/config/configuration.c + +testcases_unit_configdump_CFLAGS=-I${top_srcdir}/usr/lib/config \ + -I${top_builddir}/usr/lib/config diff -Nru opencryptoki-3.16.0+dfsg/testcases/unit/unittest.h opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/unit/unittest.h --- opencryptoki-3.16.0+dfsg/testcases/unit/unittest.h 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/testcases/unit/unittest.h 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,20 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ +#ifndef UNITTEST_H +#define UNITTEST_H + +/* AUTOTOOLS definitions for tests */ +#define TEST_SKIP 77 +#define TEST_FAIL 99 +#define TEST_PASS 0 + +#define ARRAYSIZE(X) (sizeof((X))/sizeof((X)[0])) + +#endif diff -Nru opencryptoki-3.16.0+dfsg/tools/policyexamplegen.c opencryptoki-3.17.0+dfsg+20220202.b40982e/tools/policyexamplegen.c --- opencryptoki-3.16.0+dfsg/tools/policyexamplegen.c 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/tools/policyexamplegen.c 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,114 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ + +#include + +#include + +#include + +int main(void) +{ + size_t i; + char *line = ""; + + puts("# OpenCryptoki policy example"); + puts("# Move/copy to /etc/opencryptoki/policy.cfg to use it with opencryptoki."); + puts("# Then chown it to root:pkcs11 and chmod it to 0640."); + puts("# Also create a /etc/opencryptoki/strength.cfg since this is a prerequisite"); + puts("# for policies. You could just copy the strength-example.cfg from this"); + puts("# folder, chown it to root:pkcs11 and chmod it to 0640."); + puts(""); + puts("version policy-0"); + puts(""); + puts("# Do not require any specific strength."); + puts("# You probably do not want this!"); + puts("strength = 0"); + puts(""); + puts("# Allow all mechanisms by name."); + puts("# A simpler option to configure this is to just remove the allowedmechs list."); + puts("allowedmechs ("); + for (i = 0; i < MECHTABLE_NUM_ELEMS; ++i) { + fputs(line, stdout); + printf(" %s", mechtable_rows[i].string); + line = ",\n"; + } + putchar('\n'); + puts(" # No comma after last element!"); + puts(")"); + puts(""); + puts("# Allow all elliptic curves."); + puts("# A simpler method to configure this is to just remove the allowedcurves list."); + puts("allowedcurves ("); + puts(" BRAINPOOL_P160R1,"); + puts(" BRAINPOOL_P160T1,"); + puts(" BRAINPOOL_P192R1,"); + puts(" BRAINPOOL_P192T1,"); + puts(" BRAINPOOL_P224R1,"); + puts(" BRAINPOOL_P224T1,"); + puts(" BRAINPOOL_P256R1,"); + puts(" BRAINPOOL_P256T1,"); + puts(" BRAINPOOL_P320R1,"); + puts(" BRAINPOOL_P320T1,"); + puts(" BRAINPOOL_P384R1,"); + puts(" BRAINPOOL_P384T1,"); + puts(" BRAINPOOL_P512R1,"); + puts(" BRAINPOOL_P512T1,"); + puts(" PRIME192V1,"); + puts(" SECP224R1,"); + puts(" PRIME256V1,"); + puts(" SECP384R1,"); + puts(" SECP521R1,"); + puts(" SECP256K1,"); + puts(" CURVE25519,"); + puts(" CURVE448,"); + puts(" ED25519,"); + puts(" ED448"); + puts(" # No comma after last element!"); + puts(")"); + puts(""); + puts("# Allow all MGFs."); + puts("# A simpler method to configure this is to just remove the allowedmgfs list."); + puts("allowedmgfs ("); + puts(" CKG_MGF1_SHA1,"); + puts(" CKG_MGF1_SHA224,"); + puts(" CKG_MGF1_SHA256,"); + puts(" CKG_MGF1_SHA384,"); + puts(" CKG_MGF1_SHA512,"); + puts(" CKG_IBM_MGF1_SHA3_224,"); + puts(" CKG_IBM_MGF1_SHA3_256,"); + puts(" CKG_IBM_MGF1_SHA3_384,"); + puts(" CKG_IBM_MGF1_SHA3_512"); + puts(" # No comma after last element!"); + puts(")"); + puts(""); + puts("# Allow all KDFs."); + puts("# A simpler method to configure this is to just remove the allowedkdfs list."); + puts("allowedkdfs ("); + puts(" CKD_NULL,"); + puts(" CKD_SHA1_KDF,"); + puts(" CKD_SHA1_KDF_ASN1,"); + puts(" CKD_SHA1_KDF_CONCATENATE,"); + puts(" CKD_SHA224_KDF,"); + puts(" CKD_SHA256_KDF,"); + puts(" CKD_SHA384_KDF,"); + puts(" CKD_SHA512_KDF"); + puts(" # No comma after last element!"); + puts(")"); + puts(""); + puts("# Allow all PRFs."); + puts("# A simpler method to configure this is to just remove the allowedprfs list."); + puts("allowedprfs ("); + puts(" CKP_PKCS5_PBKD2_HMAC_SHA256,"); + puts(" CKP_PKCS5_PBKD2_HMAC_SHA512"); + puts(" # No comma after last element!"); + puts(")"); + return 0; +} diff -Nru opencryptoki-3.16.0+dfsg/tools/tableidxgen.c opencryptoki-3.17.0+dfsg+20220202.b40982e/tools/tableidxgen.c --- opencryptoki-3.16.0+dfsg/tools/tableidxgen.c 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/tools/tableidxgen.c 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,738 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define MECHTABLE_IN_GEN +#include +#undef MECHTABLE_IN_GEN + +#define ARRAY_SIZE(X) (sizeof((X)) / sizeof((X)[0])) + +/* To satisfy symbols */ +const struct mechtable_funcs mechtable_funcs; + +int mechtable_idx_from_numeric(CK_ULONG mech) +{ + (void)mech; + return -1; +} + +int mechtable_idx_from_string(const char *mech) +{ + (void)mech; + return -1; +} + +const struct mechrow *mechrow_from_numeric(CK_ULONG mech) +{ + (void)mech; + return NULL; +} + +const struct mechrow *mechrow_from_string(const char *mech) +{ + (void)mech; + return NULL; +} + +/* A list of all aliases. Add every non-unique mechanism number once + to the table in mechtable.inc and add all aliases here. The one in + the table will be the one used in the string output. */ +const struct aliaslist { + const char *string; + const char *alias; +} aliases[] = { + { "CKM_ECDSA_KEY_PAIR_GEN", "CKM_EC_KEY_PAIR_GEN" }, + { "CKM_IBM_EC_C25519", "CKM_IBM_EC_X25519" }, + { "CKM_IBM_EC_C448", "CKM_IBM_EC_X448" }, + { "CKM_IBM_EDDSA_SHA512", "CKM_IBM_ED25519_SHA512" } +}; + +/* Get the table */ +#include "mechtable.inc" + +struct node; +struct node { + short table[256]; + unsigned short num; + unsigned int offset; + unsigned int used; + struct node *nextnum; +}; + +static unsigned char idxtable[256]; +static unsigned char usagetable[256]; +static unsigned int usagecount; +static unsigned short nextnum; +static struct node *root, **last; +static char *commonprefix; +static size_t commonprefixlength; + +/* Utilities */ +static struct node *getnodeforidx(short idx) +{ + short i; + struct node *res = root; + + for (i = 0; i < idx; ++i) + res = res->nextnum; + return res; +} + +static struct node *allocatenode(void) +{ + struct node *res = malloc(sizeof(struct node)); + + if (!res) + errx(1, "Failed to allocate node"); + res->num = nextnum++; + res->nextnum = NULL; + res->used = 0; + res->offset = 0; + *last = res; + memset(res->table, 0, 256 * sizeof(short)); + last = &(res->nextnum); + return res; +} + +static void freenodes(void) +{ + struct node *i, *n; + + for (i = root; i; i = n) { + n = i->nextnum; + free(i); + } +} + +static void reinitializenodes(void) +{ + freenodes(); + root = NULL; + last = &root; + nextnum = 0; + allocatenode(); +} + +/* Additions */ +static void addnumeric(const struct mechrow *m, short position) +{ + short idx; + struct node *n = root, *a; + + idx = (m->numeric & 0xff000000u) >> 24u; + if (n->table[idx] == 0) { + a = allocatenode(); + n->table[idx] = a->num; + n->used += 1; + n = a; + } else { + n = getnodeforidx(n->table[idx]); + } + idx = (m->numeric & 0x00ff0000u) >> 16u; + if (n->table[idx] == 0) { + a = allocatenode(); + n->table[idx] = a->num; + n->used += 1; + n = a; + } else { + n = getnodeforidx(n->table[idx]); + } + idx = (m->numeric & 0x0000ff00u) >> 8u; + if (n->table[idx] == 0) { + a = allocatenode(); + n->table[idx] = a->num; + n->used += 1; + n = a; + } else { + n = getnodeforidx(n->table[idx]); + } + idx = m->numeric & 0x000000ffu; + if (n->table[idx]) { + errx(1, "Duplicated key 0x%lx. Please use aliaslist in tableidxgen.c for duplicates\n", + m->numeric); + return; + } + /* Make sure we do not insert zero. Zero marks an empty cell. */ + n->table[idx] = -position - 1; + n->used += 1; +} + +static short recursiveaddstring(const char *str, short position) +{ + size_t len = strlen(str); + size_t i; + struct node *n = root, *a; + short val, readd = 0, idx; + + for (i = commonprefixlength; i <= len; ++i) { + idx = str[i]; + val = n->table[idx]; + if (val > 0) { + /* A link */ + n = getnodeforidx(val); + } else if (val == 0) { + /* An empty slot */ + n->table[idx] = -position - 1; + n->used += 1; + return readd; + } else { + /* A value */ + readd = val; + /* Duplication check */ + if (strcmp(str, mechtable_rows[-val - 1].string) == 0) + errx(1, "Dublicated string keys (%s) not supported!", str); + a = allocatenode(); + n->table[idx] = a->num; + n->used += 1; + n = a; + } + } + /* I don't see how this can happen, but the compiler disagrees. */ + errx(1, "Cannot add key %s!", str); +} + +static void addstring(const struct mechrow *m, short position) +{ + short res = position; + const struct mechrow *toadd = m; + + while ((res = recursiveaddstring(toadd->string, res)) < 0) { + res = -res - 1; + toadd = &mechtable_rows[res]; + } +} + +/* Compressors */ +static void compressnumericalphabet(void) +{ + size_t i; + unsigned int idx; + + memset(usagetable, 0, 256); + memset(idxtable, 0, 256); + usagecount = 0; + for (i = 0; i < ARRAY_SIZE(mechtable_rows); ++i) { + idx = (mechtable_rows[i].numeric & 0xff000000u) >> 24u; + if (usagetable[idx] == 0) + ++usagecount; + usagetable[idx] = 1; + idx = (mechtable_rows[i].numeric & 0x00ff0000u) >> 16u; + if (usagetable[idx] == 0) + ++usagecount; + usagetable[idx] = 1; + idx = (mechtable_rows[i].numeric & 0x0000ff00u) >> 8u; + if (usagetable[idx] == 0) + ++usagecount; + usagetable[idx] = 1; + idx = (mechtable_rows[i].numeric & 0x000000ffu); + if (usagetable[idx] == 0) + ++usagecount; + usagetable[idx] = 1; + } + idx = 0; + for (i = 0; i < 256; ++i) { + if (usagetable[i]) + idxtable[i] = (unsigned char)idx++; + } +} + +static void compressstringalphabet(void) +{ + size_t i, j; + unsigned int idx; + + memset(usagetable, 0, 256); + memset(idxtable, 0, 256); + usagecount = 0; + for (i = 0; i < ARRAY_SIZE(mechtable_rows); ++i) { + for (j = 0; j <= strlen(mechtable_rows[i].string); ++j) { + idx = mechtable_rows[i].string[j]; + if (usagetable[idx] == 0) + ++usagecount; + usagetable[idx] = 1; + } + } + idx = 0; + for (i = 0; i < 256; ++i) { + if (usagetable[i]) + idxtable[i] = (unsigned char)idx++; + } +} + +static unsigned int compresstable(void) +{ + int pos, i, k, l; + struct node *n; + unsigned int maxoffset = 0; + unsigned int offset; + /* allocate properly too much */ + unsigned char *t = calloc(nextnum, usagecount); + struct node **sorttable = calloc(nextnum, sizeof(struct node *)); + + if (!t) + errx(1, "Could not allocate compression table"); + if (!sorttable) + errx(1, "Could not allocate sort table"); + pos = 0; + /* sort nodes by used count (descending) */ + for (n = root; n; n = n->nextnum) { + for (i = 0; i < pos; ++i) { + if (n->used > sorttable[i]->used) { + memmove(sorttable + i + 1, sorttable + i, + (pos - i) * sizeof(struct node *)); + break; + } + } + sorttable[i] = n; + ++pos; + } + assert(pos == nextnum); + /* now insert and compress */ + /* for all nodes */ + for (i = 0; i < nextnum; ++i) { + /* for all possible offsets */ + for (offset = 0; offset < (nextnum - 1) * usagecount; ++offset) { + /* try to put table i at offset */ + for (k = 0; k < 256; ++k) { + if (usagetable[k] && sorttable[i]->table[k]) { + if (t[idxtable[k] + offset]) + break; + t[idxtable[k] + offset] = 1; + } + } + if (k == 256) { + /* success for node i */ + sorttable[i]->offset = offset; + if (offset > maxoffset) + maxoffset = offset; + break; + } else { + /* failure => undo t updates */ + for (l = 0; l < k; ++l) { + if (usagetable[l] && sorttable[i]->table[l]) + t[idxtable[l] + offset] = 0; + } + } + } + } + free(sorttable); + free(t); + return maxoffset; +} + +/* Common prefix elimination */ +static void eliminatecommonprefixes(void) +{ + size_t i, j, minlength, l; + + commonprefix = strdup(mechtable_rows[0].string); + if (!commonprefix) + errx(1, "Out of memory"); + commonprefixlength = strlen(commonprefix); + for (i = 1; i < ARRAY_SIZE(mechtable_rows); ++i) { + l = strlen(mechtable_rows[i].string); + minlength = commonprefixlength < l ? commonprefixlength : l; + for (j = 0; j < minlength && + commonprefix[j] == mechtable_rows[i].string[j]; ++j) { + /* Advance */ + } + commonprefix[j] = 0; + commonprefixlength = j; + } +} + +/* Builders */ +static void buildnumeric(void) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(mechtable_rows); ++i) + addnumeric(&mechtable_rows[i], i); +} + +static void buildstring(void) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(mechtable_rows); ++i) + addstring(&mechtable_rows[i], i); +} + +static short *buildcompressedtable(unsigned int maxoffset) +{ + struct node *n; + unsigned int i, idx; + short *res = calloc(maxoffset + usagecount, sizeof(short)); + + if (!res) + errx(1, "Could not allocate compressed table"); + for (n = root; n; n = n->nextnum) { + for (i = 0; i < 256; ++i) { + if (usagetable[i] && n->table[i]) { + idx = idxtable[i] + n->offset; + assert(res[idx] == 0); + if (n->table[i] < 0) + /* a value */ + res[idx] = n->table[i]; + else + /* a link */ + res[idx] = getnodeforidx(n->table[i])->offset; + } + } + } + return res; +} + +static void freecompressedtable(short *table) +{ + free(table); +} + +/* Logging */ +static void lognodes(FILE *fp) +{ + struct node *n; + int i; + + fputs("Jump table:\n", fp); + for (n = root; n; n = n->nextnum) { + fprintf(fp, "node %hd: (offset %u)\n", n->num, n->offset); + for (i = 0; i < 256; ++i) { + if (n->table[i] > 0) + fprintf(fp, " %d (%d) => node %hd\n", i, (int)idxtable[i], + n->table[i]); + else if (n->table[i] < 0) + fprintf(fp, " %d (%d) => mapping %d\n", i, (int)idxtable[i], + -(n->table[i]+1)); + } + } +} + +static FILE *openfile(char *name) +{ + FILE *res = fopen(name, "w"); + + if (!res) + err(1, "Failed to open %s", name); + return res; +} + +static void closefile(FILE *fp) +{ + fclose(fp); +} + +static void logalphabet(FILE *fp) +{ + int i; + + fputs("Alphabet mapping:\n", fp); + for (i = 0; i < 256; ++i) { + if (usagetable[i]) + fprintf(fp, "%c (%d) => %hhu\n", (char)i, i, idxtable[i]); + } +} + +/* dumpers */ +static void dumptable(unsigned int maxoffset, short *table, char *name, + FILE *fp) +{ + unsigned int i, j; + + fprintf(fp, "static const short %stable[] = {\n", name); + for (i = 0; i < (maxoffset + usagecount) / 8; ++i) { + fprintf(fp, " %hd, %hd, %hd, %hd, %hd, %hd, %hd, %hd,\n", + table[8 * i], table[8 * i + 1], table[8 * i + 2], + table[8 * i + 3], table[8 * i + 4], table[8 * i + 5], + table[8 * i + 6], table[8 * i + 7]); + } + if ((maxoffset + usagecount) % 8 != 0) { + fputc(' ', fp); + for (j = 0; j < (maxoffset + usagecount) % 8; ++j) { + fprintf(fp, " %hd,", table[8 * i + j]); + } + fputc('\n', fp); + } + fputs("};\n", fp); +} + +static void dumpalphabet(char *name, FILE *fp) +{ + int i; + + fprintf(fp, "static const unsigned char %salphabet[] = {\n", name); + for (i = 0; i < 256 / 8; ++i) { + fprintf(fp, " %hhu, %hhu, %hhu, %hhu, %hhu, %hhu, %hhu, %hhu,\n", + idxtable[8 * i], idxtable[8 * i + 1], idxtable[8 * i + 2], + idxtable[8 * i + 3], idxtable[8 * i + 4], idxtable[8 * i + 5], + idxtable[8 * i + 6], idxtable[8 * i + 7]); + } + fputs("};\n", fp); +} + +static void dumpnumericfun(FILE *fp) +{ + fputs("int mechtable_idx_from_numeric(CK_ULONG mech)\n", fp); + fputs("{\n", fp); + fputs(" unsigned int idx1, idx2, idx3, idx4;\n", fp); + fputs(" int o1, o2, o3;\n", fp); + fputs(" int midx;\n\n", fp); + fputs(" idx1 = numericalphabet[(mech & 0xff000000u) >> 24u];\n", fp); + fputs(" idx2 = numericalphabet[(mech & 0x00ff0000u) >> 16u];\n", fp); + fputs(" idx3 = numericalphabet[(mech & 0x0000ff00u) >> 8u];\n", fp); + fputs(" idx4 = numericalphabet[mech & 0x000000ffu];\n", fp); + /* No need to check idx vars since they are 0 if unsigned char is not mapped + and nothing problematic happens. The search will just be + unsuccessful. */ + fprintf(fp, " o1 = numerictable[%u + idx1];\n", root->offset); + fputs(" if (o1 < 0) return -1;\n", fp); + fputs(" o2 = numerictable[o1 + idx2];\n", fp); + fputs(" if (o2 < 0) return -1;\n", fp); + fputs(" o3 = numerictable[o2 + idx3];\n", fp); + fputs(" if (o3 < 0) return -1;\n", fp); + fputs(" midx = numerictable[o3 + idx4];\n", fp); + fputs(" midx = -(midx + 1);\n", fp); + fprintf(fp, " if (0 <= midx && midx < %lu && mechtable_rows[midx].numeric == mech)\n", + ARRAY_SIZE(mechtable_rows)); + fputs(" return midx;\n", fp); + fputs(" return -1;\n", fp); + fputs("}\n\n", fp); + fputs("const struct mechrow *mechrow_from_numeric(CK_ULONG mech)\n", fp); + fputs("{\n", fp); + fputs(" int idx = mechtable_idx_from_numeric(mech);\n", fp); + fputs("\n", fp); + fputs(" if (idx < 0)\n", fp); + fputs(" return NULL;\n", fp); + fputs(" return &mechtable_rows[idx];\n", fp); + fputs("}\n\n", fp); +} + +static void dumpstringfun(FILE *fp) +{ + size_t i; + + fprintf(fp, "static const size_t commonprefixlength = %lu;\n\n", + commonprefixlength); + fputs("int mechtable_idx_from_string(const char *mech)\n", fp); + fputs("{\n", fp); + fputs(" static const struct {\n", fp); + fputs(" const char *string;\n", fp); + fputs(" const char *alias;\n", fp); + fputs(" } aliaslist[] = {\n", fp); + for (i = 0; i < ARRAY_SIZE(aliases); ++i) { + fprintf(fp, " { \"%s\", \"%s\" },\n", + aliases[i].string, aliases[i].alias); + } + fputs(" };\n", fp); + fputs(" size_t len = strlen(mech), i;\n", fp); + fprintf(fp, " short idx = %u;\n", root->offset); + fputs(" unsigned char h;\n\n", fp); + fputs(" for (i = commonprefixlength; i <= len; ++i) {\n", fp); + fputs(" h = stringalphabet[(int)mech[i]];\n", fp); + /* No need to check the h since they are 0 if unsigned char is not mapped + and nothing problematic happens. The search will just be + unsuccessful. */ + fputs(" idx = stringtable[idx + h];\n", fp); + fputs(" if (idx < 0) {\n", fp); + fputs(" idx = -(idx + 1);\n", fp); + fputs(" if (strcmp(mech, mechtable_rows[idx].string) == 0)\n", + fp); + fputs(" return idx;\n", fp); + fputs(" goto outcheckaliases;\n", fp); + fputs(" }\n", fp); + fputs(" }\n", fp); + fputs(" outcheckaliases:\n", fp); + fputs(" for (i = 0; i < sizeof(aliaslist) / sizeof(aliaslist[0]); ++i) {\n", + fp); + fputs(" if (strcmp(aliaslist[i].string, mech) == 0)\n", fp); + fputs(" return mechtable_idx_from_string(aliaslist[i].alias);\n", + fp); + fputs(" }\n", fp); + fputs(" return -1;\n", fp); + fputs("}\n\n", fp); + fputs("const struct mechrow *mechrow_from_string(const char *mech)\n", fp); + fputs("{\n", fp); + fputs(" int idx = mechtable_idx_from_string(mech);\n\n", fp); + fputs(" if (idx < 0)\n", fp); + fputs(" return NULL;\n", fp); + fputs(" return &mechtable_rows[idx];\n", fp); + fputs("}\n\n", fp); +} + +static void generatelicense(FILE *fp) +{ + time_t t; + struct tm *tm; + char *tstr; + + t = time(NULL); + tm = localtime(&t); + tstr = asctime(tm); + /* Remove trailing newline character */ + tstr[strlen(tstr) - 1] = 0; + fputs("/*\n", fp); + fprintf(fp, " * COPYRIGHT (c) International Business Machines Corp. %d\n", + tm->tm_year + 1900); + fputs(" *\n", fp); + fputs(" * This program is provided under the terms of the Common Public License,\n", + fp); + fputs(" * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this\n", + fp); + fputs(" * software constitutes recipient's acceptance of CPL-1.0 terms which can be\n", + fp); + fputs(" * found in the file LICENSE file or at\n", fp); + fputs(" * https://opensource.org/licenses/cpl1.0.php\n", fp); + fputs(" */\n", fp); + fprintf(fp, "/* AUTO-GENERATED on %s. DO NOT EDIT! */\n\n", tstr); +} + +static void generateheader(char *hname) +{ + FILE *fp = openfile(hname); + + generatelicense(fp); + fputs("#ifndef OCK_MECHTABLE_GEN_H\n", fp); + fputs("#define OCK_MECHTABLE_GEN_H\n\n", fp); + fprintf(fp, "#define MECHTABLE_NUM_ELEMS %lu\n\n", ARRAY_SIZE(mechtable_rows)); + fputs("#endif\n\n", fp); + closefile(fp); +} + +static void dumpmechtableaccessors(FILE *fp) +{ + fputs("const struct mechtable_funcs mechtable_funcs = {\n", fp); + fputs(" .p_idx_from_num = &mechtable_idx_from_numeric,\n", fp); + fputs(" .p_idx_from_str = &mechtable_idx_from_string,\n", fp); + fputs(" .p_row_from_num = &mechrow_from_numeric,\n", fp); + fputs(" .p_row_from_str = &mechrow_from_string\n", fp); + fputs("};\n\n", fp); +} + +static void usage(char *name, int exitcode) +{ + printf("USAGE: %s [-l|--log ] [-c|--cfile ] [-d|-dname ]\n", + name); + puts("where:"); + puts("\t-l|--log specifies the destination of the log file"); + puts("\t-c|--cname specifies the destination of the generated c file"); + puts("\t-d|--dname specifies the destination of the generated header file"); + puts("\t-h|--help prints this help and exits"); + puts("All arguments are mandatory!"); + exit(exitcode); +} + +static void parseargs(int argc, char **argv, char **lname, char **cname, + char **hname) +{ + char *progname = argv[0]; + int c; + static struct option long_options[] = + { + { "log", required_argument, 0, 'l' }, + { "cname", required_argument, 0, 'c' }, + { "dname", required_argument, 0, 'd' }, + { "help", no_argument, 0, 'h' }, + { 0, 0, 0, 0 } + }; + while (1) { + c = getopt_long(argc, argv, "l:c:d:h", long_options, NULL); + if (c == -1) + break; + switch(c) { + case 'l': + *lname = optarg; + break; + case 'c': + *cname = optarg; + break; + case 'd': + *hname = optarg; + break; + case 'h': + usage(progname, 0); + break; + default: + usage(progname, 1); + break; + } + } + if (optind < argc) + /* Superfluous arguments */ + usage(progname, 1); +} + +int main(int argc, char **argv) +{ + short *table; + unsigned int maxoffset; + FILE *logfp, *cfp; + char *logname = 0, *cname = 0, *hname = 0; + + parseargs(argc, argv, &logname, &cname, &hname); + if (!logname || !cname || !hname) + usage(argv[0], 1); + logfp = openfile(logname); + cfp = openfile(cname); + + generateheader(hname); + + generatelicense(cfp); + fputs("#include \n", cfp); + fputs("#include \n", cfp); + fputs("#include \"mechtable.h\"\n", cfp); + fputs("#include \"mechtable.inc\"\n\n", cfp); + eliminatecommonprefixes(); + reinitializenodes(); + buildnumeric(); + compressnumericalphabet(); + maxoffset = compresstable(); + table = buildcompressedtable(maxoffset); + dumpalphabet("numeric", cfp); + dumptable(maxoffset, table, "numeric", cfp); + dumpnumericfun(cfp); + freecompressedtable(table); + fputs("Numeric table:\n", logfp); + logalphabet(logfp); + lognodes(logfp); + + reinitializenodes(); + buildstring(); + compressstringalphabet(); + maxoffset = compresstable(); + table = buildcompressedtable(maxoffset); + dumpalphabet("string", cfp); + dumptable(maxoffset, table, "string", cfp); + dumpstringfun(cfp); + freecompressedtable(table); + fputs("\nString table:\n", logfp); + logalphabet(logfp); + lognodes(logfp); + + dumpmechtableaccessors(cfp); + + closefile(logfp); + closefile(cfp); + free(commonprefix); + freenodes(); + return 0; +} diff -Nru opencryptoki-3.16.0+dfsg/tools/tools.mk opencryptoki-3.17.0+dfsg+20220202.b40982e/tools/tools.mk --- opencryptoki-3.16.0+dfsg/tools/tools.mk 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/tools/tools.mk 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,7 @@ +noinst_PROGRAMS += tools/tableidxgen tools/policyexamplegen + +tools_tableidxgen_SOURCES = tools/tableidxgen.c usr/lib/api/mechtable.inc +tools_tableidxgen_CFLAGS = -I${srcdir}/usr/include -I${srcdir}/usr/lib/api + +tools_policyexamplegen_SOURCES = tools/policyexamplegen.c usr/lib/api/mechtable.c +tools_policyexamplegen_CFLAGS = -I${srcdir}/usr/include -I${srcdir}/usr/lib/api -I${top_builddir}/usr/lib/api diff -Nru opencryptoki-3.16.0+dfsg/.travis.yml opencryptoki-3.17.0+dfsg+20220202.b40982e/.travis.yml --- opencryptoki-3.16.0+dfsg/.travis.yml 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/.travis.yml 2022-02-02 15:05:41.000000000 +0100 @@ -1,11 +1,12 @@ sudo: required -dist: bionic +dist: focal language: c before_install: - sudo apt-get -qq update - - sudo apt-get install -y expect trousers libldap2-dev libtspi-dev wget + - sudo apt-get install -y expect libldap2-dev wget libudev-dev + - if [ "$TRAVIS_CPU_ARCH" != "amd64" ]; then sudo apt-get install -y trousers libtspi-dev; fi - sudo wget https://launchpad.net/ubuntu/+archive/primary/+files/libica3_3.4.0-0ubuntu1_s390x.deb - sudo wget https://launchpad.net/ubuntu/+archive/primary/+files/libica-dev_3.4.0-0ubuntu1_s390x.deb - sudo dpkg -i libica3_3.4.0-0ubuntu1_s390x.deb || true # icatok needs libica >= 3.3 @@ -17,17 +18,19 @@ - name: "linux-x86-clang-locks" os: linux compiler: clang - env: CONFIG_OPTS="--enable-swtok --enable-icsftok --enable-ccatok --enable-tpmtok --enable-testcases --enable-locks" CFLAGS="-O3 -Wextra -std=c99 -pedantic -Werror -DDEBUG" + env: CONFIG_OPTS="--enable-swtok --enable-icsftok --enable-ccatok --enable-testcases --enable-locks" CFLAGS="-O3 -Wextra -std=c99 -pedantic -Werror -DDEBUG" - name: "linux-x86-gcc-tm" os: linux compiler: gcc - env: CONFIG_OPTS="--enable-swtok --enable-icsftok --enable-ccatok --enable-tpmtok --enable-testcases --disable-locks" CFLAGS="-O3 -Wno-clobbered -Wextra -std=c99 -pedantic -Werror" + env: CONFIG_OPTS="--enable-swtok --enable-icsftok --enable-ccatok --enable-testcases --disable-locks" CFLAGS="-O3 -Wno-clobbered -Wextra -std=c99 -pedantic -Werror" - name: "linux-ppc64le-clang-locks" - os: linux-ppc64le + os: linux + arch: ppc64le compiler: clang env: CONFIG_OPTS="--enable-swtok --enable-icsftok --enable-ccatok --enable-tpmtok --enable-testcases --enable-locks" CFLAGS="-O3 -Wextra -std=c99 -pedantic -Werror" - name: "linux-ppc64le-gcc-tm" - os: linux-ppc64le + os: linux + arch: ppc64le compiler: gcc env: CONFIG_OPTS="--enable-swttok --enable-icsftok --enable-ccatok --enable-tpmtok --enable-testcases --disable-locks" CFLAGS="-O3 -Wno-clobbered -Wextra -std=c99 -pedantic -Werror -DDEBUG" - name: "linux-s390x-clang-locks" diff -Nru opencryptoki-3.16.0+dfsg/usr/include/apictl.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/include/apictl.h --- opencryptoki-3.16.0+dfsg/usr/include/apictl.h 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/include/apictl.h 2022-02-02 15:05:41.000000000 +0100 @@ -13,12 +13,16 @@ #include #include #include - -#include "local_types.h" +#include #ifndef _APILOCAL_H #define _APILOCAL_H +#if OPENSSL_VERSION_PREREQ(3, 0) + #include + #include +#endif + // SAB Add a linked list of STDLL's loaded to // only load and get list once, but let multiple slots us it. @@ -57,6 +61,13 @@ API_Slot_t SltList[NUMBER_SLOTS_MANAGED]; DLL_Load_t DLLs[NUMBER_SLOTS_MANAGED]; // worst case we have a separate DLL // per slot + int socketfd; + pthread_t event_thread; +#if OPENSSL_VERSION_PREREQ(3, 0) + OSSL_LIB_CTX *openssl_libctx; + OSSL_PROVIDER *openssl_default_provider; + OSSL_PROVIDER *openssl_legacy_provider; +#endif } API_Proc_Struct_t; #endif diff -Nru opencryptoki-3.16.0+dfsg/usr/include/events.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/include/events.h --- opencryptoki-3.16.0+dfsg/usr/include/events.h 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/include/events.h 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,83 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ + +#include +#include +#include +#include + +#include "local_types.h" +#include "pkcs32.h" + +#ifndef _EVENTS_H +#define _EVENTS_H + +typedef struct { + unsigned int version; /* EVENT_VERSION_xxx */ + unsigned int type; /* EVENT_TYPE_xxx */ + unsigned int flags; /* EVENT_FLAGS_xxx */ + unsigned int token_type; /* Destination token type: EVENT_TOK_TYPE_xxx */ + char token_label[member_size(CK_TOKEN_INFO_32, label)]; + /* Label of destination token (or blanks) */ + pid_t process_id; /* Process ID of destination process (or 0) */ + unsigned int payload_len; /* Length of payload in bytes */ + /* Followed by payload_len bytes of payload (event specific) */ +} __attribute__ ((__packed__)) event_msg_t; + +typedef struct { + unsigned int version; /* EVENT_VERSION_xxx */ + unsigned int positive_replies; /* Number of tokens that replied a */ + unsigned int negative_replies; /* positive, or negative feedback, */ + unsigned int nothandled_replies; /* or that did not handle the event. */ + /* Note: Only tokens matching the event + * destination fields (pid, label, + * token-type) are counted. */ +} __attribute__ ((__packed__)) event_reply_t; + +/* Event and reply versions */ +#define EVENT_VERSION_1 1 + +/* Event classes (encoded into event type) */ +#define EVENT_CLASS_MASK 0xffff0000 +#define EVENT_CLASS_UDEV 0x00010000 +#define EVENT_CLASS_ADMIN 0x00020000 + +/* Event types */ +#define EVENT_TYPE_APQN_ADD EVENT_CLASS_UDEV + 0x00000001 +#define EVENT_TYPE_APQN_REMOVE EVENT_CLASS_UDEV + 0x00000002 + +/* Event flags */ +#define EVENT_FLAGS_NONE 0x00000000 +#define EVENT_FLAGS_REPLY_REQ 0x00000001 + +/* Event token destination types */ +#define EVENT_TOK_TYPE_ALL 0x00000000 +#define EVENT_TOK_TYPE_CCA 0x00000001 +#define EVENT_TOK_TYPE_EP11 0x00000002 + +/* Maximum event payload length 128k */ +#define EVENT_MAX_PAYLOAD_LENGTH (128 * 1024) + +/* Event payload for EVENT_TYPE_APQN_ADD and EVENT_TYPE_APQN_REMOVE */ +typedef struct { + unsigned short card; + unsigned short domain; + unsigned int device_type; /* from uevent DEV_TYPE property */ +} __attribute__ ((__packed__)) event_udev_apqn_data_t; + +/* AP device types */ +#define AP_DEVICE_TYPE_CEX3A 8 +#define AP_DEVICE_TYPE_CEX3C 9 +#define AP_DEVICE_TYPE_CEX4 10 +#define AP_DEVICE_TYPE_CEX5 11 +#define AP_DEVICE_TYPE_CEX6 12 +#define AP_DEVICE_TYPE_CEX7 13 + +#endif diff -Nru opencryptoki-3.16.0+dfsg/usr/include/include.mk opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/include/include.mk --- opencryptoki-3.16.0+dfsg/usr/include/include.mk 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/include/include.mk 2022-02-02 15:05:41.000000000 +0100 @@ -7,4 +7,5 @@ noinst_HEADERS += \ usr/include/apictl.h usr/include/local_types.h \ - usr/include/pkcs32.h usr/include/slotmgr.h usr/include/stdll.h + usr/include/pkcs32.h usr/include/slotmgr.h usr/include/stdll.h \ + usr/include/events.h diff -Nru opencryptoki-3.16.0+dfsg/usr/include/local_types.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/include/local_types.h --- opencryptoki-3.16.0+dfsg/usr/include/local_types.h 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/include/local_types.h 2022-02-02 15:05:41.000000000 +0100 @@ -11,6 +11,8 @@ #ifndef __LOCAL_TYPES #define __LOCAL_TYPES +#define member_size(type, member) sizeof(((type *)0)->member) + typedef unsigned char uint8; typedef unsigned short uint16; diff -Nru opencryptoki-3.16.0+dfsg/usr/include/pkcs11types.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/include/pkcs11types.h --- opencryptoki-3.16.0+dfsg/usr/include/pkcs11types.h 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/include/pkcs11types.h 2022-02-02 15:05:41.000000000 +0100 @@ -48,13 +48,13 @@ #define CK_PTR * -#define CK_CALLBACK_FUNCTION(returnType, name) \ +#define CK_CALLBACK_FUNCTION(returnType, name) \ returnType (* name) #ifndef NULL_PTR #define NULL_PTR NULL #endif /* NULL_PTR */ - + /* an unsigned 8-bit value */ typedef unsigned char CK_BYTE; @@ -611,8 +611,8 @@ #define CKA_NSS (CKA_VENDOR_DEFINED | NSSCK_VENDOR_NSS) #define CKA_NSS_MOZILLA_CA_POLICY (CKA_NSS + 34) -/* CK_ATTRIBUTE is a structure that includes the type, length - * and value of an attribute */ +/* CK_ATTRIBUTE is a structure that includes the type, value + * and length of an attribute */ typedef struct CK_ATTRIBUTE { CK_ATTRIBUTE_TYPE type; CK_VOID_PTR pValue; @@ -922,6 +922,8 @@ #define CKM_AES_CFB8 0x00002106 #define CKM_AES_CFB128 0x00002107 +#define CKM_AES_KEY_WRAP 0x00002109 + #define CKM_VENDOR_DEFINED 0x80000000 #ifndef OCK_NO_EP11_DEFINES @@ -1150,6 +1152,9 @@ #define CKR_FUNCTION_REJECTED 0x00000200 #define CKR_VENDOR_DEFINED 0x80000000 +/* Not really a return value, but stored in ulDeviceError of session + info for policy violations. */ +#define CKR_POLICY_VIOLATION (CKR_VENDOR_DEFINED + 0x1) /* CK_NOTIFY is an application callback that processes events */ @@ -1517,6 +1522,10 @@ #define CKD_SHA384_KDF 0x00000007UL #define CKD_SHA512_KDF 0x00000008UL +/* PBKDF2 parameters */ +#define CKP_PKCS5_PBKD2_HMAC_SHA256 0x00000004UL +#define CKP_PKCS5_PBKD2_HMAC_SHA512 0x00000006UL + #define CKF_INTERFACE_FORK_SAFE 0x00000001UL /* CK_INTERFACE is a structure which contains diff -Nru opencryptoki-3.16.0+dfsg/usr/include/slotmgr.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/include/slotmgr.h --- opencryptoki-3.16.0+dfsg/usr/include/slotmgr.h 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/include/slotmgr.h 2022-02-02 15:05:41.000000000 +0100 @@ -30,9 +30,10 @@ #define TOK_PATH SBIN_PATH "/pkcsslotd" #define OCK_API_LOCK_FILE LOCKDIR_PATH "/LCK..APIlock" -#define SOCKET_FILE_PATH "/var/run/pkcsslotd.socket" +#define PROC_SOCKET_FILE_PATH "/run/pkcsslotd.socket" +#define ADMIN_SOCKET_FILE_PATH "/run/pkcsslotd.admin.socket" -#define PID_FILE_PATH "/var/run/pkcsslotd.pid" +#define PID_FILE_PATH "/run/pkcsslotd.pid" #define OCK_CONFIG OCK_CONFDIR "/opencryptoki.conf" #ifndef CK_BOOL @@ -45,6 +46,7 @@ #define NUMBER_SLOTS_MANAGED 1024 #define NUMBER_PROCESSES_ALLOWED 1000 +#define NUMBER_ADMINS_ALLOWED 1000 // // Per Process Data structure @@ -97,6 +99,10 @@ LW_SHM_TYPE *shm_addr; // token specific shm address } Slot_Info_t; +#define FLAG_EVENT_SUPPORT_DISABLED 0x01 +#define FLAG_STATISTICS_ENABLED 0x02 +#define FLAG_STATISTICS_IMPLICIT 0x04 +#define FLAG_STATISTICS_INTERNAL 0x08 #ifdef PKCS64 @@ -198,6 +204,7 @@ typedef struct { uint8 num_slots; + uint8 flags; CK_INFO_64 ck_info; Slot_Info_t_64 slot_info[NUMBER_SLOTS_MANAGED]; } Slot_Mgr_Socket_t; @@ -212,6 +219,7 @@ typedef struct { uint8 num_slots; + uint8 flags; CK_INFO ck_info; Slot_Info_t slot_info[NUMBER_SLOTS_MANAGED]; } Slot_Mgr_Socket_t; diff -Nru opencryptoki-3.16.0+dfsg/usr/include/stdll.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/include/stdll.h --- opencryptoki-3.16.0+dfsg/usr/include/stdll.h 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/include/stdll.h 2022-02-02 15:05:41.000000000 +0100 @@ -350,6 +350,11 @@ CK_BYTE_PTR pReencryptedData, CK_ULONG_PTR pulReencryptedDataLen); +typedef CK_RV (CK_PTR ST_C_HandleEvent)(STDLL_TokData_t *tokdata, + unsigned int event_type, + unsigned int event_flags, + const char *payload, + unsigned int payload_len); struct ST_FCN_LIST { @@ -424,6 +429,9 @@ ST_C_CancelFunction ST_CancelFunction; ST_C_IBM_ReencryptSingle ST_IBM_ReencryptSingle; + + /* The functions defined below are not part of the external API */ + ST_C_HandleEvent ST_HandleEvent; }; typedef struct ST_FCN_LIST STDLL_FcnList_t; diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/api/api_interface.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/api_interface.c --- opencryptoki-3.16.0+dfsg/usr/lib/api/api_interface.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/api_interface.c 2022-02-02 15:05:41.000000000 +0100 @@ -20,10 +20,10 @@ #include #include #include - +#include +#include #include #include - #include #include @@ -34,9 +34,43 @@ #include #include "trace.h" #include "ock_syslog.h" +#include "policy.h" +#include "statistics.h" + +#include void api_init(); +#if OPENSSL_VERSION_PREREQ(3, 0) +#define BEGIN_OPENSSL_LIBCTX(ossl_ctx, rc) \ + do { \ + ERR_set_mark(); \ + OSSL_LIB_CTX *prev_ctx = OSSL_LIB_CTX_set0_default((ossl_ctx));\ + if (prev_ctx == NULL) { \ + (rc) = CKR_FUNCTION_FAILED; \ + TRACE_ERROR("OSSL_LIB_CTX_set0_default failed\n"); \ + ERR_pop_to_mark(); \ + break; \ + } + +#define END_OPENSSL_LIBCTX(rc) \ + if (OSSL_LIB_CTX_set0_default(prev_ctx) == NULL) { \ + if ((rc) == CKR_OK) \ + (rc) = CKR_FUNCTION_FAILED; \ + TRACE_ERROR("OSSL_LIB_CTX_set0_default failed\n"); \ + } \ + ERR_pop_to_mark(); \ + } while (0); +#else +#define BEGIN_OPENSSL_LIBCTX(ossl_ctx, rc) \ + do { \ + ERR_set_mark(); + +#define END_OPENSSL_LIBCTX(rc) \ + ERR_pop_to_mark(); \ + } while (0); +#endif + // NOTES: // In many cases the specificaiton does not allow returns // of CKR_ARGUMENTSB_BAD. We break the spec, since validation of parameters @@ -57,6 +91,8 @@ API_Proc_Struct_t *Anchor = NULL; // Initialized to NULL unsigned int Initialized = 0; // Initialized flag pthread_mutex_t GlobMutex = PTHREAD_MUTEX_INITIALIZER; // Global Mutex +struct policy policy; +struct statistics statistics; static CK_IBM_FUNCTION_LIST_1_0 func_list_ibm_1_0 = { {1, 0}, @@ -286,7 +322,82 @@ if (Anchor != NULL) C_Finalize(NULL); in_child_fork_initializer = FALSE; - } +} + +void parent_fork_prepare() +{ + if (Anchor == NULL) + return; + + /* + * Stop the event thread in the fork parent, since having the event thread + * active when a fork is performed causes various problems (e.g. deadlocks + * in glibc). + */ + if (Anchor->event_thread > 0) + stop_event_thread(); +} + +void parent_fork_after() +{ + if (Anchor == NULL) + return; + + /* Restart the event thread in the parent when fork is complete */ + if ((Anchor->SocketDataP.flags & FLAG_EVENT_SUPPORT_DISABLED) == 0 && + Anchor->event_thread == 0) + start_event_thread(); +} + +static CK_RV check_user_and_group() +{ + int i; + uid_t uid, euid; + struct passwd *pw, *epw; + struct group *grp; + + /* + * Check for root user or Group PKCS#11 Membershp. + * Only these are allowed. + */ + uid = getuid(); + euid = geteuid(); + + /* Root or effective Root is ok */ + if (uid == 0 || euid == 0) + return CKR_OK; + + /* + * Check for member of group. SAB get login seems to not work + * with some instances of application invocations (particularly + * when forked). So we need to get the group information. + * Really need to take the uid and map it to a name. + */ + grp = getgrnam("pkcs11"); + if (grp == NULL) { + OCK_SYSLOG(LOG_ERR, "getgrnam() failed: %s\n", strerror(errno)); + goto error; + } + + if (getgid() == grp->gr_gid || getegid() == grp->gr_gid) + return CKR_OK; + /* Check if user or effective user is member of pkcs11 group */ + pw = getpwuid(uid); + epw = getpwuid(euid); + for (i = 0; grp->gr_mem[i]; i++) { + if ((pw && (strncmp(pw->pw_name, grp->gr_mem[i], + strlen(pw->pw_name)) == 0)) || + (epw && (strncmp(epw->pw_name, grp->gr_mem[i], + strlen(epw->pw_name)) == 0))) + return CKR_OK; + } + +error: + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + + return CKR_FUNCTION_FAILED; +} + //------------------------------------------------------------------------ // API function C_CancelFunction @@ -322,6 +433,7 @@ CK_RV C_CloseAllSessions(CK_SLOT_ID slotID) { + CK_RV rc = CKR_OK; // Although why does modutil do a close all sessions. It is a single // application it can only close its sessions... // And all sessions should be closed anyhow. @@ -340,9 +452,11 @@ /* for every node in the API-level session tree, if the session's slot * matches slotID, close it */ + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rc) CloseAllSessions(slotID, FALSE); + END_OPENSSL_LIBCTX(rc) - return CKR_OK; + return rc; } // end of C_CloseAllSessions //------------------------------------------------------------------------ @@ -383,9 +497,12 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_CloseSession) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_CloseSession(sltp->TokData, &rSession, FALSE); TRACE_DEVEL("Called STDLL rv = 0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) + // If the STDLL successfully closed the session // we can free it.. Otherwise we will have to leave it // lying arround. @@ -463,9 +580,12 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_CopyObject) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_CopyObject(sltp->TokData, &rSession, hObject, pTemplate, ulCount, phNewObject); + TRACE_DEVEL("fcn->ST_CopyObject returned:0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -533,10 +653,12 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_CreateObject) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_CreateObject(sltp->TokData, &rSession, pTemplate, ulCount, phObject); TRACE_DEVEL("fcn->ST_CreateObject returned:0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -586,10 +708,12 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_Decrypt) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_Decrypt(sltp->TokData, &rSession, pEncryptedData, ulEncryptedDataLen, pData, pulDataLen); TRACE_DEVEL("fcn->ST_Decrypt returned:0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -636,11 +760,13 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_DecryptDigestUpdate) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_DecryptDigestUpdate(sltp->TokData, &rSession, pEncryptedPart, ulEncryptedPartLen, pPart, pulPartLen); TRACE_DEVEL("fcn->ST_DecryptDigestUpdate returned:0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -689,10 +815,12 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_DecryptFinal) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_DecryptFinal(sltp->TokData, &rSession, pLastPart, pulLastPartLen); TRACE_DEVEL("fcn->ST_DecryptFinal returned: 0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -746,9 +874,11 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_DecryptInit) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_DecryptInit(sltp->TokData, &rSession, pMechanism, hKey); TRACE_DEVEL("fcn->ST_DecryptInit returned:0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -798,11 +928,13 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_DecryptUpdate) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_DecryptUpdate(sltp->TokData, &rSession, pEncryptedPart, ulEncryptedPartLen, pPart, pulPartLen); TRACE_DEVEL("fcn->ST_DecryptUpdate:0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -848,11 +980,13 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_DecryptVerifyUpdate) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_DecryptVerifyUpdate(sltp->TokData, &rSession, pEncryptedPart, ulEncryptedPartLen, pPart, pulPartLen); TRACE_DEVEL("fcn->ST_DecryptVerifyUpdate returned:0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -916,10 +1050,12 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_DeriveKey) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_DeriveKey(sltp->TokData, &rSession, pMechanism, hBaseKey, pTemplate, ulAttributeCount, phKey); TRACE_DEVEL("fcn->ST_DeriveKey returned:0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -967,9 +1103,11 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_DestroyObject) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_DestroyObject(sltp->TokData, &rSession, hObject); TRACE_DEVEL("fcn->ST_DestroyObject returned:0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -1015,10 +1153,12 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_Digest) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_Digest(sltp->TokData, &rSession, pData, ulDataLen, pDigest, pulDigestLen); TRACE_DEVEL("fcn->ST_Digest:0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -1066,11 +1206,13 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_DigestEncryptUpdate) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_DigestEncryptUpdate(sltp->TokData, &rSession, pPart, ulPartLen, pEncryptedPart, pulEncryptedPartLen); TRACE_DEVEL("fcn->ST_DigestEncryptUpdate returned:0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -1114,10 +1256,12 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_DigestFinal) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_DigestFinal(sltp->TokData, &rSession, pDigest, pulDigestLen); TRACE_DEVEL("fcn->ST_DigestFinal returned:0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -1164,9 +1308,11 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_DigestInit) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_DigestInit(sltp->TokData, &rSession, pMechanism); TRACE_DEVEL("fcn->ST_DigestInit returned:0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -1209,9 +1355,11 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_DigestKey) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_DigestKey(sltp->TokData, &rSession, hKey); TRACE_DEBUG("fcn->ST_DigestKey returned:0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -1255,9 +1403,11 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_DigestUpdate) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_DigestUpdate(sltp->TokData, &rSession, pPart, ulPartLen); TRACE_DEVEL("fcn->ST_DigestUpdate returned:0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -1303,10 +1453,12 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_Encrypt) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_Encrypt(sltp->TokData, &rSession, pData, ulDataLen, pEncryptedData, pulEncryptedDataLen); TRACE_DEVEL("fcn->ST_Encrypt returned: 0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -1351,10 +1503,12 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_EncryptFinal) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_EncryptFinal(sltp->TokData, &rSession, pLastEncryptedPart, pulLastEncryptedPartLen); TRACE_DEVEL("fcn->ST_EncryptFinal: 0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -1402,9 +1556,11 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_EncryptInit) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_EncryptInit(sltp->TokData, &rSession, pMechanism, hKey); TRACE_INFO("fcn->ST_EncryptInit returned:0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -1451,11 +1607,13 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_EncryptUpdate) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_EncryptUpdate(sltp->TokData, &rSession, pPart, ulPartLen, pEncryptedPart, pulEncryptedPartLen); TRACE_DEVEL("fcn->ST_EncryptUpdate returned:0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -1490,7 +1648,10 @@ * Lock so that only one thread can run C_Initialize or C_Finalize at * a time */ - pthread_mutex_lock(&GlobMutex); // Grab Process level Global MUTEX + if (pthread_mutex_lock(&GlobMutex)) { // Grab Process level Global MUTEX + TRACE_ERROR("Global Mutex Lock failed.\n"); + return CKR_CANT_LOCK; + } TRACE_INFO("C_Finalize\n"); if (API_Initialized() == FALSE) { @@ -1501,9 +1662,24 @@ shData = &(Anchor->SocketDataP); + /* + * Stop the event thread and close the socket. + * If C_Finalize is called as part of the fork initializer, don't stop + * the thread, since a forked process does not have any threads, and don't + * close the socket, as this would close the connection of the parent + * process to the pkcsslotd as well. + * */ + if (!in_child_fork_initializer) { + if (Anchor->event_thread > 0) + stop_event_thread(); + if (Anchor->socketfd >= 0) + close(Anchor->socketfd); + } + // unload all the STDLL's from the application // This is in case the APP decides to do the re-initialize and // continue on + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rc) for (slotID = 0; slotID < NUMBER_SLOTS_MANAGED; slotID++) { sltp = &(Anchor->SltList[slotID]); if (slot_loaded[slotID]) { @@ -1516,19 +1692,40 @@ } } - DL_UnLoad(sltp, slotID); + /* + * Calling dlclose() in a atfork handler may cause a deadlock. + * dlclose() may itself modify the atfork handler table to remove + * any fork handlers that the to be unloaded library has registered. + * Since the atfork handler table is currently locked when we are in + * an atfork handler, this would produce a deadlock. + */ + DL_UnLoad(sltp, slotID, in_child_fork_initializer); } + END_OPENSSL_LIBCTX(rc) // Un register from Slot D API_UnRegister(); bt_destroy(&Anchor->sess_btree); +#if OPENSSL_VERSION_PREREQ(3, 0) + ERR_set_mark(); + if (Anchor->openssl_default_provider != NULL) + OSSL_PROVIDER_unload(Anchor->openssl_default_provider); + if (Anchor->openssl_legacy_provider != NULL) + OSSL_PROVIDER_unload(Anchor->openssl_legacy_provider); + if (Anchor->openssl_libctx != NULL) + OSSL_LIB_CTX_free(Anchor->openssl_libctx); + ERR_pop_to_mark(); +#endif + detach_shared_memory(Anchor->SharedMemP); free(Anchor); // Free API Proc Struct Anchor = NULL; trace_finalize(); + policy_unload(&policy); + statistics_term(&statistics); //close the lock file descriptor here to avoid memory leak ProcClose(); @@ -1585,10 +1782,12 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_FindObjects) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_FindObjects(sltp->TokData, &rSession, phObject, ulMaxObjectCount, pulObjectCount); TRACE_DEVEL("fcn->ST_FindObjects returned:0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -1636,9 +1835,11 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_FindObjectsFinal) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_FindObjectsFinal(sltp->TokData, &rSession); TRACE_DEVEL("fcn->ST_FindObjectsFinal returned: 0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -1689,10 +1890,12 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_FindObjectsInit) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_FindObjectsInit(sltp->TokData, &rSession, pTemplate, ulCount); TRACE_DEVEL("fcn->ST_FindObjectsInit returned:0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -1747,10 +1950,12 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_GenerateKey) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_GenerateKey(sltp->TokData, &rSession, pMechanism, pTemplate, ulCount, phKey); TRACE_DEVEL("fcn->ST_GenerateKey returned:0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -1814,6 +2019,7 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_GenerateKeyPair) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_GenerateKeyPair(sltp->TokData, &rSession, pMechanism, @@ -1823,6 +2029,7 @@ ulPrivateKeyAttributeCount, phPublicKey, phPrivateKey); TRACE_DEVEL("fcn->ST_GenerateKeyPair returned:0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -1870,10 +2077,12 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_GenerateRandom) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_GenerateRandom(sltp->TokData, &rSession, RandomData, ulRandomLen); TRACE_DEVEL("fcn->ST_GenerateRandom returned:0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -1930,10 +2139,12 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_GetAttributeValue) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_GetAttributeValue(sltp->TokData, &rSession, hObject, pTemplate, ulCount); TRACE_DEVEL("fcn->ST_GetAttributeValue returned:0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -2029,7 +2240,7 @@ API_Slot_t *sltp; STDLL_FcnList_t *fcn; - TRACE_INFO("C_GetMechansimInfo %lu %lx %p\n", slotID, type, + TRACE_INFO("C_GetMechanismInfo %lu %lx %p\n", slotID, type, (void *)pInfo); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); @@ -2051,8 +2262,10 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_GetMechanismInfo) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) rv = fcn->ST_GetMechanismInfo(sltp->TokData, slotID, type, pInfo); TRACE_DEVEL("fcn->ST_GetMechanismInfo returned:0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -2109,9 +2322,11 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_GetMechanismList) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) rv = fcn->ST_GetMechanismList(sltp->TokData, slotID, pMechanismList, pulCount); TRACE_DEVEL("fcn->ST_GetMechanismList returned: 0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -2173,9 +2388,11 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_GetObjectSize) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_GetObjectSize(sltp->TokData, &rSession, hObject, pulSize); TRACE_DEVEL("fcn->ST_GetObjectSize retuned: 0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -2225,10 +2442,12 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_GetOperationState) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_GetOperationState(sltp->TokData, &rSession, pOperationState, pulOperationStateLen); TRACE_DEVEL("fcn->ST_GetOperationState returned:0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -2281,6 +2500,7 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_GetSessionInfo) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_GetSessionInfo(sltp->TokData, &rSession, pInfo); @@ -2288,6 +2508,7 @@ TRACE_DEVEL("Slot %lu State %lx Flags %lx DevErr %lx\n", pInfo->slotID, pInfo->state, pInfo->flags, pInfo->ulDeviceError); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); @@ -2493,7 +2714,7 @@ for (index = 0; index < NUMBER_SLOTS_MANAGED; index++) { // if there is a STDLL in the slot then we have to count it // otherwise the slot is NOT counted. - if (sinfp[index].present == TRUE && slot_loaded[index] == TRUE) { + if (sinfp[index].present == TRUE) { if (tokenPresent) { if ((sinfp[index].pk_slot.flags & CKF_TOKEN_PRESENT)) { count++; @@ -2529,7 +2750,7 @@ // for (sindx = 0, index = 0; (index < NUMBER_SLOTS_MANAGED) && (sindx < count); index++) { - if (sinfp[index].present == TRUE && slot_loaded[index] == TRUE) { + if (sinfp[index].present == TRUE) { if (tokenPresent) { if (sinfp[index].pk_slot.flags & CKF_TOKEN_PRESENT) { pSlotList[sindx] = sinfp[index].slot_number; @@ -2603,11 +2824,13 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_GetTokenInfo) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) rv = fcn->ST_GetTokenInfo(sltp->TokData, slotID, pInfo); if (rv == CKR_OK) { get_sess_count(slotID, &(pInfo->ulSessionCount)); } TRACE_DEVEL("rv %lu CK_TOKEN_INFO Flags %lx\n", rv, pInfo->flags); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -2634,17 +2857,27 @@ CK_C_INITIALIZE_ARGS *pArg; char fcnmap = 0; CK_RV rc = CKR_OK; + CK_SLOT_ID slotID; + API_Slot_t *sltp; + CK_ULONG stat_flags = 0; /* * Lock so that only one thread can run C_Initialize or C_Finalize at * a time */ - pthread_mutex_lock(&GlobMutex); + if (pthread_mutex_lock(&GlobMutex)) { + TRACE_ERROR("Global Mutex Lock failed.\n"); + return CKR_CANT_LOCK; + } trace_initialize(); TRACE_INFO("C_Initialize\n"); + rc = check_user_and_group(); + if (rc != CKR_OK) + goto done; + if (!Anchor) { Anchor = (API_Proc_Struct_t *) malloc(sizeof(API_Proc_Struct_t)); if (Anchor == NULL) { @@ -2666,8 +2899,9 @@ // This must be done prior to all goto error calls, else bt_destroy() // will fail because it accesses uninitialized memory when t->size > 0. memset(Anchor, 0, sizeof(API_Proc_Struct_t)); + Anchor->socketfd = -1; - TRACE_DEBUG("Anchor allocated at %s\n", (char *) Anchor); + TRACE_DEBUG("Anchor allocated at %p\n", (void *) Anchor); // Validation of the parameters passed @@ -2703,13 +2937,7 @@ goto error; } } - // If we EVER need to create threads from this library we must - // check the Flags for the Can_Create_OS_Threads flag - // Right now the library DOES NOT create threads and therefore this - // check is irrelavant. - if (pArg->flags & CKF_LIBRARY_CANT_CREATE_OS_THREADS) { - TRACE_DEVEL("Can't create OS threads...This is OK\n"); - } + // Since this is an initialization path, we will be verbose in the // code rather than efficient. // @@ -2770,6 +2998,50 @@ bt_init(&Anchor->sess_btree, free); Anchor->Pid = getpid(); +#if OPENSSL_VERSION_PREREQ(3, 0) + /* + * OpenSSL >= 3.0: + * Create a separate library context for Opencryptoki's use of OpenSSL + * services and explicitly load the 'default' and 'legacy' providers for + * this context. + * This prevents call loops when the calling application has configured a + * PKCS#11 provider that uses Opencryptoki under the covers. This could + * produce a loop with the following calling tree: + * Application -> Openssl -> PKCS11-provider -> Opencryptoki -> OpenSSL + * -> PKCS11-provider -> Opencryptoki -> ... + * Explicitly using the 'default' provider only for Opencrypoki's OpenSSL + * usage breaks this loop. + */ + ERR_set_mark(); + Anchor->openssl_libctx = OSSL_LIB_CTX_new(); + if (Anchor->openssl_libctx == NULL) { + TRACE_ERROR("OSSL_LIB_CTX_new failed.\n"); + rc = CKR_FUNCTION_FAILED; + ERR_pop_to_mark(); + goto error; + } + + Anchor->openssl_default_provider = + OSSL_PROVIDER_load(Anchor->openssl_libctx, "default"); + if (Anchor->openssl_default_provider == NULL) { + TRACE_ERROR("OSSL_PROVIDER_load for 'default' failed.\n"); + rc = CKR_FUNCTION_FAILED; + ERR_pop_to_mark(); + goto error; + } + + Anchor->openssl_legacy_provider = + OSSL_PROVIDER_load(Anchor->openssl_libctx, "legacy"); + if (Anchor->openssl_legacy_provider == NULL) { + TRACE_ERROR("OSSL_PROVIDER_load for 'legacy' failed.\n"); + rc = CKR_FUNCTION_FAILED; + ERR_pop_to_mark(); + goto error; + } + + ERR_pop_to_mark(); +#endif + // Get shared memory if ((Anchor->SharedMemP = attach_shared_memory()) == NULL) { OCK_SYSLOG(LOG_ERR, "C_Initialize: Module failed to attach to " @@ -2781,15 +3053,58 @@ } TRACE_DEBUG("Shared memory %p \n", Anchor->SharedMemP); - if (!init_socket_data()) { + /* Connect to slot daemon and retrieve slot infos */ + Anchor->socketfd = connect_socket(PROC_SOCKET_FILE_PATH); + if (Anchor->socketfd < 0) { OCK_SYSLOG(LOG_ERR, "C_Initialize: Module failed to create a " "socket. Verify that the slot management daemon is " "running.\n"); - TRACE_ERROR("Cannot attach to socket.\n"); + TRACE_ERROR("Failed to connect to slot daemon\n"); + rc = CKR_FUNCTION_FAILED; + goto error_shm; + } + + if (!init_socket_data(Anchor->socketfd)) { + OCK_SYSLOG(LOG_ERR, "C_Initialize: Module failed to retrieve slot " + "infos from slot deamon.\n"); + TRACE_ERROR("Failed to receive slot infos from socket.\n"); rc = CKR_FUNCTION_FAILED; goto error_shm; } - // Initialize structure values + + if (pVoid != NULL) { + pArg = (CK_C_INITIALIZE_ARGS *) pVoid; + + if ((Anchor->SocketDataP.flags & FLAG_EVENT_SUPPORT_DISABLED) == 0 && + (pArg->flags & CKF_LIBRARY_CANT_CREATE_OS_THREADS) != 0) { + TRACE_ERROR("Flag CKF_LIBRARY_CANT_CREATE_OS_THREADS is set and " + "event support is enabled\n"); + OCK_SYSLOG(LOG_ERR, "C_Initialize: Application specified that " + "library can't create OS threads. PKCS11 Module requires " + "to create threads when event support is enabled.\n"); + rc = CKR_NEED_TO_CREATE_THREADS; + goto error; + } + } + + rc = policy_load(&policy); + if (rc != CKR_OK) { + TRACE_ERROR("Policy loading failed! rc=0x%lx\n", rc); + goto error; + } + + if (Anchor->SocketDataP.flags & FLAG_STATISTICS_ENABLED) { + if (Anchor->SocketDataP.flags & FLAG_STATISTICS_IMPLICIT) + stat_flags |= STATISTICS_FLAG_COUNT_IMPLICIT; + if (Anchor->SocketDataP.flags & FLAG_STATISTICS_INTERNAL) + stat_flags |= STATISTICS_FLAG_COUNT_INTERNAL; + + rc = statistics_init(&statistics, &Anchor->SocketDataP, stat_flags); + if (rc != CKR_OK) { + TRACE_ERROR("Statistics initialization failed! rc=0x%lx\n", rc); + goto error; + } + } //Register with pkcsslotd if (!API_Register()) { @@ -2802,15 +3117,43 @@ } // // load all the slot DLL's here - { - CK_SLOT_ID slotID; - API_Slot_t *sltp; + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rc) + for (slotID = 0; slotID < NUMBER_SLOTS_MANAGED; slotID++) { + sltp = &(Anchor->SltList[slotID]); + slot_loaded[slotID] = DL_Load_and_Init(sltp, slotID, &policy, + &statistics); + } + END_OPENSSL_LIBCTX(rc) + if (rc != CKR_OK) + goto error_shm; + /* Start event receiver thread */ + if ((Anchor->SocketDataP.flags & FLAG_EVENT_SUPPORT_DISABLED) == 0 && + start_event_thread() != 0) { + TRACE_ERROR("Failed to start event thread\n"); + + // unload all the STDLL's from the application + // This is in case the APP decides to do the re-initialize and + // continue on + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rc) for (slotID = 0; slotID < NUMBER_SLOTS_MANAGED; slotID++) { sltp = &(Anchor->SltList[slotID]); - slot_loaded[slotID] = DL_Load_and_Init(sltp, slotID); + if (slot_loaded[slotID]) { + if (sltp->pSTfini) { + // call the terminate function.. + sltp->pSTfini(sltp->TokData, slotID, + &Anchor->SocketDataP.slot_info[slotID], + &trace, 0); + } + } + DL_UnLoad(sltp, slotID, FALSE); } + END_OPENSSL_LIBCTX(rc) + + API_UnRegister(); + rc = CKR_FUNCTION_FAILED; + goto error_shm; } pthread_mutex_unlock(&GlobMutex); @@ -2820,7 +3163,21 @@ detach_shared_memory(Anchor->SharedMemP); error: + policy_unload(&policy); bt_destroy(&Anchor->sess_btree); + if (Anchor->socketfd >= 0) + close(Anchor->socketfd); + +#if OPENSSL_VERSION_PREREQ(3, 0) + ERR_set_mark(); + if (Anchor->openssl_default_provider != NULL) + OSSL_PROVIDER_unload(Anchor->openssl_default_provider); + if (Anchor->openssl_legacy_provider != NULL) + OSSL_PROVIDER_unload(Anchor->openssl_legacy_provider); + if (Anchor->openssl_libctx != NULL) + OSSL_LIB_CTX_free(Anchor->openssl_libctx); + ERR_pop_to_mark(); +#endif free((void *) Anchor); Anchor = NULL; @@ -2883,9 +3240,11 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_InitPIN) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_InitPIN(sltp->TokData, &rSession, pPin, ulPinLen); TRACE_DEVEL("fcn->ST_InitPIN returned: 0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -2951,8 +3310,10 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_InitToken) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) rv = fcn->ST_InitToken(sltp->TokData, slotID, pPin, ulPinLen, pLabel); TRACE_DEVEL("fcn->ST_InitToken returned: 0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -3006,9 +3367,11 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_Login) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_Login(sltp->TokData, &rSession, userType, pPin, ulPinLen); TRACE_DEVEL("fcn->ST_Login returned:0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -3056,9 +3419,11 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_Logout) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_Logout(sltp->TokData, &rSession); TRACE_DEVEL("fcn->ST_Logout returned:0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -3132,9 +3497,11 @@ } if (fcn->ST_OpenSession) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) rv = fcn->ST_OpenSession(sltp->TokData, slotID, flags, &(apiSessp->sessionh)); TRACE_DEVEL("fcn->ST_OpenSession returned: 0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) // If the session allocation is successful, then we need to // complete the API session block and return. Otherwise @@ -3146,10 +3513,12 @@ */ *phSession = AddToSessionList(apiSessp); if (*phSession == 0) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) /* failed to add the object to the API-level tree, close the * STDLL-level session and return failure */ fcn->ST_CloseSession(sltp->TokData, apiSessp, FALSE); + END_OPENSSL_LIBCTX(rv) free(apiSessp); rv = CKR_HOST_MEMORY; goto done; @@ -3219,9 +3588,11 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_SeedRandom) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_SeedRandom(sltp->TokData, &rSession, pSeed, ulSeedLen); TRACE_DEVEL("fcn->ST_SeedRandom returned: 0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -3280,10 +3651,12 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_SetAttributeValue) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_SetAttributeValue(sltp->TokData, &rSession, hObject, pTemplate, ulCount); TRACE_DEVEL("fcn->ST_SetAttributeValue returned:0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -3335,12 +3708,14 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_SetOperationState) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_SetOperationState(sltp->TokData, &rSession, pOperationState, ulOperationStateLen, hEncryptionKey, hAuthenticationKey); TRACE_DEVEL("fcn->ST_SetOperationState returned:0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -3395,10 +3770,12 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_SetPIN) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_SetPIN(sltp->TokData, &rSession, pOldPin, ulOldLen, pNewPin, ulNewLen); TRACE_DEVEL("fcn->ST_SetPIN returned: 0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -3449,10 +3826,12 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_Sign) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_Sign(sltp->TokData, &rSession, pData, ulDataLen, pSignature, pulSignatureLen); TRACE_DEVEL("fcn->ST_Sign returned: 0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -3499,11 +3878,13 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_SignEncryptUpdate) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_SignEncryptUpdate(sltp->TokData, &rSession, pPart, ulPartLen, pEncryptedPart, pulEncryptedPartLen); TRACE_DEVEL("fcn->ST_SignEncryptUpdate return: 0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -3551,10 +3932,12 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_SignFinal) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_SignFinal(sltp->TokData, &rSession, pSignature, pulSignatureLen); TRACE_DEVEL("fcn->ST_SignFinal returned: 0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -3606,9 +3989,11 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_SignInit) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_SignInit(sltp->TokData, &rSession, pMechanism, hKey); TRACE_DEVEL("fcn->ST_SignInit returned: 0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -3654,10 +4039,12 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_SignRecover) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_SignRecover(sltp->TokData, &rSession, pData, ulDataLen, pSignature, pulSignatureLen); TRACE_DEVEL("fcn->ST_SignRecover returned:0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -3705,10 +4092,12 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_SignRecoverInit) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_SignRecoverInit(sltp->TokData, &rSession, pMechanism, hKey); TRACE_DEVEL("fcn->ST_SignRecoverInit returned: 0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -3756,9 +4145,11 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_SignUpdate) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_SignUpdate(sltp->TokData, &rSession, pPart, ulPartLen); TRACE_DEVEL("fcn->ST_SignUpdate returned: 0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -3819,12 +4210,14 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_UnwrapKey) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_UnwrapKey(sltp->TokData, &rSession, pMechanism, hUnwrappingKey, pWrappedKey, ulWrappedKeyLen, pTemplate, ulAttributeCount, phKey); TRACE_DEVEL("fcn->ST_UnwrapKey returned: 0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -3871,10 +4264,12 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_Verify) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_Verify(sltp->TokData, &rSession, pData, ulDataLen, pSignature, ulSignatureLen); TRACE_DEVEL("fcn->ST_Verify returned: 0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -3918,10 +4313,12 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_VerifyFinal) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_VerifyFinal(sltp->TokData, &rSession, pSignature, ulSignatureLen); TRACE_DEVEL("fcn->ST_VerifyFinal returned: 0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -3969,9 +4366,11 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_VerifyInit) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_VerifyInit(sltp->TokData, &rSession, pMechanism, hKey); TRACE_DEVEL("fcn->ST_VerifyInit returned: 0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -4018,10 +4417,12 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_VerifyRecover) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_VerifyRecover(sltp->TokData, &rSession, pSignature, ulSignatureLen, pData, pulDataLen); TRACE_DEVEL("fcn->ST_VerifyRecover returned: 0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -4069,10 +4470,12 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_VerifyRecoverInit) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_VerifyRecoverInit(sltp->TokData, &rSession, pMechanism, hKey); TRACE_DEVEL("fcn->ST_VerifyRecoverInit returned:0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -4116,9 +4519,11 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_VerifyUpdate) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_VerifyUpdate(sltp->TokData, &rSession, pPart, ulPartLen); TRACE_DEVEL("fcn->ST_VerifyUpdate returned: 0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -4316,10 +4721,12 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_WrapKey) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_WrapKey(sltp->TokData, &rSession, pMechanism, hWrappingKey, hKey, pWrappedKey, pulWrappedKeyLen); TRACE_DEVEL("fcn->ST_WrapKey returned: 0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -4998,7 +5405,7 @@ return CKR_CRYPTOKI_NOT_INITIALIZED; } - if (!pDecrMech || !pDecrMech) { + if (!pDecrMech || !pEncrMech) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } @@ -5019,6 +5426,7 @@ return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_IBM_ReencryptSingle) { + BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv) // Map the Session to the slot session rv = fcn->ST_IBM_ReencryptSingle(sltp->TokData, &rSession, pDecrMech, hDecrKey, pEncrMech, hEncrKey, @@ -5026,6 +5434,7 @@ pReencryptedData, pulReencryptedDataLen); TRACE_DEVEL("fcn->ST_IBM_ReencryptSingle returned: 0x%lx\n", rv); + END_OPENSSL_LIBCTX(rv) } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; @@ -5044,7 +5453,8 @@ { // Should only have to do the atfork stuff at load time... if (!Initialized) { - pthread_atfork(NULL, NULL, (void (*)()) child_fork_initializer); + pthread_atfork(parent_fork_prepare, parent_fork_after, + child_fork_initializer); Initialized = 1; } } diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/api/api.mk opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/api.mk --- opencryptoki-3.16.0+dfsg/usr/lib/api/api.mk 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/api.mk 2022-02-02 15:05:41.000000000 +0100 @@ -1,6 +1,7 @@ nobase_lib_LTLIBRARIES += opencryptoki/libopencryptoki.la -noinst_HEADERS += usr/lib/api/apiproto.h +noinst_HEADERS += usr/lib/api/apiproto.h usr/lib/api/policy.h \ + usr/lib/api/statistics.h SO_CURRENT=0 SO_REVISION=0 @@ -9,17 +10,31 @@ opencryptoki_libopencryptoki_la_CFLAGS = \ -DAPI -DDEV -D_THREAD_SAFE -fPIC -I${srcdir}/usr/include \ -I${srcdir}/usr/lib/common -I${srcdir}/usr/lib/api \ - -DSTDLL_NAME=\"api\" + -I${srcdir}/usr/lib/config -I${top_builddir}/usr/lib/config \ + -DSTDLL_NAME=\"api\" -DHASHMAP_JENKINS_MIX \ + -I${top_builddir}/usr/lib/api opencryptoki_libopencryptoki_la_LDFLAGS = \ - -shared -Wl,-z,defs,-Bsymbolic -lc -ldl -lpthread \ + -shared -Wl,-z,defs,-Bsymbolic -lc -ldl -lpthread -lcrypto -lrt \ -version-info $(SO_CURRENT):$(SO_REVISION):$(SO_AGE) \ -Wl,--version-script=${srcdir}/opencryptoki.map -opencryptoki_libopencryptoki_la_SOURCES = \ - usr/lib/api/api_interface.c usr/lib/api/shrd_mem.c \ - usr/lib/api/socket_client.c usr/lib/api/apiutil.c \ - usr/lib/common/trace.c +opencryptoki_libopencryptoki_la_SOURCES = usr/lib/api/api_interface.c \ + usr/lib/api/shrd_mem.c usr/lib/api/socket_client.c \ + usr/lib/api/apiutil.c usr/lib/common/trace.c \ + usr/lib/api/policy.c usr/lib/api/hashmap.c \ + usr/lib/api/statistics.c \ + usr/lib/common/utility_common.c usr/lib/common/ec_supported.c \ + usr/lib/config/configuration.c \ + usr/lib/common/ec_curve_translation.c \ + usr/lib/common/kdf_translation.c \ + usr/lib/common/mgf_translation.c \ + usr/lib/api/supportedstrengths.c \ + usr/lib/config/cfgparse.y usr/lib/config/cfglex.l + +nodist_opencryptoki_libopencryptoki_la_SOURCES = \ + usr/lib/api/mechtable.c + if ENABLE_LOCKS opencryptoki_libopencryptoki_la_SOURCES += \ usr/lib/common/lock_btree.c @@ -28,3 +43,10 @@ usr/lib/common/btree.c opencryptoki_libopencryptoki_la_LDFLAGS += -litm endif + +usr/lib/api/mechtable.c usr/lib/api/mechtable-gen.h: tools/tableidxgen + $(AM_V_GEN)$(MKDIR_P) usr/lib/api && ${abs_builddir}/tools/tableidxgen -c usr/lib/api/mechtable.c -d usr/lib/api/mechtable-gen.h -l usr/lib/api/mechtable.log + +BUILT_SOURCES += usr/lib/api/mechtable-gen.h +EXTRA_DIST += usr/lib/api/mechtable.inc + diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/api/apiproto.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/apiproto.h --- opencryptoki-3.16.0+dfsg/usr/lib/api/apiproto.h 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/apiproto.h 2022-02-02 15:05:41.000000000 +0100 @@ -1,5 +1,5 @@ /* - * COPYRIGHT (c) International Business Machines Corp. 2001-2017 + * COPYRIGHT (c) International Business Machines Corp. 2001-2021 * * This program is provided under the terms of the Common Public License, * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this @@ -19,6 +19,8 @@ #define _APIEXT_H #include "apictl.h" +#include "policy.h" +#include "statistics.h" void *attach_shared_memory(); void detach_shared_memory(char *); @@ -27,7 +29,8 @@ int API_Initialized(); int API_Register(); void API_UnRegister(); -int DL_Load_and_Init(API_Slot_t *, CK_SLOT_ID); +int DL_Load_and_Init(API_Slot_t *, CK_SLOT_ID, policy_t policy, + statistics_t statistics); CK_RV CreateProcLock(); @@ -42,7 +45,7 @@ unsigned long AddToSessionList(ST_SESSION_T *); void RemoveFromSessionList(CK_SESSION_HANDLE); int Valid_Session(CK_SESSION_HANDLE, ST_SESSION_T *); -void DL_UnLoad(API_Slot_t *, CK_SLOT_ID); +void DL_UnLoad(API_Slot_t *, CK_SLOT_ID, CK_BBOOL inchildforkinit); void DL_Unload(API_Slot_t *); void CK_Info_From_Internal(CK_INFO_PTR dest, CK_INFO_PTR_64 src); @@ -50,6 +53,9 @@ int sessions_exist(CK_SLOT_ID); void CloseAllSessions(CK_SLOT_ID slot_id, CK_BBOOL in_fork_initializer); -int init_socket_data(); +int connect_socket(const char *file_path); +int init_socket_data(int socketfd); +int start_event_thread(); +int stop_event_thread(); #endif diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/api/apiutil.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/apiutil.c --- opencryptoki-3.16.0+dfsg/usr/lib/api/apiutil.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/apiutil.c 2022-02-02 15:05:41.000000000 +0100 @@ -440,7 +440,7 @@ ProcUnLock(); } -void DL_UnLoad(API_Slot_t *sltp, CK_SLOT_ID slotID) +void DL_UnLoad(API_Slot_t *sltp, CK_SLOT_ID slotID, CK_BBOOL inchildforkinit) { Slot_Mgr_Socket_t *shData = &(Anchor->SocketDataP); #ifdef PKCS64 @@ -449,6 +449,15 @@ Slot_Info_t *sinfp; #endif + if (sltp->TokData) { +#ifdef ENABLE_LOCKS + pthread_rwlock_destroy(&sltp->TokData->sess_list_rwlock); +#endif + pthread_mutex_destroy(&sltp->TokData->login_mutex); + free(sltp->TokData); + sltp->TokData = NULL; + } + sinfp = &(shData->slot_info[slotID]); if (sinfp->present == FALSE) { @@ -457,6 +466,8 @@ if (!sltp->dlop_p) { return; } + if (inchildforkinit) + return; // Call the routine to properly unload the DLL DL_Unload(sltp); @@ -542,7 +553,8 @@ sltp->pSTcloseall = NULL; } -int DL_Load_and_Init(API_Slot_t *sltp, CK_SLOT_ID slotID) +int DL_Load_and_Init(API_Slot_t *sltp, CK_SLOT_ID slotID, policy_t policy, + statistics_t statistics) { Slot_Mgr_Socket_t *shData = &(Anchor->SocketDataP); #ifdef PKCS64 @@ -551,9 +563,9 @@ Slot_Info_t *sinfp; #endif CK_RV (*pSTinit)(API_Slot_t *, CK_SLOT_ID, SLOT_INFO *, - struct trace_handle_t); + struct trace_handle_t); CK_RV rv; - int dll_len, dl_index; + int dl_index; DLL_Load_t *dllload; // Get pointer to shared memory from the anchor block @@ -566,7 +578,31 @@ return FALSE; } - if ((dll_len = strlen(sinfp->dll_location))) { + if (sltp->TokData != NULL) { + TRACE_ERROR("Already initialized.\n"); + return FALSE; + } + + /* + * Create separate memory area for each token specific data + */ + sltp->TokData = (STDLL_TokData_t *) calloc(1, sizeof(STDLL_TokData_t)); + if (!sltp->TokData) { + TRACE_ERROR("Allocating host memory failed.\n"); + return FALSE; + } + sltp->TokData->slot_id = slotID; + sltp->TokData->ro_session_count = 0; + sltp->TokData->global_login_state = CKS_RO_PUBLIC_SESSION; +#ifdef ENABLE_LOCKS + pthread_rwlock_init(&sltp->TokData->sess_list_rwlock, NULL); +#endif + pthread_mutex_init(&sltp->TokData->login_mutex, NULL); + sltp->TokData->policy = policy; + sltp->TokData->mechtable_funcs = &mechtable_funcs; + sltp->TokData->statistics = statistics; + + if (strlen(sinfp->dll_location) > 0) { // Check if this DLL has been loaded already.. If so, just increment // the counter in the dllload structure and copy the data to // the slot pointer. @@ -584,15 +620,15 @@ } if (!sltp->dlop_p) { - TRACE_DEBUG("DL_Load_and_Init pointer %p\n", sltp->dlop_p); - + TRACE_DEBUG("DL_Load_and_Init pointer NULL\n"); + DL_UnLoad(sltp, slotID, FALSE); return FALSE; } *(void **)(&pSTinit) = dlsym(sltp->dlop_p, "ST_Initialize"); if (!pSTinit) { // Unload the DLL - DL_Unload(sltp); + DL_UnLoad(sltp, slotID, FALSE); return FALSE; } // Returns true or false @@ -601,11 +637,12 @@ if (rv != CKR_OK) { // clean up and unload - DL_Unload(sltp); + DL_UnLoad(sltp, slotID, FALSE); sltp->DLLoaded = FALSE; return FALSE; } else { sltp->DLLoaded = TRUE; + sinfp->pk_slot.flags |= CKF_TOKEN_PRESENT; // Check if a SC_Finalize function has been exported *(void **)(&sltp->pSTfini) = dlsym(sltp->dlop_p, "SC_Finalize"); *(void **)(&sltp->pSTcloseall) = diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/api/hashmap.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/hashmap.c --- opencryptoki-3.16.0+dfsg/usr/lib/api/hashmap.c 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/hashmap.c 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,275 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ +#include +#include + +#include +#include "hashmap.h" + +/* + * Hash map for mechanisms. It stores the mechanism number in a + * linked hash map. Note that it does not directly store the + * mechanism number, but the mechanism number plus one. This is done + * to have 0 represent an empty bucket. The structure is optimized + * for the non-chaining case in which case the value is directly + * stored in the root of the bucket chain. Only further chain + * elements are allocated separately. + * + * Furthermore, we use a size optimization to not pre-allocate buckets + * when creating a new hash. Only on first addition to the hash do we + * create the bucket list. + * + * The hash is a power of 2 hash to speed up hash value computation + * (subtraction + binary and versus modulo computation). + */ + +/* Default hash size has to be a power of 2. */ +#define HASH_DEFAULT_CAPA 16 + +static unsigned int hash(unsigned int capa, CK_ULONG value) +{ +#ifdef HASHMAP_FULL_JENKINS + /* Full Jenkins hash */ + unsigned char *key = (unsigned char *)&value; + size_t i = 0; + unsigned int hash = 0; + + while (i != 8) { + hash += key[i++]; + hash += hash << 10; + hash ^= hash >> 6; + } + hash += hash << 3; + hash ^= hash >> 11; + hash += hash << 15; + return hash & (capa - 1); +#else +# ifdef HASHMAP_JENKINS_MIX + /* Jenkins hash mix function */ + value += value << 3; + value ^= value >> 11; + value += value << 15; +# endif + return value & (capa - 1); +#endif +} + +struct hashmap_bucket; +struct hashmap_bucket { + CK_ULONG key; + union hashmap_value value; + struct hashmap_bucket *next; +}; + +struct hashmap { + struct hashmap_bucket *buckets; + unsigned int size; + unsigned int capa; + freefunc_t freefunc; +}; + +/* Create size-optimized empty hash. First add will expand the hash to its + * default capacity. + */ +struct hashmap *hashmap_new() +{ + struct hashmap *res = malloc(sizeof(struct hashmap)); + if (!res) + return res; + res->buckets = NULL; + res->size = 0; + res->capa = 0; + return res; +} + +static void freebucketchain(struct hashmap_bucket *b, freefunc_t f) +{ + struct hashmap_bucket *n; + + while (b) { + n = b->next; + if (f) + f(b->value); + free(b); + b = n; + } +} + +static void freebuckets(struct hashmap_bucket *buckets, unsigned int size, + freefunc_t f) +{ + unsigned int i; + + for (i = 0; i < size; ++i) + freebucketchain(buckets[i].next, f); +} + +void hashmap_free(struct hashmap *h, freefunc_t f) +{ + if (h) { + if (h->buckets) { + freebuckets(h->buckets, h->capa, f); + free(h->buckets); + } + free(h); + } +} + +static int do_add(struct hashmap_bucket *buckets, unsigned int size, + CK_ULONG key, union hashmap_value val) +{ + unsigned int hval; + struct hashmap_bucket *newbucket; + + hval = hash(size, key); + if (buckets[hval].key) { + newbucket = malloc(sizeof(struct hashmap_bucket)); + if (!newbucket) + return 1; + newbucket->next = buckets[hval].next; + newbucket->key = key; + newbucket->value = val; + buckets[hval].next = newbucket; + } else { + buckets[hval].key = key; + buckets[hval].value = val; + } + return 0; +} + +static int grow(struct hashmap *h) +{ + unsigned int i; + unsigned int newcapa; + struct hashmap_bucket *newarr, *walk; + + newcapa = h->capa ? h->capa << 1 : HASH_DEFAULT_CAPA; + if (newcapa < h->capa) + return 1; + newarr = calloc(newcapa, sizeof(struct hashmap_bucket)); + if (!newarr) + return 1; + for (i = 0; i < h->capa; ++i) { + if (h->buckets[i].key) { + walk = &h->buckets[i]; + while (walk) { + if (do_add(newarr, newcapa, walk->key, walk->value)) { + /* Pass no free function here since the values are + still in the old hash buckets that remain in + the hash. */ + freebuckets(newarr, newcapa, NULL); + free(newarr); + return 1; + } + walk = walk->next; + } + } + } + if (h->buckets) { + /* Pass no free function here since we copied the values into + the new bucket array. */ + freebuckets(h->buckets, h->capa, NULL); + free(h->buckets); + } + h->buckets = newarr; + h->capa = newcapa; + return 0; +} + +static struct hashmap_bucket *hashmap_findbucket(struct hashmap *h, + CK_ULONG key) +{ + unsigned int hval; + struct hashmap_bucket *b = NULL; + + if (h->buckets) { + hval = hash(h->capa, key + 1); + b = &h->buckets[hval]; + while (b && b->key != key + 1) + b = b->next; + } + return b; +} + +int hashmap_find(struct hashmap *h, CK_ULONG key, union hashmap_value *val) +{ + struct hashmap_bucket *b = 0; + + if (!h) + /* The non-existing hash is universal. */ + return 1; + b = hashmap_findbucket(h, key); + if (b && val) + *val = b->value; + return !!b; +} + +int hashmap_add(struct hashmap *h, CK_ULONG key, union hashmap_value val, + union hashmap_value *oldval) +{ + struct hashmap_bucket *b; + + b = hashmap_findbucket(h, key); + if (b) { + if (oldval) + *oldval = b->value; + b->value = val; + return 0; + } + /* 0.75 fill factor */ + if (h->capa - (h->capa / 4) < h->size + 1) { + if (grow(h)) + return 1; + } + if (do_add(h->buckets, h->capa, key + 1, val)) + return 1; + h->size++; + return 0; +} + +int hashmap_delete(struct hashmap *h, CK_ULONG key, union hashmap_value *val) +{ + int retval = 0; + unsigned int hval; + struct hashmap_bucket *b, **indirect; + + if (h->buckets) { + hval = hash(h->capa, key + 1); + if (h->buckets[hval].key == key + 1) { + if (val) + *val = h->buckets[hval].value; + if ((b = h->buckets[hval].next) != NULL) { + h->buckets[hval].key = b->key; + h->buckets[hval].value = b->value; + h->buckets[hval].next = b->next; + free(b); + } else { + h->buckets[hval].key = 0; + } + retval = 1; + } else { + b = h->buckets[hval].next; + indirect = &h->buckets[hval].next; + while (b && b->key != key + 1) { + indirect = &b->next; + b = b->next; + } + if (b) { + if (val) + *val = b->value; + *indirect = b->next; + free(b); + retval = 1; + } + } + } + h->size -= retval; + return retval; +} diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/api/hashmap.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/hashmap.h --- opencryptoki-3.16.0+dfsg/usr/lib/api/hashmap.h 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/hashmap.h 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,31 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ +#ifndef OCK_HASHMAP_H +#define OCK_HASHMAP_H + +#include + +struct hashmap; + +union hashmap_value { + CK_ULONG ulVal; + void *pVal; +}; + +typedef void (*freefunc_t)(union hashmap_value); + +struct hashmap *hashmap_new(void); +void hashmap_free(struct hashmap *h, freefunc_t f); +int hashmap_find(struct hashmap *h, CK_ULONG key, union hashmap_value *val); +int hashmap_add(struct hashmap *h, CK_ULONG key, union hashmap_value val, + union hashmap_value *oldval); +int hashmap_delete(struct hashmap *h, CK_ULONG key, union hashmap_value *val); + +#endif diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/api/mechtable.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/mechtable.h --- opencryptoki-3.16.0+dfsg/usr/lib/api/mechtable.h 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/mechtable.h 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,83 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ +#ifndef OCK_MECHTABLE_H +#define OCK_MECHTABLE_H + +#include + +#include + +/* This include can only be done once the file is generated. Since + the generator itself includes the current header file before + generating mechtable-gen.h, we have to guard the include. */ +#ifndef MECHTABLE_IN_GEN +# include "mechtable-gen.h" +#endif + +/* block size or output size not available */ +#define MC_INFORMATION_UNAVAILABLE 0xffffu +/* output size depends on key*/ +#define MC_KEY_DEPENDENT 0xfffeu + +/*** Flags ***/ +#define MCF_DIGEST (1u << 0u) +#define MCF_SIGNVERIFY (1u << 1u) +#define MCF_ENCRYPTDECRYPT (1u << 2u) +#define MCF_KEYGEN (1u << 3u) +#define MCF_WRAPUNWRAP (1u << 4u) +#define MCF_DERIVE (1u << 5u) + +#define MCF_NEEDSPARAM (1u << 8u) +#define MCF_OPTIONALPARAM (1u << 9u) +#define MCF_MAC_GENERAL (1u << 10u) + +struct mechrow { + const char * string; + CK_MECHANISM_TYPE numeric; + uint16_t blocksize; + /* the maximum size of general macs */ + uint16_t outputsize; + uint32_t flags; +}; + +struct mechtable_funcs { + int (*p_idx_from_num)(CK_ULONG mech); + int (*p_idx_from_str)(const char *mech); + const struct mechrow *(*p_row_from_num)(CK_ULONG mech); + const struct mechrow *(*p_row_from_str)(const char *mech); +}; + +extern const struct mechtable_funcs mechtable_funcs; + +/* The table. It has exactly MECHTABLE_NUM_ELEMS elements. The + constant is in the generated header mechtable-gen.h which is + included by this header. */ +extern const struct mechrow mechtable_rows[]; + +/*** Index functions ***/ +/* Locate a table row by numeric value of the mechanism. Returns -1 + if the name is invalid. */ +int mechtable_idx_from_numeric(CK_ULONG mech); + +/* Locate a table row by a string key. This respects aliases, so the + row at the returned index might have a different string + representation if the name changed in the meantime. Returns -1 if + the name is invalid. */ +int mechtable_idx_from_string(const char *mech); + +/* Translate a mechanism number into a mechanism column. + Returns NULL if the mechanism number is not known to the table. */ +const struct mechrow *mechrow_from_numeric(CK_ULONG mech); + +/* Translate a mechanism name into a mechanism column. + Returns NULL if the mechanism name is not known to the table. */ +const struct mechrow *mechrow_from_string(const char *mech); + +#endif diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/api/mechtable.inc opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/mechtable.inc --- opencryptoki-3.16.0+dfsg/usr/lib/api/mechtable.inc 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/mechtable.inc 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,151 @@ +/* -*- mode: C -*- */ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ + +/* This table will be included in the generated table index file to + provide the global data. Since the inclusion happens at top level, + keep the table constant. Order of the table elements matters as + the order in this table reflects the index returned by the index + search functions. + + The numeric value has to be unique (the string value also has to be + unique, but that is easier to ensure). If you need to map multiple + strings to the same numeric value (e.g., for EC_KEY_GEN and + ECDSA_KEY_GEN), the update the aliaslist in the tableidxgen.c + generator source. + + Feel free to add new rows or columns. The generator only cares + about the columns "string" and "numeric". Everything else is + ignored by the generator and simply included in the generated C + file. +*/ +const struct mechrow mechtable_rows[] = + { + /* string, numeric, blocksize, outputsize, flags */ + { "CKM_AES_CBC", CKM_AES_CBC, 16, MC_INFORMATION_UNAVAILABLE, MCF_ENCRYPTDECRYPT | MCF_WRAPUNWRAP | MCF_NEEDSPARAM }, + { "CKM_AES_CBC_PAD", CKM_AES_CBC_PAD, 16, MC_INFORMATION_UNAVAILABLE, MCF_ENCRYPTDECRYPT | MCF_WRAPUNWRAP | MCF_NEEDSPARAM }, + { "CKM_AES_CFB128", CKM_AES_CFB128, 16, MC_INFORMATION_UNAVAILABLE, MCF_ENCRYPTDECRYPT | MCF_NEEDSPARAM }, + { "CKM_AES_CFB64", CKM_AES_CFB64, 16, MC_INFORMATION_UNAVAILABLE, MCF_ENCRYPTDECRYPT | MCF_NEEDSPARAM }, + { "CKM_AES_CFB8", CKM_AES_CFB8, 16, MC_INFORMATION_UNAVAILABLE, MCF_ENCRYPTDECRYPT | MCF_NEEDSPARAM }, + { "CKM_AES_CMAC", CKM_AES_CMAC, 16, 16, MCF_SIGNVERIFY }, + { "CKM_AES_CMAC_GENERAL", CKM_AES_CMAC_GENERAL, 16, 16, MCF_SIGNVERIFY | MCF_MAC_GENERAL | MCF_NEEDSPARAM }, + { "CKM_AES_CTR", CKM_AES_CTR, 16, MC_INFORMATION_UNAVAILABLE, MCF_ENCRYPTDECRYPT | MCF_WRAPUNWRAP | MCF_NEEDSPARAM }, + { "CKM_AES_ECB", CKM_AES_ECB, 16, MC_INFORMATION_UNAVAILABLE, MCF_ENCRYPTDECRYPT | MCF_WRAPUNWRAP }, + { "CKM_AES_GCM", CKM_AES_GCM, 16, MC_INFORMATION_UNAVAILABLE, MCF_ENCRYPTDECRYPT | MCF_WRAPUNWRAP | MCF_NEEDSPARAM }, + { "CKM_AES_KEY_GEN", CKM_AES_KEY_GEN, 0, MC_INFORMATION_UNAVAILABLE, MCF_KEYGEN }, + { "CKM_AES_MAC", CKM_AES_MAC, 16, 8, MCF_SIGNVERIFY }, + { "CKM_AES_MAC_GENERAL", CKM_AES_MAC_GENERAL, 16, 16, MCF_SIGNVERIFY | MCF_NEEDSPARAM | MCF_MAC_GENERAL }, + { "CKM_AES_OFB", CKM_AES_OFB, 16, MC_INFORMATION_UNAVAILABLE, MCF_ENCRYPTDECRYPT | MCF_WRAPUNWRAP | MCF_NEEDSPARAM }, + { "CKM_DES2_KEY_GEN", CKM_DES2_KEY_GEN, 0, MC_INFORMATION_UNAVAILABLE, MCF_KEYGEN }, + { "CKM_DES3_CBC", CKM_DES3_CBC, 8, MC_INFORMATION_UNAVAILABLE, MCF_ENCRYPTDECRYPT | MCF_WRAPUNWRAP | MCF_NEEDSPARAM }, + { "CKM_DES3_CBC_PAD", CKM_DES3_CBC_PAD, 8, MC_INFORMATION_UNAVAILABLE, MCF_ENCRYPTDECRYPT | MCF_WRAPUNWRAP | MCF_NEEDSPARAM }, + { "CKM_DES3_CMAC", CKM_DES3_CMAC, 8, 8, MCF_SIGNVERIFY }, + { "CKM_DES3_CMAC_GENERAL", CKM_DES3_CMAC_GENERAL, 8, 8, MCF_SIGNVERIFY | MCF_NEEDSPARAM | MCF_MAC_GENERAL }, + { "CKM_DES3_ECB", CKM_DES3_ECB, 8, MC_INFORMATION_UNAVAILABLE, MCF_ENCRYPTDECRYPT | MCF_WRAPUNWRAP }, + { "CKM_DES3_KEY_GEN", CKM_DES3_KEY_GEN, 0, MC_INFORMATION_UNAVAILABLE, MCF_KEYGEN }, + { "CKM_DES3_MAC", CKM_DES3_MAC, 8, 4, MCF_SIGNVERIFY }, + { "CKM_DES3_MAC_GENERAL", CKM_DES3_MAC_GENERAL, 8, 8, MCF_SIGNVERIFY | MCF_NEEDSPARAM | MCF_MAC_GENERAL }, + { "CKM_DES_CBC", CKM_DES_CBC, 8, MC_INFORMATION_UNAVAILABLE, MCF_ENCRYPTDECRYPT | MCF_WRAPUNWRAP | MCF_NEEDSPARAM }, + { "CKM_DES_CBC_PAD", CKM_DES_CBC_PAD, 8, MC_INFORMATION_UNAVAILABLE, MCF_ENCRYPTDECRYPT | MCF_WRAPUNWRAP | MCF_NEEDSPARAM }, + { "CKM_DES_CFB64", CKM_DES_CFB64, 8, MC_INFORMATION_UNAVAILABLE, MCF_ENCRYPTDECRYPT | MCF_NEEDSPARAM }, + { "CKM_DES_CFB8", CKM_DES_CFB8, 8, MC_INFORMATION_UNAVAILABLE, MCF_ENCRYPTDECRYPT | MCF_NEEDSPARAM }, + { "CKM_DES_ECB", CKM_DES_ECB, 8, MC_INFORMATION_UNAVAILABLE, MCF_ENCRYPTDECRYPT | MCF_WRAPUNWRAP }, + { "CKM_DES_KEY_GEN", CKM_DES_KEY_GEN, 0, MC_INFORMATION_UNAVAILABLE, MCF_KEYGEN }, + { "CKM_DES_OFB64", CKM_DES_OFB64, 8, MC_INFORMATION_UNAVAILABLE, MCF_ENCRYPTDECRYPT | MCF_WRAPUNWRAP | MCF_NEEDSPARAM }, + { "CKM_DH_PKCS_DERIVE", CKM_DH_PKCS_DERIVE, 0, MC_INFORMATION_UNAVAILABLE, MCF_DERIVE | MCF_NEEDSPARAM }, + { "CKM_DH_PKCS_KEY_PAIR_GEN", CKM_DH_PKCS_KEY_PAIR_GEN, 0, MC_INFORMATION_UNAVAILABLE, MCF_KEYGEN }, + { "CKM_DH_PKCS_PARAMETER_GEN", CKM_DH_PKCS_PARAMETER_GEN, 0, MC_INFORMATION_UNAVAILABLE, MCF_KEYGEN }, + { "CKM_DSA", CKM_DSA, 0, MC_KEY_DEPENDENT, MCF_SIGNVERIFY }, + { "CKM_DSA_KEY_PAIR_GEN", CKM_DSA_KEY_PAIR_GEN, 0, MC_INFORMATION_UNAVAILABLE, MCF_KEYGEN }, + { "CKM_DSA_PARAMETER_GEN", CKM_DSA_PARAMETER_GEN, 0, MC_INFORMATION_UNAVAILABLE, MCF_KEYGEN }, + { "CKM_DSA_SHA1", CKM_DSA_SHA1, 0, MC_KEY_DEPENDENT, MCF_SIGNVERIFY }, + { "CKM_ECDH1_DERIVE", CKM_ECDH1_DERIVE, 0, MC_INFORMATION_UNAVAILABLE, MCF_DERIVE | MCF_NEEDSPARAM }, + { "CKM_ECDSA", CKM_ECDSA, 0, MC_KEY_DEPENDENT, MCF_SIGNVERIFY }, + { "CKM_ECDSA_SHA1", CKM_ECDSA_SHA1, 0, MC_KEY_DEPENDENT, MCF_SIGNVERIFY }, + { "CKM_ECDSA_SHA224", CKM_ECDSA_SHA224, 0, MC_KEY_DEPENDENT, MCF_SIGNVERIFY }, + { "CKM_ECDSA_SHA256", CKM_ECDSA_SHA256, 0, MC_KEY_DEPENDENT, MCF_SIGNVERIFY }, + { "CKM_ECDSA_SHA384", CKM_ECDSA_SHA384, 0, MC_KEY_DEPENDENT, MCF_SIGNVERIFY }, + { "CKM_ECDSA_SHA512", CKM_ECDSA_SHA512, 0, MC_KEY_DEPENDENT, MCF_SIGNVERIFY }, + { "CKM_EC_KEY_PAIR_GEN", CKM_EC_KEY_PAIR_GEN, 0, MC_INFORMATION_UNAVAILABLE, MCF_KEYGEN }, + { "CKM_GENERIC_SECRET_KEY_GEN", CKM_GENERIC_SECRET_KEY_GEN, 0, MC_INFORMATION_UNAVAILABLE, MCF_KEYGEN }, + { "CKM_IBM_ATTRIBUTEBOUND_WRAP", CKM_IBM_ATTRIBUTEBOUND_WRAP, 0, MC_INFORMATION_UNAVAILABLE, MCF_WRAPUNWRAP | MCF_NEEDSPARAM }, + { "CKM_IBM_CMAC", CKM_IBM_CMAC, 0, MC_KEY_DEPENDENT, MCF_SIGNVERIFY }, + { "CKM_IBM_DILITHIUM", CKM_IBM_DILITHIUM, 0, 3366, MCF_SIGNVERIFY },/* Size unknown */ + { "CKM_IBM_EC_X25519", CKM_IBM_EC_X25519, 0, MC_INFORMATION_UNAVAILABLE, MCF_DERIVE }, + { "CKM_IBM_EC_X448", CKM_IBM_EC_X448, 0, MC_INFORMATION_UNAVAILABLE, MCF_DERIVE }, + { "CKM_IBM_ED25519_SHA512", CKM_IBM_ED25519_SHA512, 128, MC_KEY_DEPENDENT, MCF_SIGNVERIFY }, + { "CKM_IBM_ED448_SHA3", CKM_IBM_ED448_SHA3, 144, MC_KEY_DEPENDENT, MCF_SIGNVERIFY }, + { "CKM_IBM_SHA3_224", CKM_IBM_SHA3_224, 144, 24, MCF_DIGEST }, + { "CKM_IBM_SHA3_224_HMAC", CKM_IBM_SHA3_224_HMAC, 144, 24, MCF_SIGNVERIFY }, + { "CKM_IBM_SHA3_256", CKM_IBM_SHA3_256, 136, 32, MCF_DIGEST }, + { "CKM_IBM_SHA3_256_HMAC", CKM_IBM_SHA3_256_HMAC, 136, 32, MCF_SIGNVERIFY }, + { "CKM_IBM_SHA3_384", CKM_IBM_SHA3_384, 104, 48, MCF_DIGEST }, + { "CKM_IBM_SHA3_384_HMAC", CKM_IBM_SHA3_384_HMAC, 104, 48, MCF_SIGNVERIFY }, + { "CKM_IBM_SHA3_512", CKM_IBM_SHA3_512, 72, 64, MCF_DIGEST }, + { "CKM_IBM_SHA3_512_HMAC", CKM_IBM_SHA3_512_HMAC, 72, 64, MCF_SIGNVERIFY }, + { "CKM_MD5", CKM_MD5, 64, 16, MCF_DIGEST }, + { "CKM_MD5_HMAC", CKM_MD5_HMAC, 64, 16, MCF_SIGNVERIFY }, + { "CKM_MD5_HMAC_GENERAL", CKM_MD5_HMAC_GENERAL, 64, 16, MCF_SIGNVERIFY | MCF_NEEDSPARAM }, + { "CKM_MD5_RSA_PKCS", CKM_MD5_RSA_PKCS, 0, MC_KEY_DEPENDENT, MCF_SIGNVERIFY }, + { "CKM_PBE_SHA1_DES3_EDE_CBC", CKM_PBE_SHA1_DES3_EDE_CBC, 0, MC_INFORMATION_UNAVAILABLE, MCF_KEYGEN | MCF_NEEDSPARAM }, + { "CKM_RSA_PKCS", CKM_RSA_PKCS, 0, MC_KEY_DEPENDENT, MCF_ENCRYPTDECRYPT | MCF_SIGNVERIFY | MCF_WRAPUNWRAP }, + { "CKM_RSA_PKCS_KEY_PAIR_GEN", CKM_RSA_PKCS_KEY_PAIR_GEN, 0, MC_INFORMATION_UNAVAILABLE, MCF_KEYGEN }, + { "CKM_RSA_PKCS_OAEP", CKM_RSA_PKCS_OAEP, 0, MC_KEY_DEPENDENT, MCF_ENCRYPTDECRYPT | MCF_WRAPUNWRAP | MCF_NEEDSPARAM }, + { "CKM_RSA_PKCS_PSS", CKM_RSA_PKCS_PSS, 0, MC_KEY_DEPENDENT, MCF_SIGNVERIFY | MCF_NEEDSPARAM }, + { "CKM_RSA_X_509", CKM_RSA_X_509, 0, MC_KEY_DEPENDENT, MCF_ENCRYPTDECRYPT | MCF_SIGNVERIFY | MCF_WRAPUNWRAP }, + { "CKM_RSA_X9_31", CKM_RSA_X9_31, 0, MC_KEY_DEPENDENT, MCF_SIGNVERIFY }, + { "CKM_RSA_X9_31_KEY_PAIR_GEN", CKM_RSA_X9_31_KEY_PAIR_GEN, 0, MC_INFORMATION_UNAVAILABLE, MCF_KEYGEN }, + { "CKM_SHA_1", CKM_SHA_1, 64, 20, MCF_DIGEST }, + { "CKM_SHA_1_HMAC", CKM_SHA_1_HMAC, 64, 20, MCF_SIGNVERIFY }, + { "CKM_SHA_1_HMAC_GENERAL", CKM_SHA_1_HMAC_GENERAL, 64, 20, MCF_SIGNVERIFY | MCF_NEEDSPARAM | MCF_MAC_GENERAL }, + { "CKM_SHA1_KEY_DERIVATION", CKM_SHA1_KEY_DERIVATION, 0, MC_INFORMATION_UNAVAILABLE, MCF_DERIVE }, + { "CKM_SHA1_RSA_PKCS", CKM_SHA1_RSA_PKCS, 0, MC_KEY_DEPENDENT, MCF_SIGNVERIFY }, + { "CKM_SHA1_RSA_PKCS_PSS", CKM_SHA1_RSA_PKCS_PSS, 0, MC_KEY_DEPENDENT, MCF_SIGNVERIFY | MCF_NEEDSPARAM }, + { "CKM_SHA1_RSA_X9_31", CKM_SHA1_RSA_X9_31, 0, MC_KEY_DEPENDENT, MCF_SIGNVERIFY }, + { "CKM_SHA224", CKM_SHA224, 64, 28, MCF_DIGEST }, + { "CKM_SHA224_HMAC", CKM_SHA224_HMAC, 64, 28, MCF_SIGNVERIFY }, + { "CKM_SHA224_HMAC_GENERAL", CKM_SHA224_HMAC_GENERAL, 64, 28, MCF_SIGNVERIFY | MCF_NEEDSPARAM | MCF_MAC_GENERAL }, + { "CKM_SHA224_KEY_DERIVATION", CKM_SHA224_KEY_DERIVATION, 0, MC_INFORMATION_UNAVAILABLE, MCF_DERIVE }, + { "CKM_SHA224_RSA_PKCS", CKM_SHA224_RSA_PKCS, 0, MC_KEY_DEPENDENT, MCF_SIGNVERIFY }, + { "CKM_SHA224_RSA_PKCS_PSS", CKM_SHA224_RSA_PKCS_PSS, 0, MC_KEY_DEPENDENT, MCF_SIGNVERIFY | MCF_NEEDSPARAM }, + { "CKM_SHA256", CKM_SHA256, 64, 32, MCF_DIGEST }, + { "CKM_SHA256_HMAC", CKM_SHA256_HMAC, 64, 32, MCF_SIGNVERIFY }, + { "CKM_SHA256_HMAC_GENERAL", CKM_SHA256_HMAC_GENERAL, 64, 32, MCF_SIGNVERIFY | MCF_NEEDSPARAM | MCF_MAC_GENERAL }, + { "CKM_SHA256_KEY_DERIVATION", CKM_SHA256_KEY_DERIVATION, 0, MC_INFORMATION_UNAVAILABLE, MCF_DERIVE }, + { "CKM_SHA256_RSA_PKCS", CKM_SHA256_RSA_PKCS, 0, MC_KEY_DEPENDENT, MCF_SIGNVERIFY }, + { "CKM_SHA256_RSA_PKCS_PSS", CKM_SHA256_RSA_PKCS_PSS, 0, MC_KEY_DEPENDENT, MCF_SIGNVERIFY | MCF_NEEDSPARAM }, + { "CKM_SHA384", CKM_SHA384, 128, 48, MCF_DIGEST }, + { "CKM_SHA384_HMAC", CKM_SHA384_HMAC, 128, 48, MCF_SIGNVERIFY }, + { "CKM_SHA384_HMAC_GENERAL", CKM_SHA384_HMAC_GENERAL, 128, 48, MCF_SIGNVERIFY | MCF_NEEDSPARAM | MCF_MAC_GENERAL }, + { "CKM_SHA384_KEY_DERIVATION", CKM_SHA384_KEY_DERIVATION, 0, MC_INFORMATION_UNAVAILABLE, MCF_DERIVE }, + { "CKM_SHA384_RSA_PKCS", CKM_SHA384_RSA_PKCS, 0, MC_KEY_DEPENDENT, MCF_SIGNVERIFY }, + { "CKM_SHA384_RSA_PKCS_PSS", CKM_SHA384_RSA_PKCS_PSS, 0, MC_KEY_DEPENDENT, MCF_SIGNVERIFY | MCF_NEEDSPARAM }, + { "CKM_SHA512", CKM_SHA512, 128, 64, MCF_DIGEST }, + { "CKM_SHA512_224", CKM_SHA512_224, 128, 28, MCF_DIGEST }, + { "CKM_SHA512_224_HMAC", CKM_SHA512_224_HMAC, 128, 28, MCF_SIGNVERIFY }, + { "CKM_SHA512_224_HMAC_GENERAL", CKM_SHA512_224_HMAC_GENERAL, 128, 28, MCF_SIGNVERIFY | MCF_NEEDSPARAM | MCF_MAC_GENERAL }, + { "CKM_SHA512_256", CKM_SHA512_256, 128, 32, MCF_DIGEST }, + { "CKM_SHA512_256_HMAC", CKM_SHA512_256_HMAC, 128, 32, MCF_SIGNVERIFY }, + { "CKM_SHA512_256_HMAC_GENERAL", CKM_SHA512_256_HMAC_GENERAL, 128, 32, MCF_SIGNVERIFY | MCF_NEEDSPARAM | MCF_MAC_GENERAL }, + { "CKM_SHA512_HMAC", CKM_SHA512_HMAC, 128, 64, MCF_SIGNVERIFY }, + { "CKM_SHA512_HMAC_GENERAL", CKM_SHA512_HMAC_GENERAL, 128, 64, MCF_SIGNVERIFY | MCF_NEEDSPARAM | MCF_MAC_GENERAL }, + { "CKM_SHA512_KEY_DERIVATION", CKM_SHA512_KEY_DERIVATION, 0, MC_INFORMATION_UNAVAILABLE, MCF_DIGEST }, + { "CKM_SHA512_RSA_PKCS", CKM_SHA512_RSA_PKCS, 0, MC_KEY_DEPENDENT, MCF_SIGNVERIFY }, + { "CKM_SHA512_RSA_PKCS_PSS", CKM_SHA512_RSA_PKCS_PSS, 0, MC_KEY_DEPENDENT, MCF_SIGNVERIFY | MCF_NEEDSPARAM }, + { "CKM_SSL3_KEY_AND_MAC_DERIVE", CKM_SSL3_KEY_AND_MAC_DERIVE, 0, MC_INFORMATION_UNAVAILABLE, MCF_DERIVE | MCF_NEEDSPARAM }, + { "CKM_SSL3_MASTER_KEY_DERIVE", CKM_SSL3_MASTER_KEY_DERIVE, 0, 48, MCF_DERIVE | MCF_NEEDSPARAM }, + { "CKM_SSL3_MD5_MAC", CKM_SSL3_MD5_MAC, 64, 8, MCF_SIGNVERIFY | MCF_NEEDSPARAM }, + { "CKM_SSL3_PRE_MASTER_KEY_GEN", CKM_SSL3_PRE_MASTER_KEY_GEN, 0, 48, MCF_DERIVE | MCF_NEEDSPARAM }, + { "CKM_SSL3_SHA1_MAC", CKM_SSL3_SHA1_MAC, 64, 8, MCF_SIGNVERIFY | MCF_NEEDSPARAM }, + { "CKM_TLS_KEY_AND_MAC_DERIVE", CKM_TLS_KEY_AND_MAC_DERIVE, 0, MC_INFORMATION_UNAVAILABLE, MCF_DERIVE | MCF_NEEDSPARAM }, + /* Not supported by any token, but needed for Token Store */ + { "CKM_AES_KEY_WRAP", CKM_AES_KEY_WRAP, 16, MC_INFORMATION_UNAVAILABLE, MCF_ENCRYPTDECRYPT | MCF_WRAPUNWRAP | MCF_OPTIONALPARAM }, + { "CKM_PKCS5_PBKD2", CKM_PKCS5_PBKD2, 0, MC_INFORMATION_UNAVAILABLE, MCF_KEYGEN | MCF_NEEDSPARAM }, + }; diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/api/policy.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/policy.c --- opencryptoki-3.16.0+dfsg/usr/lib/api/policy.c 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/policy.c 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,1736 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ + +#include "cfgparser.h" +#include "stringtranslations.h" +#include "policy.h" +#include "trace.h" +#include "ock_syslog.h" +#include +#include +#include "hashmap.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* in h_extern.h, but not included since it creates too many unneeded + dependencies for unit tests. */ +extern CK_RV get_sha_size(CK_ULONG mech, CK_ULONG *hsize); + +#define COMPARE_MODEXP 0 +#define COMPARE_ECC 1 +#define COMPARE_SYMMETRIC 2 +/* This is handled specially for now. Value chosen such that it is + not a valid index for struct strength.strength.arr. */ +#define COMPARE_PQC 5 +#define COMPARE_NOKEY 0xff + +#define OCK_POLICY_CFG OCK_CONFDIR "/policy.conf" +#define OCK_STRENGTH_CFG OCK_CONFDIR "/strength.conf" + +#define OCK_POLICY_MINVERSION 0u +#define OCK_STRENGTH_MINVERSION 0u + +#define OCK_POLICY_PERMS (0640u) + +struct strength { + union { + CK_ULONG arr[5]; + struct { + /* Keep this order in sync with the COMPARE_* definitions */ + CK_ULONG modexp; + CK_ULONG ecc; + CK_ULONG symmetric; + CK_ULONG digests; + CK_ULONG signatures; + } details; + } strength; + CK_BBOOL set; +}; + +struct policy_private { + struct hashmap *allowedmechs; + const struct _ec **allowedcurves; + unsigned int minstrengthidx; + int numallowedcurves; /* negative if all curves are allowed */ + CK_ULONG allowedmgfs; + CK_ULONG allowedvendormgfs; + CK_ULONG allowedkdfs; + CK_ULONG allowedprfs; + CK_ULONG maxcurvesize; + /* Strength struct ordered from highest to lowest. */ + struct strength strengths[NUM_SUPPORTED_STRENGTHS]; +}; + +struct policy_private *policy_private_alloc(void) +{ + return calloc(1, sizeof(struct policy_private)); +} + +struct policy_private *policy_private_free(struct policy_private *pp) +{ + if (pp) { + if (pp->allowedmechs) + hashmap_free(pp->allowedmechs, NULL); + if (pp->allowedcurves) + free(pp->allowedcurves); + free(pp); + } + return NULL; +} + +void policy_private_deactivate(struct policy_private *pp) +{ + hashmap_free(pp->allowedmechs, NULL); + /* Non-existing hash is universal. */ + pp->allowedmechs = NULL; + free(pp->allowedcurves); + pp->allowedcurves = NULL; + pp->minstrengthidx = NUM_SUPPORTED_STRENGTHS; + pp->numallowedcurves = -1; + pp->allowedmgfs = ~0lu; + pp->allowedvendormgfs = ~0lu; + pp->allowedkdfs = ~0lu; + pp->allowedprfs = ~0lu; + pp->maxcurvesize = 521u; +} + +static void policy_compute_strength(struct policy_private *pp, + struct objstrength *s, + CK_ULONG size, CK_ULONG ct) +{ + unsigned int i; + + if (ct == COMPARE_NOKEY || ct == COMPARE_PQC) { + s->strength = 0; + } else { + for (i = 0; i < NUM_SUPPORTED_STRENGTHS; ++i) { + if (pp->strengths[i].set == CK_TRUE && + size >= pp->strengths[i].strength.arr[ct]) { + break; + } + } + s->strength = i; + } +} + +static void policy_check_ec_allowed(struct policy_private *pp, + struct objstrength *s, + const CK_BYTE *oid, CK_ULONG oidlen) +{ + int i; + + if (pp->numallowedcurves >= 0) { + s->allowed = CK_FALSE; + for (i = 0; i < pp->numallowedcurves; ++i) { + if (pp->allowedcurves[i]->data_size == oidlen && + memcmp(oid, pp->allowedcurves[i]->data, oidlen)) { + s->allowed = CK_TRUE; + break; + } + } + } else { + s->allowed = CK_TRUE; + } +} + +static CK_RV policy_get_curve_args(get_attr_val_f getattr, void *d, + free_attr_f free_attr, CK_ULONG *size, + const CK_BYTE **oid, CK_ULONG *oidlen) +{ + CK_ATTRIBUTE *ec_params = NULL; + CK_RV rv; + int i; + + rv = getattr(d, CKA_EC_PARAMS, &ec_params); + if (rv == CKR_OK) { + *oid = ec_params->pValue; + *oidlen = ec_params->ulValueLen; + if (*oid == NULL || *oidlen == 0) { + TRACE_ERROR("Invalid CKA_EC_PARAMS value\n"); + rv = CKR_FUNCTION_FAILED; + goto out; + } + for (i = 0; i < NUMEC; ++i) { + if (der_ec_supported[i].data_size == ec_params->ulValueLen && + memcmp(ec_params->pValue, der_ec_supported[i].data, + ec_params->ulValueLen) == 0) { + *size = der_ec_supported[i].prime_bits; + break; + } + } + } + out: + if (free_attr && ec_params) + free_attr(ec_params); + return rv; +} + +static CK_RV policy_extract_key_data(get_attr_val_f getattr, void *d, + free_attr_f free_attr, + CK_ULONG *comptarget, CK_ULONG *size, + const CK_BYTE **oid, CK_ULONG *oidlen, + CK_ULONG *siglen) +{ + CK_RV rv; + CK_ATTRIBUTE *keytype = NULL, *keysize = NULL, *sigsize = NULL; + + *oid = NULL; + *oidlen = 0; + *size = 0; + rv = getattr(d, CKA_KEY_TYPE, &keytype); + if (rv != CKR_OK) { + TRACE_INFO("Failed to retrieve key type. rv=0x%lx\n", rv); + *comptarget = COMPARE_NOKEY; + *siglen = 0; + return CKR_OK; + } + if (keytype->ulValueLen != sizeof(CK_ULONG)) { + TRACE_ERROR("Wrong type for key type!\n"); + rv = CKR_FUNCTION_FAILED; + goto out; + } + switch (*(CK_ULONG *)keytype->pValue) { + case CKK_RSA: + rv = getattr(d, CKA_MODULUS, &keysize); + if (rv != CKR_OK) { + TRACE_ERROR("Did not find CKA_MODULUS for RSA key!\n"); + goto out; + } + *size = keysize->ulValueLen * 8; + *siglen = *size; + *comptarget = COMPARE_MODEXP; + break; + case CKK_DSA: + rv = getattr(d, CKA_SUBPRIME, &sigsize); + if (rv != CKR_OK) { + TRACE_ERROR("Did not find CKA_SUBPRIME for DSA key\n"); + goto out; + } + *siglen = sigsize->ulValueLen * 8 * 2; + /* Fallthrough */ + case CKK_DH: + /* Fallthrough */ + case CKK_X9_42_DH: + rv = getattr(d, CKA_PRIME, &keysize); + if (rv != CKR_OK) { + TRACE_ERROR("Did not find CKA_PRIME for key type 0x%lx\n", + *(CK_ULONG *)keytype->pValue); + return rv; + } + *size = keysize->ulValueLen * 8; + *comptarget = COMPARE_MODEXP; + break; + case CKK_EC: + rv = policy_get_curve_args(getattr, d, free_attr, size, oid, oidlen); + *siglen = *size * 2; + *comptarget = COMPARE_ECC; + break; + case CKK_DES: + *size = 56; + *siglen = 64; + *comptarget = COMPARE_SYMMETRIC; + break; + case CKK_DES2: + *size = 80; + *siglen = 64; + *comptarget = COMPARE_SYMMETRIC; + break; + case CKK_DES3: + *size = 112; + *siglen = 64; + *comptarget = COMPARE_SYMMETRIC; + break; + case CKK_AES: + *siglen = 128; + /* Fallthrough */ + case CKK_GENERIC_SECRET: + rv = getattr(d, CKA_VALUE_LEN, &keysize); + if (rv != CKR_OK) { + TRACE_ERROR("Did not find CKA_PRIME for key type 0x%lx\n", + *(CK_ULONG *)keytype->pValue); + goto out; + } + if (keysize->ulValueLen != sizeof(CK_ULONG)) { + TRACE_ERROR("Unexpected type for CKA_VALUE_LEN\n"); + rv = CKR_FUNCTION_FAILED; + goto out; + } + *size = (*(CK_ULONG*)keysize->pValue) * 8; + *comptarget = COMPARE_SYMMETRIC; + break; + case CKK_IBM_PQC_DILITHIUM: + *size = 256; + *comptarget = COMPARE_PQC; + break; + /* POLICY: New CKK */ + default: + TRACE_ERROR("Strength determination not implemented for key type 0x%lx\n", + *(CK_ULONG *)keytype->pValue); + rv = CKR_FUNCTION_FAILED; + } + out: + if (free_attr) { + if (keytype) + free_attr(keytype); + if (keysize) + free_attr(keysize); + if (sigsize) + free_attr(sigsize); + } + return rv; +} + +static CK_RV policy_get_digest_size(CK_MECHANISM_TYPE mech, CK_ULONG *hsize) +{ + CK_RV rv = CKR_OK; + + if (mech == CKM_MD2 || mech == CKM_MD5) { + *hsize = 128; + /* POLICY: New CKM digest */ + } else { + rv = get_sha_size(mech, hsize); + if (rv == CKR_OK) + *hsize *= 8; + } + return rv; +} + +static CK_RV policy_get_sig_size(CK_MECHANISM_PTR mech, struct objstrength *s, + CK_ULONG *ssize) +{ + const struct mechrow *col = mechrow_from_numeric(mech->mechanism); + CK_ULONG size; + + if (!col) + return CKR_FUNCTION_FAILED; + if (col->flags & MCF_MAC_GENERAL) { + if (mech->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)) { + TRACE_ERROR("Invalid mechanism parameter\n"); + return CKR_FUNCTION_FAILED; + } + size = *(CK_MAC_GENERAL_PARAMS *)mech->pParameter; + if (size > col->outputsize) + size = col->outputsize; + *ssize = size * 8; + return CKR_OK; + } + if (col->outputsize == MC_KEY_DEPENDENT) { + switch (mech->mechanism) { + /* POLICY: New CKM Sign/Verify */ + case CKM_IBM_CMAC: + /* Fallthrough */ + case CKM_DSA: + /* Fallthrough */ + case CKM_ECDSA: + /* Fallthrough */ + case CKM_RSA_PKCS: + /* Fallthrough */ + case CKM_RSA_PKCS_PSS: + /* Fallthrough */ + case CKM_RSA_X_509: + /* Fallthrough */ + case CKM_RSA_X9_31: + /* Fallthrough */ + case CKM_IBM_ED448_SHA3: + *ssize = s->siglen; + break; + case CKM_DSA_SHA1: + /* Fallthrough */ + case CKM_ECDSA_SHA1: + /* Fallthrough */ + case CKM_SHA1_RSA_PKCS: + /* Fallthrough */ + case CKM_SHA1_RSA_PKCS_PSS: + /* Fallthrough */ + case CKM_SHA1_RSA_X9_31: + *ssize = MIN(s->siglen, 160); + break; + case CKM_MD5_RSA_PKCS: + *ssize = MIN(s->siglen, 128); + break; + case CKM_ECDSA_SHA224: + /* Fallthrough */ + case CKM_SHA224_RSA_PKCS: + /* Fallthrough */ + case CKM_SHA224_RSA_PKCS_PSS: + *ssize = MIN(s->siglen, 224); + break; + case CKM_ECDSA_SHA256: + /* Fallthrough */ + case CKM_SHA256_RSA_PKCS: + /* Fallthrough */ + case CKM_SHA256_RSA_PKCS_PSS: + *ssize = MIN(s->siglen, 256); + break; + case CKM_ECDSA_SHA384: + /* Fallthrough */ + case CKM_SHA384_RSA_PKCS: + /* Fallthrough */ + case CKM_SHA384_RSA_PKCS_PSS: + *ssize = MIN(s->siglen, 384); + break; + case CKM_ECDSA_SHA512: + /* Fallthrough */ + case CKM_SHA512_RSA_PKCS: + /* Fallthrough */ + case CKM_SHA512_RSA_PKCS_PSS: + /* Fallthrough */ + case CKM_IBM_ED25519_SHA512: + *ssize = MIN(s->siglen, 512); + break; + default: + return CKR_FUNCTION_FAILED; + } + return CKR_OK; + } + if (col->outputsize == MC_INFORMATION_UNAVAILABLE) + return CKR_FUNCTION_FAILED; + *ssize = col->outputsize * 8; + return CKR_OK; +} + +static inline CK_RV policy_is_mgf_allowed(struct policy_private *pp, + CK_RSA_PKCS_MGF_TYPE mgf) +{ + if (mgf > CKG_VENDOR_DEFINED) { + if (pp->allowedvendormgfs & (1u << (mgf - CKG_VENDOR_DEFINED - 1))) + return CKR_OK; + } else { + if (pp->allowedmgfs & (1u << mgf)) + return CKR_OK; + } + TRACE_WARNING("POLICY VIOLATION: mgf not allowed: 0x%lx\n", mgf); + return CKR_FUNCTION_FAILED; +} + +static inline CK_RV policy_is_kdf_allowed(struct policy_private *pp, + CK_ULONG kdf) +{ + if (pp->allowedkdfs & (1u << kdf)) + return CKR_OK; + TRACE_WARNING("POLICY VIOLATION: kdf not allowed: 0x%lx\n", kdf); + return CKR_FUNCTION_FAILED; +} + +static inline CK_RV policy_is_prf_allowed(struct policy_private *pp, + CK_ULONG val) +{ + if (pp->allowedprfs & (1u << val)) + return CKR_OK; + TRACE_WARNING("POLICY VIOLATION: prf not allowed: 0x%lx\n", val); + return CKR_FUNCTION_FAILED; +} + +static CK_RV policy_is_key_allowed_i(struct policy_private *pp, + struct objstrength *s) +{ + /* 1. Check strength */ + if (s->strength > pp->minstrengthidx) { + TRACE_WARNING("POLICY VIOLATION: Key does not satisfy minimal strength constraint\n"); + return CKR_FUNCTION_FAILED; + } + /* 2. EC check */ + if (!s->allowed) { + TRACE_WARNING("POLICY VIOLATION: Key belongs to a forbidden EC curve\n"); + return CKR_FUNCTION_FAILED; + } + return CKR_OK; +} + +static CK_RV policy_update_modexp(struct policy_private *pp, + CK_MECHANISM_INFO_PTR info) +{ + CK_ULONG minsize; + + if (pp->minstrengthidx < NUM_SUPPORTED_STRENGTHS && + pp->strengths[pp->minstrengthidx].set) { + minsize = pp->strengths[pp->minstrengthidx].strength.details.modexp; + if (minsize > info->ulMaxKeySize) + return CKR_MECHANISM_INVALID; + if (minsize > info->ulMinKeySize) + info->ulMinKeySize = minsize; + } + return CKR_OK; +} + +static CK_RV policy_update_symmetric(struct policy_private *pp, + CK_MECHANISM_INFO_PTR info, + CK_BBOOL isbytes) +{ + CK_ULONG minsize; + + if (pp->minstrengthidx < NUM_SUPPORTED_STRENGTHS && + pp->strengths[pp->minstrengthidx].set) { + minsize = pp->strengths[pp->minstrengthidx].strength.details.symmetric; + if (isbytes == CK_TRUE) + minsize /= 8; + if (minsize > info->ulMaxKeySize) + return CKR_MECHANISM_INVALID; + if (minsize > info->ulMinKeySize) + info->ulMinKeySize = minsize; + } + return CKR_OK; +} + +static CK_RV policy_update_ec(struct policy_private *pp, + CK_MECHANISM_INFO_PTR info) +{ + CK_ULONG minsize; + + if (pp->numallowedcurves == 0) + /* We do not have any allowed curves */ + return CKR_MECHANISM_INVALID; + if (pp->minstrengthidx < NUM_SUPPORTED_STRENGTHS && + pp->strengths[pp->minstrengthidx].set) { + minsize = pp->strengths[pp->minstrengthidx].strength.details.ecc; + if (minsize > info->ulMaxKeySize) + return CKR_MECHANISM_INVALID; + if (minsize > info->ulMinKeySize) + info->ulMinKeySize = minsize; + } + return CKR_OK; +} + +static CK_RV policy_update_digest(struct policy_private *pp, + CK_MECHANISM_TYPE mech) +{ + CK_ULONG digestsize; + + if (pp->minstrengthidx < NUM_SUPPORTED_STRENGTHS && + pp->strengths[pp->minstrengthidx].set) { + if (policy_get_digest_size(mech, &digestsize) != CKR_OK) + /* Policy would reject this unknown mechanism */ + return CKR_MECHANISM_INVALID; + if (digestsize < pp->strengths[pp->minstrengthidx].strength.details.digests) + return CKR_MECHANISM_INVALID; + } + return CKR_OK; +} + +static CK_RV policy_check_signature_size(struct policy_private *pp, + CK_MECHANISM_TYPE mech, + CK_MECHANISM_INFO_PTR info) +{ + CK_ULONG minsiglen; + CK_ULONG siglen = 0; + CK_MECHANISM testmech; + struct objstrength s; + CK_MAC_GENERAL_PARAMS params = 0; + + if (info->flags & + (CKF_SIGN | CKF_SIGN_RECOVER | CKF_VERIFY | CKF_VERIFY_RECOVER)) { + testmech.mechanism = mech; + testmech.pParameter = ¶ms; + testmech.ulParameterLen = sizeof(params); + if (pp->minstrengthidx < NUM_SUPPORTED_STRENGTHS && + pp->strengths[pp->minstrengthidx].set) { + minsiglen = + pp->strengths[pp->minstrengthidx].strength.details.signatures; + switch (mech) { + /* POLICY: New CKM Sign/Verify */ + case CKM_RSA_PKCS: + /* Fallthrough */ + case CKM_RSA_PKCS_PSS: + /* Fallthrough */ + case CKM_RSA_X_509: + /* Fallthrough */ + case CKM_RSA_X9_31: + /* Fallthrough */ + case CKM_SHA1_RSA_PKCS: + /* Fallthrough */ + case CKM_SHA256_RSA_PKCS: + /* Fallthrough */ + case CKM_SHA384_RSA_PKCS: + /* Fallthrough */ + case CKM_SHA512_RSA_PKCS: + /* Fallthrough */ + case CKM_SHA1_RSA_PKCS_PSS: + /* Fallthrough */ + case CKM_SHA256_RSA_PKCS_PSS: + /* Fallthrough */ + case CKM_SHA384_RSA_PKCS_PSS: + /* Fallthrough */ + case CKM_SHA512_RSA_PKCS_PSS: + /* Fallthrough */ + case CKM_SHA1_RSA_X9_31: + siglen = info->ulMaxKeySize; + break; + case CKM_DSA: + /* Fallthrough */ + case CKM_DSA_SHA1: + /* Max size of CKA_SUBPRIME is 256 bits, so this is the biggest + * signature we can create with a DSA key. */ + siglen = 2u * 256u; + break; + case CKM_ECDSA: + /* Fallthrough */ + case CKM_ECDSA_SHA1: + /* Fallthrough */ + case CKM_ECDSA_SHA224: + /* Fallthrough */ + case CKM_ECDSA_SHA256: + /* Fallthrough */ + case CKM_ECDSA_SHA384: + /* Fallthrough */ + case CKM_ECDSA_SHA512: + if (pp->numallowedcurves == 0) { + /* No curve allowed */ + return CKR_MECHANISM_INVALID; + } + siglen = 2u * pp->maxcurvesize; + break; + case CKM_AES_CMAC_GENERAL: + /* Fallthrough */ + case CKM_AES_MAC_GENERAL: + params = 128 / 8; + break; + case CKM_DES3_CMAC_GENERAL: + /* Fallthrough */ + case CKM_DES3_MAC_GENERAL: + params = 64 / 8; + break; + case CKM_MD5_HMAC_GENERAL: + params = 128 / 8; + break; + case CKM_SHA_1_HMAC_GENERAL: + params = 160 / 8; + break; + case CKM_SHA512_224_HMAC_GENERAL: + /* Fallthrough */ + case CKM_SHA224_HMAC_GENERAL: + params = 224 / 8; + break; + case CKM_SHA512_256_HMAC_GENERAL: + /* Fallthrough */ + case CKM_SHA256_HMAC_GENERAL: + params = 256 / 8; + break; + case CKM_SHA384_HMAC_GENERAL: + params = 384 / 8; + break; + case CKM_SHA512_HMAC_GENERAL: + params = 512 / 8; + break; + case CKM_SSL3_MD5_MAC: + /* Fallthrough */ + case CKM_SSL3_SHA1_MAC: + params = 8; + break; + default: + break; + } + s.siglen = siglen; + if (policy_get_sig_size(&testmech, &s, &siglen) != CKR_OK) + return CKR_MECHANISM_INVALID; + if (siglen < minsiglen) + return CKR_MECHANISM_INVALID; + } + } + return CKR_OK; +} + +/* main functions (exported via function pointers) */ + +static CK_RV policy_is_key_allowed(policy_t p, struct objstrength *s, + SESSION *sess) +{ + struct policy_private *pp = p->priv; + CK_RV rv = CKR_OK; + + if (pp) { + rv = policy_is_key_allowed_i(pp, s); + if (rv != CKR_OK && sess) + sess->session_info.ulDeviceError = CKR_POLICY_VIOLATION; + } + return rv; +} + +static CK_RV policy_store_object_strength(policy_t p, struct objstrength *s, + get_attr_val_f getattr, void *d, + free_attr_f free_attr, SESSION *sess) +{ + struct policy_private *pp = p->priv; + /* silence maybe uninitialized warning for ct and siglen */ + CK_ULONG ct = 0, size, oidlen, siglen = 0; + const CK_BYTE *oid; + CK_RV rv = CKR_OK; + + if (pp) { + rv = policy_extract_key_data(getattr, d, free_attr, &ct, &size, + &oid, &oidlen, &siglen); + if (rv == CKR_OK) { + s->siglen = siglen; + policy_compute_strength(pp, s, size, ct); + if (ct == COMPARE_ECC) + policy_check_ec_allowed(pp, s, oid, oidlen); + else + s->allowed = CK_TRUE; + rv = policy_is_key_allowed_i(pp, s); + if (rv != CKR_OK) { + switch (ct) { + case COMPARE_MODEXP: + TRACE_ERROR("POLICY: Modular exponentiation compare size %lu too small!\n", + size); + break; + case COMPARE_ECC: + if (s->allowed) + TRACE_ERROR("POLICY: ECC curve size %lu too small!\n", + size); + else + TRACE_ERROR("POLICY: ECC curve not allowed!\n"); + break; + case COMPARE_SYMMETRIC: + TRACE_ERROR("POLICY: Symmetric key compare size %lu too small!\n", + size); + break; + case COMPARE_PQC: + TRACE_ERROR("POLICY: PQ key not allowed!\n"); + break; + case COMPARE_NOKEY: + TRACE_ERROR("POLICY: non-key object not allowed!\n"); + break; + default: + TRACE_ERROR("POLICY: Invalid compare target %lu!\n", ct); + break; + } + } + } else { + TRACE_ERROR("POLICY: Failed to extract key data.\n"); + s->strength = POLICY_STRENGTH_IDX_0; + s->siglen = 0; + s->allowed = CK_FALSE; + } + if (rv != CKR_OK && sess) + sess->session_info.ulDeviceError = CKR_POLICY_VIOLATION; + } else { + s->strength = POLICY_STRENGTH_IDX_0; + s->siglen = 0; + s->allowed = CK_TRUE; + } + return rv; +} + +static CK_RV policy_is_mech_allowed(policy_t p, CK_MECHANISM_PTR mech, + struct objstrength *s, int check, + SESSION *sess) +{ + struct policy_private *pp = p->priv; + CK_ULONG size; + CK_RV rv = CKR_OK; + + if (pp) { + if (s && policy_is_key_allowed_i(pp, s) != CKR_OK) { + rv = CKR_FUNCTION_FAILED; + goto out; + } + if (hashmap_find(pp->allowedmechs, mech->mechanism, NULL) == 0) { + TRACE_WARNING("Mechanism 0x%lx not allowed by policy\n", + mech->mechanism); + rv = CKR_FUNCTION_FAILED; + goto out; + } + if (check == POLICY_CHECK_DIGEST) { + if (policy_get_digest_size(mech->mechanism, &size) != CKR_OK) { + TRACE_WARNING("POLICY ERROR: Failed to retrieve digest size.\n"); + rv = CKR_FUNCTION_FAILED; + goto out; + } + if (pp->minstrengthidx < NUM_SUPPORTED_STRENGTHS && + size < + pp->strengths[pp->minstrengthidx].strength.details.digests) { + TRACE_WARNING("Digest output too small for policy.\n"); + rv = CKR_FUNCTION_FAILED; + goto out; + } + } else if (check == POLICY_CHECK_SIGNATURE || + check == POLICY_CHECK_VERIFY) { + if (policy_get_sig_size(mech, s, &size) != CKR_OK) { + TRACE_WARNING("POLICY ERROR: Failed to retrieve signature size.\n"); + rv = CKR_FUNCTION_FAILED; + goto out; + } + if (pp->minstrengthidx < NUM_SUPPORTED_STRENGTHS && + size < + pp->strengths[pp->minstrengthidx].strength.details.signatures) { + TRACE_WARNING("Signature too small for policy.\n"); + rv = CKR_FUNCTION_FAILED; + goto out; + } + } + switch (mech->mechanism) { + /* POLICY: New CKM Deep Check */ + case CKM_RSA_PKCS_PSS: + case CKM_SHA1_RSA_PKCS_PSS: + case CKM_SHA224_RSA_PKCS_PSS: + case CKM_SHA256_RSA_PKCS_PSS: + case CKM_SHA384_RSA_PKCS_PSS: + case CKM_SHA512_RSA_PKCS_PSS: + if (hashmap_find(pp->allowedmechs, + ((CK_RSA_PKCS_PSS_PARAMS *)mech->pParameter)->hashAlg, NULL) == 0) { + TRACE_WARNING("POLICY VIOLATION: PSS hash algorithm not allowed by policy.\n"); + rv = CKR_FUNCTION_FAILED; + } else if (policy_is_mgf_allowed(pp, + ((CK_RSA_PKCS_PSS_PARAMS *)mech->pParameter)->mgf) != CKR_OK) { + rv = CKR_FUNCTION_FAILED; + } + break; + case CKM_RSA_PKCS_OAEP: + if (hashmap_find(pp->allowedmechs, + ((CK_RSA_PKCS_OAEP_PARAMS *)mech->pParameter)->hashAlg, NULL) == 0) { + TRACE_WARNING("POLICY VIOLATION: OAEP hash algorithm not allowed by policy.\n"); + rv = CKR_FUNCTION_FAILED; + } else if (policy_is_mgf_allowed(pp, + ((CK_RSA_PKCS_OAEP_PARAMS *)mech->pParameter)->mgf) != CKR_OK) { + rv = CKR_FUNCTION_FAILED; + } + break; + case CKM_ECDH1_DERIVE: + if (policy_is_kdf_allowed(pp, + ((CK_ECDH1_DERIVE_PARAMS *)mech->pParameter)->kdf) != CKR_OK) + rv = CKR_FUNCTION_FAILED; + break; + default: + break; + } + } + out: + if (rv != CKR_OK && sess) + sess->session_info.ulDeviceError = CKR_POLICY_VIOLATION; + return rv; +} + +static CK_RV policy_update_mech_info(policy_t p, CK_MECHANISM_TYPE mech, + CK_MECHANISM_INFO_PTR info) +{ + struct policy_private *pp = p->priv; + /* Silence spurious maybe-uninitialized warning. */ + struct objstrength tmp = { 0, 0, CK_TRUE }; + const struct mechrow *row; + + if (pp) { + if (hashmap_find(pp->allowedmechs, mech, NULL) == 0) + return CKR_MECHANISM_INVALID; + switch (mech) { + /* POLICY: New CKM */ + case CKM_AES_CBC: + case CKM_AES_CBC_PAD: + case CKM_AES_CFB128: + case CKM_AES_CFB64: + case CKM_AES_CFB8: + case CKM_AES_CMAC: + case CKM_AES_CMAC_GENERAL: + case CKM_AES_CTR: + case CKM_AES_ECB: + case CKM_AES_GCM: + case CKM_AES_KEY_GEN: + case CKM_AES_MAC: + case CKM_AES_MAC_GENERAL: + case CKM_AES_OFB: + case CKM_IBM_CMAC: + case CKM_SHA1_KEY_DERIVATION: + case CKM_SHA224_KEY_DERIVATION: + case CKM_SHA256_KEY_DERIVATION: + case CKM_SHA384_KEY_DERIVATION: + case CKM_SHA512_KEY_DERIVATION: + case CKM_SSL3_MASTER_KEY_DERIVE: + case CKM_SSL3_PRE_MASTER_KEY_GEN: + if (policy_update_symmetric(pp, info, CK_TRUE) != CKR_OK) { + row = mechrow_from_numeric(mech); + TRACE_DEVEL("Mechanism %s (0x%lx) blocked by policy!\n", + row ? row->string : "UNKNOWN", mech); + return CKR_MECHANISM_INVALID; + } + break; + case CKM_DES_KEY_GEN: + case CKM_DES_CBC: + case CKM_DES_CBC_PAD: + case CKM_DES_CFB64: + case CKM_DES_CFB8: + case CKM_DES_ECB: + case CKM_DES_OFB64: + policy_compute_strength(pp, &tmp, 56, COMPARE_SYMMETRIC); + if (policy_is_key_allowed_i(pp, &tmp) != CKR_OK) + return CKR_MECHANISM_INVALID; + break; + case CKM_DES2_KEY_GEN: + policy_compute_strength(pp, &tmp, 80, COMPARE_SYMMETRIC); + if (policy_is_key_allowed_i(pp, &tmp) != CKR_OK) + return CKR_MECHANISM_INVALID; + break; + case CKM_DES3_KEY_GEN: + case CKM_DES3_CBC: + case CKM_DES3_CBC_PAD: + case CKM_DES3_CMAC: + case CKM_DES3_CMAC_GENERAL: + case CKM_DES3_ECB: + case CKM_DES3_MAC: + case CKM_DES3_MAC_GENERAL: + policy_compute_strength(pp, &tmp, 112, COMPARE_SYMMETRIC); + if (policy_is_key_allowed_i(pp, &tmp) != CKR_OK) + return CKR_MECHANISM_INVALID; + break; + case CKM_DH_PKCS_DERIVE: + case CKM_DH_PKCS_KEY_PAIR_GEN: + case CKM_DH_PKCS_PARAMETER_GEN: + case CKM_DSA: + case CKM_DSA_KEY_PAIR_GEN: + case CKM_DSA_PARAMETER_GEN: + case CKM_DSA_SHA1: + case CKM_MD5_RSA_PKCS: + case CKM_RSA_PKCS: + case CKM_RSA_PKCS_KEY_PAIR_GEN: + case CKM_RSA_PKCS_OAEP: + case CKM_RSA_PKCS_PSS: + case CKM_RSA_X_509: + case CKM_RSA_X9_31: + case CKM_RSA_X9_31_KEY_PAIR_GEN: + case CKM_SHA1_RSA_PKCS: + case CKM_SHA1_RSA_PKCS_PSS: + case CKM_SHA1_RSA_X9_31: + case CKM_SHA224_RSA_PKCS: + case CKM_SHA224_RSA_PKCS_PSS: + case CKM_SHA256_RSA_PKCS: + case CKM_SHA256_RSA_PKCS_PSS: + case CKM_SHA384_RSA_PKCS: + case CKM_SHA384_RSA_PKCS_PSS: + case CKM_SHA512_RSA_PKCS: + case CKM_SHA512_RSA_PKCS_PSS: + if (policy_update_modexp(pp, info) != CKR_OK) { + TRACE_DEVEL("Mechanism 0x%lx blocked by policy!\n", mech); + return CKR_MECHANISM_INVALID; + } + break; + case CKM_ECDH1_DERIVE: + case CKM_ECDSA: + case CKM_ECDSA_KEY_PAIR_GEN: + case CKM_ECDSA_SHA1: + case CKM_ECDSA_SHA224: + case CKM_ECDSA_SHA256: + case CKM_ECDSA_SHA384: + case CKM_ECDSA_SHA512: + case CKM_IBM_EC_C25519: + case CKM_IBM_EC_C448: + case CKM_IBM_ED25519_SHA512: + case CKM_IBM_ED448_SHA3: + if (policy_update_ec(pp, info) != CKR_OK) { + TRACE_DEVEL("Mechanism 0x%lx blocked by policy!\n", mech); + return CKR_MECHANISM_INVALID; + } + break; + case CKM_GENERIC_SECRET_KEY_GEN: + case CKM_IBM_SHA3_224_HMAC: + case CKM_IBM_SHA3_256_HMAC: + case CKM_IBM_SHA3_384_HMAC: + case CKM_IBM_SHA3_512_HMAC: + case CKM_SSL3_MD5_MAC: + case CKM_SSL3_SHA1_MAC: + if (policy_update_symmetric(pp, info, CK_FALSE) != CKR_OK) { + TRACE_DEVEL("Mechanism 0x%lx blocked by policy!\n", mech); + return CKR_MECHANISM_INVALID; + } + break; + case CKM_IBM_DILITHIUM: + break; + case CKM_IBM_SHA3_224: + case CKM_IBM_SHA3_256: + case CKM_IBM_SHA3_384: + case CKM_IBM_SHA3_512: + case CKM_MD5: + case CKM_SHA_1: + case CKM_SHA224: + case CKM_SHA256: + case CKM_SHA384: + case CKM_SHA512: + case CKM_SHA512_224: + case CKM_SHA512_256: + if (policy_update_digest(pp, mech) != CKR_OK) { + TRACE_DEVEL("Mechanism 0x%lx blocked by policy!\n", mech); + return CKR_MECHANISM_INVALID; + } + break; + case CKM_PBE_SHA1_DES3_EDE_CBC: + /* For this mechanism, the standard does not specify a + value for the MECHANISM_INFO structure. But this + mechanism generates a DES3 key. Check if DES3 keys can + be generated in this policy. If not, block this + mechanism since it can only fail. */ + tmp.strength = POLICY_STRENGTH_IDX_112; + tmp.allowed = CK_TRUE; + if (policy_is_key_allowed_i(pp, &tmp) != CKR_OK) + return CKR_MECHANISM_INVALID; + break; + case CKM_KEY_WRAP_LYNKS: + case CKM_MD5_HMAC: + case CKM_MD5_HMAC_GENERAL: + case CKM_SHA_1_HMAC: + case CKM_SHA_1_HMAC_GENERAL: + case CKM_SHA224_HMAC: + case CKM_SHA224_HMAC_GENERAL: + case CKM_SHA256_HMAC: + case CKM_SHA256_HMAC_GENERAL: + case CKM_SHA384_HMAC: + case CKM_SHA384_HMAC_GENERAL: + case CKM_SHA512_224_HMAC: + case CKM_SHA512_224_HMAC_GENERAL: + case CKM_SHA512_256_HMAC: + case CKM_SHA512_256_HMAC_GENERAL: + case CKM_SHA512_HMAC: + case CKM_SHA512_HMAC_GENERAL: + case CKM_SSL3_KEY_AND_MAC_DERIVE: + case CKM_TLS_KEY_AND_MAC_DERIVE: + case CKM_IBM_ATTRIBUTEBOUND_WRAP: + /* For these mechanisms, the standard does not specify a + value for info. So we only pass them to the generic + check for signature size. */ + break; + default: + TRACE_ERROR("Mechanism 0x%lx unknown to policy!\n", mech); + return CKR_MECHANISM_INVALID; + } + if (policy_check_signature_size(pp, mech, info) != CKR_OK) { + row = mechrow_from_numeric(mech); + TRACE_DEVEL("Policy removes SIGN/VERIFY from %s (0x%lx)\n", + row ? row->string : "UNKNOWN", mech); + info->flags &= ~(CKF_SIGN | CKF_SIGN_RECOVER | + CKF_VERIFY | CKF_VERIFY_RECOVER); + if ((info->flags & + ~(CKF_HW|CKF_EC_F_P|CKF_EC_NAMEDCURVE|CKF_EC_UNCOMPRESS)) == 0) { + TRACE_DEVEL("Mechanism %s (0x%lx) does not provide any feature after policy adjustment!\n", + row ? row->string : "UNKNOWN", mech); + return CKR_MECHANISM_INVALID; + } + } + } + return CKR_OK; +} + +/* If encalgo is NULL, the function assumes it should check the ICSF token. */ +static CK_RV policy_check_token_store(policy_t p, CK_BBOOL newversion, + CK_MECHANISM_TYPE encalgo, + CK_SLOT_ID slot, + struct tokstore_strength *ts) +{ + struct policy_private *pp = p->priv; + struct objstrength s; + + if (pp) { + s.allowed = CK_TRUE; + if (newversion) { + if (hashmap_find(pp->allowedmechs, CKM_AES_KEY_GEN, NULL) == 0) { + TRACE_WARNING("POLICY VIOLATION: CKM_AES_KEY_GEN needed by Token-Store for slot %lu\n", slot); + OCK_SYSLOG(LOG_ERR, "POLICY VIOLATION: CKM_AES_KEY_GEN needed by Token-Store for slot %lu\n", slot); + return CKR_GENERAL_ERROR; + } + if (hashmap_find(pp->allowedmechs, CKM_AES_KEY_WRAP, NULL) == 0) { + TRACE_WARNING("POLICY VIOLATION: CKM_AES_KEY_WRAP needed by Token-Store for slot %lu\n", slot); + OCK_SYSLOG(LOG_ERR, "POLICY VIOLATION: CKM_AES_KEY_WRAP needed by Token-Store for slot %lu\n", slot); + return CKR_GENERAL_ERROR; + } + if (hashmap_find(pp->allowedmechs, CKM_AES_GCM, NULL) == 0) { + TRACE_WARNING("POLICY VIOLATION: CKM_AES_GCM needed by Token-Store for slot %lu\n", slot); + OCK_SYSLOG(LOG_ERR, "POLICY VIOLATION: CKM_AES_GCM needed by Token-Store for slot %lu\n", slot); + return CKR_GENERAL_ERROR; + } + policy_compute_strength(pp, &s, 256, COMPARE_SYMMETRIC); + if (hashmap_find(pp->allowedmechs, CKM_PKCS5_PBKD2, NULL) == 0) { + TRACE_WARNING("POLICY VIOLATION: CKM_PKCS5_PBKD2 needed by Token-Store for slot %lu\n", slot); + OCK_SYSLOG(LOG_ERR, "POLICY VIOLATION: CKM_PKCS5_PBKD2 needed by Token-Store for slot %lu\n", slot); + return CKR_GENERAL_ERROR; + } + if (policy_is_prf_allowed(pp, CKP_PKCS5_PBKD2_HMAC_SHA512) != CKR_OK) { + TRACE_WARNING("POLICY VIOLATION: CKP_PKCS5_PBKD2_HMAC_SHA512 needed by Token-Store for slot %lu\n", slot); + OCK_SYSLOG(LOG_ERR, "POLICY VIOLATION: CKP_PKCS5_PBKD2_HMAC_SHA512 needed by Token-Store for slot %lu\n", slot); + return CKR_GENERAL_ERROR; + } + if (ts) { + ts->mk_keygen.mechanism = CKM_AES_KEY_GEN; + ts->mk_crypt.mechanism = CKM_AES_GCM; + ts->wrap_crypt.mechanism = CKM_AES_GCM; + ts->mk_keygen.pParameter = ts->mk_crypt.pParameter = + ts->wrap_crypt.pParameter = NULL; + ts->mk_keygen.ulParameterLen = ts->mk_crypt.ulParameterLen = + ts->wrap_crypt.ulParameterLen = 0; + ts->mk_strength = ts->wrap_strength = s.strength; + } + } else { + /* ICSF does not use a datastore, so encalgo is 0. */ + if (encalgo && hashmap_find(pp->allowedmechs, encalgo, NULL) == 0) { + TRACE_WARNING("POLICY VIOLATION: Token-Store encryption method not allowed for slot %lu!\n", slot); + OCK_SYSLOG(LOG_ERR, "POLICY VIOLATION: Token-Store encryption method not allowed for slot %lu!\n", slot); + return CKR_GENERAL_ERROR; + } + /* SO pin hash */ + if (hashmap_find(pp->allowedmechs, CKM_SHA_1, NULL) == 0) { + TRACE_WARNING("POLICY VIOLATION: Token-Store requires SHA1 for slot %lu!\n", slot); + OCK_SYSLOG(LOG_ERR, "POLICY VIOLATION: Token-Store requires SHA1 for slot %lu!\n", slot); + return CKR_GENERAL_ERROR; + } + /* User pin hash */ + if (hashmap_find(pp->allowedmechs, CKM_MD5, NULL) == 0) { + TRACE_WARNING("POLICY VIOLATION: Token-Store requires MD5 for slot %lu!\n", slot); + OCK_SYSLOG(LOG_ERR, "POLICY VIOLATION: Token-Store requires MD5 for slot %lu!\n", slot); + return CKR_GENERAL_ERROR; + } + if (encalgo == CKM_DES3_CBC) { + if (hashmap_find(pp->allowedmechs, CKM_DES3_KEY_GEN, NULL) == 0) { + TRACE_WARNING("POLICY VIOLATION: CKM_DES3_KEY_GEN needed by Token-Store for slot %lu\n", slot); + OCK_SYSLOG(LOG_ERR, "POLICY VIOLATION: CKM_DES3_KEY_GEN needed by Token-Store for slot %lu\n", slot); + return CKR_GENERAL_ERROR; + } + /* We use a 3DES key with three parts as master key... */ + policy_compute_strength(pp, &s, 112, COMPARE_SYMMETRIC); + if (ts) + ts->mk_strength = s.strength; + /* ... and a 2Key 3DES keys as wrapping key. */ + policy_compute_strength(pp, &s, 80, COMPARE_SYMMETRIC); + if (ts) { + ts->mk_keygen.mechanism = CKM_DES3_KEY_GEN; + ts->mk_crypt.mechanism = ts->wrap_crypt.mechanism = encalgo; + ts->mk_keygen.pParameter = ts->mk_crypt.pParameter = + ts->wrap_crypt.pParameter = NULL; + ts->mk_keygen.ulParameterLen = ts->mk_crypt.ulParameterLen = + ts->wrap_crypt.ulParameterLen = 0; + ts->wrap_strength = s.strength; + } + } else if (encalgo == CKM_AES_CBC) { + if (hashmap_find(pp->allowedmechs, CKM_AES_KEY_GEN, NULL) == 0) { + TRACE_WARNING("POLICY VIOLATION: CKM_AES_KEY_GEN needed by Token-Store for slot %lu\n", slot); + OCK_SYSLOG(LOG_ERR, "POLICY VIOLATION: CKM_AES_KEY_GEN needed by Token-Store for slot %lu\n", slot); + return CKR_GENERAL_ERROR; + } + policy_compute_strength(pp, &s, 256, COMPARE_SYMMETRIC); + if (ts) { + ts->mk_keygen.mechanism = CKM_AES_KEY_GEN; + ts->mk_crypt.mechanism = ts->wrap_crypt.mechanism = encalgo; + ts->mk_keygen.pParameter = ts->mk_crypt.pParameter = + ts->wrap_crypt.pParameter = NULL; + ts->mk_keygen.ulParameterLen = ts->mk_crypt.ulParameterLen = + ts->wrap_crypt.ulParameterLen = 0; + ts->mk_strength = ts->wrap_strength = s.strength; + } + } else if (encalgo) { + TRACE_WARNING("POLICY VIOLATION: Unknown Token-Store encryption method for slot %lu!\n", slot); + OCK_SYSLOG(LOG_ERR, "POLICY VIOLATION: Unknown Token-Store encryption method for slot %lu!\n", slot); + return CKR_GENERAL_ERROR; + } else { + /* ICSF token */ + if (hashmap_find(pp->allowedmechs, CKM_AES_KEY_GEN, NULL) == 0) { + TRACE_WARNING("POLICY VIOLATION: CKM_AES_KEY_GEN needed by Token-Store for slot %lu\n", slot); + OCK_SYSLOG(LOG_ERR, "POLICY VIOLATION: CKM_AES_KEY_GEN needed by Token-Store for slot %lu\n", slot); + return CKR_GENERAL_ERROR; + } + if (hashmap_find(pp->allowedmechs, CKM_AES_CBC, NULL) == 0) { + TRACE_WARNING("POLICY VIOLATION: CKM_AES_CBC needed by Token-Store for slot %lu\n", slot); + OCK_SYSLOG(LOG_ERR, "POLICY VIOLATION: CKM_AES_CBC needed by Token-Store for slot %lu\n", slot); + return CKR_GENERAL_ERROR; + } + policy_compute_strength(pp, &s, 256, COMPARE_SYMMETRIC); + if (hashmap_find(pp->allowedmechs, CKM_PKCS5_PBKD2, NULL) == 0) { + TRACE_WARNING("POLICY VIOLATION: CKM_PKCS5_PBKD2 needed by Token-Store for slot %lu\n", slot); + OCK_SYSLOG(LOG_ERR, "POLICY VIOLATION: CKM_PKCS5_PBKD2 needed by Token-Store for slot %lu\n", slot); + return CKR_GENERAL_ERROR; + } + if (policy_is_prf_allowed(pp, CKP_PKCS5_PBKD2_HMAC_SHA256) != CKR_OK) { + TRACE_WARNING("POLICY VIOLATION: CKP_PKCS5_PBKD2_HMAC_SHA256 needed by Token-Store for slot %lu\n", slot); + OCK_SYSLOG(LOG_ERR, "POLICY VIOLATION: CKP_PKCS5_PBKD2_HMAC_SHA256 needed by Token-Store for slot %lu\n", slot); + return CKR_GENERAL_ERROR; + } + if (ts) { + ts->mk_keygen.mechanism = CKM_AES_KEY_GEN; + ts->mk_crypt.mechanism = ts->wrap_crypt.mechanism = + CKM_AES_CBC; + ts->mk_keygen.pParameter = ts->mk_crypt.pParameter = + ts->wrap_crypt.pParameter = NULL; + ts->mk_keygen.ulParameterLen = ts->mk_crypt.ulParameterLen = + ts->wrap_crypt.ulParameterLen = 0; + ts->mk_strength = ts->wrap_strength = s.strength; + } + } + } + /* Both token store versions now have the weakest key strength in s */ + if (policy_is_key_allowed_i(pp, &s) != CKR_OK) { + TRACE_WARNING("POLICY VIOLATION: Token-Store encryption key too weak for slot %lu!\n", slot); + OCK_SYSLOG(LOG_ERR, "POLICY VIOLATION: Token-Store encryption key too weak for slot %lu!\n", slot); + return CKR_GENERAL_ERROR; + } + } + return CKR_OK; +} + +/* Policy loading support (internal functions) */ +static CK_RV policy_check_cfg_file(FILE *fp, const char *name) +{ + struct stat statbuf; + struct group *grp = NULL; + int err; + + grp = getgrnam("pkcs11"); + if (!grp) { + TRACE_ERROR("Could not retrieve \"pkcs11\" group!"); + OCK_SYSLOG(LOG_ERR, "POLICY: Could not retrieve \"pkcs11\" group!"); + return CKR_GENERAL_ERROR; + } + if (fstat(fileno(fp), &statbuf)) { + err = errno; + TRACE_ERROR("Could not stat configuration file %s: %s\n", + name, strerror(err)); + OCK_SYSLOG(LOG_ERR, "POLICY: Could not stat configuration file %s: %s\n", + name, strerror(err)); + return CKR_GENERAL_ERROR; + } + if (statbuf.st_uid != 0) { + TRACE_ERROR("Policy configuration file %s should be owned by \"root\"!\n", + name); + OCK_SYSLOG(LOG_ERR, "POLICY: Configuration file %s should be owned by \"root\"!\n", + name); + return CKR_GENERAL_ERROR; + } + if (statbuf.st_gid != grp->gr_gid) { + TRACE_ERROR("Policy configuration file %s should have group \"pkcs11\"!\n", + name); + OCK_SYSLOG(LOG_ERR, "POLICY: Configuration file %s should have group \"pkcs11\"!\n", + name); + return CKR_GENERAL_ERROR; + } + if ((statbuf.st_mode & ~S_IFMT) != OCK_POLICY_PERMS) { + TRACE_ERROR("Configuration file %s has wrong permissions!\n", name); + OCK_SYSLOG(LOG_ERR, "POLICY: Configuration file %s has wrong permissions!\n", + name); + return CKR_GENERAL_ERROR; + } + return CKR_OK; +} + +/* Policy loading support (externalized for testing purpose) */ +void policy_init_policy(struct policy *p) +{ + p->store_object_strength = policy_store_object_strength; + p->is_key_allowed = policy_is_key_allowed; + p->is_mech_allowed = policy_is_mech_allowed; + p->update_mech_info = policy_update_mech_info; + p->check_token_store = policy_check_token_store; + p->active = CK_FALSE; +} + +static void parse_error_hook(int line, int col, const char *msg) +{ + TRACE_ERROR("Parse error at %d:%d: %s\n", line, col, msg); +} + +static CK_RV policy_fileversion_check(struct ConfigBaseNode *cfg, + char *versionprefix, size_t prefixlen, + unsigned int minversion, + unsigned int *vers) +{ + const char *filevers; + + if (!confignode_hastype(cfg, CT_FILEVERSION)) { + TRACE_ERROR("Fileversion not found!\n"); + return CKR_FUNCTION_FAILED; + } + filevers = cfg->key; + if (strncmp(versionprefix, filevers, prefixlen) != 0 || + sscanf(filevers + prefixlen, "%u", vers) != 1 || *vers < minversion) { + TRACE_ERROR("Wrong version. Expected \"%s%d\" or higher but got \"%s\"\n", + versionprefix, minversion, filevers); + return CKR_FUNCTION_FAILED; + } + cfg->flags = 1; + return CKR_OK; +} + +static CK_RV policy_extract_strength_key(struct ConfigIdxStructNode *sd, + const char *key, CK_ULONG *val, int i) +{ + struct ConfigBaseNode *n; + + n = confignode_find(sd->value, key); + if (!n) { + TRACE_DEVEL("Strength configuration for %lu does not specify %s.\n", + supportedstrengths[i], key); + *val = ~0u; + } else if (!confignode_hastype(n, CT_INTVAL)) { + TRACE_ERROR("Strength configuration for %lu does not specify integer value for %s!\n", + supportedstrengths[i], key); + return CKR_FUNCTION_FAILED; + } else { + *val = confignode_to_intval(n)->value; + n->flags = 1; + } + return CKR_OK; +} + +static CK_RV policy_check_unmarked(struct ConfigBaseNode *n) +{ + struct ConfigBaseNode *i; + CK_RV rc = CKR_OK; + int f; + + confignode_foreach(i, n, f) { + if (i->flags != 1) { + TRACE_ERROR("Unknown keyword \"%s\" in line %hd\n", + i->key, i->line); + rc = CKR_FUNCTION_FAILED; + } + } + return rc; +} + +static CK_RV policy_parse_mechlist(struct policy_private *pp, + struct ConfigBaseNode *list) +{ + union hashmap_value val = { .ulVal = 0 }; + struct ConfigBaseNode *i; + const char *mechstr; + struct hashmap *h; + CK_RV rc = CKR_OK; + CK_ULONG mech; + int f; + + h = hashmap_new(); + if (!h) + return CKR_HOST_MEMORY; + if (list) { + confignode_foreach(i, list, f) { + mechstr = i->key; + rc = translate_string_to_mech(mechstr, strlen(mechstr), &mech); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY: Unknown mechanism: %s (line %hd)\n", + mechstr, i->line); + break; + } + if (hashmap_add(h, mech, val, NULL)) { + TRACE_ERROR("POLICY: failed to add mechanism to hash!\n"); + rc = CKR_HOST_MEMORY; + break; + } + } + } + pp->allowedmechs = h; + return rc; +} + +static CK_RV policy_parse_curvelist(struct policy_private *pp, + struct ConfigBaseNode *list) +{ + const struct _ec **curves; + struct ConfigBaseNode *i; + const struct _ec *curve; + int f, count = 0, p = 0; + CK_ULONG maxsize = 0; + CK_RV rc = CKR_OK; + + /* Compute size */ + if (list) { + confignode_foreach(i, list, f) { + rc = translate_string_to_curve(i->key, strlen(i->key), &curve); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY: Unknown curve \"%s\" in line %hd\n", + i->key, i->line); + OCK_SYSLOG(LOG_ERR, "POLICY: Unknown curve \"%s\" in line %hd\n", + i->key, i->line); + return rc; + } + ++count; + if (curve->prime_bits > maxsize) + maxsize = curve->prime_bits; + } + } + pp->numallowedcurves = count; + pp->maxcurvesize = maxsize; + if (count == 0) + return CKR_OK; + curves = calloc(count, sizeof(const struct _ec *)); + if (!curves) { + TRACE_ERROR("POLICY: Not enough memory for curves array!\n"); + return CKR_HOST_MEMORY; + } + confignode_foreach(i, list, f) { + /* Ignore rc since it has been checked before. */ + translate_string_to_curve(i->key, strlen(i->key), &curve); + curves[p++] = curve; + } + pp->allowedcurves = curves; + return rc; +} + +static CK_RV policy_parse_mgfs(struct policy_private *pp, + struct ConfigBaseNode *list) +{ + CK_ULONG smgfs = 0, vmgfs = 0; + struct ConfigBaseNode *i; + CK_RV rc = CKR_OK; + CK_ULONG mgf; + int f; + + if (list) { + confignode_foreach(i, list, f) { + rc = translate_string_to_mgf(i->key, strlen(i->key), &mgf); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY: Unknown MGF: \"%s\" (line %hd)\n", + i->key, i->line); + break; + } + if (mgf >= CKG_VENDOR_DEFINED) + vmgfs |= (1u << (mgf - CKG_VENDOR_DEFINED - 1)); + else + smgfs |= (1u << mgf); + } + } + pp->allowedmgfs = smgfs; + pp->allowedvendormgfs = vmgfs; + return CKR_OK; +} + +static CK_RV policy_parse_kdfs(struct policy_private *pp, + struct ConfigBaseNode *list) +{ + struct ConfigBaseNode *i; + CK_ULONG kdfs = 0, kdf; + CK_RV rc = CKR_OK; + int f; + + if (list) { + confignode_foreach(i, list, f) { + rc = translate_string_to_kdf(i->key, strlen(i->key), &kdf); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY: Unknown KDF: \"%s\" (line %hd)\n", + i->key, i->line); + break; + } + kdfs |= (1u << kdf); + } + } + pp->allowedkdfs = kdfs; + return rc; +} + +static CK_RV policy_parse_prfs(struct policy_private *pp, + struct ConfigBaseNode *list) +{ + struct ConfigBaseNode *i; + CK_ULONG prfs = 0, prf; + CK_RV rc = CKR_OK; + int f; + + if (list) { + confignode_foreach(i, list, f) { + rc = translate_string_to_prf(i->key, strlen(i->key), &prf); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY: Unknown PRF: \"%s\" (line %hd)\n", + i->key, i->line); + break; + } + prfs |= (1u << prf); + } + } + pp->allowedprfs = prfs; + return rc; +} + +CK_RV policy_load_strength_cfg(struct policy_private *pp, + FILE *fp) +{ + struct ConfigIdxStructNode *sd; + struct ConfigBaseNode *cfg; + CK_RV rc = CKR_OK; + unsigned int vers; + int i; + + TRACE_DEVEL("Parsing strength configuration file\n"); + if (parse_configlib_file(fp, &cfg, parse_error_hook, 0)) { + TRACE_ERROR("Parsing strength configuration failed!\n"); + return CKR_FUNCTION_FAILED; + } + rc = policy_fileversion_check(cfg, "strength-", strlen("strength-"), + OCK_STRENGTH_MINVERSION, &vers); + if (rc != CKR_OK) + goto out; + for (i = 0; i < NUM_SUPPORTED_STRENGTHS; ++i) { + sd = confignode_findidx(cfg, "strength", supportedstrengths[i]); + if (sd) { + sd->base.flags = 1; + rc = policy_extract_strength_key(sd, "MOD_EXP", + &pp->strengths[i].strength.details.modexp, + i); + if (rc != CKR_OK) + goto out; + rc = policy_extract_strength_key(sd, "ECC", + &pp->strengths[i].strength.details.ecc, + i); + if (rc != CKR_OK) + goto out; + rc = policy_extract_strength_key(sd, "SYMMETRIC", + &pp->strengths[i].strength.details.symmetric, + i); + if (rc != CKR_OK) + goto out; + rc = policy_extract_strength_key(sd, "digest", + &pp->strengths[i].strength.details.digests, + i); + if (rc != CKR_OK) + goto out; + rc = policy_extract_strength_key(sd, "signature", + &pp->strengths[i].strength.details.signatures, + i); + if (rc != CKR_OK) + goto out; + pp->strengths[i].set = CK_TRUE; + rc = policy_check_unmarked(sd->value); + if (rc != CKR_OK) + goto out; + } else { + pp->strengths[i].set = CK_FALSE; + } + } + out: + if (rc == CKR_OK) + rc = policy_check_unmarked(cfg); + confignode_deepfree(cfg); + return rc; +} + +CK_RV policy_load_policy_cfg(struct policy_private *pp, + FILE *fp, CK_BBOOL *restricting) +{ + struct ConfigBaseNode *cfg, *strength, *allowedmechs, *allowedcurves, + *allowedmgfs, *allowedkdfs, *allowedprfs; + unsigned long reqstrength; + CK_RV rc = CKR_OK; + unsigned int vers; + int i; + + *restricting = CK_FALSE; + if (parse_configlib_file(fp, &cfg, parse_error_hook, 0)) { + TRACE_ERROR("Parsing policy configuration failed!\n"); + OCK_SYSLOG(LOG_ERR, "Parsing policy configuration failed!\n"); + return CKR_FUNCTION_FAILED; + } + rc = policy_fileversion_check(cfg, "policy-", strlen("policy-"), + OCK_STRENGTH_MINVERSION, &vers); + if (rc != CKR_OK) + return rc; + strength = confignode_find(cfg, "strength"); + if (!strength || !confignode_hastype(strength, CT_INTVAL)) { + TRACE_ERROR("Invalid strength configuration in policy!\n"); + OCK_SYSLOG(LOG_ERR, "Invalid strength configuration in policy!\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + strength->flags = 1; + reqstrength = confignode_to_intval(strength)->value; + for (i = 0; i < NUM_SUPPORTED_STRENGTHS; ++i) { + if (reqstrength == supportedstrengths[i]) { + TRACE_DEVEL("POLICY: Using strength %lu\n", supportedstrengths[i]); + break; + } else if (reqstrength > supportedstrengths[i]) { + if (i > 0) + i -= 1; + TRACE_DEVEL("POLICY: Using strength %lu\n", supportedstrengths[i]); + break; + } + } + if (i == NUM_SUPPORTED_STRENGTHS && reqstrength > 0) { + i -=1; + TRACE_DEVEL("POLICY: Using strength %lu\n", supportedstrengths[i]); + } + if (i != NUM_SUPPORTED_STRENGTHS) + *restricting = CK_TRUE; + pp->minstrengthidx = i; + allowedmechs = confignode_find(cfg, "allowedmechs"); + if (!allowedmechs) { + TRACE_DEVEL("POLICY: No mechanism restriction\n"); + } else if (!confignode_hastype(allowedmechs, CT_BARELIST)) { + TRACE_ERROR("POLICY: allowedmechs has wrong type!\n"); + OCK_SYSLOG(LOG_ERR, "POLICY: allowedmechs has wrong type!\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } else { + *restricting = CK_TRUE; + allowedmechs->flags = 1; + rc = policy_parse_mechlist(pp, + confignode_to_barelist(allowedmechs)->value); + if (rc != CKR_OK) + goto out; + } + allowedcurves = confignode_find(cfg, "allowedcurves"); + if (!allowedcurves) { + TRACE_DEVEL("POLICY: No curve restrictions\n"); + pp->allowedcurves = NULL; + pp->numallowedcurves = -1; + pp->maxcurvesize = 521; + } else if (!confignode_hastype(allowedcurves, CT_BARELIST)) { + TRACE_ERROR("POLICY: allowedcurves has wrong type!\n"); + OCK_SYSLOG(LOG_ERR, "POLICY: allowedcurves has wrong type!\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } else { + *restricting = CK_TRUE; + allowedcurves->flags = 1; + rc = policy_parse_curvelist(pp, + confignode_to_barelist(allowedcurves)-> + value); + if (rc != CKR_OK) + goto out; + } + allowedmgfs = confignode_find(cfg, "allowedmgfs"); + if (!allowedmgfs) { + TRACE_DEVEL("POLICY: No MGF restrictions\n"); + pp->allowedmgfs = ~0u; + pp->allowedvendormgfs = ~0u; + } else if (!confignode_hastype(allowedmgfs, CT_BARELIST)) { + TRACE_ERROR("POLICY: allowedmgfs has wrong type!\n"); + OCK_SYSLOG(LOG_ERR, "POLICY: allowedmgfs has wrong type!\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } else { + *restricting = CK_TRUE; + allowedmgfs->flags = 1; + rc = policy_parse_mgfs(pp, + confignode_to_barelist(allowedmgfs)->value); + if (rc != CKR_OK) + goto out; + } + allowedkdfs = confignode_find(cfg, "allowedkdfs"); + if (!allowedkdfs) { + TRACE_DEVEL("POLICY: No KDF restrictions\n"); + pp->allowedkdfs = ~0u; + } else if (!confignode_hastype(allowedkdfs, CT_BARELIST)) { + TRACE_ERROR("POLICY: allowedkdfs has wrong type!\n"); + OCK_SYSLOG(LOG_ERR, "POLICY: allowedkdfs has wrong type!\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } else { + *restricting = CK_TRUE; + allowedkdfs->flags = 1; + rc = policy_parse_kdfs(pp, + confignode_to_barelist(allowedkdfs)->value); + if (rc != CKR_OK) + goto out; + } + allowedprfs = confignode_find(cfg, "allowedprfs"); + if (!allowedprfs) { + TRACE_DEVEL("POLICY: No PRF restrictions\n"); + pp->allowedprfs = ~0u; + } else if (!confignode_hastype(allowedprfs, CT_BARELIST)) { + TRACE_ERROR("POLICY: allowedprfs has wrong type!\n"); + OCK_SYSLOG(LOG_ERR, "POLICY: allowedprfs has wrong type!\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } else { + *restricting = CK_TRUE; + allowedprfs->flags = 1; + rc = policy_parse_prfs(pp, + confignode_to_barelist(allowedprfs)->value); + if (rc != CKR_OK) + goto out; + } + out: + if (rc == CKR_OK) + rc = policy_check_unmarked(cfg); + if (rc == CKR_FUNCTION_FAILED) + rc = CKR_GENERAL_ERROR; + confignode_deepfree(cfg); + return rc; +} + +/* Loading and unloading from API library */ + +CK_RV policy_load(struct policy *p) +{ + FILE *fp = NULL; + CK_RV rc = CKR_OK; + struct policy_private *pp = NULL; + int err; + CK_BBOOL restricting = CK_FALSE; + + policy_init_policy(p); + /* Load the strength definition */ + fp = fopen(OCK_STRENGTH_CFG, "r"); + if (fp == NULL) { + err = errno; + TRACE_ERROR("Failed to open " OCK_STRENGTH_CFG ": %s\n", + strerror(err)); + OCK_SYSLOG(LOG_ERR, "POLICY: Failed to open " OCK_STRENGTH_CFG ": %s\n", + strerror(err)); + rc = CKR_GENERAL_ERROR; + goto out; + } + rc = policy_check_cfg_file(fp, OCK_STRENGTH_CFG); + if (rc != CKR_OK) + goto out; + pp = policy_private_alloc(); + if (pp == NULL) { + TRACE_ERROR("Could not allocate policy private data!\n"); + OCK_SYSLOG(LOG_ERR, "POLICY: Could not allocate policy private data!\n"); + rc = CKR_HOST_MEMORY; + goto out; + } + rc = policy_load_strength_cfg(pp, fp); + if (rc != CKR_OK) { + TRACE_ERROR("Strength definition failed to parse!\n"); + OCK_SYSLOG(LOG_ERR, "POLICY: Strength definition %s failed to parse!\n", + OCK_STRENGTH_CFG); + goto out; + } + fclose(fp); + /* Load the policy definition */ + fp = fopen(OCK_POLICY_CFG, "r"); + if (fp == NULL) { + err = errno; + if (errno == ENOENT) { + /* If policy does not exit, but strength definition, run + * without policy. + */ + policy_private_deactivate(pp); + goto out; + } + TRACE_ERROR("Failed to open " OCK_POLICY_CFG ": %s\n", + strerror(err)); + OCK_SYSLOG(LOG_ERR, "POLICY: Failed to open " OCK_POLICY_CFG ": %s\n", + strerror(err)); + return CKR_GENERAL_ERROR; + } + rc = policy_check_cfg_file(fp, OCK_POLICY_CFG); + if (rc != CKR_OK) + goto out; + rc = policy_load_policy_cfg(pp, fp, &restricting); + if (rc != CKR_OK) { + TRACE_ERROR("Policy definition failed to parse!\n"); + OCK_SYSLOG(LOG_ERR, "POLICY: Policy definition %s failed to parse!\n", + OCK_POLICY_CFG); + } + out: + if (fp) + fclose(fp); + if (rc != CKR_OK) { + pp = policy_private_free(pp); + restricting = CK_FALSE; + } + p->priv = pp; + p->active = restricting; + return rc; +} + +void policy_unload(struct policy *p) +{ + struct policy_private *pp = p->priv; + + p->active = CK_FALSE; + if (pp) + p->priv = policy_private_free(pp); +} diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/api/policy.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/policy.h --- opencryptoki-3.16.0+dfsg/usr/lib/api/policy.h 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/policy.h 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,134 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ +#ifndef OCK_POLICY_H +#define OCK_POLICY_H + +#include +#include "supportedstrengths.h" + +#define POLICY_CHECK_DIGEST 0 +#define POLICY_CHECK_SIGNATURE 1 +#define POLICY_CHECK_VERIFY 2 +#define POLICY_CHECK_ENCRYPT 3 +#define POLICY_CHECK_DECRYPT 4 +#define POLICY_CHECK_KEYGEN 5 +#define POLICY_CHECK_DERIVE 6 +#define POLICY_CHECK_WRAP 7 +#define POLICY_CHECK_UNWRAP 8 + +struct policy; +typedef struct policy *policy_t; + +struct _SESSION; + +struct objstrength { + /* Just the index into the supportedstrengths array. */ + CK_ULONG strength; + CK_ULONG siglen; + CK_BBOOL allowed; +}; + +struct tokstore_strength { + CK_MECHANISM mk_keygen; + CK_MECHANISM mk_crypt; + CK_MECHANISM wrap_crypt; + /* Next two are just indices into the supportedstrengths array. */ + CK_ULONG mk_strength; + CK_ULONG wrap_strength; +}; + +/* + * Helper function to retrieve attribute values from different + * sources. This allows us to implement token specific input to the + * policy while the policy drives the whole determination of strength. + */ +typedef CK_RV (*get_attr_val_f)(void *data, + CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE **attr); + +/* + * Helper function to free a returned attribute. + */ +typedef void (*free_attr_f)(CK_ATTRIBUTE *attr); + +/* + * Stores into `obj` the strength and whether or not the EC is + * allowed. Returns CKR_FUNCTION_FAILED if the strength is below the + * required strength or the curve is not allowed. + */ +typedef CK_RV (*store_object_strength_f)(policy_t p, struct objstrength *s, + get_attr_val_f get_attr_val, void *d, + free_attr_f free_attr, + struct _SESSION *session); + +/* + * Return CKR_FUNCTION_FAILED if the key is not allowed in the current + * policy. + */ +typedef CK_RV (*is_key_allowed_f)(policy_t p, struct objstrength *s, + struct _SESSION *session); + +/* + * Check if a given mechanism is allowed. \c check should be one of + * the \c POLICY_CHECK_* values. + */ +typedef CK_RV (*is_mech_allowed_f)(policy_t p, CK_MECHANISM_PTR mech, + struct objstrength *s, int check, + struct _SESSION *session); + +/* + * Update the mechanism info for a given mechanism to correctly + * reflect the profile. Returns CKR_MECHANISM_INVALID if the + * mechanism is not supported in the current profile either due to the + * allowed-list or due key size constraints. + */ +typedef CK_RV (*update_mech_info_f)(policy_t p, CK_MECHANISM_TYPE mech, + CK_MECHANISM_INFO_PTR info); + +/* + * Check whether the crypto operations needed by a specific token + * store are allowed by the policy. This check only has to be done + * once since dynamic policy updates are not supported. + */ +typedef CK_RV (*check_token_store_f)(policy_t p, CK_BBOOL newversion, + CK_MECHANISM_TYPE encalgo, CK_SLOT_ID slot, + struct tokstore_strength *ts); + +struct policy { + void *priv; + CK_BBOOL active; + store_object_strength_f store_object_strength; + is_key_allowed_f is_key_allowed; + is_mech_allowed_f is_mech_allowed; + update_mech_info_f update_mech_info; + check_token_store_f check_token_store; +}; + +/* + * Load the policy and the strength definition into a pre-allocated struct. + */ +CK_RV policy_load(struct policy *policy); + +/* + * Unload a pre-allocated policy. This does not free \c policy, but + * all its contents and resets the policy to an empty one. + */ +void policy_unload(struct policy *policy); + +/* + * Helper function for store_object_strength_f callbacks. This + * function extracts the attribute from a template passed as data. It + * does not need a corresponding free function. But either the object + * has to be locked or it should not be visible yet. + */ +CK_RV policy_get_attr_from_template(void *data, + CK_ATTRIBUTE_TYPE type, + CK_ATTRIBUTE **attr); + +#endif diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/api/policyhelper.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/policyhelper.c --- opencryptoki-3.16.0+dfsg/usr/lib/api/policyhelper.c 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/policyhelper.c 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,21 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ + +#include "pkcs11types.h" +#include "h_extern.h" + +CK_RV policy_get_attr_from_template(void *data, + CK_ATTRIBUTE_TYPE type, + CK_ATTRIBUTE **attr) +{ + TEMPLATE *t = data; + + return template_attribute_get_non_empty(t, type, attr); +} diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/api/socket_client.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/socket_client.c --- opencryptoki-3.16.0+dfsg/usr/lib/api/socket_client.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/socket_client.c 2022-02-02 15:05:41.000000000 +0100 @@ -23,114 +23,456 @@ #include #include #include +#include +#include #include "apiproto.h" #include "slotmgr.h" #include "apictl.h" +#include "trace.h" #include "ock_syslog.h" +#include "events.h" extern API_Proc_Struct_t *Anchor; -// -// Will fill out the Slot_Mgr_Socket_t structure in the Anchor global data -// structure with the values passed by the pkcsslotd via a socket RPC. -int init_socket_data() + +int connect_socket(const char *file_path) { int socketfd; struct sockaddr_un daemon_address; struct stat file_info; struct group *grp; - int n; - unsigned int bytes_received = 0; - Slot_Mgr_Socket_t *daemon_socket_data = NULL; - int ret = FALSE; - if (stat(SOCKET_FILE_PATH, &file_info)) { + if (stat(file_path, &file_info)) { OCK_SYSLOG(LOG_ERR, - "init_socket_data: failed to find socket file, errno=%d", + "connect_socket: failed to find socket file, errno=%d", errno); - return FALSE; + return -1; } grp = getgrnam("pkcs11"); if (!grp) { OCK_SYSLOG(LOG_ERR, - "init_socket_data: pkcs11 group does not exist, errno=%d", + "connect_socket: pkcs11 group does not exist, errno=%d", errno); - return FALSE; + return -1; } if (file_info.st_uid != 0 || file_info.st_gid != grp->gr_gid) { OCK_SYSLOG(LOG_ERR, - "init_socket_data: incorrect permissions on socket file"); - return FALSE; + "connect_socket: incorrect permissions on socket file"); + return -1; } if ((socketfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { OCK_SYSLOG(LOG_ERR, - "init_socket_data: failed to create socket, errno=%d", + "connect_socket: failed to create socket, errno=%d", errno); - return FALSE; + return -1; } memset(&daemon_address, 0, sizeof(struct sockaddr_un)); daemon_address.sun_family = AF_UNIX; - strcpy(daemon_address.sun_path, SOCKET_FILE_PATH); + strncpy(daemon_address.sun_path, file_path, + sizeof(daemon_address.sun_path)); + daemon_address.sun_path[sizeof(daemon_address.sun_path) - 1] = '\0'; if (connect(socketfd, (struct sockaddr *) &daemon_address, sizeof(struct sockaddr_un)) != 0) { OCK_SYSLOG(LOG_ERR, - "init_socket_data: failed to connect to slotmanager daemon, " + "connect_socket: failed to connect to slotmanager daemon, " "errno=%d", errno); - goto exit; + goto error; } - // allocate data buffer - daemon_socket_data = - (Slot_Mgr_Socket_t *) malloc(sizeof(*daemon_socket_data)); - if (!daemon_socket_data) { - OCK_SYSLOG(LOG_ERR, "init_socket_data: failed to \ - allocate %lu bytes \ - for daemon data, errno=%d", - sizeof(*daemon_socket_data), errno); - goto exit; - } - - while (bytes_received < sizeof(*daemon_socket_data)) { - n = read(socketfd, ((char *) daemon_socket_data) + bytes_received, - sizeof(*daemon_socket_data) - bytes_received); + + return socketfd; + +error: + close(socketfd); + return -1; +} + +static ssize_t read_all(int socketfd, char *buffer, size_t size) +{ + size_t bytes_received = 0; + ssize_t n; + + while (bytes_received < size) { + n = read(socketfd, buffer + bytes_received, size - bytes_received); if (n < 0) { // read error if (errno == EINTR) continue; - OCK_SYSLOG(LOG_ERR, "init_socket_data: read error \ - on daemon socket, errno=%d", errno); - goto exit; - } else if (n == 0) { - // eof but we still expect some bytes - OCK_SYSLOG(LOG_ERR, "init_socket_data: read returned \ - with eof but we still \ - expect %lu bytes from daemon", - sizeof(*daemon_socket_data) - bytes_received); - goto exit; - } else { - // n > 0, we got some bytes - bytes_received += n; + return -errno; } + if (n == 0) + break; + + bytes_received += n; } - ret = TRUE; - - // copy the Slot_Mgr_Socket_t struct into global - // Anchor SocketDataPdata buffer - memcpy(&(Anchor->SocketDataP), daemon_socket_data, - sizeof(*daemon_socket_data)); - -exit: - //free the data buffer after copy - if (daemon_socket_data) - free(daemon_socket_data); + return bytes_received; +} - close(socketfd); +static ssize_t send_all(int socketfd, char *buffer, size_t size) +{ + size_t bytes_sent = 0; + ssize_t n; + + while (bytes_sent < size) { + n = send(socketfd, buffer + bytes_sent, size - bytes_sent, 0); + if (n < 0) { + // send error + if (errno == EINTR) + continue; + return -errno; + } + if (n == 0) + break; + + bytes_sent += n; + } + + return bytes_sent; +} + +// +// Will fill out the Slot_Mgr_Socket_t structure in the Anchor global data +// structure with the values passed by the pkcsslotd via a socket RPC. +int init_socket_data(int socketfd) +{ + ssize_t n; + int ret = TRUE; + + n = read_all(socketfd, (char *)&Anchor->SocketDataP, + sizeof(Anchor->SocketDataP)); + if (n < 0) { + // read error + OCK_SYSLOG(LOG_ERR, "init_socket_data: read error \ + on daemon socket, errno=%zd", -n); + ret = FALSE; + } + if (n != sizeof(Anchor->SocketDataP)) { + // eof but we still expect some bytes + OCK_SYSLOG(LOG_ERR, "init_socket_data: read returned \ + with eof but we still \ + expect %lu bytes from daemon", + sizeof(Anchor->SocketDataP) - n); + ret = FALSE; + } return ret; } + +static bool match_token_label_filter(event_msg_t *event, API_Slot_t *sltp) +{ + if (event->token_label[0] == ' ' || event->token_label[0] == '\0') + return true; + + return memcmp(event->token_label, + sltp->TokData->nv_token_data->token_info.label, + sizeof(event->token_label)) == 0; +} + +struct type_model { + unsigned int type; + char model[member_size(CK_TOKEN_INFO_32, model)]; +}; + +static const struct type_model type_model_flt[] = { + { .type = EVENT_TOK_TYPE_CCA, .model = "CCA " }, + { .type = EVENT_TOK_TYPE_EP11, .model = "EP11 " }, +}; + +static bool match_token_type_filter(event_msg_t *event, API_Slot_t *sltp) +{ + size_t i; + + if (event->token_type == EVENT_TOK_TYPE_ALL) + return true; + + for (i = 0; i < sizeof(type_model_flt) / sizeof(struct type_model); i++) { + if (memcmp(sltp->TokData->nv_token_data->token_info.model, + type_model_flt[i].model, + sizeof(type_model_flt[i].model)) == 0 && + (event->token_type & type_model_flt[i].type) != 0) + return true; + } + + return false; +} + +static int handle_event(API_Proc_Struct_t *anchor, event_msg_t *event, + char *payload, event_reply_t *reply) +{ + CK_SLOT_ID slotID; + API_Slot_t *sltp; + CK_RV rc; + + /* If its not for our process, ignore it, don't increment reply counters */ + if (event->process_id != 0 && event->process_id != anchor->Pid) + return 0; + + for (slotID = 0; slotID < NUMBER_SLOTS_MANAGED; slotID++) { + sltp = &anchor->SltList[slotID]; + if (sltp->DLLoaded == FALSE || sltp->FcnList == NULL) + continue; + + if (!match_token_label_filter(event, sltp)) + continue; + if (!match_token_type_filter(event, sltp)) + continue; + + if (sltp->FcnList->ST_HandleEvent != NULL) + rc = sltp->FcnList->ST_HandleEvent(sltp->TokData, event->type, + event->flags, payload, + event->payload_len); + else + rc = CKR_FUNCTION_NOT_SUPPORTED; + + TRACE_DEVEL("Slot %lu ST_HandleEvent rc: 0x%lx\n", slotID, rc); + switch (rc) { + case CKR_OK: + reply->positive_replies++; + break; + case CKR_FUNCTION_NOT_SUPPORTED: + reply->nothandled_replies++; + break; + default: + reply->negative_replies++; + break; + } + } + + return 0; +} + +struct cleanup_data { + API_Proc_Struct_t *anchor; +#if OPENSSL_VERSION_PREREQ(3, 0) + OSSL_LIB_CTX *prev_libctx; +#endif +}; + +static void event_thread_cleanup(void *arg) +{ + struct cleanup_data *cleanup = arg; + +#if OPENSSL_VERSION_PREREQ(3, 0) + OSSL_LIB_CTX_set0_default(cleanup->prev_libctx); +#else + UNUSED(cleanup); +#endif + + TRACE_DEVEL("Event thread %lu terminating\n", pthread_self()); +} + +static void *event_thread(void *arg) +{ + API_Proc_Struct_t *anchor = arg; + struct cleanup_data cleanup; +#if OPENSSL_VERSION_PREREQ(3, 0) + OSSL_LIB_CTX *prev_libctx; +#endif + int oldstate, oldtype; + struct pollfd pollfd; + event_msg_t event; + char *payload; + event_reply_t reply; + ssize_t num; + int rc; + + UNUSED(arg); + + TRACE_DEVEL("Event thread %lu running\n", pthread_self()); + + if (anchor->socketfd < 0) { + TRACE_ERROR("socket is already closed.\n"); + TRACE_DEVEL("Event thread %lu terminating\n", pthread_self()); + return NULL; + } + +#if OPENSSL_VERSION_PREREQ(3, 0) + /* Ensure that the event thread uses Opencryptoki's own library context */ + prev_libctx = OSSL_LIB_CTX_set0_default(Anchor->openssl_libctx); + if (prev_libctx == NULL) { + TRACE_ERROR("OSSL_LIB_CTX_set0_default failed\n"); + TRACE_DEVEL("Event thread %lu terminating\n", pthread_self()); + return NULL; + } +#endif + + /* Enable cancellation */ + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); + pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype); + cleanup.anchor = anchor; +#if OPENSSL_VERSION_PREREQ(3, 0) + cleanup.prev_libctx = prev_libctx; +#endif + pthread_cleanup_push(event_thread_cleanup, &cleanup); + + pollfd.fd = anchor->socketfd; + pollfd.events = POLLIN | POLLHUP | POLLERR; + + while (1) { + pollfd.revents = 0; + rc = poll(&pollfd, 1, -1); + if (rc < 0) { + if (errno == EINTR) + continue; + TRACE_ERROR("poll failed: %d\n", errno); + break; + } + + if (rc == 0) + continue; + + if (pollfd.revents & (POLLHUP | POLLERR)) { + TRACE_ERROR("Error on socket, possibly closed by slot daemon\n"); + break; + } + if ((pollfd.revents & POLLIN) == 0) + continue; + + /* Disable for cancellation while we are working on an event */ + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); + + TRACE_DEVEL("Receive new event ....\n"); + + num = read_all(anchor->socketfd, (char *)&event, sizeof(event)); + if (num != sizeof(event)) { + TRACE_ERROR("Error receiving the event, rc: %ld\n", num); + break; + } + + TRACE_DEBUG("Event version: %u\n", event.version); + TRACE_DEBUG("Event type: 0x%08x\n", event.type); + TRACE_DEBUG("Event flags: 0x%08x\n", event.flags); + TRACE_DEBUG("Event token_type: 0x%08x\n", event.token_type); + TRACE_DEBUG("Event token_name: '%.32s'\n", event.token_label); + TRACE_DEBUG("Event process_id: %u\n", event.process_id); + TRACE_DEBUG("Event payload_len: %u\n", event.payload_len); + + if (event.version != EVENT_VERSION_1) { + TRACE_ERROR("Event version invalid: %u\n", event.version); + break; + } + + payload = NULL; + if (event.payload_len > 0) { + payload = malloc(event.payload_len); + if (payload == NULL) { + TRACE_ERROR("Failed to allocate buffer for event payload\n"); + break; + } + + num = read_all(anchor->socketfd, payload, event.payload_len); + if (num != event.payload_len) { + TRACE_ERROR("Error receiving the event payload, rc: %ld\n", num); + if (payload != NULL) + free(payload); + break; + } + + TRACE_DEBUG("Event payload:\n"); + TRACE_DEBUG_DUMP(" ", payload, event.payload_len); + } + + memset(&reply, 0, sizeof(reply)); + reply.version = EVENT_VERSION_1; + rc = handle_event(anchor, &event, payload, &reply); + if (rc != 0) { + TRACE_ERROR("Error handling the event, rc: %d\n", rc); + if (payload != NULL) + free(payload); + break; + } + + TRACE_DEBUG("Reply version: %u\n", reply.version); + TRACE_DEBUG("Reply positive: %u\n", reply.positive_replies); + TRACE_DEBUG("Reply negative: %u\n", reply.negative_replies); + TRACE_DEBUG("Reply not-handled: %u\n", reply.nothandled_replies); + + if (event.flags & EVENT_FLAGS_REPLY_REQ) { + num = send_all(anchor->socketfd, (char *)&reply, sizeof(reply)); + if (num != sizeof(reply)) { + TRACE_ERROR("Error sending the event reply, rc: %ld\n", num); + if (payload != NULL) + free(payload); + break; + } + } + + if (payload != NULL) + free(payload); + + /* Re-enable for and test if we got canceled in the meantime */ + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); + pthread_testcancel(); + } + + /* + * Close the socket if we encounter an unrecoverable error (e.g. received + * invalid event) and stop the thread because of that. + * If the thread is stopped via stop_event_thread(), then it gets canceled + * via pthread_cancel(), and will not reach this place, thus the socket is + * not closed. This is intended, and the socket will then be closed by + * C_Finalize(). The atfork 'prepare' handler in the parent process also + * stops the thread (via stop_event_thread()), and the socket must not be + * closed in this case, because the thread is restarted in the atfork + * 'parent' handler, and should continue to receive events from the + * socket. + */ + close(anchor->socketfd); + anchor->socketfd = -1; + +#if OPENSSL_VERSION_PREREQ(3, 0) + OSSL_LIB_CTX_set0_default(prev_libctx); +#endif + + pthread_cleanup_pop(1); + return NULL; +} + +int start_event_thread() +{ + int rc; + + rc = pthread_create(&Anchor->event_thread, NULL, event_thread, Anchor); + if (rc != 0) { + OCK_SYSLOG(LOG_ERR, "start_event_thread: pthread_create failed, " + "errno=%d", rc); + TRACE_ERROR("Failed to start event thread, errno=%d\n", rc); + return rc; + } + + TRACE_DEVEL("Event thread %lu has been started\n", Anchor->event_thread); + return 0; +} + +int stop_event_thread() +{ + int rc; + void *status; + + TRACE_DEVEL("Canceling event thread %lu\n", Anchor->event_thread); + rc = pthread_cancel(Anchor->event_thread); + if (rc != 0 && rc != ESRCH) + return rc; + + TRACE_DEVEL("Waiting for event thread %lu to terminate\n", + Anchor->event_thread); + rc = pthread_join(Anchor->event_thread, &status); + if (rc != 0) + return rc; + + if (status != PTHREAD_CANCELED) { + TRACE_ERROR("Event thread was stopped, but did not return the " + "expected status\n"); + } + + TRACE_DEVEL("Event thread %lu has terminated\n", Anchor->event_thread); + + Anchor->event_thread = 0; + return 0; +} diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/api/statistics.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/statistics.c --- opencryptoki-3.16.0+dfsg/usr/lib/api/statistics.c 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/statistics.c 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,318 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "statistics.h" +#include "trace.h" +#include "h_extern.h" +#include "ock_syslog.h" + +static CK_RV statistics_increment(struct statistics *statistics, + CK_SLOT_ID slot, + const CK_MECHANISM *mech, + CK_ULONG strength_idx) +{ + CK_ULONG ofs; + counter_t *counter; + int mech_idx; + CK_MECHANISM implicit_mech = { 0, NULL, 0 }; + CK_RV rc; + + if (slot >= NUMBER_SLOTS_MANAGED || strength_idx > POLICY_STRENGTH_IDX_0 || + mech == NULL) + return CKR_ARGUMENTS_BAD; + + ofs = statistics->slot_shm_offsets[slot]; + if (ofs > statistics->shm_size) + return CKR_SLOT_ID_INVALID; + + mech_idx = mechtable_idx_from_numeric(mech->mechanism); + if (mech_idx < 0) + return CKR_MECHANISM_INVALID; + + ofs += mech_idx * (NUM_SUPPORTED_STRENGTHS + 1) * sizeof(counter_t); + + strength_idx = NUM_SUPPORTED_STRENGTHS - strength_idx; + ofs += strength_idx * sizeof(counter_t); + + if (ofs > statistics->shm_size) + return CKR_FUNCTION_FAILED; + + counter = (counter_t*)(statistics->shm_data + ofs); + __sync_add_and_fetch(counter, 1); + + if ((statistics->flags & STATISTICS_FLAG_COUNT_IMPLICIT) == 0) + return CKR_OK; + + /* deep inspect certain mechanism params for implicit mechanism use */ + switch (mech->mechanism) { + case CKM_RSA_PKCS_PSS: + case CKM_SHA1_RSA_PKCS_PSS: + case CKM_SHA224_RSA_PKCS_PSS: + case CKM_SHA256_RSA_PKCS_PSS: + case CKM_SHA384_RSA_PKCS_PSS: + case CKM_SHA512_RSA_PKCS_PSS: + implicit_mech.mechanism = + ((CK_RSA_PKCS_PSS_PARAMS *)mech->pParameter)->hashAlg; + rc = statistics_increment(statistics, slot, &implicit_mech, + POLICY_STRENGTH_IDX_0); + if (rc != CKR_OK) + return rc; + + rc = get_mgf_mech(((CK_RSA_PKCS_PSS_PARAMS *)mech->pParameter)->mgf, + &implicit_mech.mechanism); + if (rc != CKR_OK) + return rc; + rc = statistics_increment(statistics, slot, &implicit_mech, + POLICY_STRENGTH_IDX_0); + if (rc != CKR_OK) + return rc; + break; + case CKM_RSA_PKCS_OAEP: + implicit_mech.mechanism = + ((CK_RSA_PKCS_OAEP_PARAMS *)mech->pParameter)->hashAlg; + rc = statistics_increment(statistics, slot, &implicit_mech, + POLICY_STRENGTH_IDX_0); + if (rc != CKR_OK) + return rc; + + rc = get_mgf_mech(((CK_RSA_PKCS_OAEP_PARAMS *)mech->pParameter)->mgf, + &implicit_mech.mechanism); + if (rc != CKR_OK) + return rc; + rc = statistics_increment(statistics, slot, &implicit_mech, + POLICY_STRENGTH_IDX_0); + if (rc != CKR_OK) + return rc; + break; + case CKM_ECDH1_DERIVE: + if (((CK_ECDH1_DERIVE_PARAMS *)mech->pParameter)->kdf == CKD_NULL) + break; + rc = digest_from_kdf(((CK_ECDH1_DERIVE_PARAMS *)mech->pParameter)->kdf, + &implicit_mech.mechanism); + if (rc != CKR_OK) + return rc; + rc = statistics_increment(statistics, slot, &implicit_mech, + POLICY_STRENGTH_IDX_0); + if (rc != CKR_OK) + return rc; + break; + default: + break; + } + + return CKR_OK; +} + +/* + * Open the statistics shared memory segment for the specified user. + * If user is -1, then it is opened for the current user. + * If create is TRUE then the shared memory segment is created if it is not + * already existent. + */ +static CK_RV statistics_open_shm(struct statistics *statistics, int user, + CK_BBOOL create) +{ + int i, err, clear = 0; + struct stat stat_buf; + + snprintf(statistics->shm_name, sizeof(statistics->shm_name) - 1, + "%s_stats_%u", CONFIG_PATH, user == -1 ? geteuid() : (uid_t)user); + for (i = 1; statistics->shm_name[i] != '\0'; i++) { + if (statistics->shm_name[i] == '/') + statistics->shm_name[i] = '.'; + } + if (statistics->shm_name[0] != '/') { + memmove(&statistics->shm_name[1], &statistics->shm_name[0], + strlen(statistics->shm_name) + 1); + statistics->shm_name[0] = '/'; + } + + TRACE_INFO("Statistics SHM name: '%s'\n", statistics->shm_name); + + statistics->shm_handle = shm_open(statistics->shm_name, O_RDWR, + S_IRUSR | S_IWUSR); + if (statistics->shm_handle == -1) { + if (create) { + /* try to create it */ + statistics->shm_handle = shm_open(statistics->shm_name, + O_CREAT | O_RDWR, + S_IRUSR | S_IWUSR); + if (statistics->shm_handle == -1) { + err = errno; + TRACE_ERROR("Failed to create SHM '%s': %s\n", + statistics->shm_name, strerror(err)); + OCK_SYSLOG(LOG_ERR, "Failed to create SHM '%s': %s\n", + statistics->shm_name, strerror(err)); + return CKR_FUNCTION_FAILED; + } + + if (fchmod(statistics->shm_handle, S_IRUSR | S_IWUSR) == -1) { + err = errno; + TRACE_ERROR("Failed to change mode of SHM '%s': %s\n", + statistics->shm_name, strerror(err)); + OCK_SYSLOG(LOG_ERR, "Failed to change mode of SHM '%s': %s\n", + statistics->shm_name, strerror(err)); + close(statistics->shm_handle); + shm_unlink(statistics->shm_name); + return CKR_FUNCTION_FAILED; + } + } else { + err = errno; + TRACE_ERROR("Failed to open SHM '%s': %s\n", + statistics->shm_name, strerror(err)); + OCK_SYSLOG(LOG_ERR, "Failed to open SHM '%s': %s\n", + statistics->shm_name, strerror(err)); + return CKR_FUNCTION_FAILED; + } + } + + if (fstat(statistics->shm_handle, &stat_buf)) { + err = errno; + TRACE_ERROR("Failed to stat SHM '%s': %s\n", + statistics->shm_name, strerror(err)); + OCK_SYSLOG(LOG_ERR, "Failed to stat SHM '%s': %s\n", + statistics->shm_name, strerror(err)); + close(statistics->shm_handle); + return CKR_FUNCTION_FAILED; + } + + /* + * If the shared memory segment does not belong to the current user or does + * not have correct permissions, do not use it. + */ + if (stat_buf.st_uid != (user == -1 ? geteuid() : (uid_t)user) || + (stat_buf.st_mode & ~S_IFMT) != (S_IRUSR | S_IWUSR)) { + TRACE_ERROR("SHM '%s' has wrong mode/owner\n", statistics->shm_name); + OCK_SYSLOG(LOG_ERR, "SHM '%s' has wrong mode/owner\n", + statistics->shm_name); + close(statistics->shm_handle); + return CKR_FUNCTION_FAILED; + } + + if ((CK_ULONG)stat_buf.st_size != statistics->shm_size) { + if (create) { + if (ftruncate(statistics->shm_handle, statistics->shm_size) < 0) { + err = errno; + TRACE_ERROR("Failed to set size of SHM '%s': %s\n", + statistics->shm_name, strerror(err)); + OCK_SYSLOG(LOG_ERR, "Failed to set size of SHM '%s': %s\n", + statistics->shm_name, strerror(err)); + close(statistics->shm_handle); + return CKR_FUNCTION_FAILED; + } + + clear = 1; + } else { + TRACE_ERROR("SHM '%s' has wrong size\n", statistics->shm_name); + OCK_SYSLOG(LOG_ERR, "SHM '%s' has wrong size\n", + statistics->shm_name); + return CKR_FUNCTION_FAILED; + } + } + + statistics->shm_data = (CK_BYTE *)mmap(NULL, statistics->shm_size, + PROT_READ | PROT_WRITE, MAP_SHARED, + statistics->shm_handle, 0); + if (statistics->shm_data == MAP_FAILED) { + err = errno; + TRACE_ERROR("Failed to memory-map SHM '%s': %s\n", + statistics->shm_name, strerror(err)); + OCK_SYSLOG(LOG_ERR, "Failed to memory-map SHM '%s': %s\n", + statistics->shm_name, strerror(err)); + close(statistics->shm_handle); + statistics->shm_data = NULL; + return CKR_FUNCTION_FAILED; + } + + if (clear) + memset(statistics->shm_data, 0, sizeof(statistics->shm_size)); + + return CKR_OK; +} + +static CK_RV statistics_close_shm(struct statistics *statistics, + CK_BBOOL destroy) +{ + CK_RV rc; + + if (statistics->shm_data == NULL || statistics->shm_handle == -1) + return CKR_ARGUMENTS_BAD; + + munmap(statistics->shm_data, statistics->shm_size); + close(statistics->shm_handle); + + if (destroy) { + rc = shm_unlink(statistics->shm_name); + if (rc != 0) { + TRACE_ERROR("Failed to unlink SHM '%s': %s\n", + statistics->shm_name, strerror(errno)); + return CKR_FUNCTION_FAILED; + } + } + + statistics->shm_data = NULL; + statistics->shm_size = -1; + + return CKR_OK; +} + +CK_RV statistics_init(struct statistics *statistics, + Slot_Mgr_Socket_t *slots_infos, CK_ULONG flags) +{ + CK_ULONG i; + CK_RV rc; + + statistics->flags = flags; + statistics->shm_handle = -1; + statistics->shm_data = NULL; + + /* Count number of configured slots and calculate slot offsets. */ + statistics->num_slots = 0; + for (i = 0; i < NUMBER_SLOTS_MANAGED; i++) { + if (slots_infos->slot_info[i].present) { + statistics->slot_shm_offsets[i] = + statistics->num_slots * STAT_SLOT_SIZE; + statistics->num_slots++; + } else { + statistics->slot_shm_offsets[i] = (CK_ULONG)-1; + } + } + statistics->shm_size = statistics->num_slots * STAT_SLOT_SIZE; + + TRACE_INFO("%lu slots defined\n", statistics->num_slots); + TRACE_INFO("Statistics SHM size: %lu\n", statistics->shm_size); + + rc = statistics_open_shm(statistics, -1, CK_TRUE); + if (rc != CKR_OK) + goto error; + + statistics->increment_func = statistics_increment; + + return CKR_OK; + +error: + statistics_term(statistics); + return rc; +} + +void statistics_term(struct statistics *statistics) +{ + statistics_close_shm(statistics, CK_FALSE); +} + diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/api/statistics.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/statistics.h --- opencryptoki-3.16.0+dfsg/usr/lib/api/statistics.h 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/statistics.h 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,70 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ +#ifndef OCK_STATISTICS_H +#define OCK_STATISTICS_H + +#include +#include "slotmgr.h" +#include "mechtable.h" +#include "supportedstrengths.h" + +/* + * Statistics are collected in a shared memory segment per user. + * The statistics shared memory segment has the following layout: + * - For each configured slot: + * - For each supported mechanism: + * - one counter (counter_t) for non-key mechanisms (strength=0) + * - one counter for each supported strength (counter_t each) + * + * The size of the shared segment therefore is: + * Num configured slots * num supp.mechanisms * (num supp. strength + 1) * + * size of a counter + */ + +typedef CK_ULONG counter_t; + +#define STAT_MECH_SIZE ((NUM_SUPPORTED_STRENGTHS + 1) * sizeof(counter_t)) +#define STAT_SLOT_SIZE (MECHTABLE_NUM_ELEMS * STAT_MECH_SIZE) + +struct statistics; +typedef struct statistics *statistics_t; + +typedef CK_RV (*statistics_increment_f)(struct statistics *statistics, + CK_SLOT_ID slot, + const CK_MECHANISM *mech, + CK_ULONG strength); + +#define STATISTICS_FLAG_COUNT_IMPLICIT (1 << 0) +#define STATISTICS_FLAG_COUNT_INTERNAL (1 << 1) + +struct statistics { + CK_ULONG flags; + CK_ULONG num_slots; + CK_ULONG slot_shm_offsets[NUMBER_SLOTS_MANAGED]; + CK_ULONG shm_size; + char shm_name[PATH_MAX]; + int shm_handle; + CK_BYTE *shm_data; + statistics_increment_f increment_func; /* NULL if statistics disabled */ +}; + +#define INC_COUNTER(tokdata, sess, mech, key, no_key_strength) \ + do { \ + if ((tokdata)->statistics->increment_func != NULL) \ + (tokdata)->statistics->increment_func((tokdata)->statistics, \ + (sess)->session_info.slotID, (mech), (key) != NULL ? \ + ((OBJECT *)(key))->strength.strength : (no_key_strength));\ + } while (0) + +CK_RV statistics_init(struct statistics *statistics, + Slot_Mgr_Socket_t *slots_infos, CK_ULONG flags); +void statistics_term(struct statistics *statistics); + +#endif diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/api/supportedstrengths.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/supportedstrengths.c --- opencryptoki-3.16.0+dfsg/usr/lib/api/supportedstrengths.c 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/supportedstrengths.c 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,21 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ + +#include +#include "supportedstrengths.h" + +/* This file exists to allow external tools to access the supported + strengths array without adding dependencies on the policy + implementations. */ + +/* Specifies the strength value corresponding to the index of the + strengths array. KEEP IN SYNC! ALSO KEEP IN DESCENDING ORDER! */ +const CK_ULONG supportedstrengths[NUM_SUPPORTED_STRENGTHS] = + { 256, 192, 128, 112 }; diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/api/supportedstrengths.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/supportedstrengths.h --- opencryptoki-3.16.0+dfsg/usr/lib/api/supportedstrengths.h 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/api/supportedstrengths.h 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,25 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ +#ifndef OCK_SUPPORTEDSTRENGTHS_H +#define OCK_SUPPORTEDSTRENGTHS_H + +/* The number of supported non-0 strengths. */ +#define NUM_SUPPORTED_STRENGTHS 4 + +#define POLICY_STRENGTH_IDX_0 NUM_SUPPORTED_STRENGTHS +#define POLICY_STRENGTH_IDX_112 3 +#define POLICY_STRENGTH_IDX_128 2 +#define POLICY_STRENGTH_IDX_192 1 +#define POLICY_STRENGTH_IDX_256 0 + +/* Non-0 supported strengths in descending order. */ +extern const CK_ULONG supportedstrengths[NUM_SUPPORTED_STRENGTHS]; + +#endif diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/cca_stdll/cca_specific.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/cca_stdll/cca_specific.c --- opencryptoki-3.16.0+dfsg/usr/lib/cca_stdll/cca_specific.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/cca_stdll/cca_specific.c 2022-02-02 15:05:41.000000000 +0100 @@ -578,8 +578,14 @@ TRACE_INFO("cca %s slot=%lu running\n", __func__, SlotNumber); - tokdata->mech_list = (MECH_LIST_ELEMENT *)cca_mech_list; - tokdata->mech_list_len = cca_mech_list_len; + rc = ock_generic_filter_mechanism_list(tokdata, + cca_mech_list, cca_mech_list_len, + &(tokdata->mech_list), + &(tokdata->mech_list_len)); + if (rc != CKR_OK) { + TRACE_ERROR("Mechanism filtering failed! rc = 0x%lx\n", rc); + return rc; + } lib_csulcca = dlopen(CCASHAREDLIB, RTLD_GLOBAL | RTLD_NOW); if (lib_csulcca == NULL) { @@ -625,11 +631,12 @@ CK_RV token_specific_final(STDLL_TokData_t *tokdata, CK_BBOOL in_fork_initializer) { - UNUSED(tokdata); UNUSED(in_fork_initializer); TRACE_INFO("cca %s running\n", __func__); + free(tokdata->mech_list); + return CKR_OK; } diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/cca_stdll/cca_stdll.mk opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/cca_stdll/cca_stdll.mk --- opencryptoki-3.16.0+dfsg/usr/lib/cca_stdll/cca_stdll.mk 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/cca_stdll/cca_stdll.mk 2022-02-02 15:05:41.000000000 +0100 @@ -9,33 +9,36 @@ -DLINUX -DNOCDMF -DNODSA -DNODH -DNOECB \ -DTOK_NEW_DATA_STORE=0x0003000c \ -I${srcdir}/usr/lib/cca_stdll -I${srcdir}/usr/lib/common \ - -I${srcdir}/usr/include -DSTDLL_NAME=\"ccatok\" + -I${srcdir}/usr/include -DSTDLL_NAME=\"ccatok\" \ + -I${top_builddir}/usr/lib/api -I${srcdir}/usr/lib/api opencryptoki_stdll_libpkcs11_cca_la_LDFLAGS = -shared \ -Wl,-z,defs,-Bsymbolic -lcrypto -lpthread -nostartfiles \ -Wl,-soname,$@ -lrt -ldl \ -Wl,--version-script=${srcdir}/opencryptoki_tok.map -opencryptoki_stdll_libpkcs11_cca_la_SOURCES = \ - usr/lib/common/asn1.c usr/lib/common/dig_mgr.c \ - usr/lib/common/hwf_obj.c usr/lib/common/trace.c \ - usr/lib/common/key.c usr/lib/common/mech_list.c \ - usr/lib/common/mech_dh.c usr/lib/common/mech_rng.c \ - usr/lib/common/new_host.c usr/lib/common/sign_mgr.c \ - usr/lib/common/cert.c usr/lib/common/dp_obj.c \ - usr/lib/common/mech_aes.c usr/lib/common/mech_rsa.c \ - usr/lib/common/mech_ec.c usr/lib/common/obj_mgr.c \ - usr/lib/common/template.c usr/lib/common/data_obj.c \ - usr/lib/common/encr_mgr.c usr/lib/common/key_mgr.c \ - usr/lib/common/mech_md2.c usr/lib/common/mech_sha.c \ - usr/lib/common/object.c usr/lib/common/decr_mgr.c \ - usr/lib/common/globals.c usr/lib/common/loadsave.c \ - usr/lib/common/utility.c usr/lib/common/mech_des.c \ - usr/lib/common/mech_des3.c usr/lib/common/mech_md5.c \ - usr/lib/common/mech_ssl3.c usr/lib/common/verify_mgr.c \ - usr/lib/common/p11util.c usr/lib/common/sw_crypt.c \ - usr/lib/common/shared_memory.c usr/lib/common/profile_obj.c \ - usr/lib/cca_stdll/cca_specific.c usr/lib/common/attributes.c +opencryptoki_stdll_libpkcs11_cca_la_SOURCES = usr/lib/common/asn1.c \ + usr/lib/common/dig_mgr.c usr/lib/common/hwf_obj.c \ + usr/lib/common/trace.c usr/lib/common/key.c \ + usr/lib/common/mech_list.c usr/lib/common/mech_dh.c \ + usr/lib/common/mech_rng.c usr/lib/common/new_host.c \ + usr/lib/common/sign_mgr.c usr/lib/common/cert.c \ + usr/lib/common/dp_obj.c usr/lib/common/mech_aes.c \ + usr/lib/common/mech_rsa.c usr/lib/common/mech_ec.c \ + usr/lib/common/obj_mgr.c usr/lib/common/template.c \ + usr/lib/common/data_obj.c usr/lib/common/encr_mgr.c \ + usr/lib/common/key_mgr.c usr/lib/common/mech_md2.c \ + usr/lib/common/mech_sha.c usr/lib/common/object.c \ + usr/lib/common/decr_mgr.c usr/lib/common/globals.c \ + usr/lib/common/loadsave.c usr/lib/common/utility.c \ + usr/lib/common/mech_des.c usr/lib/common/mech_des3.c \ + usr/lib/common/mech_md5.c usr/lib/common/mech_ssl3.c \ + usr/lib/common/verify_mgr.c usr/lib/common/p11util.c \ + usr/lib/common/sw_crypt.c usr/lib/common/shared_memory.c \ + usr/lib/common/profile_obj.c usr/lib/cca_stdll/cca_specific.c \ + usr/lib/common/attributes.c usr/lib/common/dlist.c \ + usr/lib/common/utility_common.c usr/lib/common/ec_supported.c \ + usr/lib/api/policyhelper.c if ENABLE_LOCKS opencryptoki_stdll_libpkcs11_cca_la_SOURCES += \ diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/cca_stdll/tok_struct.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/cca_stdll/tok_struct.h --- opencryptoki-3.16.0+dfsg/usr/lib/cca_stdll/tok_struct.h 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/cca_stdll/tok_struct.h 2022-02-02 15:05:41.000000000 +0100 @@ -134,6 +134,7 @@ &token_specific_reencrypt_single, NULL, // set_attribute_values NULL, // set_attrs_for_new_object + NULL, // handle_event }; #endif diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/asn1.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/asn1.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/asn1.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/asn1.c 2022-02-02 15:05:41.000000000 +0100 @@ -1195,7 +1195,6 @@ return CKR_HOST_MEMORY; } offset = 0; - rc = 0; rc = ber_encode_INTEGER(FALSE, &buf2, &len, version, sizeof(version)); if (rc != CKR_OK) { @@ -1654,7 +1653,7 @@ CK_BYTE *buf = NULL; CK_BYTE *buf2 = NULL; CK_BYTE *buf3 = NULL; - BerValue *val; + BerValue *val = NULL; BerElement *ber; UNUSED(length_only); @@ -1680,7 +1679,6 @@ return CKR_HOST_MEMORY; } offset = 0; - rc = 0; rc = ber_encode_INTEGER(FALSE, &buf2, &len, (CK_BYTE *) modulus + sizeof(CK_ATTRIBUTE), @@ -1740,8 +1738,16 @@ /* need a bitstring */ ber = ber_alloc_t(LBER_USE_DER); - rc = ber_put_bitstring(ber, (char *)buf2, len * 8, 0x03); - rc = ber_flatten(ber, &val); + rc = (ber_put_bitstring(ber, (char *)buf2, len * 8, 0x03) <= 0 ? 1 : 0); + rc |= ber_flatten(ber, &val); + if (rc != 0) { + TRACE_DEVEL("%s ber_alloc_t/ber_flatten failed \n", __func__); + rc = CKR_FUNCTION_FAILED; + ber_free(ber, 1); + ber_bvfree(val); + free(buf2); + goto out; + } memcpy(buf3 + total_len, val->bv_val, val->bv_len); total_len += val->bv_len; ber_free(ber, 1); @@ -1752,6 +1758,7 @@ if (rc != CKR_OK) TRACE_DEVEL("%s ber_encode_Seq failed with rc=0x%lx\n", __func__, rc); +out: free(buf3); return rc; } @@ -1882,6 +1889,7 @@ // offset = 0; rc = 0; + len = 0; rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, prime1->ulValueLen); offset += len; @@ -2201,7 +2209,7 @@ CK_RV rc = 0; CK_BYTE *buf = NULL; CK_BYTE *buf2 = NULL; - BerValue *val; + BerValue *val = NULL; BerElement *ber; /* Calculate the BER container length @@ -2237,14 +2245,22 @@ rc |= ber_encode_INTEGER(FALSE, &buf, &len, value->pValue, value->ulValueLen); ber = ber_alloc_t(LBER_USE_DER); - rc = ber_put_bitstring(ber, (char *)buf, len * 8, 0x03); - rc = ber_flatten(ber, &val); + rc |= (ber_put_bitstring(ber, (char *)buf, len * 8, 0x03) <= 0 ? 1 : 0); + rc |= ber_flatten(ber, &val); + if (rc != 0) { + TRACE_DEVEL("%s ber_alloc_t/ber_flatten failed \n", __func__); + ber_free(ber, 1); + ber_bvfree(val); + free(buf); + return CKR_FUNCTION_FAILED; + } + pub_len = val->bv_len; ber_free(ber, 1); free(buf); ber_bvfree(val); - rc |= ber_encode_SEQUENCE(TRUE, NULL, &total, NULL, id_len + pub_len); + rc = ber_encode_SEQUENCE(TRUE, NULL, &total, NULL, id_len + pub_len); if (rc != CKR_OK) { TRACE_DEVEL("%s der_encode_sequence failed with rc=0x%lx\n", __func__, @@ -2323,19 +2339,28 @@ value->ulValueLen); if (rc != CKR_OK) { TRACE_DEVEL("%s ber_encode_Int failed with rc=0x%lx\n", __func__, rc); + free(buf2); return rc; } ber = ber_alloc_t(LBER_USE_DER); - rc = ber_put_bitstring(ber, (char *)buf, len * 8, 0x03); - rc = ber_flatten(ber, &val); + rc = (ber_put_bitstring(ber, (char *)buf, len * 8, 0x03) <= 0 ? 1 : 0); + rc |= ber_flatten(ber, &val); free(buf); + if (rc != 0) { + TRACE_DEVEL("%s ber_put_bitstring/ber_flatten failed\n", __func__); + ber_free(ber, 1); + ber_bvfree(val); + free(buf2); + return CKR_FUNCTION_FAILED; + } buf = (CK_BYTE *) malloc(id_len + val->bv_len); if (!buf) { TRACE_ERROR("%s Memory allocation failed\n", __func__); ber_free(ber, 1); ber_bvfree(val); + free(buf2); return CKR_HOST_MEMORY; } memcpy(buf, buf2, id_len); @@ -2499,7 +2524,7 @@ CK_BYTE *ecpoint; CK_ULONG ecpoint_len, field_len; BerElement *ber; - BerValue *val; + BerValue *val = NULL; CK_RV rc = 0; /* Calculate BER encoding length @@ -2529,8 +2554,15 @@ } ber = ber_alloc_t(LBER_USE_DER); - rc = ber_put_bitstring(ber, (char *)ecpoint, ecpoint_len * 8, 0x03); - rc = ber_flatten(ber, &val); + rc = (ber_put_bitstring(ber, (char *)ecpoint, ecpoint_len * 8, 0x03) + <= 0 ? 1 : 0); + rc |= ber_flatten(ber, &val); + if (rc != 0) { + TRACE_DEVEL("ber_put_bitstring/ber_flatten failed\n"); + ber_free(ber, 1); + ber_bvfree(val); + return CKR_FUNCTION_FAILED; + } ber_encode_CHOICE(TRUE, 1, &buf2, &len, (CK_BYTE *)val->bv_val, val->bv_len); @@ -2561,7 +2593,6 @@ return CKR_HOST_MEMORY; } offset = 0; - rc = 0; rc = ber_encode_INTEGER(FALSE, &buf2, &len, version, sizeof(version)); if (rc != CKR_OK) { @@ -2595,12 +2626,21 @@ &field_len); if (rc != CKR_OK || pubkey->ulValueLen != field_len) { TRACE_DEVEL("ber decoding of public key failed\n"); - return CKR_ATTRIBUTE_VALUE_INVALID; + rc = CKR_ATTRIBUTE_VALUE_INVALID; + goto error; } ber = ber_alloc_t(LBER_USE_DER); - rc = ber_put_bitstring(ber, (char *)ecpoint, ecpoint_len * 8, 0x03); - rc = ber_flatten(ber, &val); + rc = (ber_put_bitstring(ber, (char *)ecpoint, ecpoint_len * 8, 0x03) + <= 0 ? 1 : 0); + rc |= ber_flatten(ber, &val); + if (rc != 0) { + TRACE_DEVEL("ber_put_bitstring/ber_flatten failed\n"); + ber_free(ber, 1); + ber_bvfree(val); + rc = CKR_FUNCTION_FAILED; + goto error; + } ber_encode_CHOICE(FALSE, 1, &buf2, &len, (CK_BYTE *)val->bv_val, val->bv_len); @@ -2830,7 +2870,7 @@ CK_ULONG algid_len = der_AlgIdECBaseLen + params->ulValueLen; CK_RV rc = 0; CK_BYTE *buf = NULL; - BerValue *val; + BerValue *val = NULL; BerElement *ber; CK_BYTE *ecpoint; CK_ULONG ecpoint_len, field_len; @@ -2862,8 +2902,15 @@ /* public key */ ber = ber_alloc_t(LBER_USE_DER); - rc = ber_put_bitstring(ber, (char *)ecpoint, ecpoint_len * 8, 0x03); - rc = ber_flatten(ber, &val); + rc = (ber_put_bitstring(ber, (char *)ecpoint, ecpoint_len * 8, 0x03) + <= 0 ? 1 : 0); + rc |= ber_flatten(ber, &val); + if (rc != CKR_OK) { + TRACE_DEVEL("%s ber_put_bitstring/ber_flatten failed\n", __func__); + ber_free(ber, 1); + ber_bvfree(val); + return CKR_FUNCTION_FAILED; + } rc = ber_encode_SEQUENCE(TRUE, NULL, &total, NULL, len + val->bv_len); ber_free(ber, 1); @@ -2892,8 +2939,16 @@ /* generate bitstring */ ber = ber_alloc_t(LBER_USE_DER); - rc = ber_put_bitstring(ber, (char *)ecpoint, ecpoint_len * 8, 0x03); - rc = ber_flatten(ber, &val); + rc = (ber_put_bitstring(ber, (char *)ecpoint, ecpoint_len * 8, 0x03) + <= 0 ? 1 : 0); + rc |= ber_flatten(ber, &val); + if (rc != CKR_OK) { + TRACE_DEVEL("%s ber_put_bitstring/ber_flatten failed\n", __func__); + ber_free(ber, 1); + ber_bvfree(val); + free(buf); + return CKR_FUNCTION_FAILED; + } memcpy(buf + der_AlgIdECBaseLen + params->ulValueLen, val->bv_val, val->bv_len); @@ -3041,6 +3096,7 @@ // build the DSS parameters first offset = 0; rc = 0; + len = 0; rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, prime->ulValueLen); offset += len; @@ -3298,7 +3354,7 @@ CK_RV rc = 0; CK_BYTE *buf = NULL; CK_BYTE *buf2 = NULL; - BerValue *val; + BerValue *val = NULL; BerElement *ber; /* Calculate the BER container length @@ -3332,8 +3388,16 @@ rc |= ber_encode_INTEGER(FALSE, &buf, &len, value->pValue, value->ulValueLen); ber = ber_alloc_t(LBER_USE_DER); - rc = ber_put_bitstring(ber, (char *)buf, len * 8, 0x03); - rc = ber_flatten(ber, &val); + rc |= (ber_put_bitstring(ber, (char *)buf, len * 8, 0x03) <= 0 ? 1 : 0); + rc |= ber_flatten(ber, &val); + if (rc != CKR_OK) { + TRACE_DEVEL("%s ber_put_bitstring/ber_flatten failed\n", __func__); + ber_free(ber, 1); + ber_bvfree(val); + free(buf); + return CKR_FUNCTION_FAILED; + } + pub_len = val->bv_len; ber_free(ber, 1); ber_bvfree(val); @@ -3412,9 +3476,17 @@ } ber = ber_alloc_t(LBER_USE_DER); - rc = ber_put_bitstring(ber, (char *)buf, len * 8, 0x03); - rc = ber_flatten(ber, &val); + rc = (ber_put_bitstring(ber, (char *)buf, len * 8, 0x03) <= 0 ? 1 : 0); + rc |= ber_flatten(ber, &val); free(buf); + if (rc != CKR_OK) { + TRACE_DEVEL("%s ber_put_bitstring/ber_flatten failed\n", __func__); + ber_free(ber, 1); + ber_bvfree(val); + free(buf); + free(buf2); + return CKR_FUNCTION_FAILED; + } buf = (CK_BYTE *) malloc(id_len + val->bv_len); if (!buf) { @@ -3432,11 +3504,11 @@ /* outer sequence */ rc = ber_encode_SEQUENCE(FALSE, data, data_len, buf, id_len + pub_len); + free(buf); if (rc != CKR_OK) { TRACE_DEVEL("%s der_encode_Seq failed with rc=0x%lx\n", __func__, rc); return rc; } - free(buf); return rc; } @@ -3813,7 +3885,7 @@ CK_ATTRIBUTE *t1) { CK_BYTE *buf = NULL, *buf2 = NULL, *buf3 = NULL; - CK_ULONG len, len2, offset; + CK_ULONG len, len2 = 0, offset; CK_BYTE version[] = { 0 }; CK_RV rc; @@ -3870,7 +3942,6 @@ return CKR_HOST_MEMORY; } offset = 0; - rc = 0; /* Version */ rc = ber_encode_INTEGER(FALSE, &buf2, &len, version, sizeof(version)); @@ -4183,8 +4254,6 @@ free(t1_attr); if (rho_attr) free(rho_attr); - if (seed_attr) - free(seed_attr); if (tr_attr) free(tr_attr); if (s1_attr) diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/common.mk opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/common.mk --- opencryptoki-3.16.0+dfsg/usr/lib/common/common.mk 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/common.mk 2022-02-02 15:05:41.000000000 +0100 @@ -4,7 +4,5 @@ usr/lib/common/shared_memory.h usr/lib/common/tok_spec_struct.h \ usr/lib/common/trace.h usr/lib/common/h_extern.h \ usr/lib/common/sw_crypt.h usr/lib/common/defs.h \ - usr/lib/common/p11util.h \ + usr/lib/common/p11util.h usr/lib/common/event_client.h \ usr/lib/common/list.h usr/lib/common/tok_specific.h - -usr/lib/common/lexer.c: usr/lib/common/parser.h diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/configparser.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/configparser.h --- opencryptoki-3.16.0+dfsg/usr/lib/common/configparser.h 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/configparser.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,76 +0,0 @@ -/* - * COPYRIGHT (c) International Business Machines Corp. 2020 - * - * This program is provided under the terms of the Common Public License, - * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this - * software constitutes recipient's acceptance of CPL-1.0 terms which can be - * found in the file LICENSE file or at - * https://opensource.org/licenses/cpl1.0.php - */ - -#ifndef _CONFIGPARSER_H -#define _CONFIGPARSER_H 1 - -#include - -#define DEF_MANUFID "IBM" -#define DEF_SLOTDESC "Linux" - -typedef enum { - KW_STDLL, - KW_SLOTDESC, - KW_MANUFID, - KW_HWVERSION, - KW_FWVERSION, - KW_CONFNAME, - KW_TOKNAME, - KW_TOKVERSION, - KW_MAX -} keyword_token; - -typedef int (*ockversion_f)(void *private, const char *version); -typedef void (*eol_f)(void *private); -typedef int (*begin_slot_f)(void *private, int slot, int nl_before_begin); -typedef int (*end_slot_f)(void *private); -typedef int (*key_str_f)(void *private, int tok, const char *val); -typedef int (*key_vers_f)(void *private, int tok, unsigned int vers); -typedef void (*eolcomment_f)(void *private, const char *comment); -/* - * Report an error. If the error is not reported by the parser itself - * but via one of the parse functions, \c parsermsg will be \c NULL. - * In such a case it is the responsibility of the parse functions to - * store appropriate error information. - */ -typedef void (*error_f)(void *private, int line, const char *parsermsg); - -/* - * Function pointers called by the parser to notify consumer about some parse - * event. If the consumer is not interested in a specific event, the function - * pointer should be set to NULL. - * Every function gets a pointer to a private object that is opaque to the - * parser. - */ -struct parsefuncs { - ockversion_f version; - eol_f eol; - begin_slot_f begin_slot; - end_slot_f end_slot; - key_str_f key_str; - key_vers_f key_vers; - eolcomment_f eolcomment; - error_f parseerror; -}; - -extern const char *keyword_token_to_str(int tok); - -/* - * Load and parse a configuration file via the given parser functions - * and parser private data. - * \return 0 on success, - * -1 if \c configfile could not be opened for reading, - * 1 if parsing ended with errors. - */ -extern int load_and_parse(const char *configfile, - struct parsefuncs *funcs, void *private); - -#endif diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/decr_mgr.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/decr_mgr.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/decr_mgr.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/decr_mgr.c 2022-02-02 15:05:41.000000000 +0100 @@ -24,19 +24,25 @@ #include "tok_spec_struct.h" #include "trace.h" +#include "../api/policy.h" +#include "../api/statistics.h" + // // CK_RV decr_mgr_init(STDLL_TokData_t *tokdata, SESSION *sess, ENCR_DECR_CONTEXT *ctx, CK_ULONG operation, - CK_MECHANISM *mech, CK_OBJECT_HANDLE key_handle) + CK_MECHANISM *mech, CK_OBJECT_HANDLE key_handle, + CK_BBOOL checkpolicy) { OBJECT *key_obj = NULL; CK_BYTE *ptr = NULL; CK_KEY_TYPE keytype; CK_BBOOL flag; CK_RV rc; + int check; + CK_ULONG strength = POLICY_STRENGTH_IDX_0; if (!sess) { TRACE_ERROR("Invalid function arguments.\n"); @@ -71,6 +77,7 @@ rc = CKR_KEY_FUNCTION_NOT_PERMITTED; goto done; } + check = POLICY_CHECK_DECRYPT; } else if (operation == OP_UNWRAP) { rc = object_mgr_find_in_map1(tokdata, key_handle, &key_obj, READ_LOCK); if (rc != CKR_OK) { @@ -93,12 +100,22 @@ rc = CKR_KEY_FUNCTION_NOT_PERMITTED; goto done; } + check = POLICY_CHECK_UNWRAP; } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); rc = CKR_FUNCTION_FAILED; goto done; } + if (checkpolicy) { + rc = tokdata->policy->is_mech_allowed(tokdata->policy, mech, + &key_obj->strength, check, sess); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: decrypt/unwrap init\n"); + goto done; + } + } + if (!key_object_is_mechanism_allowed(key_obj->template, mech->mechanism)) { TRACE_ERROR("Mechanism not allwed per CKA_ALLOWED_MECHANISMS.\n"); rc = CKR_MECHANISM_INVALID; @@ -540,6 +557,12 @@ } memset(ctx->context, 0x0, sizeof(AES_GCM_CONTEXT)); + strength = key_obj->strength.strength; + + /* Release obj lock, token specific aes-gcm may re-acquire the lock */ + object_put(tokdata, key_obj, TRUE); + key_obj = NULL; + rc = aes_gcm_init(tokdata, sess, ctx, mech, key_handle, 0); if (rc) { TRACE_ERROR("Could not initialize AES_GCM parms.\n"); @@ -608,6 +631,9 @@ rc = CKR_OK; done: + if (ctx->count_statistics == TRUE && rc == CKR_OK) + INC_COUNTER(tokdata, sess, mech, key_obj, strength); + object_put(tokdata, key_obj, TRUE); key_obj = NULL; @@ -616,7 +642,8 @@ // // -CK_RV decr_mgr_cleanup(ENCR_DECR_CONTEXT *ctx) +CK_RV decr_mgr_cleanup(STDLL_TokData_t *tokdata, SESSION *sess, + ENCR_DECR_CONTEXT *ctx) { if (!ctx) { TRACE_ERROR("Invalid function argument.\n"); @@ -631,6 +658,8 @@ ctx->init_pending = FALSE; ctx->context_len = 0; ctx->pkey_active = FALSE; + ctx->state_unsaveable = FALSE; + ctx->count_statistics = FALSE; if (ctx->mech.pParameter) { free(ctx->mech.pParameter); @@ -638,9 +667,14 @@ } if (ctx->context) { - free(ctx->context); + if (ctx->context_free_func != NULL) + ctx->context_free_func(tokdata, sess, ctx->context, + ctx->context_len); + else + free(ctx->context); ctx->context = NULL; } + ctx->context_free_func = NULL; return CKR_OK; } diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/defs.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/defs.h --- opencryptoki-3.16.0+dfsg/usr/lib/common/defs.h 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/defs.h 2022-02-02 15:05:41.000000000 +0100 @@ -17,6 +17,20 @@ #ifndef _DEFS_H #define _DEFS_H +#include + +#ifndef OPENSSL_VERSION_PREREQ + #if defined(OPENSSL_VERSION_MAJOR) && defined(OPENSSL_VERSION_MINOR) + #define OPENSSL_VERSION_PREREQ(maj, min) \ + ((OPENSSL_VERSION_MAJOR << 16) + \ + OPENSSL_VERSION_MINOR >= ((maj) << 16) + (min)) + #else + #define OPENSSL_VERSION_PREREQ(maj, min) \ + (OPENSSL_VERSION_NUMBER >= (((maj) << 28) | \ + ((min) << 20))) + #endif +#endif + #define MAX_SESSION_COUNT 64 #define MAX_PIN_LEN 8 #define MIN_PIN_LEN 4 @@ -79,7 +93,7 @@ #define ENCRYPT 1 #define DECRYPT 0 -#define MAX_RSA_KEYLEN 1920 +#define MAX_RSA_KEYLEN (OPENSSL_RSA_MAX_MODULUS_BITS / 8) #define AES_KEY_SIZE_256 32 #define AES_KEY_SIZE_192 24 diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/dig_mgr.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/dig_mgr.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/dig_mgr.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/dig_mgr.c 2022-02-02 15:05:41.000000000 +0100 @@ -23,12 +23,13 @@ #include "h_extern.h" #include "tok_spec_struct.h" #include "trace.h" - +#include "../api/statistics.h" // // CK_RV digest_mgr_init(STDLL_TokData_t *tokdata, - SESSION *sess, DIGEST_CONTEXT *ctx, CK_MECHANISM *mech) + SESSION *sess, DIGEST_CONTEXT *ctx, CK_MECHANISM *mech, + CK_BBOOL checkpolicy) { CK_RV rc = CKR_OK; CK_BYTE *ptr = NULL; @@ -41,6 +42,16 @@ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); return CKR_OPERATION_ACTIVE; } + if (checkpolicy) { + rc = tokdata->policy->is_mech_allowed(tokdata->policy, mech, + NULL, POLICY_CHECK_DIGEST, sess); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: digest init\n"); + return rc; + } + } + + // is the mechanism supported? is the parameter present if required? // switch (mech->mechanism) { @@ -63,7 +74,7 @@ ctx->context = NULL; rc = sha_init(tokdata, sess, ctx, mech); if (rc != CKR_OK) { - digest_mgr_cleanup(ctx); // to de-initialize context above + digest_mgr_cleanup(tokdata, sess, ctx); // to de-initialize context above TRACE_ERROR("Failed to init sha context.\n"); return rc; } @@ -76,7 +87,7 @@ ctx->context_len = sizeof(MD2_CONTEXT); ctx->context = (CK_BYTE *) malloc(sizeof(MD2_CONTEXT)); if (!ctx->context) { - digest_mgr_cleanup(ctx); // to de-initialize context above + digest_mgr_cleanup(tokdata, sess, ctx); // to de-initialize context above TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } @@ -90,7 +101,7 @@ ctx->context = NULL; rc = md5_init(tokdata, sess, ctx, mech); if (rc != CKR_OK) { - digest_mgr_cleanup(ctx); // to de-initialize context above + digest_mgr_cleanup(tokdata, sess, ctx); // to de-initialize context above TRACE_ERROR("Failed to init md5 context.\n"); return rc; } @@ -103,7 +114,7 @@ if (mech->ulParameterLen > 0 && mech->pParameter != NULL) { ptr = (CK_BYTE *) malloc(mech->ulParameterLen); if (!ptr) { - digest_mgr_cleanup(ctx); // to de-initialize context above + digest_mgr_cleanup(tokdata, sess, ctx); // to de-initialize context above TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } @@ -116,13 +127,17 @@ ctx->multi = FALSE; ctx->active = TRUE; + if (ctx->count_statistics == TRUE) + INC_COUNTER(tokdata, sess, mech, NULL, POLICY_STRENGTH_IDX_0); + return CKR_OK; } // // -CK_RV digest_mgr_cleanup(DIGEST_CONTEXT *ctx) +CK_RV digest_mgr_cleanup(STDLL_TokData_t *tokdata, SESSION *sess, + DIGEST_CONTEXT *ctx) { if (!ctx) { TRACE_ERROR("Invalid function argument.\n"); @@ -134,6 +149,8 @@ ctx->multi = FALSE; ctx->active = FALSE; ctx->context_len = 0; + ctx->state_unsaveable = FALSE; + ctx->count_statistics = FALSE; if (ctx->mech.pParameter) { free(ctx->mech.pParameter); @@ -141,9 +158,14 @@ } if (ctx->context != NULL) { - free(ctx->context); + if (ctx->context_free_func != NULL) + ctx->context_free_func(tokdata, sess, ctx->context, + ctx->context_len); + else + free(ctx->context); ctx->context = NULL; } + ctx->context_free_func = NULL; return CKR_OK; } @@ -232,7 +254,7 @@ // unless it returns CKR_BUFFER_TOO_SMALL or is a successful call (i.e., // one which returns CKR_OK) to determine the length of the buffer // needed to hold the message digest." - digest_mgr_cleanup(ctx); + digest_mgr_cleanup(tokdata, sess, ctx); } return rc; @@ -301,7 +323,7 @@ out: if (rc != CKR_OK) { - digest_mgr_cleanup(ctx); + digest_mgr_cleanup(tokdata, sess, ctx); // "A call to C_DigestUpdate which results in an error // terminates the current digest operation." } @@ -373,7 +395,7 @@ out: if (rc != CKR_OK) { - digest_mgr_cleanup(ctx); + digest_mgr_cleanup(tokdata, sess, ctx); } object_put(tokdata, key_obj, TRUE); @@ -451,7 +473,7 @@ // operation unless it returns CKR_BUFFER_TOO_SMALL or is a successful // call (i.e., one which returns CKR_OK) to determine the length of the // buffer needed to hold the message digest." - digest_mgr_cleanup(ctx); + digest_mgr_cleanup(tokdata, sess, ctx); } return rc; diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/dlist.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/dlist.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/dlist.c 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/dlist.c 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,218 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ + +#include +#include +#include +#include +#include +#include + +#include "dlist.h" +#include "host_defs.h" +#include "h_extern.h" + + +// Function: dlist_add_as_first() +// +// Adds the specified node to the start of the list +// +// Returns: pointer to the start of the list +// +DL_NODE *dlist_add_as_first(DL_NODE *list, void *data) +{ + DL_NODE *node = NULL; + + if (!data) + return list; + + node = (DL_NODE *) malloc(sizeof(DL_NODE)); + if (!node) + return NULL; + + node->data = data; + node->prev = NULL; + node->next = list; + if (list) + list->prev = node; + + return node; +} + +// Function: dlist_add_as_last() +// +// Adds the specified node to the end of the list +// +// Returns: pointer to the start of the list +// +DL_NODE *dlist_add_as_last(DL_NODE *list, void *data) +{ + DL_NODE *node = NULL; + + if (!data) + return list; + + node = (DL_NODE *) malloc(sizeof(DL_NODE)); + if (!node) + return NULL; + + node->data = data; + node->next = NULL; + + if (!list) { + node->prev = NULL; + return node; + } else { + DL_NODE *temp = dlist_get_last(list); + temp->next = node; + node->prev = temp; + + return list; + } +} + +// Function: dlist_find() +// +DL_NODE *dlist_find(DL_NODE *list, void *data) +{ + DL_NODE *node = list; + + while (node && node->data != data) + node = node->next; + + return node; +} + +// Function: dlist_get_first() +// +// Returns the last node in the list or NULL if list is empty +// +DL_NODE *dlist_get_first(DL_NODE *list) +{ + DL_NODE *temp = list; + + if (!list) + return NULL; + + while (temp->prev != NULL) + temp = temp->prev; + + return temp; +} + +// Function: dlist_get_last() +// +// Returns the last node in the list or NULL if list is empty +// +DL_NODE *dlist_get_last(DL_NODE *list) +{ + DL_NODE *temp = list; + + if (!list) + return NULL; + + while (temp->next != NULL) + temp = temp->next; + + return temp; +} + +// +// +CK_ULONG dlist_length(DL_NODE *list) +{ + DL_NODE *temp = list; + CK_ULONG len = 0; + + while (temp) { + len++; + temp = temp->next; + } + + return len; +} + +// +// +DL_NODE *dlist_next(DL_NODE *node) +{ + if (!node) + return NULL; + + return node->next; +} + +// +// +DL_NODE *dlist_prev(DL_NODE *node) +{ + if (!node) + return NULL; + + return node->prev; +} + +// +// +void dlist_purge(DL_NODE *list) +{ + DL_NODE *node; + + if (!list) + return; + + do { + node = list->next; + free(list); + list = node; + } while (list); +} + +// Function: dlist_remove_node() +// +// Attempts to remove the specified node from the list. The caller is +// responsible for freeing the data associated with the node prior to +// calling this routine +// +DL_NODE *dlist_remove_node(DL_NODE *list, DL_NODE *node) +{ + DL_NODE *temp = list; + + if (!list || !node) + return NULL; + + // special case: removing head of the list + // + if (list == node) { + temp = list->next; + if (temp) + temp->prev = NULL; + + free(list); + return temp; + } + // we have no guarantee that the node is in the list + // so search through the list to find it + // + while ((temp != NULL) && (temp->next != node)) + temp = temp->next; + + if (temp != NULL) { + DL_NODE *next = node->next; + + temp->next = next; + if (next) + next->prev = temp; + + free(node); + } + + return list; +} diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/dlist.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/dlist.h --- opencryptoki-3.16.0+dfsg/usr/lib/common/dlist.h 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/dlist.h 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,32 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ + + + +#ifndef _DLIST_H_ +#define _DLIST_H_ + +#include "pkcs11types.h" +#include "defs.h" + +// linked-list routines +// +DL_NODE *dlist_add_as_first(DL_NODE *list, void *data); +DL_NODE *dlist_add_as_last(DL_NODE *list, void *data); +DL_NODE *dlist_find(DL_NODE *list, void *data); +DL_NODE *dlist_get_first(DL_NODE *list); +DL_NODE *dlist_get_last(DL_NODE *list); +CK_ULONG dlist_length(DL_NODE *list); +DL_NODE *dlist_next(DL_NODE *list); +DL_NODE *dlist_prev(DL_NODE *list); +void dlist_purge(DL_NODE *list); +DL_NODE *dlist_remove_node(DL_NODE *list, DL_NODE *node); + +#endif diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/ec_curve_translation.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/ec_curve_translation.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/ec_curve_translation.c 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/ec_curve_translation.c 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,69 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ + +#include +#include +#include +#include +#include +#include "ec_defs.h" + +static int get_curve_index(const char *str) +{ + /* Keep in sync with the order in der_ec_supported */ + static const struct nameidxmapping { + const char *name; + int idx; + } mappings[] = { + { "BRAINPOOL_P160R1", 0 }, + { "BRAINPOOL_P160T1", 1 }, + { "BRAINPOOL_P192R1", 2 }, + { "BRAINPOOL_P192T1", 3 }, + { "BRAINPOOL_P224R1", 4 }, + { "BRAINPOOL_P224T1", 5 }, + { "BRAINPOOL_P256R1", 6 }, + { "BRAINPOOL_P256T1", 7 }, + { "BRAINPOOL_P320R1", 8 }, + { "BRAINPOOL_P320T1", 9 }, + { "BRAINPOOL_P384R1", 10 }, + { "BRAINPOOL_P384T1", 11 }, + { "BRAINPOOL_P512R1", 12 }, + { "BRAINPOOL_P512T1", 13 }, + { "PRIME192V1", 14 }, + { "SECP224R1", 15 }, + { "PRIME256V1", 16 }, + { "SECP384R1", 17 }, + { "SECP521R1", 18 }, + { "SECP256K1", 19 }, + { "CURVE25519", 20 }, + { "CURVE448", 21 }, + { "ED25519", 22 }, + { "ED448", 23 }, + }; + size_t i; + + for (i = 0; i < sizeof(mappings) / sizeof(struct nameidxmapping); ++i) { + if (strcmp(mappings[i].name, str) == 0) + return i; + } + return -1; +} + +CK_RV translate_string_to_curve(const char *str, size_t len, + const struct _ec **curve) +{ + (void)len; + int idx = get_curve_index(str); + if (idx >= 0) { + *curve = &der_ec_supported[idx]; + return CKR_OK; + } + return CKR_FUNCTION_FAILED; +} diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/ec_defs.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/ec_defs.h --- opencryptoki-3.16.0+dfsg/usr/lib/common/ec_defs.h 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/ec_defs.h 2022-02-02 15:05:41.000000000 +0100 @@ -11,16 +11,10 @@ #ifndef _EC_DEFS #define _EC_DEFS +#include #include #include "ec_curves.h" -/* OpenSSL compat */ -#if OPENSSL_VERSION_NUMBER < 0x10101000L -# define EC_POINT_get_affine_coordinates EC_POINT_get_affine_coordinates_GFp -# define EC_POINT_set_compressed_coordinates \ - EC_POINT_set_compressed_coordinates_GFp -#endif - // Elliptic Curve type // #define PRIME_CURVE 0x00 @@ -36,6 +30,7 @@ #define CURVE256 0x0100 #define CURVE320 0x0140 #define CURVE384 0x0180 +#define CURVE448 0x01C0 #define CURVE456 0x01C8 #define CURVE512 0x0200 #define CURVE521 0x0209 @@ -72,7 +67,8 @@ struct _ec { uint8_t curve_type; /* uint8_t - prime or brainpool curve */ - uint16_t len_bits; /* uint16_t - len in bits */ + uint16_t len_bits; /* uint16_t - signature len in bits */ + uint16_t prime_bits; /* len of the prime in bits */ int nid; CK_ULONG data_size; void const *data; diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/ec_supported.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/ec_supported.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/ec_supported.c 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/ec_supported.c 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,121 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ +#include "pkcs11types.h" +#include "ec_defs.h" + +#include "openssl/obj_mac.h" +#include + +#ifndef NID_brainpoolP160r1 +/* + * Older OpenSSL versions may not have the brainpool NIDs defined, define them + * here + */ +#define NID_brainpoolP160r1 921 +#define NID_brainpoolP160t1 922 +#define NID_brainpoolP192r1 923 +#define NID_brainpoolP192t1 924 +#define NID_brainpoolP224r1 925 +#define NID_brainpoolP224t1 926 +#define NID_brainpoolP256r1 927 +#define NID_brainpoolP256t1 928 +#define NID_brainpoolP320r1 929 +#define NID_brainpoolP320t1 930 +#define NID_brainpoolP384r1 931 +#define NID_brainpoolP384t1 932 +#define NID_brainpoolP512r1 933 +#define NID_brainpoolP512t1 934 + +#endif + +#ifndef NID_X25519 +#define NID_X25519 1034 +#define NID_X448 1035 +#endif +#ifndef NID_ED25519 +#define NID_ED25519 1087 +#define NID_ED448 1088 +#endif + +const CK_BYTE brainpoolP160r1[] = OCK_BRAINPOOL_P160R1; +const CK_BYTE brainpoolP160t1[] = OCK_BRAINPOOL_P160T1; +const CK_BYTE brainpoolP192r1[] = OCK_BRAINPOOL_P192R1; +const CK_BYTE brainpoolP192t1[] = OCK_BRAINPOOL_P192T1; +const CK_BYTE brainpoolP224r1[] = OCK_BRAINPOOL_P224R1; +const CK_BYTE brainpoolP224t1[] = OCK_BRAINPOOL_P224T1; +const CK_BYTE brainpoolP256r1[] = OCK_BRAINPOOL_P256R1; +const CK_BYTE brainpoolP256t1[] = OCK_BRAINPOOL_P256T1; +const CK_BYTE brainpoolP320r1[] = OCK_BRAINPOOL_P320R1; +const CK_BYTE brainpoolP320t1[] = OCK_BRAINPOOL_P320T1; +const CK_BYTE brainpoolP384r1[] = OCK_BRAINPOOL_P384R1; +const CK_BYTE brainpoolP384t1[] = OCK_BRAINPOOL_P384T1; +const CK_BYTE brainpoolP512r1[] = OCK_BRAINPOOL_P512R1; +const CK_BYTE brainpoolP512t1[] = OCK_BRAINPOOL_P512T1; +const CK_BYTE prime192v1[] = OCK_PRIME192V1; +const CK_BYTE secp224r1[] = OCK_SECP224R1; +const CK_BYTE prime256v1[] = OCK_PRIME256V1; +const CK_BYTE secp384r1[] = OCK_SECP384R1; +const CK_BYTE secp521r1[] = OCK_SECP521R1; +const CK_BYTE secp256k1[] = OCK_SECP256K1; +const CK_BYTE curve25519[] = OCK_CURVE25519; +const CK_BYTE curve448[] = OCK_CURVE448; +const CK_BYTE ed25519[] = OCK_ED25519; +const CK_BYTE ed448[] = OCK_ED448; + +const struct _ec der_ec_supported[NUMEC] = { + {BRAINPOOL_CURVE, CURVE160, CURVE160, NID_brainpoolP160r1, + sizeof(brainpoolP160r1), &brainpoolP160r1}, + {BRAINPOOL_CURVE, CURVE160, CURVE160, NID_brainpoolP160t1, + sizeof(brainpoolP160t1), &brainpoolP160t1}, + {BRAINPOOL_CURVE, CURVE192, CURVE192, NID_brainpoolP192r1, + sizeof(brainpoolP192r1), &brainpoolP192r1}, + {BRAINPOOL_CURVE, CURVE192, CURVE192, NID_brainpoolP192t1, + sizeof(brainpoolP192t1), &brainpoolP192t1}, + {BRAINPOOL_CURVE, CURVE224, CURVE224, NID_brainpoolP224r1, + sizeof(brainpoolP224r1), &brainpoolP224r1}, + {BRAINPOOL_CURVE, CURVE224, CURVE224, NID_brainpoolP224t1, + sizeof(brainpoolP224t1), &brainpoolP224t1}, + {BRAINPOOL_CURVE, CURVE256, CURVE256, NID_brainpoolP256r1, + sizeof(brainpoolP256r1), &brainpoolP256r1}, + {BRAINPOOL_CURVE, CURVE256, CURVE256, NID_brainpoolP256t1, + sizeof(brainpoolP256t1), &brainpoolP256t1}, + {BRAINPOOL_CURVE, CURVE320, CURVE320, NID_brainpoolP320r1, + sizeof(brainpoolP320r1), &brainpoolP320r1}, + {BRAINPOOL_CURVE, CURVE320, CURVE320, NID_brainpoolP320t1, + sizeof(brainpoolP320t1), &brainpoolP320t1}, + {BRAINPOOL_CURVE, CURVE384, CURVE384, NID_brainpoolP384r1, + sizeof(brainpoolP384r1), &brainpoolP384r1}, + {BRAINPOOL_CURVE, CURVE384, CURVE384, NID_brainpoolP384t1, + sizeof(brainpoolP384t1), &brainpoolP384t1}, + {BRAINPOOL_CURVE, CURVE512, CURVE512, NID_brainpoolP512r1, + sizeof(brainpoolP512r1), &brainpoolP512r1}, + {BRAINPOOL_CURVE, CURVE512, CURVE512, NID_brainpoolP512t1, + sizeof(brainpoolP512t1), &brainpoolP512t1}, + {PRIME_CURVE, CURVE192, CURVE192, NID_X9_62_prime192v1, + sizeof(prime192v1), &prime192v1}, + {PRIME_CURVE, CURVE224, CURVE224, NID_secp224r1, + sizeof(secp224r1), &secp224r1}, + {PRIME_CURVE, CURVE256, CURVE256, NID_X9_62_prime256v1, + sizeof(prime256v1), &prime256v1}, + {PRIME_CURVE, CURVE384, CURVE384, NID_secp384r1, + sizeof(secp384r1), &secp384r1}, + {PRIME_CURVE, CURVE521, CURVE521, NID_secp521r1, + sizeof(secp521r1), &secp521r1}, + {PRIME_CURVE, CURVE256, CURVE256, NID_secp256k1, + sizeof(secp256k1), &secp256k1}, + {MONTGOMERY_CURVE, CURVE256, CURVE256, NID_X25519, + sizeof(curve25519), &curve25519}, + {MONTGOMERY_CURVE, CURVE456, CURVE448, NID_X448, + sizeof(curve448), &curve448}, + {EDWARDS_CURVE, CURVE256, CURVE256, NID_ED25519, + sizeof(ed25519), &ed25519}, + {EDWARDS_CURVE, CURVE456, CURVE448, NID_ED448, + sizeof(ed448), &ed448}, +}; diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/encr_mgr.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/encr_mgr.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/encr_mgr.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/encr_mgr.c 2022-02-02 15:05:41.000000000 +0100 @@ -24,6 +24,9 @@ #include "tok_spec_struct.h" #include "trace.h" +#include "../api/policy.h" +#include "../api/statistics.h" + #include // @@ -32,14 +35,16 @@ SESSION *sess, ENCR_DECR_CONTEXT *ctx, CK_ULONG operation, - CK_MECHANISM *mech, CK_OBJECT_HANDLE key_handle) + CK_MECHANISM *mech, CK_OBJECT_HANDLE key_handle, + CK_BBOOL checkpolicy) { OBJECT *key_obj = NULL; CK_BYTE *ptr = NULL; CK_KEY_TYPE keytype; CK_BBOOL flag; CK_RV rc; - + int check; + CK_ULONG strength = POLICY_STRENGTH_IDX_0; if (!sess || !ctx || !mech) { TRACE_ERROR("Invalid function arguments.\n"); @@ -74,6 +79,7 @@ rc = CKR_KEY_FUNCTION_NOT_PERMITTED; goto done; } + check = POLICY_CHECK_ENCRYPT; } else if (operation == OP_WRAP) { rc = object_mgr_find_in_map1(tokdata, key_handle, &key_obj, READ_LOCK); if (rc != CKR_OK) { @@ -97,12 +103,21 @@ rc = CKR_KEY_FUNCTION_NOT_PERMITTED; goto done; } + check = POLICY_CHECK_WRAP; } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); rc = CKR_FUNCTION_FAILED; goto done; } + if (checkpolicy) { + rc = tokdata->policy->is_mech_allowed(tokdata->policy, mech, + &key_obj->strength, check, sess); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: encrypt/wrap init\n"); + goto done; + } + } if (!key_object_is_mechanism_allowed(key_obj->template, mech->mechanism)) { TRACE_ERROR("Mechanism not allwed per CKA_ALLOWED_MECHANISMS.\n"); rc = CKR_MECHANISM_INVALID; @@ -537,6 +552,12 @@ } memset(ctx->context, 0x0, sizeof(AES_GCM_CONTEXT)); + strength = key_obj->strength.strength; + + /* Release obj lock, token specific aes-gcm may re-acquire the lock */ + object_put(tokdata, key_obj, TRUE); + key_obj = NULL; + rc = aes_gcm_init(tokdata, sess, ctx, mech, key_handle, 1); if (rc != CKR_OK) { TRACE_ERROR("Could not initialize AES_GCM parms.\n"); @@ -605,6 +626,9 @@ rc = CKR_OK; done: + if (ctx->count_statistics == TRUE && rc == CKR_OK) + INC_COUNTER(tokdata, sess, mech, key_obj, strength); + object_put(tokdata, key_obj, TRUE); key_obj = NULL; @@ -613,7 +637,8 @@ // // -CK_RV encr_mgr_cleanup(ENCR_DECR_CONTEXT *ctx) +CK_RV encr_mgr_cleanup(STDLL_TokData_t *tokdata, SESSION *sess, + ENCR_DECR_CONTEXT *ctx) { if (!ctx) { TRACE_ERROR("Invalid function argument.\n"); @@ -628,6 +653,8 @@ ctx->init_pending = FALSE; ctx->context_len = 0; ctx->pkey_active = FALSE; + ctx->state_unsaveable = FALSE; + ctx->count_statistics = FALSE; if (ctx->mech.pParameter) { free(ctx->mech.pParameter); @@ -635,9 +662,14 @@ } if (ctx->context) { - free(ctx->context); + if (ctx->context_free_func != NULL) + ctx->context_free_func(tokdata, sess, ctx->context, + ctx->context_len); + else + free(ctx->context); ctx->context = NULL; } + ctx->context_free_func = NULL; return CKR_OK; } @@ -1098,6 +1130,20 @@ rc = CKR_KEY_HANDLE_INVALID; goto done; } + rc = tokdata->policy->is_mech_allowed(tokdata->policy, decr_mech, + &decr_key_obj->strength, + POLICY_CHECK_DECRYPT, sess); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Reencrypt_single decryption\n"); + goto done; + } + rc = tokdata->policy->is_mech_allowed(tokdata->policy, encr_mech, + &encr_key_obj->strength, + POLICY_CHECK_ENCRYPT, sess); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Reencrypt_single encryption\n"); + goto done; + } if (!key_object_is_mechanism_allowed(decr_key_obj->template, decr_mech->mechanism)) { @@ -1152,18 +1198,25 @@ if (rc != CKR_OK) TRACE_DEVEL("Token specific reencrypt single failed.\n"); + if (decr_ctx->count_statistics == TRUE && rc == CKR_OK) + INC_COUNTER(tokdata, sess, decr_mech, decr_key_obj, + POLICY_STRENGTH_IDX_0); + if (encr_ctx->count_statistics == TRUE && rc == CKR_OK) + INC_COUNTER(tokdata, sess, encr_mech, encr_key_obj, + POLICY_STRENGTH_IDX_0); + goto done; } /* No token specific reencrypt_single function, perform it manually */ - + /* Enforces policy */ rc = decr_mgr_init(tokdata, sess, decr_ctx, OP_DECRYPT_INIT, decr_mech, - decr_key); + decr_key, TRUE); if (rc != CKR_OK) goto done; - + /* Enforces Policy */ rc = encr_mgr_init(tokdata, sess, encr_ctx, OP_ENCRYPT_INIT, encr_mech, - encr_key); + encr_key, TRUE); if (rc != CKR_OK) goto done; @@ -1200,8 +1253,8 @@ free(decr_data); } - decr_mgr_cleanup(decr_ctx); - encr_mgr_cleanup(encr_ctx); + decr_mgr_cleanup(tokdata, sess, decr_ctx); + encr_mgr_cleanup(tokdata, sess, encr_ctx); return rc; } diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/event_client.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/event_client.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/event_client.c 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/event_client.c 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,217 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "slotmgr.h" +#include "event_client.h" + +static int connect_socket(const char *file_path) +{ + int socketfd; + struct sockaddr_un daemon_address; + struct stat file_info; + struct group *grp; + int rc; + + if (stat(file_path, &file_info)) + return -errno; + + grp = getgrnam("pkcs11"); + if (!grp) + return -errno; + + if (file_info.st_uid != 0 || file_info.st_gid != grp->gr_gid) + return -EPERM; + + if ((socketfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) + return -errno; + + memset(&daemon_address, 0, sizeof(struct sockaddr_un)); + daemon_address.sun_family = AF_UNIX; + strncpy(daemon_address.sun_path, file_path, + sizeof(daemon_address.sun_path)); + daemon_address.sun_path[sizeof(daemon_address.sun_path) - 1] = '\0'; + + if (connect(socketfd, (struct sockaddr *) &daemon_address, + sizeof(struct sockaddr_un)) != 0) { + rc = -errno; + goto error; + } + + return socketfd; + +error: + close(socketfd); + return rc; +} + +static ssize_t read_all(int socketfd, char *buffer, size_t size) +{ + size_t bytes_received = 0; + ssize_t n; + + while (bytes_received < size) { + n = read(socketfd, buffer + bytes_received, size - bytes_received); + if (n < 0) { + // read error + if (errno == EINTR) + continue; + return -errno; + } + if (n == 0) + break; + + bytes_received += n; + } + + return bytes_received; +} + +static ssize_t send_all(int socketfd, char *buffer, size_t size) +{ + size_t bytes_sent = 0; + ssize_t n; + + while (bytes_sent < size) { + n = send(socketfd, buffer + bytes_sent, size - bytes_sent, 0); + if (n < 0) { + // send error + if (errno == EINTR) + continue; + return -errno; + } + if (n == 0) + break; + + bytes_sent += n; + } + + return bytes_sent; +} + +/* + * Initialize an admin connection to the pkcsslotd. + * Returns a file descriptor representing the connection, or a negative errno + * in case of an error. + */ +int init_event_client() +{ + int fd; + + fd = connect_socket(ADMIN_SOCKET_FILE_PATH); + + return fd; +} + +/* + * Send an event though the admin connection to the pkcsslotd, and thus to + * all active token instances. + * If parameter fd is < 0, then a connection to pkcsslotd is established + * inside the function and closed before return. This is for a one shot event. + * Otherwise, pass a file descriptor received from init_event_client(). This + * is to send multiple events. + * Event type is mandatory, flags can be zero. + * The event payload is optional, if payload_len is non-zero, then payload must + * point to a buffer containing the payload to send with the event. + * The event destination can be used to selectively send the event to certain + * token instances only. If destination is NULL, it is sent to all token + * instances. + * If flag EVENT_FLAGS_REPLY_REQ is on in the flags parameter, then it is waited + * until all active token instances have replied. The combined result of the + * replies from the token instances is returned in the reply structure. + * Parameter reply must be non-NULL if flag EVENT_FLAGS_REPLY_REQ is set. + * Returns zero for success, or a negative errno in case of an error. In most + * error cases the connection to the pkcsslotd is out of sequence and can no + * longer be used to send further events. + */ +int send_event(int fd, unsigned int type, unsigned int flags, + unsigned int payload_len, const char *payload, + const struct event_destination *destination, + struct event_reply *reply) +{ + event_msg_t event_msg; + event_reply_t event_reply; + int rc, term = 0; + + if (payload_len > 0 && payload == NULL) + return -EINVAL; + if ((flags & EVENT_FLAGS_REPLY_REQ) && reply == NULL) + return -EINVAL; + if (payload_len > EVENT_MAX_PAYLOAD_LENGTH) + return -EMSGSIZE; + + if (fd < 0) { + fd = init_event_client(); + if (fd < 0) + return fd; + term = 1; + } + + memset(&event_msg, 0, sizeof(event_msg)); + event_msg.version = EVENT_VERSION_1; + event_msg.type = type; + event_msg.flags = flags; + if (destination != NULL) { + event_msg.token_type = destination->token_type; + memcpy(event_msg.token_label, destination->token_label, + sizeof(event_msg.token_label)); + event_msg.process_id = destination->process_id; + } else { + memset(event_msg.token_label, ' ', sizeof(event_msg.token_label)); + } + event_msg.payload_len = payload_len; + + rc = send_all(fd, (char *)&event_msg, sizeof(event_msg)); + if (rc < 0) + goto out; + + if (payload_len > 0) { + rc = send_all(fd, (char *)payload, payload_len); + if (rc < 0) + goto out; + } + + if (flags & EVENT_FLAGS_REPLY_REQ) { + rc = read_all(fd, (char *)&event_reply, sizeof(event_reply)); + if (rc < 0) + goto out; + + reply->positive_replies = event_reply.positive_replies; + reply->negative_replies = event_reply.negative_replies; + reply->nothandled_replies = event_reply.nothandled_replies; + } + + rc = 0; + +out: + if (term) + term_event_client(fd); + + return rc; +} + +/* + * Terminate the admin connection to the pkcsslotd. + */ +void term_event_client(int fd) +{ + if (fd >= 0) + close(fd); +} + diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/event_client.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/event_client.h --- opencryptoki-3.16.0+dfsg/usr/lib/common/event_client.h 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/event_client.h 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,39 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ + + +#ifndef _EVENT_CLIENT_H_ +#define _EVENT_CLIENT_H_ + +#include "events.h" + +struct event_destination { + unsigned int token_type; /* Destination token type: EVENT_TOK_TYPE_xxx */ + char token_label[member_size(event_msg_t, token_label)]; + /* Label of destination token (or blanks) */ + pid_t process_id; /* Process ID of destination process (or 0) */ +}; + +struct event_reply { + unsigned long positive_replies; + unsigned long negative_replies; + unsigned long nothandled_replies; +}; + +int init_event_client(); + +int send_event(int fd, unsigned int type, unsigned int flags, + unsigned int payload_len, const char *payload, + const struct event_destination *destination, + struct event_reply *reply); + +void term_event_client(int fd); + +#endif diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/h_extern.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/h_extern.h --- opencryptoki-3.16.0+dfsg/usr/lib/common/h_extern.h 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/h_extern.h 2022-02-02 15:05:41.000000000 +0100 @@ -24,6 +24,13 @@ #define _H_EXTERN_H #include +#include "dlist.h" +#include "host_defs.h" + +#include + +/* Forward declaration to keep dependencies as small as possible. */ +struct policy; // global variables // @@ -450,6 +457,11 @@ void copy_token_contents_sensibly(CK_TOKEN_INFO_PTR pInfo, TOKEN_DATA *nv_token_data); +CK_RV compute_PKCS5_PBKDF2_HMAC(STDLL_TokData_t *tokdata, + CK_CHAR *pPin, CK_ULONG ulPinLen, + CK_BYTE *salt, CK_ULONG salt_len, + CK_ULONG it_count, const EVP_MD *digest, + CK_ULONG key_len, CK_BYTE *key); CK_RV compute_md5(STDLL_TokData_t *tokdata, CK_BYTE *data, CK_ULONG len, CK_BYTE *hash); CK_RV compute_sha1(STDLL_TokData_t *tokdata, CK_BYTE *data, CK_ULONG len, @@ -723,6 +735,8 @@ CK_BYTE *out_data, CK_ULONG *out_data_len, CK_ULONG type); +CK_RV get_mgf_mech(CK_RSA_PKCS_MGF_TYPE mgf, CK_MECHANISM_TYPE *mech); + // RSA mechanisms // CK_RV ckm_rsa_key_pair_gen(STDLL_TokData_t *tokdata, TEMPLATE *publ_tmpl, @@ -825,10 +839,12 @@ // DH mechanisms // CK_RV ckm_dh_pkcs_derive(STDLL_TokData_t *tokdata, + SESSION *sess, CK_VOID_PTR other_pubkey, CK_ULONG other_pubkey_len, CK_OBJECT_HANDLE base_key, - CK_BYTE *secret, CK_ULONG *secret_len); + CK_BYTE *secret, CK_ULONG *secret_len, + CK_MECHANISM_PTR mech); CK_RV ckm_dh_key_pair_gen(STDLL_TokData_t *tokdata, TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl); @@ -838,6 +854,8 @@ #endif /* End code contributed by Corrent corp. */ +CK_RV digest_from_kdf(CK_EC_KDF_TYPE kdf, CK_MECHANISM_TYPE *mech); + CK_RV pkcs_get_keytype(CK_ATTRIBUTE *attrs, CK_ULONG attrs_len, CK_MECHANISM_PTR mech, CK_ULONG *type, CK_ULONG *class); @@ -1542,7 +1560,7 @@ // SHA mechanisms // -void sw_sha1_init(DIGEST_CONTEXT *ctx); +CK_RV sw_sha1_init(DIGEST_CONTEXT *ctx); CK_RV sw_sha1_hash(DIGEST_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, @@ -1666,7 +1684,7 @@ CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG sig_len); -void sw_md5_init(DIGEST_CONTEXT *ctx); +CK_RV sw_md5_init(DIGEST_CONTEXT *ctx); CK_RV sw_md5_hash(DIGEST_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, @@ -1759,26 +1777,12 @@ CK_BBOOL *allocated, CK_BYTE **ec_point, CK_ULONG *ec_point_len); -// linked-list routines -// -DL_NODE *dlist_add_as_first(DL_NODE *list, void *data); -DL_NODE *dlist_add_as_last(DL_NODE *list, void *data); -DL_NODE *dlist_find(DL_NODE *list, void *data); -DL_NODE *dlist_get_first(DL_NODE *list); -DL_NODE *dlist_get_last(DL_NODE *list); -CK_ULONG dlist_length(DL_NODE *list); -DL_NODE *dlist_next(DL_NODE *list); -DL_NODE *dlist_prev(DL_NODE *list); -void dlist_purge(DL_NODE *list); -DL_NODE *dlist_remove_node(DL_NODE *list, DL_NODE *node); - CK_RV attach_shm(STDLL_TokData_t *tokdata, CK_SLOT_ID slot_id); CK_RV detach_shm(STDLL_TokData_t *tokdata, CK_BBOOL ignore_ref_count); //get keytype CK_RV get_keytype(STDLL_TokData_t *tokdata, CK_OBJECT_HANDLE hkey, CK_KEY_TYPE *keytype); -CK_RV check_user_and_group(); //lock and unlock routines CK_RV XProcLock(STDLL_TokData_t *tokdata); @@ -1800,9 +1804,11 @@ SESSION *sess, ENCR_DECR_CONTEXT *ctx, CK_ULONG operation, - CK_MECHANISM *mech, CK_OBJECT_HANDLE key_handle); + CK_MECHANISM *mech, CK_OBJECT_HANDLE key_handle, + CK_BBOOL checkpolicy); -CK_RV encr_mgr_cleanup(ENCR_DECR_CONTEXT *ctx); +CK_RV encr_mgr_cleanup(STDLL_TokData_t *tokdata, SESSION *sess, + ENCR_DECR_CONTEXT *ctx); CK_RV encr_mgr_encrypt(STDLL_TokData_t *tokdata, SESSION *sess, CK_BBOOL length_only, @@ -1835,9 +1841,11 @@ SESSION *sess, ENCR_DECR_CONTEXT *ctx, CK_ULONG operation, - CK_MECHANISM *mech, CK_OBJECT_HANDLE key_handle); + CK_MECHANISM *mech, CK_OBJECT_HANDLE key_handle, + CK_BBOOL checkpolicy); -CK_RV decr_mgr_cleanup(ENCR_DECR_CONTEXT *ctx); +CK_RV decr_mgr_cleanup(STDLL_TokData_t *tokdata, SESSION *sess, + ENCR_DECR_CONTEXT *ctx); CK_RV decr_mgr_decrypt(STDLL_TokData_t *tokdata, SESSION *sess, CK_BBOOL length_only, @@ -1878,11 +1886,13 @@ // digest manager routines // -CK_RV digest_mgr_cleanup(DIGEST_CONTEXT *ctx); +CK_RV digest_mgr_cleanup(STDLL_TokData_t *tokdata, SESSION *sess, + DIGEST_CONTEXT *ctx); CK_RV digest_mgr_init(STDLL_TokData_t *tokdata, SESSION *sess, - DIGEST_CONTEXT *ctx, CK_MECHANISM *mech); + DIGEST_CONTEXT *ctx, CK_MECHANISM *mech, + CK_BBOOL checkpolicy); CK_RV digest_mgr_digest(STDLL_TokData_t *tokdata, SESSION *sess, CK_BBOOL length_only, @@ -1965,9 +1975,11 @@ SESSION *sess, SIGN_VERIFY_CONTEXT *ctx, CK_MECHANISM *mech, - CK_BBOOL recover_mode, CK_OBJECT_HANDLE key_handle); + CK_BBOOL recover_mode, CK_OBJECT_HANDLE key_handle, + CK_BBOOL checkpolicy); -CK_RV sign_mgr_cleanup(SIGN_VERIFY_CONTEXT *ctx); +CK_RV sign_mgr_cleanup(STDLL_TokData_t *tokdata, SESSION *sess, + SIGN_VERIFY_CONTEXT *ctx); CK_RV sign_mgr_sign(STDLL_TokData_t *tokdata, SESSION *sess, @@ -2002,9 +2014,11 @@ SESSION *sess, SIGN_VERIFY_CONTEXT *ctx, CK_MECHANISM *mech, - CK_BBOOL recover_mode, CK_OBJECT_HANDLE key_handle); + CK_BBOOL recover_mode, CK_OBJECT_HANDLE key_handle, + CK_BBOOL checkpolicy); -CK_RV verify_mgr_cleanup(SIGN_VERIFY_CONTEXT *ctx); +CK_RV verify_mgr_cleanup(STDLL_TokData_t *tokdata, SESSION *sess, + SIGN_VERIFY_CONTEXT *ctx); CK_RV verify_mgr_verify(STDLL_TokData_t *tokdata, SESSION *sess, @@ -2039,6 +2053,8 @@ CK_RV session_mgr_new(STDLL_TokData_t *tokdata, CK_ULONG flags, CK_SLOT_ID slot_id, CK_SESSION_HANDLE_PTR phSession); SESSION *session_mgr_find(STDLL_TokData_t *tokdata, CK_SESSION_HANDLE handle); +SESSION *session_mgr_find_reset_error(STDLL_TokData_t *tokdata, + CK_SESSION_HANDLE handle); void session_mgr_put(STDLL_TokData_t *tokdata, SESSION *session); CK_RV session_mgr_login_all(STDLL_TokData_t *tokdata, CK_USER_TYPE user_type); CK_RV session_mgr_logout_all(STDLL_TokData_t *tokdata); @@ -2048,10 +2064,11 @@ CK_BBOOL session_mgr_user_session_exists(STDLL_TokData_t *tokdata); CK_BBOOL session_mgr_public_session_exists(STDLL_TokData_t *tokdata); -CK_RV session_mgr_get_op_state(SESSION *sess, CK_BBOOL length_only, +CK_RV session_mgr_get_op_state(SESSION *sess, + CK_BBOOL length_only, CK_BYTE *data, CK_ULONG *data_len); -CK_RV session_mgr_set_op_state(SESSION *sess, +CK_RV session_mgr_set_op_state(STDLL_TokData_t *tokdata, SESSION *sess, CK_OBJECT_HANDLE encr_key, CK_OBJECT_HANDLE auth_key, CK_BYTE *data, CK_ULONG data_len); @@ -2227,9 +2244,7 @@ CK_ULONG object_get_size(OBJECT *obj); -CK_RV object_restore(CK_BYTE *data, OBJECT **obj, CK_BBOOL replace); - -CK_RV object_restore_withSize(CK_BYTE *data, +CK_RV object_restore_withSize(struct policy *policy, CK_BYTE *data, OBJECT **obj, CK_BBOOL replace, int data_size); CK_RV object_set_attribute_values(STDLL_TokData_t *tokdata, @@ -2829,6 +2844,208 @@ CK_ATTRIBUTE **t0, CK_ATTRIBUTE **t1); +typedef CK_RV (*t_rsa_encrypt)(STDLL_TokData_t *, CK_BYTE *in_data, + CK_ULONG in_data_len, CK_BYTE *out_data, + OBJECT *key_obj); +typedef CK_RV (*t_rsa_decrypt)(STDLL_TokData_t *, CK_BYTE *in_data, + CK_ULONG in_data_len, CK_BYTE *out_data, + OBJECT *key_obj); + +CK_RV openssl_specific_rsa_keygen(TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl); +CK_RV openssl_specific_rsa_encrypt(STDLL_TokData_t *, CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, OBJECT *key_obj); +CK_RV openssl_specific_rsa_decrypt(STDLL_TokData_t *, CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, OBJECT *key_obj); +CK_RV openssl_specific_rsa_pkcs_decrypt(STDLL_TokData_t *, CK_BYTE *, + CK_ULONG, CK_BYTE *, CK_ULONG *, + OBJECT *, t_rsa_decrypt); +CK_RV openssl_specific_rsa_pkcs_encrypt(STDLL_TokData_t *, CK_BYTE *, + CK_ULONG, CK_BYTE *, CK_ULONG *, + OBJECT *, t_rsa_encrypt); +CK_RV openssl_specific_rsa_pkcs_sign(STDLL_TokData_t *, SESSION *, CK_BYTE *, + CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *, + t_rsa_decrypt); +CK_RV openssl_specific_rsa_pkcs_verify(STDLL_TokData_t *tokdata, SESSION *, + CK_BYTE *, CK_ULONG, CK_BYTE *, + CK_ULONG, OBJECT *, t_rsa_encrypt); +CK_RV openssl_specific_rsa_pkcs_verify_recover(STDLL_TokData_t *tokdata, + CK_BYTE *, CK_ULONG, CK_BYTE *, + CK_ULONG *, OBJECT *, + t_rsa_encrypt); +CK_RV openssl_specific_rsa_pss_sign(STDLL_TokData_t *, SESSION *, + SIGN_VERIFY_CONTEXT *, CK_BYTE *, CK_ULONG, + CK_BYTE *, CK_ULONG *, t_rsa_decrypt); +CK_RV openssl_specific_rsa_pss_verify(STDLL_TokData_t *, SESSION *, + SIGN_VERIFY_CONTEXT *, CK_BYTE *, + CK_ULONG, CK_BYTE *, CK_ULONG, + t_rsa_encrypt); +CK_RV openssl_specific_rsa_x509_encrypt(STDLL_TokData_t *tokdata, CK_BYTE *, + CK_ULONG, CK_BYTE *, CK_ULONG *, + OBJECT *, t_rsa_encrypt); +CK_RV openssl_specific_rsa_x509_decrypt(STDLL_TokData_t *tokdata, CK_BYTE *, + CK_ULONG, CK_BYTE *, CK_ULONG *, + OBJECT *, t_rsa_decrypt); +CK_RV openssl_specific_rsa_x509_sign(STDLL_TokData_t *tokdata, CK_BYTE *, + CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *, + t_rsa_decrypt); +CK_RV openssl_specific_rsa_x509_verify(STDLL_TokData_t *tokdata, CK_BYTE *, + CK_ULONG, CK_BYTE *, CK_ULONG, OBJECT *, + t_rsa_encrypt); +CK_RV openssl_specific_rsa_x509_verify_recover(STDLL_TokData_t *tokdata, + CK_BYTE *, CK_ULONG, CK_BYTE *, + CK_ULONG *, OBJECT *, + t_rsa_encrypt); +CK_RV openssl_specific_rsa_oaep_encrypt(STDLL_TokData_t *, ENCR_DECR_CONTEXT *, + CK_BYTE *, CK_ULONG, CK_BYTE *, + CK_ULONG *, CK_BYTE *, CK_ULONG, + t_rsa_encrypt); +CK_RV openssl_specific_rsa_oaep_decrypt(STDLL_TokData_t *, ENCR_DECR_CONTEXT *, + CK_BYTE *, CK_ULONG, CK_BYTE *, + CK_ULONG *, CK_BYTE *, CK_ULONG, + t_rsa_decrypt); + +CK_RV openssl_make_ec_key_from_template(TEMPLATE *template, EVP_PKEY **pkey); +CK_RV openssl_specific_ec_generate_keypair(STDLL_TokData_t *tokdata, + TEMPLATE *publ_tmpl, + TEMPLATE *priv_tmpl); +CK_RV openssl_specific_ec_sign(STDLL_TokData_t *tokdata, SESSION *sess, + CK_BYTE *in_data, CK_ULONG in_data_len, + CK_BYTE *out_data, CK_ULONG *out_data_len, + OBJECT *key_obj); +CK_RV openssl_specific_ec_verify(STDLL_TokData_t *tokdata, + SESSION *sess, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *signature, + CK_ULONG signature_len, OBJECT *key_obj); +CK_RV openssl_specific_ecdh_pkcs_derive(STDLL_TokData_t *tokdata, + CK_BYTE *priv_bytes, + CK_ULONG priv_length, + CK_BYTE *pub_bytes, + CK_ULONG pub_length, + CK_BYTE *secret_value, + CK_ULONG *secret_value_len, + CK_BYTE *oid, CK_ULONG oid_length); + +CK_RV openssl_specific_sha_init(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx, + CK_MECHANISM *mech); +CK_RV openssl_specific_sha(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx, + CK_BYTE *in_data, CK_ULONG in_data_len, + CK_BYTE *out_data, CK_ULONG *out_data_len); +CK_RV openssl_specific_sha_update(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx, + CK_BYTE *in_data, CK_ULONG in_data_len); +CK_RV openssl_specific_sha_final(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx, + CK_BYTE *out_data, CK_ULONG *out_data_len); + +CK_RV openssl_specific_aes_ecb(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, + CK_ULONG *out_data_len, + OBJECT *key, CK_BYTE encrypt); +CK_RV openssl_specific_aes_cbc(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, + CK_ULONG *out_data_len, + OBJECT *key, CK_BYTE *init_v, CK_BYTE encrypt); +CK_RV openssl_specific_aes_ctr(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, + CK_ULONG *out_data_len, + OBJECT *key, + CK_BYTE *counterblock, + CK_ULONG counter_width, CK_BYTE encrypt); +CK_RV openssl_specific_aes_ofb(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, + OBJECT *key, + CK_BYTE *init_v, CK_BYTE encrypt); +CK_RV openssl_specific_aes_cfb(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, + OBJECT *key, + CK_BYTE *init_v, CK_ULONG cfb_len, + CK_BYTE encrypt); +CK_RV openssl_specific_aes_gcm_init(STDLL_TokData_t *tokdata, SESSION *sess, + ENCR_DECR_CONTEXT *ctx, CK_MECHANISM *mech, + CK_OBJECT_HANDLE hkey, CK_BYTE encrypt); +CK_RV openssl_specific_aes_gcm(STDLL_TokData_t *tokdata, SESSION *sess, + ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, + CK_ULONG in_data_len, CK_BYTE *out_data, + CK_ULONG *out_data_len, CK_BYTE encrypt); +CK_RV openssl_specific_aes_gcm_update(STDLL_TokData_t *tokdata, SESSION *sess, + ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, + CK_ULONG in_data_len, CK_BYTE *out_data, + CK_ULONG *out_data_len, CK_BYTE encrypt); +CK_RV openssl_specific_aes_gcm_final(STDLL_TokData_t *tokdata, SESSION *sess, + ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, + CK_ULONG *out_data_len, CK_BYTE encrypt); +CK_RV openssl_specific_aes_mac(STDLL_TokData_t *tokdata, CK_BYTE *message, + CK_ULONG message_len, OBJECT *key, CK_BYTE *mac); +CK_RV openssl_specific_aes_cmac(STDLL_TokData_t *tokdata, CK_BYTE *message, + CK_ULONG message_len, OBJECT *key, CK_BYTE *mac, + CK_BBOOL first, CK_BBOOL last, CK_VOID_PTR *ctx); + +CK_RV openssl_specific_des_ecb(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, + CK_ULONG *out_data_len, + OBJECT *key, CK_BYTE encrypt); +CK_RV openssl_specific_des_cbc(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, + CK_ULONG *out_data_len, + OBJECT *key, CK_BYTE *init_v, CK_BYTE encrypt); +CK_RV openssl_specific_tdes_ecb(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, + CK_ULONG *out_data_len, + OBJECT *key, CK_BYTE encrypt); +CK_RV openssl_specific_tdes_cbc(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, + CK_ULONG *out_data_len, + OBJECT *key, CK_BYTE *init_v, CK_BYTE encrypt); +CK_RV openssl_specific_tdes_ofb(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, + OBJECT *key, CK_BYTE *init_v, CK_BYTE encrypt); +CK_RV openssl_specific_tdes_cfb(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, + OBJECT *key, + CK_BYTE *init_v, CK_ULONG cfb_len, + CK_BYTE encrypt); +CK_RV openssl_specific_tdes_mac(STDLL_TokData_t *tokdata, CK_BYTE *message, + CK_ULONG message_len, OBJECT *key, CK_BYTE *mac); +CK_RV openssl_specific_tdes_cmac(STDLL_TokData_t *tokdata, CK_BYTE *message, + CK_ULONG message_len, OBJECT *key, CK_BYTE *mac, + CK_BBOOL first, CK_BBOOL last, CK_VOID_PTR *ctx); + +CK_RV openssl_specific_hmac_init(STDLL_TokData_t *tokdata, + SIGN_VERIFY_CONTEXT *ctx, + CK_MECHANISM_PTR mech, + CK_OBJECT_HANDLE Hkey); +CK_RV openssl_specific_hmac(SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, + CK_ULONG in_data_len, CK_BYTE *signature, + CK_ULONG *sig_len, CK_BBOOL sign); +CK_RV openssl_specific_hmac_update(SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, + CK_ULONG in_data_len, CK_BBOOL sign); +CK_RV openssl_specific_hmac_final(SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *signature, + CK_ULONG *sig_len, CK_BBOOL sign); + #include "tok_spec_struct.h" extern token_spec_t token_specific; diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/host_defs.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/host_defs.h --- opencryptoki-3.16.0+dfsg/usr/lib/common/host_defs.h 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/host_defs.h 2022-02-02 15:05:41.000000000 +0100 @@ -20,28 +20,42 @@ #include #include "local_types.h" +#include "../api/policy.h" +#include "../api/mechtable.h" +#include "../api/statistics.h" + +struct _SESSION; + +typedef void (*context_free_func_t)(STDLL_TokData_t *tokdata, struct _SESSION *sess, + CK_BYTE *context, CK_ULONG context_len); typedef struct _ENCR_DECR_CONTEXT { CK_OBJECT_HANDLE key; CK_MECHANISM mech; CK_BYTE *context; CK_ULONG context_len; + context_free_func_t context_free_func; CK_BBOOL multi; CK_BBOOL active; CK_BBOOL init_pending; // indicate init request pending CK_BBOOL multi_init; // multi field is initialized // on first call *after* init CK_BBOOL pkey_active; + CK_BBOOL state_unsaveable; + CK_BBOOL count_statistics; } ENCR_DECR_CONTEXT; typedef struct _DIGEST_CONTEXT { CK_MECHANISM mech; CK_BYTE *context; CK_ULONG context_len; + context_free_func_t context_free_func; CK_BBOOL multi; CK_BBOOL active; CK_BBOOL multi_init; // multi field is initialized // on first call *after* init + CK_BBOOL state_unsaveable; + CK_BBOOL count_statistics; } DIGEST_CONTEXT; typedef struct _SIGN_VERIFY_CONTEXT { @@ -49,6 +63,7 @@ CK_MECHANISM mech; // current sign mechanism CK_BYTE *context; // temporary work area CK_ULONG context_len; + context_free_func_t context_free_func; CK_BBOOL multi; // is this a multi-part operation? CK_BBOOL recover; // are we in recover mode? CK_BBOOL active; @@ -56,6 +71,8 @@ CK_BBOOL multi_init; // multi field is initialized // on first call *after* init CK_BBOOL pkey_active; + CK_BBOOL state_unsaveable; + CK_BBOOL count_statistics; } SIGN_VERIFY_CONTEXT; @@ -185,6 +202,9 @@ CK_ULONG count_lo; // only significant for token objects CK_ULONG index; // SAB Index into the SHM CK_OBJECT_HANDLE map_handle; + + // policy support (set via store_object_strength_f pointer) + struct objstrength strength; } OBJECT; @@ -305,6 +325,13 @@ *head); /* mech_list.c */ +CK_RV ock_generic_filter_mechanism_list(STDLL_TokData_t *tokdata, + const MECH_LIST_ELEMENT *list, + CK_ULONG listlen, + MECH_LIST_ELEMENT **reslist, + CK_ULONG *reslen); + +/* mech_list.c */ CK_RV ock_generic_get_mechanism_list(STDLL_TokData_t * tokdata, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount); @@ -333,6 +360,7 @@ struct _STDLL_TokData_t { CK_SLOT_INFO slot_info; + CK_SLOT_ID slot_id; int spinxplfd; // token specific lock unsigned int spinxplfd_count; // counter for recursive file lock pthread_mutex_t spinxplfd_mutex; // token specific pthread lock @@ -361,6 +389,10 @@ struct btree priv_token_obj_btree; MECH_LIST_ELEMENT *mech_list; CK_ULONG mech_list_len; + struct policy *policy; + const struct mechtable_funcs *mechtable_funcs; + struct statistics *statistics; + struct tokstore_strength store_strength; }; #endif diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/kdf_translation.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/kdf_translation.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/kdf_translation.c 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/kdf_translation.c 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,61 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ +#include +#include + +CK_RV translate_string_to_kdf(const char *str, size_t len, CK_ULONG* kdf) +{ + switch(len) { + case 8: + if (strcmp("CKD_NULL", str) == 0) { + *kdf = CKD_NULL; + return CKR_OK; + } + return CKR_FUNCTION_FAILED; + case 12: + if (strcmp("CKD_SHA1_KDF", str) == 0) { + *kdf = CKD_SHA1_KDF; + return CKR_OK; + } + return CKR_FUNCTION_FAILED; + case 17: + if (strcmp("CKD_SHA1_KDF_ASN1", str) == 0) { + *kdf = CKD_SHA1_KDF_ASN1; + return CKR_OK; + } + return CKR_FUNCTION_FAILED; + case 24: + if (strcmp("CKD_SHA1_KDF_CONCATENATE", str) == 0) { + *kdf = CKD_SHA1_KDF_CONCATENATE; + return CKR_OK; + } + return CKR_FUNCTION_FAILED; + case 14: + if (strcmp("CKD_SHA224_KDF", str) == 0) { + *kdf = CKD_SHA224_KDF; + return CKR_OK; + } + if (strcmp("CKD_SHA256_KDF", str) == 0) { + *kdf = CKD_SHA256_KDF; + return CKR_OK; + } + if (strcmp("CKD_SHA384_KDF", str) == 0) { + *kdf = CKD_SHA384_KDF; + return CKR_OK; + } + if (strcmp("CKD_SHA512_KDF", str) == 0) { + *kdf = CKD_SHA512_KDF; + return CKR_OK; + } + return CKR_FUNCTION_FAILED; + default: + return CKR_FUNCTION_FAILED; + } +} diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/key.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/key.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/key.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/key.c 2022-02-02 15:05:41.000000000 +0100 @@ -510,8 +510,6 @@ CK_ATTRIBUTE *trusted_attr = NULL; CK_ATTRIBUTE *pki_attr = NULL; CK_ATTRIBUTE *wraptmpl_attr = NULL; - - CK_OBJECT_CLASS class = CKO_PUBLIC_KEY; CK_RV rc; @@ -538,7 +536,7 @@ pki_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE)); wraptmpl_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE)); - if (!class || !subject_attr || !encrypt_attr || + if (!class_attr || !subject_attr || !encrypt_attr || !verify_attr || !verify_recover_attr || !wrap_attr || !trusted_attr || !pki_attr || !wraptmpl_attr) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); @@ -1186,6 +1184,8 @@ free(local); if (always_sens) free(always_sens); + if (sensitive) + free(sensitive); if (extractable) free(extractable); if (never_extract) @@ -1303,6 +1303,7 @@ * support the attribute, the command SHALL return * CKR_ATTRIBUTE_TYPE_INVALID. */ + TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_TYPE_INVALID)); return CKR_ATTRIBUTE_TYPE_INVALID; case CKA_UNWRAP_TEMPLATE: if ((attr->ulValueLen > 0 && attr->pValue == NULL) || @@ -1622,8 +1623,8 @@ if (always_sens_attr) free(always_sens_attr); if (trusted_attr) - free(wrap_trusted_attr); - if (trusted_attr) + free(trusted_attr); + if (wrap_trusted_attr) free(wrap_trusted_attr); if (chkval_attr) free(chkval_attr); @@ -1748,6 +1749,8 @@ cleanup: if (local) free(local); + if (sensitive) + free(sensitive); if (extractable) free(extractable); if (always_sens) @@ -2318,8 +2321,8 @@ free(type_attr); if (modulus_attr) free(modulus_attr); - if (public_exp_attr) - free(public_exp_attr); + if (private_exp_attr) + free(private_exp_attr); if (public_exp_attr) free(public_exp_attr); @@ -4308,11 +4311,16 @@ prime_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE)); base_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE)); value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE)); - value_bits_attr = - (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG)); + if (mode != MODE_CREATE && mode != MODE_UNWRAP) + value_bits_attr = + (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG)); - if (!type_attr || !prime_attr || !base_attr || !value_attr - || !value_bits_attr) { + if (!type_attr || !prime_attr || !base_attr || !value_attr) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + rc = CKR_HOST_MEMORY; + goto error; + } + if (mode != MODE_CREATE && mode != MODE_UNWRAP && !value_bits_attr) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto error; @@ -4330,11 +4338,13 @@ value_attr->ulValueLen = 0; value_attr->pValue = NULL; - value_bits_attr->type = CKA_VALUE_BITS; - value_bits_attr->ulValueLen = sizeof(CK_ULONG); - value_bits_attr->pValue = - (CK_BYTE *) value_bits_attr + sizeof(CK_ATTRIBUTE); - *(CK_ULONG *) value_bits_attr->pValue = bits; + if (mode != MODE_CREATE && mode != MODE_UNWRAP) { + value_bits_attr->type = CKA_VALUE_BITS; + value_bits_attr->ulValueLen = sizeof(CK_ULONG); + value_bits_attr->pValue = + (CK_BYTE *) value_bits_attr + sizeof(CK_ATTRIBUTE); + *(CK_ULONG *) value_bits_attr->pValue = bits; + } type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof(CK_KEY_TYPE); @@ -4365,12 +4375,14 @@ goto error; } value_attr = NULL; - rc = template_update_attribute(tmpl, value_bits_attr); - if (rc != CKR_OK) { - TRACE_ERROR("template_update_attribute failed\n"); - goto error; + if (mode != MODE_CREATE && mode != MODE_UNWRAP) { + rc = template_update_attribute(tmpl, value_bits_attr); + if (rc != CKR_OK) { + TRACE_ERROR("template_update_attribute failed\n"); + goto error; + } + value_bits_attr = NULL; } - value_bits_attr = NULL; return CKR_OK; @@ -4498,6 +4510,8 @@ CK_ATTRIBUTE *prime = NULL; CK_ATTRIBUTE *base = NULL; CK_ATTRIBUTE *value = NULL; + CK_ATTRIBUTE *value_bits = NULL; + CK_ULONG num_bits; CK_RV rc; rc = ber_decode_DHPublicKey(data, total_length, &prime, &base, &value); @@ -4530,6 +4544,19 @@ } value = NULL; + rc = build_attribute(CKA_VALUE_BITS, (CK_BYTE *)&num_bits, sizeof(num_bits), + &value_bits); + if (rc != CKR_OK) { + TRACE_DEVEL("build_attribute failed\n"); + goto error; + } + rc = template_update_attribute(tmpl, value_bits); + if (rc != CKR_OK) { + TRACE_ERROR("template_update_attribute failed\n"); + goto error; + } + value_bits = NULL; + return CKR_OK; error: @@ -4539,6 +4566,8 @@ free(base); if (value) free(value); + if (value_bits) + free(value_bits); return rc; } diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/key_mgr.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/key_mgr.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/key_mgr.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/key_mgr.c 2022-02-02 15:05:41.000000000 +0100 @@ -36,6 +36,9 @@ #include "tok_spec_struct.h" #include "trace.h" +#include "../api/policy.h" +#include "../api/statistics.h" + #include static CK_BBOOL true = TRUE, false = FALSE; @@ -63,6 +66,13 @@ TRACE_ERROR("%s received bad argument(s)\n", __func__); return CKR_FUNCTION_FAILED; } + rc = tokdata->policy->is_mech_allowed(tokdata->policy, mech, NULL, + POLICY_CHECK_KEYGEN, sess); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Key generation mechanism not allowed\n"); + return rc; + } + // it's silly but Cryptoki allows the user to specify the CKA_CLASS // in the template. so we have to iterate through the provided template // and make sure that if CKA_CLASS is CKO_SECRET_KEY, if it is present. @@ -269,13 +279,16 @@ // at this point, the key should be fully constructed...assign // an object handle and store the key - // + // Enforce policy rc = object_mgr_create_final(tokdata, sess, key_obj, handle); if (rc != CKR_OK) { TRACE_DEVEL("object_mgr_create_final failed.\n"); goto error; } + if (rc == CKR_OK) + INC_COUNTER(tokdata, sess, mech, key_obj, POLICY_STRENGTH_IDX_0); + return rc; error: @@ -323,6 +336,12 @@ TRACE_ERROR("%s received bad argument(s)\n", __func__); return CKR_FUNCTION_FAILED; } + rc = tokdata->policy->is_mech_allowed(tokdata->policy, mech, NULL, + POLICY_CHECK_KEYGEN, sess); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Keypair generation mechanism not allowed\n"); + return rc; + } // it's silly but Cryptoki allows the user to specify the CKA_CLASS // in the template. so we have to iterate through the provided template // and make sure that if CKA_CLASS is valid, if it is present. @@ -601,7 +620,7 @@ // at this point, the keys should be fully constructed...assign // object handles and store the keys - // + // Enforce policy rc = object_mgr_create_final(tokdata, sess, publ_key_obj, publ_key_handle); if (rc != CKR_OK) { TRACE_DEVEL("object_mgr_create_final failed.\n"); @@ -615,6 +634,9 @@ goto error; } + if (rc == CKR_OK) + INC_COUNTER(tokdata, sess, mech, priv_key_obj, POLICY_STRENGTH_IDX_0); + return rc; error: @@ -676,6 +698,19 @@ goto done; } + rc = tokdata->policy->is_mech_allowed(tokdata->policy, mech, + &wrapping_key_obj->strength, + POLICY_CHECK_WRAP, sess); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: key wrap\n"); + goto done; + } + rc = tokdata->policy->is_key_allowed(tokdata->policy, &key_obj->strength, + sess); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: key wrap\n"); + goto done; + } if (!key_object_is_mechanism_allowed(wrapping_key_obj->template, mech->mechanism)) { TRACE_ERROR("Mechanism not allwed per CKA_ALLOWED_MECHANISMS.\n"); @@ -992,7 +1027,9 @@ // prepare to do the encryption // - rc = encr_mgr_init(tokdata, sess, ctx, OP_WRAP, mech, h_wrapping_key); + /* Policy already checked */ + rc = encr_mgr_init(tokdata, sess, ctx, OP_WRAP, mech, h_wrapping_key, + FALSE); if (rc != CKR_OK) { TRACE_DEVEL("encr_mgr_init failed.\n"); free(ctx); @@ -1011,10 +1048,14 @@ OPENSSL_cleanse(data, data_len); free(data); } - encr_mgr_cleanup(ctx); + encr_mgr_cleanup(tokdata, sess, ctx); free(ctx); done: + if (rc == CKR_OK) + INC_COUNTER(tokdata, sess, mech, wrapping_key_obj, + POLICY_STRENGTH_IDX_0); + if (wrapping_key_obj != NULL) { object_put(tokdata, wrapping_key_obj, TRUE); wrapping_key_obj = NULL; @@ -1064,6 +1105,13 @@ goto done; } + rc = tokdata->policy->is_mech_allowed(tokdata->policy, mech, + &unwrapping_key_obj->strength, + POLICY_CHECK_UNWRAP, sess); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: key unwrap\n"); + goto done; + } if (!key_object_is_mechanism_allowed(unwrapping_key_obj->template, mech->mechanism)) { TRACE_ERROR("Mechanism not allwed per CKA_ALLOWED_MECHANISMS.\n"); @@ -1235,7 +1283,9 @@ } memset(ctx, 0x0, sizeof(ENCR_DECR_CONTEXT)); - rc = decr_mgr_init(tokdata, sess, ctx, OP_UNWRAP, mech, h_unwrapping_key); + /* Policy already checked */ + rc = decr_mgr_init(tokdata, sess, ctx, OP_UNWRAP, mech, h_unwrapping_key, + FALSE); if (rc != CKR_OK) goto done; @@ -1259,7 +1309,7 @@ FALSE, ctx, wrapped_key, wrapped_key_len, data, &data_len); - decr_mgr_cleanup(ctx); + decr_mgr_cleanup(tokdata, sess, ctx); free(ctx); ctx = NULL; @@ -1332,6 +1382,10 @@ } done: + if (rc == CKR_OK) + INC_COUNTER(tokdata, sess, mech, unwrapping_key_obj, + POLICY_STRENGTH_IDX_0); + if (rc != CKR_OK && key_obj) object_free(key_obj); if (unwrapping_key_obj != NULL) { @@ -1345,7 +1399,7 @@ free(data); } if (ctx != NULL) { - decr_mgr_cleanup(ctx); + decr_mgr_cleanup(tokdata, sess, ctx); free(ctx); } diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/lexer.l opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/lexer.l --- opencryptoki-3.16.0+dfsg/usr/lib/common/lexer.l 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/lexer.l 1970-01-01 01:00:00.000000000 +0100 @@ -1,86 +0,0 @@ -/* - * COPYRIGHT (c) International Business Machines Corp. 2002-2017 - * - * This program is provided under the terms of the Common Public License, - * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this - * software constitutes recipient's acceptance of CPL-1.0 terms which can be - * found in the file LICENSE file or at - * https://opensource.org/licenses/cpl1.0.php - */ - -%{ -/* Parser for /etc/opencryptoki.conf */ - -#include -#include -#include - -#include "parser.h" - -/* Ignore -Wsign-compare for autogenerated code. */ -#pragma GCC diagnostic ignored "-Wsign-compare" - -int line_num; - -extern void yyerror(const char *s); -extern char *configparse_strdup(const char *s); -%} - -%option noyywrap -%option nounput -%option noinput - -%% - -[\t ]+ /* ignore spaces */ ; - -= return EQUAL; - -\{ return BEGIN_DEF; - -\} return END_DEF; - -\n { - line_num++; - return EOL; - } - -#[^\n]* { - yylval.str = configparse_strdup(yytext + 1); - return COMMENT; - } - -[0-9]+"."[0-9]+ { /* version */ - unsigned long major, minor; - char *dot = strchr(yytext, '.'); - - *dot = '\0'; - major = strtoul(yytext, NULL, 10); - minor = strtoul(dot + 1, NULL, 10); - - yylval.num = (uint32_t)major << 16 | (uint32_t)minor; - return TOKVERSION; - } - -[0-9]+ { /* number */ - yylval.num = strtoul(yytext, NULL, 10); - return INTEGER; - } - -version return OCKVERSION; -slot return SLOT; - -[^\"= \t\n]+ { - yylval.str = configparse_strdup(yytext); - return STRING; - } - -\"[^\"\n]*\" { - yylval.str = configparse_strdup(yytext+1); - if (yylval.str) yylval.str[strlen(yylval.str)-1]='\0'; - return STRING; - } - -. yyerror(yytext); - -%% diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/loadsave.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/loadsave.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/loadsave.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/loadsave.c 2022-02-02 15:05:41.000000000 +0100 @@ -390,93 +390,18 @@ return initial_vector; } -static CK_RV encrypt_data(STDLL_TokData_t *tokdata, CK_BYTE *key, - CK_ULONG keylen, const CK_BYTE *iv, - CK_BYTE *clear, CK_ULONG clear_len, - CK_BYTE *cipher, CK_ULONG *p_cipher_len) -{ -#ifndef CLEARTEXT - CK_RV rc = CKR_OK; - CK_BYTE *initial_vector = NULL; - OBJECT *keyobj = NULL; - CK_KEY_TYPE keyType; - CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; - CK_ATTRIBUTE key_tmpl[] = { - {CKA_CLASS, &keyClass, sizeof(keyClass)} - , - {CKA_KEY_TYPE, &keyType, sizeof(keyType)} - , - {CKA_VALUE, key, keylen} - }; - - switch (token_specific.data_store.encryption_algorithm) { - case CKM_DES3_CBC: - keyType = CKK_DES3; - break; - case CKM_AES_CBC: - keyType = CKK_AES; - break; - default: - TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); - return CKR_MECHANISM_INVALID; - } - rc = object_create_skel(tokdata, key_tmpl, 3, MODE_CREATE, - CKO_SECRET_KEY, keyType, &keyobj); - if (rc != CKR_OK) { - TRACE_DEVEL("object_create_skel failed.\n"); - return rc; - } - - initial_vector = duplicate_initial_vector(iv); - if (initial_vector == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - return CKR_HOST_MEMORY; - } - - switch (token_specific.data_store.encryption_algorithm) { - case CKM_DES3_CBC: - rc = ckm_des3_cbc_encrypt(tokdata, clear, clear_len, - cipher, p_cipher_len, initial_vector, keyobj); - break; - case CKM_AES_CBC: - rc = ckm_aes_cbc_encrypt(tokdata, clear, clear_len, - cipher, p_cipher_len, initial_vector, keyobj); - break; - default: - TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); - rc = CKR_MECHANISM_INVALID; - } - - if (initial_vector) - free(initial_vector); - - return rc; - -#else - memcpy(cipher, clear, clear_len); - return CKR_OK; -#endif -} - static CK_RV encrypt_data_with_clear_key(STDLL_TokData_t *tokdata, CK_BYTE *key, CK_ULONG keylen, const CK_BYTE *iv, CK_BYTE *clear, CK_ULONG clear_len, CK_BYTE *cipher, - CK_ULONG *p_cipher_len) + CK_ULONG *p_cipher_len, + CK_BBOOL mk_crypt) { #ifndef CLEARTEXT CK_RV rc = CKR_OK; CK_BYTE *initial_vector = NULL; - if (!token_specific.secure_key_token && - token_specific.data_store.encryption_algorithm != CKM_DES3_CBC) { - return encrypt_data(tokdata, key, keylen, iv, clear, clear_len, - cipher, p_cipher_len); - } - - /* Fall back to a software alternative if key is secure, or - * if token's data store encryption algorithm is 3DES_CBC */ initial_vector = duplicate_initial_vector(iv); if (initial_vector == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); @@ -500,76 +425,24 @@ if (initial_vector) free(initial_vector); - return rc; - -#else - memcpy(cipher, clear, clear_len); - return CKR_OK; -#endif -} - -static CK_RV decrypt_data(STDLL_TokData_t *tokdata, - CK_BYTE *key, CK_ULONG keylen, const CK_BYTE *iv, - CK_BYTE *cipher, CK_ULONG cipher_len, - CK_BYTE *clear, CK_ULONG *p_clear_len) -{ -#ifndef CLEARTEXT - CK_RV rc = CKR_OK; - CK_BYTE *initial_vector = NULL; - OBJECT *keyobj = NULL; - CK_KEY_TYPE keyType; - CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; - CK_ATTRIBUTE key_tmpl[] = { - { CKA_CLASS, &keyClass, sizeof(keyClass) }, - { CKA_KEY_TYPE, &keyType, sizeof(keyType) }, - { CKA_VALUE, key, keylen } - }; - - switch (token_specific.data_store.encryption_algorithm) { - case CKM_DES3_CBC: - keyType = CKK_DES3; - break; - case CKM_AES_CBC: - keyType = CKK_AES; - break; - default: - TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); - return CKR_MECHANISM_INVALID; - } - rc = object_create_skel(tokdata, key_tmpl, 3, MODE_CREATE, - CKO_SECRET_KEY, keyType, &keyobj); - if (rc != CKR_OK) { - TRACE_DEVEL("object_create_skel failed.\n"); - return rc; - } - - initial_vector = duplicate_initial_vector(iv); - if (initial_vector == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - return CKR_HOST_MEMORY; - } - - switch (token_specific.data_store.encryption_algorithm) { - case CKM_DES3_CBC: - rc = ckm_des3_cbc_decrypt(tokdata, cipher, cipher_len, - clear, p_clear_len, initial_vector, keyobj); - break; - case CKM_AES_CBC: - rc = ckm_aes_cbc_decrypt(tokdata, cipher, cipher_len, - clear, p_clear_len, initial_vector, keyobj); - break; - default: - TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); - rc = CKR_MECHANISM_INVALID; + if (rc == CKR_OK && + (tokdata->statistics->flags & STATISTICS_FLAG_COUNT_INTERNAL) != 0) { + if (mk_crypt) + tokdata->statistics->increment_func(tokdata->statistics, + tokdata->slot_id, + &tokdata->store_strength.mk_crypt, + tokdata->store_strength.mk_strength); + else + tokdata->statistics->increment_func(tokdata->statistics, + tokdata->slot_id, + &tokdata->store_strength.wrap_crypt, + tokdata->store_strength.wrap_strength); } - if (initial_vector) - free(initial_vector); - return rc; #else - memcpy(clear, cipher, cipher_len); + memcpy(cipher, clear, clear_len); return CKR_OK; #endif } @@ -579,20 +452,13 @@ const CK_BYTE *iv, CK_BYTE *cipher, CK_ULONG cipher_len, CK_BYTE *clear, - CK_ULONG *p_clear_len) + CK_ULONG *p_clear_len, + CK_BBOOL mk_crypt) { #ifndef CLEARTEXT CK_RV rc = CKR_OK; CK_BYTE *initial_vector = NULL; - if (!token_specific.secure_key_token && - token_specific.data_store.encryption_algorithm != CKM_DES3_CBC) { - return decrypt_data(tokdata, key, keylen, iv, cipher, - cipher_len, clear, p_clear_len); - } - - /* Fall back to a software alternative if key is secure, or - * if token's data store encryption algorithm is 3DES_CBC */ initial_vector = duplicate_initial_vector(iv); if (initial_vector == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); @@ -616,6 +482,20 @@ if (initial_vector) free(initial_vector); + if (rc == CKR_OK && + (tokdata->statistics->flags & STATISTICS_FLAG_COUNT_INTERNAL) != 0) { + if (mk_crypt) + tokdata->statistics->increment_func(tokdata->statistics, + tokdata->slot_id, + &tokdata->store_strength.mk_crypt, + tokdata->store_strength.mk_strength); + else + tokdata->statistics->increment_func(tokdata->statistics, + tokdata->slot_id, + &tokdata->store_strength.wrap_crypt, + tokdata->store_strength.wrap_strength); + } + return rc; #else @@ -663,7 +543,7 @@ set_perm(fileno(fp)); /* Load generic token data */ - if (!fread(&td, sizeof(TOKEN_DATA_OLD), 1, fp)) { + if (fread(&td, sizeof(TOKEN_DATA_OLD), 1, fp) != 1) { TRACE_ERROR("fread(%s): %s\n", fname, ferror(fp) ? strerror(errno) : "failed"); rc = CKR_FUNCTION_FAILED; @@ -836,7 +716,7 @@ rc = encrypt_data_with_clear_key(tokdata, key, key_len, token_specific.data_store. obj_initial_vector, clear, padded_len, - cipher, &cipher_len); + cipher, &cipher_len, CK_FALSE); if (rc != CKR_OK) { goto error; } @@ -876,8 +756,6 @@ rc = CKR_HOST_MEMORY; error: - if (fp) - fclose(fp); if (obj_data) free(obj_data); if (clear) @@ -916,12 +794,12 @@ if (!fp2) continue; - if (!fread(&size, sizeof(CK_ULONG_32), 1, fp2)) { + if (fread(&size, sizeof(CK_ULONG_32), 1, fp2) != 1) { fclose(fp2); OCK_SYSLOG(LOG_ERR, "Cannot read size\n"); continue; } - if (!fread(&priv, sizeof(CK_BBOOL), 1, fp2)) { + if (fread(&priv, sizeof(CK_BBOOL), 1, fp2) != 1) { fclose(fp2); OCK_SYSLOG(LOG_ERR, "Cannot read boolean\n"); continue; @@ -1059,7 +937,7 @@ rc = decrypt_data_with_clear_key(tokdata, key, key_len, token_specific.data_store. pin_initial_vector, cipher, cipher_len, - clear, &clear_len); + clear, &clear_len, CK_TRUE); if (rc != CKR_OK) { TRACE_DEVEL("decrypt_data_with_clear_key failed.\n"); goto done; @@ -1184,7 +1062,7 @@ rc = decrypt_data_with_clear_key(tokdata, key, key_len, token_specific.data_store. pin_initial_vector, cipher, cipher_len, - clear, &clear_len); + clear, &clear_len, CK_TRUE); if (rc != CKR_OK) { TRACE_DEVEL("decrypt_data_with_clear_key failed.\n"); goto done; @@ -1271,7 +1149,7 @@ rc = encrypt_data_with_clear_key(tokdata, key, key_len, token_specific.data_store. pin_initial_vector, clear, clear_len, - cipher, &cipher_len); + cipher, &cipher_len, CK_TRUE); if (rc != CKR_OK) { goto done; } @@ -1352,7 +1230,7 @@ rc = encrypt_data_with_clear_key(tokdata, key, key_len, token_specific.data_store. pin_initial_vector, clear, clear_len, - cipher, &cipher_len); + cipher, &cipher_len, CK_TRUE); if (rc != CKR_OK) { goto done; } @@ -1401,14 +1279,24 @@ if (!token_specific.data_store.use_master_key) return CKR_OK; - if ((rc = get_encryption_info(&key_len, NULL)) != CKR_OK) + if (get_encryption_info(&key_len, NULL) != CKR_OK) return CKR_FUNCTION_FAILED; /* For secure key tokens, object encrypt/decrypt uses * software(openssl), not token. So generate masterkey via RNG. */ - if (token_specific.secure_key_token) - return rng_generate(tokdata, key, key_len); + if (token_specific.secure_key_token) { + rc = rng_generate(tokdata, key, key_len); + + if (rc == CKR_OK && + (tokdata->statistics->flags & STATISTICS_FLAG_COUNT_INTERNAL) != 0) + tokdata->statistics->increment_func(tokdata->statistics, + tokdata->slot_id, + &tokdata->store_strength.mk_keygen, + tokdata->store_strength.mk_strength); + + return rc; + } /* For clear key tokens, let token generate masterkey * since token will also encrypt/decrypt the objects. @@ -1440,6 +1328,12 @@ memcpy(key, master_key, master_key_len); free(master_key); + if ((tokdata->statistics->flags & STATISTICS_FLAG_COUNT_INTERNAL) != 0) + tokdata->statistics->increment_func(tokdata->statistics, + tokdata->slot_id, + &tokdata->store_strength.mk_keygen, + tokdata->store_strength.mk_strength); + return CKR_OK; } @@ -1488,7 +1382,7 @@ rc = decrypt_data_with_clear_key(tokdata, key, key_len, token_specific.data_store. obj_initial_vector, data, len, clear, - &clear_len); + &clear_len, CK_FALSE); if (rc != CKR_OK) { goto done; } @@ -1578,13 +1472,13 @@ set_perm(fileno(fp)); - if (!fread(&size, sizeof(CK_ULONG_32), 1, fp)) { + if (fread(&size, sizeof(CK_ULONG_32), 1, fp) != 1) { OCK_SYSLOG(LOG_ERR, "Cannot read size\n"); rc = CKR_FUNCTION_FAILED; goto done; } - if (!fread(&priv, sizeof(CK_BBOOL), 1, fp)) { + if (fread(&priv, sizeof(CK_BBOOL), 1, fp) != 1) { OCK_SYSLOG(LOG_ERR, "Cannot read boolean\n"); rc = CKR_FUNCTION_FAILED; goto done; @@ -1671,8 +1565,6 @@ return CKR_OK; error: - if (fp) - fclose(fp); if (clear) free(clear); @@ -1704,12 +1596,12 @@ if (!fp2) continue; - if (!fread(&size, sizeof(CK_ULONG_32), 1, fp2)) { + if (fread(&size, sizeof(CK_ULONG_32), 1, fp2) != 1) { fclose(fp2); OCK_SYSLOG(LOG_ERR, "Cannot read size\n"); continue; } - if (!fread(&priv, sizeof(CK_BBOOL), 1, fp2)) { + if (fread(&priv, sizeof(CK_BBOOL), 1, fp2) != 1) { fclose(fp2); OCK_SYSLOG(LOG_ERR, "Cannot read boolean\n"); continue; @@ -1758,7 +1650,8 @@ * tokversion >= 3.12 object store */ -static CK_RV aes_256_gcm_seal(unsigned char *out, +static CK_RV aes_256_gcm_seal(STDLL_TokData_t *tokdata, + unsigned char *out, unsigned char tag[16], const unsigned char *aad, size_t aadlen, @@ -1792,12 +1685,20 @@ } rc = CKR_OK; + + if ((tokdata->statistics->flags & STATISTICS_FLAG_COUNT_INTERNAL) != 0) + tokdata->statistics->increment_func(tokdata->statistics, + tokdata->slot_id, + &tokdata->store_strength.mk_crypt, + tokdata->store_strength.mk_strength); + done: EVP_CIPHER_CTX_free(ctx); return rc; } -static CK_RV aes_256_gcm_unseal(unsigned char *out, +static CK_RV aes_256_gcm_unseal(STDLL_TokData_t *tokdata, + unsigned char *out, const unsigned char *aad, size_t aadlen, const unsigned char *in, @@ -1831,12 +1732,20 @@ } rc = CKR_OK; + + if ((tokdata->statistics->flags & STATISTICS_FLAG_COUNT_INTERNAL) != 0) + tokdata->statistics->increment_func(tokdata->statistics, + tokdata->slot_id, + &tokdata->store_strength.mk_crypt, + tokdata->store_strength.mk_strength); + done: EVP_CIPHER_CTX_free(ctx); return rc; } -static CK_RV aes_256_wrap(unsigned char out[40], +static CK_RV aes_256_wrap(STDLL_TokData_t *tokdata, + unsigned char out[40], const unsigned char in[32], const unsigned char kek[32]) { @@ -1865,12 +1774,20 @@ memcpy(out, buffer, 40); rc = CKR_OK; + + if ((tokdata->statistics->flags & STATISTICS_FLAG_COUNT_INTERNAL) != 0) + tokdata->statistics->increment_func(tokdata->statistics, + tokdata->slot_id, + &tokdata->store_strength.wrap_crypt, + tokdata->store_strength.wrap_strength); + done: EVP_CIPHER_CTX_free(ctx); return rc; } -static CK_RV aes_256_unwrap(unsigned char key[32], +static CK_RV aes_256_unwrap(STDLL_TokData_t *tokdata, + unsigned char key[32], const unsigned char in[40], const unsigned char kek[32]) { @@ -1899,6 +1816,13 @@ memcpy(key, buffer, 32); rc = CKR_OK; + + if ((tokdata->statistics->flags & STATISTICS_FLAG_COUNT_INTERNAL) != 0) + tokdata->statistics->increment_func(tokdata->statistics, + tokdata->slot_id, + &tokdata->store_strength.wrap_crypt, + tokdata->store_strength.wrap_strength); + done: EVP_CIPHER_CTX_free(ctx); return rc; @@ -1906,11 +1830,23 @@ CK_RV generate_master_key(STDLL_TokData_t *tokdata, CK_BYTE *key) { + CK_RV rc; + if (tokdata->version < TOK_NEW_DATA_STORE) return generate_master_key_old(tokdata, key); /* generate a 256-bit AES key */ - return rng_generate(tokdata, key, 32); + rc = rng_generate(tokdata, key, 32); + + if (rc == CKR_OK && + (tokdata->statistics->flags & STATISTICS_FLAG_COUNT_INTERNAL) != 0) + tokdata->statistics->increment_func(tokdata->statistics, + tokdata->slot_id, + &tokdata->store_strength.mk_keygen, + tokdata->store_strength.mk_strength); + + return rc; + } /** @@ -1933,7 +1869,8 @@ return CKR_OK; /* wrap master key with so_wrap_key */ - rc = aes_256_wrap(outbuf, tokdata->master_key, tokdata->so_wrap_key); + rc = aes_256_wrap(tokdata, outbuf, tokdata->master_key, + tokdata->so_wrap_key); if (rc != CKR_OK) goto done; @@ -1994,7 +1931,8 @@ } /* unwrap master key with so_wrap_key */ - rc = aes_256_unwrap(tokdata->master_key, inbuf, tokdata->so_wrap_key); + rc = aes_256_unwrap(tokdata, tokdata->master_key, inbuf, + tokdata->so_wrap_key); if (rc != CKR_OK) goto done; @@ -2021,7 +1959,8 @@ return save_masterkey_user_old(tokdata); /* wrap master key with so_wrap_key */ - rc = aes_256_wrap(outbuf, tokdata->master_key, tokdata->user_wrap_key); + rc = aes_256_wrap(tokdata, outbuf, tokdata->master_key, + tokdata->user_wrap_key); if (rc != CKR_OK) goto done; @@ -2083,7 +2022,8 @@ } /* unwrap master key with user_wrap_key */ - rc = aes_256_unwrap(tokdata->master_key, inbuf, tokdata->user_wrap_key); + rc = aes_256_unwrap(tokdata, tokdata->master_key, inbuf, + tokdata->user_wrap_key); if (rc != CKR_OK) goto done; @@ -2222,7 +2162,7 @@ set_perm(fileno(fp)); /* Load generic token data */ - if (!fread(&td, sizeof(TOKEN_DATA), 1, fp)) { + if (fread(&td, sizeof(TOKEN_DATA), 1, fp) != 1) { TRACE_ERROR("fread(%s): %s\n", fname, ferror(fp) ? strerror(errno) : "failed"); rc = CKR_FUNCTION_FAILED; @@ -2391,7 +2331,8 @@ memcpy(obj_key_wrapped, data + 8, 40); /* get key */ - rc = aes_256_unwrap(obj_key, obj_key_wrapped, tokdata->master_key); + rc = aes_256_unwrap(tokdata, obj_key, obj_key_wrapped, + tokdata->master_key); if (rc != CKR_OK) goto done; } @@ -2408,7 +2349,8 @@ obj_iv[11] = 1; /* get wrapped key */ - rc = aes_256_wrap(obj_key_wrapped, obj_key, tokdata->master_key); + rc = aes_256_wrap(tokdata, obj_key_wrapped, obj_key, + tokdata->master_key); if (rc != CKR_OK) goto done; } @@ -2428,7 +2370,8 @@ tmp = htobe32(obj_data_len_32); memcpy(data + 60, &tmp, 4); - rc = aes_256_gcm_seal(/* ciphertext */ + rc = aes_256_gcm_seal(tokdata, + /* ciphertext */ data + HEADER_LEN, /* tag */ data + HEADER_LEN @@ -2534,6 +2477,7 @@ continue; } if (fread(footer, FOOTER_LEN, 1, fp2) != 1) { + free(buf); fclose(fp2); OCK_SYSLOG(LOG_ERR, "Cannot read token object %s " "(ignoring it)", fname); @@ -2582,7 +2526,7 @@ /* iv */ memcpy(obj_iv, header + 48, 12); - rc = aes_256_unwrap(obj_key, obj_key_wrapped, tokdata->master_key); + rc = aes_256_unwrap(tokdata, obj_key, obj_key_wrapped, tokdata->master_key); if (rc != CKR_OK) { rc = CKR_FUNCTION_FAILED; goto done; @@ -2595,7 +2539,8 @@ goto done; } - rc = aes_256_gcm_unseal(buff, /* plain-text */ + rc = aes_256_gcm_unseal(tokdata, + buff, /* plain-text */ header, HEADER_LEN, /* aad */ data, len, /* cipher-text*/ footer, /* tag */ diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/lock_sess_mgr.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/lock_sess_mgr.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/lock_sess_mgr.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/lock_sess_mgr.c 2022-02-02 15:05:41.000000000 +0100 @@ -47,6 +47,27 @@ return result; } +// session_mgr_find_reset_error() +// +// search for the specified session and reset the ulDeviceError field +// in the session info. returning a pointer to the session might be +// dangerous, but performs well +// +// The returned session must be put back (using bt_put_node_value()) by the +// caller to decrease the reference count! +// +// Returns: SESSION * or NULL +// +SESSION *session_mgr_find_reset_error(STDLL_TokData_t *tokdata, + CK_SESSION_HANDLE handle) +{ + SESSION *res = session_mgr_find(tokdata, handle); + + if (res) + res->session_info.ulDeviceError = 0; + return res; +} + void session_mgr_put(STDLL_TokData_t *tokdata, SESSION *session) { bt_put_node_value(&tokdata->sess_btree, session); @@ -276,32 +297,62 @@ if (sess->find_list) free(sess->find_list); - if (sess->encr_ctx.context) - free(sess->encr_ctx.context); + if (sess->encr_ctx.context) { + if (sess->encr_ctx.context_free_func != NULL) + sess->encr_ctx.context_free_func(tokdata, sess, + sess->encr_ctx.context, + sess->encr_ctx.context_len); + else + free(sess->encr_ctx.context); + } if (sess->encr_ctx.mech.pParameter) free(sess->encr_ctx.mech.pParameter); - if (sess->decr_ctx.context) - free(sess->decr_ctx.context); + if (sess->decr_ctx.context) { + if (sess->decr_ctx.context_free_func != NULL) + sess->decr_ctx.context_free_func(tokdata, sess, + sess->decr_ctx.context, + sess->decr_ctx.context_len); + else + free(sess->decr_ctx.context); + } if (sess->decr_ctx.mech.pParameter) free(sess->decr_ctx.mech.pParameter); - if (sess->digest_ctx.context) - free(sess->digest_ctx.context); + if (sess->digest_ctx.context) { + if (sess->digest_ctx.context_free_func != NULL) + sess->digest_ctx.context_free_func(tokdata, sess, + sess->digest_ctx.context, + sess->digest_ctx.context_len); + else + free(sess->digest_ctx.context); + } if (sess->digest_ctx.mech.pParameter) free(sess->digest_ctx.mech.pParameter); - if (sess->sign_ctx.context) - free(sess->sign_ctx.context); + if (sess->sign_ctx.context) { + if (sess->sign_ctx.context_free_func != NULL) + sess->sign_ctx.context_free_func(tokdata, sess, + sess->sign_ctx.context, + sess->sign_ctx.context_len); + else + free(sess->sign_ctx.context); + } if (sess->sign_ctx.mech.pParameter) free(sess->sign_ctx.mech.pParameter); - if (sess->verify_ctx.context) - free(sess->verify_ctx.context); + if (sess->verify_ctx.context) { + if (sess->verify_ctx.context_free_func != NULL) + sess->verify_ctx.context_free_func(tokdata, sess, + sess->verify_ctx.context, + sess->verify_ctx.context_len); + else + free(sess->verify_ctx.context); + } if (sess->verify_ctx.mech.pParameter) free(sess->verify_ctx.mech.pParameter); @@ -354,32 +405,62 @@ if (sess->find_list) free(sess->find_list); - if (sess->encr_ctx.context) - free(sess->encr_ctx.context); + if (sess->encr_ctx.context) { + if (sess->encr_ctx.context_free_func != NULL) + sess->encr_ctx.context_free_func(tokdata, sess, + sess->encr_ctx.context, + sess->encr_ctx.context_len); + else + free(sess->encr_ctx.context); + } if (sess->encr_ctx.mech.pParameter) free(sess->encr_ctx.mech.pParameter); - if (sess->decr_ctx.context) - free(sess->decr_ctx.context); + if (sess->decr_ctx.context) { + if (sess->decr_ctx.context_free_func != NULL) + sess->decr_ctx.context_free_func(tokdata, sess, + sess->decr_ctx.context, + sess->decr_ctx.context_len); + else + free(sess->decr_ctx.context); + } if (sess->decr_ctx.mech.pParameter) free(sess->decr_ctx.mech.pParameter); - if (sess->digest_ctx.context) - free(sess->digest_ctx.context); + if (sess->digest_ctx.context) { + if (sess->digest_ctx.context_free_func != NULL) + sess->digest_ctx.context_free_func(tokdata, sess, + sess->digest_ctx.context, + sess->digest_ctx.context_len); + else + free(sess->digest_ctx.context); + } if (sess->digest_ctx.mech.pParameter) free(sess->digest_ctx.mech.pParameter); - if (sess->sign_ctx.context) - free(sess->sign_ctx.context); + if (sess->sign_ctx.context) { + if (sess->sign_ctx.context_free_func != NULL) + sess->sign_ctx.context_free_func(tokdata, sess, + sess->sign_ctx.context, + sess->sign_ctx.context_len); + else + free(sess->sign_ctx.context); + } if (sess->sign_ctx.mech.pParameter) free(sess->sign_ctx.mech.pParameter); - if (sess->verify_ctx.context) - free(sess->verify_ctx.context); + if (sess->verify_ctx.context) { + if (sess->verify_ctx.context_free_func != NULL) + sess->verify_ctx.context_free_func(tokdata, sess, + sess->verify_ctx.context, + sess->verify_ctx.context_len); + else + free(sess->verify_ctx.context); + } if (sess->verify_ctx.mech.pParameter) free(sess->verify_ctx.mech.pParameter); @@ -528,6 +609,10 @@ active_ops = 0; if (sess->encr_ctx.active == TRUE) { + if (sess->encr_ctx.state_unsaveable) { + TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE)); + return CKR_STATE_UNSAVEABLE; + } active_ops++; if (op_data != NULL) { TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE)); @@ -572,6 +657,10 @@ } if (sess->decr_ctx.active == TRUE) { + if (sess->decr_ctx.state_unsaveable) { + TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE)); + return CKR_STATE_UNSAVEABLE; + } active_ops++; if (op_data != NULL) { TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE)); @@ -616,6 +705,10 @@ } if (sess->digest_ctx.active == TRUE) { + if (sess->digest_ctx.state_unsaveable) { + TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE)); + return CKR_STATE_UNSAVEABLE; + } active_ops++; if (op_data != NULL) { TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE)); @@ -660,6 +753,10 @@ } if (sess->sign_ctx.active == TRUE) { + if (sess->sign_ctx.state_unsaveable) { + TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE)); + return CKR_STATE_UNSAVEABLE; + } active_ops++; if (op_data != NULL) { TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE)); @@ -704,6 +801,10 @@ } if (sess->verify_ctx.active == TRUE) { + if (sess->verify_ctx.state_unsaveable) { + TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE)); + return CKR_STATE_UNSAVEABLE; + } active_ops++; if (op_data != NULL) { TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE)); @@ -759,7 +860,7 @@ // // -CK_RV session_mgr_set_op_state(SESSION *sess, +CK_RV session_mgr_set_op_state(STDLL_TokData_t *tokdata, SESSION *sess, CK_OBJECT_HANDLE encr_key, CK_OBJECT_HANDLE auth_key, CK_BYTE *data, CK_ULONG data_len) @@ -939,19 +1040,19 @@ // state information looks okay. cleanup the current session state, first // if (sess->encr_ctx.active) - encr_mgr_cleanup(&sess->encr_ctx); + encr_mgr_cleanup(tokdata, sess, &sess->encr_ctx); if (sess->decr_ctx.active) - decr_mgr_cleanup(&sess->decr_ctx); + decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx); if (sess->digest_ctx.active) - digest_mgr_cleanup(&sess->digest_ctx); + digest_mgr_cleanup(tokdata, sess, &sess->digest_ctx); if (sess->sign_ctx.active) - sign_mgr_cleanup(&sess->sign_ctx); + sign_mgr_cleanup(tokdata, sess, &sess->sign_ctx); if (sess->verify_ctx.active) - verify_mgr_cleanup(&sess->verify_ctx); + verify_mgr_cleanup(tokdata, sess, &sess->verify_ctx); // copy the new state information diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/mech_aes.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/mech_aes.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/mech_aes.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/mech_aes.c 2022-02-02 15:05:41.000000000 +0100 @@ -2359,6 +2359,8 @@ memcpy(out_data, ((AES_DATA_CONTEXT *) ctx->context)->iv, mac_len); *out_data_len = mac_len; + sign_mgr_cleanup(tokdata, sess, ctx); + return rc; } } @@ -2497,6 +2499,8 @@ memcpy(out_data, context->iv, mac_len); *out_data_len = mac_len; + sign_mgr_cleanup(tokdata, sess, ctx); + return rc; } @@ -2554,8 +2558,12 @@ } if (CRYPTO_memcmp(out_data, ((AES_DATA_CONTEXT *) ctx->context)->iv, - out_data_len) == 0) + out_data_len) == 0) { + verify_mgr_cleanup(tokdata, sess, ctx); return CKR_OK; + } + + verify_mgr_cleanup(tokdata, sess, ctx); return CKR_SIGNATURE_INVALID; } @@ -2685,12 +2693,34 @@ } } - if (CRYPTO_memcmp(signature, context->iv, signature_len) == 0) + if (CRYPTO_memcmp(signature, context->iv, signature_len) == 0) { + verify_mgr_cleanup(tokdata, sess, ctx); return CKR_OK; + } + + verify_mgr_cleanup(tokdata, sess, ctx); return CKR_SIGNATURE_INVALID; } +static void aes_cmac_cleanup(STDLL_TokData_t *tokdata, SESSION *sess, + CK_BYTE *context, CK_ULONG context_len) +{ + UNUSED(tokdata); + UNUSED(sess); + UNUSED(context_len); + + if (((AES_CMAC_CONTEXT *)context)->ctx != NULL) { + token_specific.t_aes_cmac(tokdata, (CK_BYTE *)"", 0, NULL, + ((AES_CMAC_CONTEXT *)context)->iv, + CK_FALSE, CK_TRUE, + ((AES_CMAC_CONTEXT *)context)->ctx); + ((AES_CMAC_CONTEXT *)context)->ctx = NULL; + } + + free(context); +} + CK_RV aes_cmac_sign(STDLL_TokData_t *tokdata, SESSION *sess, CK_BBOOL length_only, @@ -2740,9 +2770,16 @@ goto done; } + if (((AES_CMAC_CONTEXT *)ctx->context)->ctx != NULL) + ctx->state_unsaveable = CK_TRUE; + + ctx->context_free_func = aes_cmac_cleanup; + memcpy(out_data, ((AES_CMAC_CONTEXT *) ctx->context)->iv, mac_len); *out_data_len = mac_len; + sign_mgr_cleanup(tokdata, sess, ctx); + done: object_put(tokdata, key_obj, TRUE); key_obj = NULL; @@ -2810,6 +2847,11 @@ context->len = remain; context->initialized = CK_TRUE; + + if (context->ctx != NULL) + ctx->state_unsaveable = CK_TRUE; + + ctx->context_free_func = aes_cmac_cleanup; } else { TRACE_DEVEL("Token specific aes cmac failed.\n"); } @@ -2873,6 +2915,11 @@ goto done; } + if (context->ctx != NULL) + ctx->state_unsaveable = CK_TRUE; + + ctx->context_free_func = aes_cmac_cleanup; + memcpy(out_data, context->iv, mac_len); *out_data_len = mac_len; @@ -2880,6 +2927,8 @@ object_put(tokdata, key_obj, TRUE); key_obj = NULL; + sign_mgr_cleanup(tokdata, sess, ctx); + return rc; } @@ -2929,11 +2978,19 @@ return rc; } + if (((AES_CMAC_CONTEXT *)ctx->context)->ctx != NULL) + ctx->state_unsaveable = CK_TRUE; + + ctx->context_free_func = aes_cmac_cleanup; + if (CRYPTO_memcmp(out_data, ((AES_CMAC_CONTEXT *) ctx->context)->iv, out_data_len) == 0) { + verify_mgr_cleanup(tokdata, sess, ctx); return CKR_OK; } + verify_mgr_cleanup(tokdata, sess, ctx); + return CKR_SIGNATURE_INVALID; } @@ -2997,6 +3054,11 @@ context->len = remain; context->initialized = CK_TRUE; + + if (context->ctx != NULL) + ctx->state_unsaveable = CK_TRUE; + + ctx->context_free_func = aes_cmac_cleanup; } else { TRACE_DEVEL("Token specific aes cmac failed.\n"); } @@ -3052,13 +3114,22 @@ object_put(tokdata, key_obj, TRUE); key_obj = NULL; + if (context->ctx != NULL) + ctx->state_unsaveable = CK_TRUE; + + ctx->context_free_func = aes_cmac_cleanup; + if (rc != CKR_OK) { TRACE_DEVEL("Token specific aes mac failed.\n"); return rc; } - if (CRYPTO_memcmp(signature, context->iv, signature_len) == 0) + if (CRYPTO_memcmp(signature, context->iv, signature_len) == 0) { + verify_mgr_cleanup(tokdata, sess, ctx); return CKR_OK; + } + + verify_mgr_cleanup(tokdata, sess, ctx); return CKR_SIGNATURE_INVALID; } @@ -3440,6 +3511,7 @@ else memcpy(value_attr->pValue, aes_key, key_size); free(aes_key); + aes_key = NULL; key_type_attr->type = CKA_KEY_TYPE; key_type_attr->ulValueLen = sizeof(CK_KEY_TYPE); diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/mech_des3.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/mech_des3.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/mech_des3.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/mech_des3.c 2022-02-02 15:05:41.000000000 +0100 @@ -2006,6 +2006,8 @@ *out_data_len = mac_len; + sign_mgr_cleanup(tokdata, sess, ctx); + return rc; } } @@ -2144,6 +2146,8 @@ *out_data_len = mac_len; + sign_mgr_cleanup(tokdata, sess, ctx); + return rc; } @@ -2197,8 +2201,12 @@ key_obj = NULL; if (CRYPTO_memcmp(out_data, ((DES_DATA_CONTEXT *) ctx->context)->iv, - out_data_len) == 0) + out_data_len) == 0) { + verify_mgr_cleanup(tokdata, sess, ctx); return CKR_OK; + } + + verify_mgr_cleanup(tokdata, sess, ctx); return CKR_SIGNATURE_INVALID; } @@ -2328,12 +2336,34 @@ } } - if (CRYPTO_memcmp(signature, context->iv, signature_len) == 0) + if (CRYPTO_memcmp(signature, context->iv, signature_len) == 0) { + verify_mgr_cleanup(tokdata, sess, ctx); return CKR_OK; + } + + verify_mgr_cleanup(tokdata, sess, ctx); return CKR_SIGNATURE_INVALID; } +static void des3_cmac_cleanup(STDLL_TokData_t *tokdata, SESSION *sess, + CK_BYTE *context, CK_ULONG context_len) +{ + UNUSED(tokdata); + UNUSED(sess); + UNUSED(context_len); + + if (((DES_CMAC_CONTEXT *)context)->ctx != NULL) { + token_specific.t_tdes_cmac(tokdata, (CK_BYTE *)"", 0, NULL, + ((DES_CMAC_CONTEXT *)context)->iv, + CK_FALSE, CK_TRUE, + ((DES_CMAC_CONTEXT *)context)->ctx); + ((DES_CMAC_CONTEXT *)context)->ctx = NULL; + } + + free(context); +} + CK_RV des3_cmac_sign(STDLL_TokData_t *tokdata, SESSION *sess, CK_BBOOL length_only, @@ -2380,6 +2410,11 @@ if (rc != CKR_OK) TRACE_DEVEL("Token specific des3 cmac failed.\n"); + if (((DES_CMAC_CONTEXT *)ctx->context)->ctx != NULL) + ctx->state_unsaveable = CK_TRUE; + + ctx->context_free_func = des3_cmac_cleanup; + memcpy(out_data, ((DES_CMAC_CONTEXT *) ctx->context)->iv, mac_len); *out_data_len = mac_len; @@ -2387,6 +2422,8 @@ object_put(tokdata, key_obj, TRUE); key_obj = NULL; + sign_mgr_cleanup(tokdata, sess, ctx); + return rc; } @@ -2450,6 +2487,11 @@ context->len = remain; context->initialized = CK_TRUE; + + if (context->ctx != NULL) + ctx->state_unsaveable = CK_TRUE; + + ctx->context_free_func = des3_cmac_cleanup; } else { TRACE_DEVEL("Token specific des3 cmac failed.\n"); } @@ -2512,6 +2554,11 @@ goto done; } + if (context->ctx != NULL) + ctx->state_unsaveable = CK_TRUE; + + ctx->context_free_func = des3_cmac_cleanup; + memcpy(out_data, context->iv, mac_len); *out_data_len = mac_len; @@ -2520,6 +2567,8 @@ object_put(tokdata, key_obj, TRUE); key_obj = NULL; + sign_mgr_cleanup(tokdata, sess, ctx); + return rc; } @@ -2565,10 +2614,19 @@ object_put(tokdata, key_obj, TRUE); key_obj = NULL; + if (((DES_CMAC_CONTEXT *)ctx->context)->ctx != NULL) + ctx->state_unsaveable = CK_TRUE; + + ctx->context_free_func = des3_cmac_cleanup; + if (CRYPTO_memcmp(out_data, ((DES_CMAC_CONTEXT *) ctx->context)->iv, out_data_len) == 0) { + verify_mgr_cleanup(tokdata, sess, ctx); return CKR_OK; } + + verify_mgr_cleanup(tokdata, sess, ctx); + return CKR_SIGNATURE_INVALID; } @@ -2631,6 +2689,11 @@ context->len = remain; context->initialized = CK_TRUE; + + if (context->ctx != NULL) + ctx->state_unsaveable = CK_TRUE; + + ctx->context_free_func = des3_cmac_cleanup; } else { TRACE_DEVEL("Token specific des3 cmac failed.\n"); } @@ -2691,8 +2754,17 @@ return rc; } - if (CRYPTO_memcmp(signature, context->iv, signature_len) == 0) + if (context->ctx != NULL) + ctx->state_unsaveable = CK_TRUE; + + ctx->context_free_func = des3_cmac_cleanup; + + if (CRYPTO_memcmp(signature, context->iv, signature_len) == 0) { + verify_mgr_cleanup(tokdata, sess, ctx); return CKR_OK; + } + + verify_mgr_cleanup(tokdata, sess, ctx); return CKR_SIGNATURE_INVALID; } @@ -2776,6 +2848,7 @@ else memcpy(value_attr->pValue, des_key, 3 * DES_KEY_SIZE); free(des_key); + des_key = NULL; key_type_attr->type = CKA_KEY_TYPE; key_type_attr->ulValueLen = sizeof(CK_KEY_TYPE); diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/mech_des.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/mech_des.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/mech_des.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/mech_des.c 2022-02-02 15:05:41.000000000 +0100 @@ -1288,6 +1288,7 @@ else memcpy(value_attr->pValue, des_key, DES_KEY_SIZE); free(des_key); + des_key = NULL; key_type_attr->type = CKA_KEY_TYPE; key_type_attr->ulValueLen = sizeof(CK_KEY_TYPE); diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/mech_dh.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/mech_dh.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/mech_dh.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/mech_dh.c 2022-02-02 15:05:41.000000000 +0100 @@ -94,8 +94,10 @@ // Extract public-key from mechanism parameters. base-key contains the // private key, prime, and base. The return value will be in the handle. - rc = ckm_dh_pkcs_derive(tokdata, mech->pParameter, mech->ulParameterLen, - base_key, secret_key_value, &secret_key_value_len); + rc = ckm_dh_pkcs_derive(tokdata, sess, + mech->pParameter, mech->ulParameterLen, + base_key, secret_key_value, &secret_key_value_len, + mech); if (rc != CKR_OK) return rc; @@ -146,10 +148,12 @@ // // CK_RV ckm_dh_pkcs_derive(STDLL_TokData_t *tokdata, + SESSION *sess, CK_VOID_PTR other_pubkey, CK_ULONG other_pubkey_len, CK_OBJECT_HANDLE base_key, - CK_BYTE *secret_value, CK_ULONG *secret_value_len) + CK_BYTE *secret_value, CK_ULONG *secret_value_len, + CK_MECHANISM_PTR mech) { CK_RV rc; CK_BYTE p[256]; @@ -169,6 +173,14 @@ else return rc; } + rc = tokdata->policy->is_mech_allowed(tokdata->policy, mech, + &base_key_obj->strength, + POLICY_CHECK_DERIVE, + base_key_obj->session); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: derive key\n"); + goto done; + } if (!key_object_is_mechanism_allowed(base_key_obj->template, CKM_DH_PKCS_DERIVE)) { @@ -236,6 +248,9 @@ TRACE_DEVEL("Token specific dh pkcs derive failed.\n"); done: + if (rc == CKR_OK) + INC_COUNTER(tokdata, sess, mech, base_key_obj, POLICY_STRENGTH_IDX_0); + object_put(tokdata, base_key_obj, TRUE); base_key_obj = NULL; diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/mech_ec.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/mech_ec.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/mech_ec.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/mech_ec.c 2022-02-02 15:05:41.000000000 +0100 @@ -1,5 +1,5 @@ /* - * COPYRIGHT (c) International Business Machines Corp. 2001-2017 + * COPYRIGHT (c) International Business Machines Corp. 2001-2021 * * This program is provided under the terms of the Common Public License, * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this @@ -32,134 +32,6 @@ #include "openssl/obj_mac.h" #include -#if OPENSSL_VERSION_NUMBER < 0x10100000L -/* - * Older OpenSLL versions do not have BN_bn2binpad, so implement it here - */ -static int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen) -{ - int len, pad; - unsigned char *buf; - - len = BN_num_bytes(a); - buf = (unsigned char *)malloc(len); - if (buf == NULL) - return -1; - BN_bn2bin(a, buf); - - if (len >= tolen) { - memcpy(to, buf, tolen); - } else { - pad = tolen - len; - memset(to, 0, pad); - memcpy(to + pad, buf, len); - } - - free(buf); - return tolen; -} -#endif - -#ifndef NID_brainpoolP160r1 -/* - * Older OpenSLL versions may not have the brainpool NIDs defined, define them - * here - */ -#define NID_brainpoolP160r1 921 -#define NID_brainpoolP160t1 922 -#define NID_brainpoolP192r1 923 -#define NID_brainpoolP192t1 924 -#define NID_brainpoolP224r1 925 -#define NID_brainpoolP224t1 926 -#define NID_brainpoolP256r1 927 -#define NID_brainpoolP256t1 928 -#define NID_brainpoolP320r1 929 -#define NID_brainpoolP320t1 930 -#define NID_brainpoolP384r1 931 -#define NID_brainpoolP384t1 932 -#define NID_brainpoolP512r1 933 -#define NID_brainpoolP512t1 934 - -#endif - -#ifndef NID_X25519 -#define NID_X25519 1034 -#define NID_X448 1035 -#endif -#ifndef NID_ED25519 -#define NID_ED25519 1087 -#define NID_ED448 1088 -#endif - -const CK_BYTE brainpoolP160r1[] = OCK_BRAINPOOL_P160R1; -const CK_BYTE brainpoolP160t1[] = OCK_BRAINPOOL_P160T1; -const CK_BYTE brainpoolP192r1[] = OCK_BRAINPOOL_P192R1; -const CK_BYTE brainpoolP192t1[] = OCK_BRAINPOOL_P192T1; -const CK_BYTE brainpoolP224r1[] = OCK_BRAINPOOL_P224R1; -const CK_BYTE brainpoolP224t1[] = OCK_BRAINPOOL_P224T1; -const CK_BYTE brainpoolP256r1[] = OCK_BRAINPOOL_P256R1; -const CK_BYTE brainpoolP256t1[] = OCK_BRAINPOOL_P256T1; -const CK_BYTE brainpoolP320r1[] = OCK_BRAINPOOL_P320R1; -const CK_BYTE brainpoolP320t1[] = OCK_BRAINPOOL_P320T1; -const CK_BYTE brainpoolP384r1[] = OCK_BRAINPOOL_P384R1; -const CK_BYTE brainpoolP384t1[] = OCK_BRAINPOOL_P384T1; -const CK_BYTE brainpoolP512r1[] = OCK_BRAINPOOL_P512R1; -const CK_BYTE brainpoolP512t1[] = OCK_BRAINPOOL_P512T1; -const CK_BYTE prime192v1[] = OCK_PRIME192V1; -const CK_BYTE secp224r1[] = OCK_SECP224R1; -const CK_BYTE prime256v1[] = OCK_PRIME256V1; -const CK_BYTE secp384r1[] = OCK_SECP384R1; -const CK_BYTE secp521r1[] = OCK_SECP521R1; -const CK_BYTE secp256k1[] = OCK_SECP256K1; -const CK_BYTE curve25519[] = OCK_CURVE25519; -const CK_BYTE curve448[] = OCK_CURVE448; -const CK_BYTE ed25519[] = OCK_ED25519; -const CK_BYTE ed448[] = OCK_ED448; - -const struct _ec der_ec_supported[NUMEC] = { - {BRAINPOOL_CURVE, CURVE160, NID_brainpoolP160r1, - sizeof(brainpoolP160r1), &brainpoolP160r1}, - {BRAINPOOL_CURVE, CURVE160, NID_brainpoolP160t1, - sizeof(brainpoolP160t1), &brainpoolP160t1}, - {BRAINPOOL_CURVE, CURVE192, NID_brainpoolP192r1, - sizeof(brainpoolP192r1), &brainpoolP192r1}, - {BRAINPOOL_CURVE, CURVE192, NID_brainpoolP192t1, - sizeof(brainpoolP192t1), &brainpoolP192t1}, - {BRAINPOOL_CURVE, CURVE224, NID_brainpoolP224r1, - sizeof(brainpoolP224r1), &brainpoolP224r1}, - {BRAINPOOL_CURVE, CURVE224, NID_brainpoolP224t1, - sizeof(brainpoolP224t1), &brainpoolP224t1}, - {BRAINPOOL_CURVE, CURVE256, NID_brainpoolP256r1, - sizeof(brainpoolP256r1), &brainpoolP256r1}, - {BRAINPOOL_CURVE, CURVE256, NID_brainpoolP256t1, - sizeof(brainpoolP256t1), &brainpoolP256t1}, - {BRAINPOOL_CURVE, CURVE320, NID_brainpoolP320r1, - sizeof(brainpoolP320r1), &brainpoolP320r1}, - {BRAINPOOL_CURVE, CURVE320, NID_brainpoolP320t1, - sizeof(brainpoolP320t1), &brainpoolP320t1}, - {BRAINPOOL_CURVE, CURVE384, NID_brainpoolP384r1, - sizeof(brainpoolP384r1), &brainpoolP384r1}, - {BRAINPOOL_CURVE, CURVE384, NID_brainpoolP384t1, - sizeof(brainpoolP384t1), &brainpoolP384t1}, - {BRAINPOOL_CURVE, CURVE512, NID_brainpoolP512r1, - sizeof(brainpoolP512r1), &brainpoolP512r1}, - {BRAINPOOL_CURVE, CURVE512, NID_brainpoolP512t1, - sizeof(brainpoolP512t1), &brainpoolP512t1}, - {PRIME_CURVE, CURVE192, NID_X9_62_prime192v1, - sizeof(prime192v1), &prime192v1}, - {PRIME_CURVE, CURVE224, NID_secp224r1, sizeof(secp224r1), &secp224r1}, - {PRIME_CURVE, CURVE256, NID_X9_62_prime256v1, - sizeof(prime256v1), &prime256v1}, - {PRIME_CURVE, CURVE384, NID_secp384r1, sizeof(secp384r1), &secp384r1}, - {PRIME_CURVE, CURVE521, NID_secp521r1, sizeof(secp521r1), &secp521r1}, - {PRIME_CURVE, CURVE256, NID_secp256k1, sizeof(secp256k1), &secp256k1}, - {MONTGOMERY_CURVE, CURVE256, NID_X25519, sizeof(curve25519), &curve25519}, - {MONTGOMERY_CURVE, CURVE456, NID_X448, sizeof(curve448), &curve448}, - {EDWARDS_CURVE, CURVE256, NID_ED25519, sizeof(ed25519), &ed25519}, - {EDWARDS_CURVE, CURVE456, NID_ED448, sizeof(ed448), &ed448}, -}; - - CK_RV get_ecsiglen(OBJECT *key_obj, CK_ULONG *size) { CK_ATTRIBUTE *attr = NULL; @@ -432,7 +304,7 @@ return rc; } - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); + rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; @@ -442,7 +314,7 @@ in_data_len, hash, &hash_len); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Digest failed.\n"); - digest_mgr_cleanup(&digest_ctx); + digest_mgr_cleanup(tokdata, sess, &digest_ctx); return rc; } @@ -450,7 +322,8 @@ sign_mech.ulParameterLen = 0; sign_mech.pParameter = NULL; - rc = sign_mgr_init(tokdata, sess, &sign_ctx, &sign_mech, FALSE, ctx->key); + rc = sign_mgr_init(tokdata, sess, &sign_ctx, &sign_mech, FALSE, ctx->key, + FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Sign Mgr Init failed.\n"); goto error; @@ -462,7 +335,7 @@ TRACE_DEVEL("Sign Mgr Sign failed.\n"); error: - sign_mgr_cleanup(&sign_ctx); + sign_mgr_cleanup(tokdata, sess, &sign_ctx); return rc; } @@ -507,12 +380,13 @@ digest_mech.pParameter = NULL; rc = digest_mgr_init(tokdata, sess, &context->hash_context, - &digest_mech); + &digest_mech, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } context->flag = TRUE; + ctx->state_unsaveable |= context->hash_context.state_unsaveable; } rc = digest_mgr_digest_update(tokdata, sess, &context->hash_context, @@ -571,7 +445,8 @@ sign_mech.ulParameterLen = 0; sign_mech.pParameter = NULL; - rc = sign_mgr_init(tokdata, sess, &sign_ctx, &sign_mech, FALSE, ctx->key); + rc = sign_mgr_init(tokdata, sess, &sign_ctx, &sign_mech, FALSE, ctx->key, + FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Sign Mgr Init failed.\n"); goto done; @@ -584,12 +459,12 @@ TRACE_DEVEL("Sign Mgr Sign failed.\n"); if (length_only == TRUE || rc == CKR_BUFFER_TOO_SMALL) { - sign_mgr_cleanup(&sign_ctx); + sign_mgr_cleanup(tokdata, sess, &sign_ctx); return rc; } done: - sign_mgr_cleanup(&sign_ctx); + sign_mgr_cleanup(tokdata, sess, &sign_ctx); return rc; } @@ -645,7 +520,7 @@ return rc; } - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); + rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; @@ -655,7 +530,7 @@ in_data_len, hash, &hash_len); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Digest failed.\n"); - digest_mgr_cleanup(&digest_ctx); + digest_mgr_cleanup(tokdata, sess, &digest_ctx); return rc; } // Verify the Signed BER-encoded Data block @@ -665,7 +540,7 @@ verify_mech.pParameter = NULL; rc = verify_mgr_init(tokdata, sess, &verify_ctx, &verify_mech, FALSE, - ctx->key); + ctx->key, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Verify Mgr Init failed.\n"); goto done; @@ -677,7 +552,7 @@ if (rc != CKR_OK) TRACE_DEVEL("Verify Mgr Verify failed.\n"); done: - sign_mgr_cleanup(&verify_ctx); + sign_mgr_cleanup(tokdata, sess, &verify_ctx); return rc; } @@ -723,12 +598,13 @@ digest_mech.pParameter = NULL; rc = digest_mgr_init(tokdata, sess, &context->hash_context, - &digest_mech); + &digest_mech, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } context->flag = TRUE; + ctx->state_unsaveable |= context->hash_context.state_unsaveable; } rc = digest_mgr_digest_update(tokdata, sess, &context->hash_context, @@ -785,7 +661,7 @@ verify_mech.pParameter = NULL; rc = verify_mgr_init(tokdata, sess, &verify_ctx, &verify_mech, FALSE, - ctx->key); + ctx->key, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Verify Mgr Init failed.\n"); goto done; @@ -796,7 +672,7 @@ if (rc != CKR_OK) TRACE_DEVEL("Verify Mgr Verify failed.\n"); done: - verify_mgr_cleanup(&verify_ctx); + verify_mgr_cleanup(tokdata, sess, &verify_ctx); return rc; } @@ -841,7 +717,7 @@ return CKR_FUNCTION_NOT_SUPPORTED; } - rc = digest_mgr_init(tokdata, sess, &ctx, &digest_mech); + rc = digest_mgr_init(tokdata, sess, &ctx, &digest_mech, FALSE); if (rc != CKR_OK) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return rc; @@ -851,7 +727,7 @@ h_len); if (rc != CKR_OK) { TRACE_ERROR("digest_mgr_digest failed with rc = %s\n", ock_err(rc)); - digest_mgr_cleanup(&ctx); + digest_mgr_cleanup(tokdata, sess, &ctx); return rc; } @@ -914,9 +790,11 @@ return CKR_OK; } -CK_RV ckm_ecdh_pkcs_derive(STDLL_TokData_t *tokdata, CK_VOID_PTR other_pubkey, - CK_ULONG other_pubkey_len, CK_OBJECT_HANDLE base_key, - CK_BYTE *secret_value, CK_ULONG *secret_value_len) +CK_RV ckm_ecdh_pkcs_derive(STDLL_TokData_t *tokdata, SESSION *sess, + CK_VOID_PTR other_pubkey, CK_ULONG other_pubkey_len, + CK_OBJECT_HANDLE base_key, + CK_BYTE *secret_value, CK_ULONG *secret_value_len, + CK_MECHANISM_PTR mech) { CK_RV rc; CK_ATTRIBUTE *attr; @@ -940,6 +818,14 @@ else return rc; } + rc = tokdata->policy->is_mech_allowed(tokdata->policy, mech, + &base_key_obj->strength, + POLICY_CHECK_DERIVE, + base_key_obj->session); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: derive key\n"); + goto done; + } if (!key_object_is_mechanism_allowed(base_key_obj->template, CKM_ECDH1_DERIVE)) { @@ -1005,38 +891,15 @@ } done: + if (rc == CKR_OK) + INC_COUNTER(tokdata, sess, mech, base_key_obj, POLICY_STRENGTH_IDX_0); + object_put(tokdata, base_key_obj, TRUE); base_key_obj = NULL; return rc; } -static CK_RV digest_from_kdf(CK_EC_KDF_TYPE kdf, CK_MECHANISM_TYPE *mech) -{ - switch (kdf) { - case CKD_SHA1_KDF: - *mech = CKM_SHA_1; - break; - case CKD_SHA224_KDF: - *mech = CKM_SHA224; - break; - case CKD_SHA256_KDF: - *mech = CKM_SHA256; - break; - case CKD_SHA384_KDF: - *mech = CKM_SHA384; - break; - case CKD_SHA512_KDF: - *mech = CKM_SHA512; - break; - default: - TRACE_ERROR("Error unsupported KDF %ld.\n", kdf); - return CKR_FUNCTION_FAILED; - } - - return CKR_OK; -} - CK_RV pkcs_get_keytype(CK_ATTRIBUTE *attrs, CK_ULONG attrs_len, CK_MECHANISM_PTR mech, CK_ULONG *type, CK_ULONG *class) { @@ -1077,6 +940,9 @@ case CKM_AES_KEY_GEN: *type = CKK_AES; break; + case CKM_GENERIC_SECRET_KEY_GEN: + *type = CKK_GENERIC_SECRET; + break; case CKM_RSA_PKCS_KEY_PAIR_GEN: *type = CKK_RSA; break; @@ -1215,7 +1081,7 @@ { CK_RV rc; CK_ULONG class = 0, keytype = 0, key_len = 0; - CK_ATTRIBUTE *new_attr; + CK_ATTRIBUTE *value_attr, *vallen_attr = NULL; OBJECT *temp_obj = NULL; CK_ECDH1_DERIVE_PARAMS *pParms; CK_BYTE z_value[MAX_ECDH_SHARED_SECRET_SIZE]; @@ -1259,9 +1125,9 @@ } /* Derive the shared secret */ - rc = ckm_ecdh_pkcs_derive(tokdata, pParms->pPublicData, + rc = ckm_ecdh_pkcs_derive(tokdata, sess, pParms->pPublicData, pParms->ulPublicDataLen, base_key, z_value, - &z_len); + &z_len, mech); if (rc != CKR_OK) { TRACE_ERROR("Error deriving the shared secret.\n"); return rc; @@ -1315,31 +1181,59 @@ goto end; /* Return the hashed and truncated derived bytes as CKA_VALUE attribute */ - rc = build_attribute(CKA_VALUE, derived_key, key_len, &new_attr); + rc = build_attribute(CKA_VALUE, derived_key, key_len, &value_attr); if (rc != CKR_OK) { TRACE_ERROR("Failed to build the attribute from CKA_VALUE, rc=%s.\n", ock_err(rc)); goto end; } + switch (keytype) { + case CKK_GENERIC_SECRET: + case CKK_AES: + /* Supply CKA_VAUE_LEN since this is required for those key types */ + rc = build_attribute(CKA_VALUE_LEN, (CK_BYTE*)&key_len, + sizeof(key_len), &vallen_attr); + if (rc != CKR_OK) { + TRACE_ERROR("Failed to build the attribute from CKA_VALUE_LEN, rc=%s.\n", + ock_err(rc)); + free(value_attr); + goto end; + } + break; + default: + break; + } + /* Create the object that will be passed back as a handle. This will contain * the new (computed) value of the attribute. */ rc = object_mgr_create_skel(tokdata, sess, pTemplate, ulCount, MODE_KEYGEN, class, keytype, &temp_obj); if (rc != CKR_OK) { TRACE_ERROR("Object Mgr create skeleton failed, rc=%s.\n", ock_err(rc)); - free(new_attr); + free(value_attr); + free(vallen_attr); goto end; } /* Update the template in the object with the new attribute */ - rc = template_update_attribute(temp_obj->template, new_attr); + rc = template_update_attribute(temp_obj->template, value_attr); if (rc != CKR_OK) { TRACE_ERROR("template_update_attribute failed\n"); - free(new_attr); + free(value_attr); + free(vallen_attr); goto end; } + if (vallen_attr != NULL) { + rc = template_update_attribute(temp_obj->template, vallen_attr); + if (rc != CKR_OK) { + TRACE_ERROR("template_update_attribute failed\n"); + free(vallen_attr); + goto end; + } + } + /* At this point, the derived key is fully constructed...assign an object * handle and store the key */ rc = object_mgr_create_final(tokdata, sess, temp_obj, derived_key_obj); @@ -1522,9 +1416,8 @@ CK_BYTE *d, CK_ULONG d_len, CK_BYTE **point, CK_ULONG *point_len) { - EC_KEY *eckey = NULL; EC_POINT *pub_key = NULL; - const EC_GROUP *group = NULL; + EC_GROUP *group = NULL; int nid, p_len; BIGNUM *bn_d = NULL, *bn_x = NULL, *bn_y = NULL; CK_RV rc = CKR_OK; @@ -1541,17 +1434,7 @@ goto done; } - eckey = EC_KEY_new_by_curve_name(nid); - if (eckey == NULL) { - rc = CKR_FUNCTION_FAILED; - goto done; - } - if (EC_KEY_set_private_key(eckey, bn_d) != 1) { - rc = CKR_FUNCTION_FAILED; - goto done; - } - - group = EC_KEY_get0_group(eckey); + group = EC_GROUP_new_by_curve_name(nid); if (group == NULL) { rc = CKR_FUNCTION_FAILED; goto done; @@ -1576,7 +1459,7 @@ rc = CKR_HOST_MEMORY; goto done; } - if (!EC_POINT_get_affine_coordinates_GFp(group, pub_key, bn_x, bn_y, NULL)) { + if (!EC_POINT_get_affine_coordinates(group, pub_key, bn_x, bn_y, NULL)) { rc = CKR_FUNCTION_FAILED; goto done; } @@ -1599,13 +1482,11 @@ done: if (pub_key) EC_POINT_free(pub_key); - if (eckey) - EC_KEY_free(eckey); BN_clear_free(bn_x); BN_clear_free(bn_y); BN_clear_free(bn_d); - if (ec_point != NULL) - free(ec_point); + if (group != NULL) + EC_GROUP_free(group); return rc; } diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/mech_list.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/mech_list.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/mech_list.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/mech_list.c 2022-02-02 15:05:41.000000000 +0100 @@ -18,6 +18,29 @@ #include "tok_spec_struct.h" #include "trace.h" +CK_RV ock_generic_filter_mechanism_list(STDLL_TokData_t *tokdata, + const MECH_LIST_ELEMENT *list, + CK_ULONG listlen, + MECH_LIST_ELEMENT **reslist, + CK_ULONG *reslen) +{ + CK_ULONG i, j; + + *reslist = calloc(listlen, sizeof(MECH_LIST_ELEMENT)); + if (!*reslist) + return CKR_HOST_MEMORY; + for (i = 0, j = 0; i < listlen; ++i) { + memcpy(*reslist + j, list + i, sizeof(MECH_LIST_ELEMENT)); + if (tokdata->policy->update_mech_info(tokdata->policy, + (*reslist)[j].mech_type, + &(*reslist)[j].mech_info) == + CKR_OK) + ++j; + } + *reslen = j; + *reslist = realloc(*reslist, sizeof(MECH_LIST_ELEMENT) * j); + return CKR_OK; +} CK_RV ock_generic_get_mechanism_list(STDLL_TokData_t * tokdata, CK_MECHANISM_TYPE_PTR pMechanismList, @@ -70,9 +93,8 @@ */ static void netscape_hack(CK_MECHANISM_TYPE_PTR mech_arr_ptr, CK_ULONG count) { - char *envrn; CK_ULONG i; - if ((envrn = getenv("NS_SERVER_HOME")) != NULL) { + if (getenv("NS_SERVER_HOME") != NULL) { for (i = 0; i < count; i++) { switch (mech_arr_ptr[i]) { case CKM_SSL3_PRE_MASTER_KEY_GEN: diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/mech_md2.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/mech_md2.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/mech_md2.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/mech_md2.c 2022-02-02 15:05:41.000000000 +0100 @@ -235,7 +235,7 @@ digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); + rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); goto done; @@ -245,7 +245,7 @@ attr->pValue, attr->ulValueLen, hash, &hash_len); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Digest failed.\n"); - digest_mgr_cleanup(&digest_ctx); + digest_mgr_cleanup(tokdata, sess, &digest_ctx); goto done; } memset(&digest_ctx, 0x0, sizeof(DIGEST_CONTEXT)); @@ -276,7 +276,7 @@ // inner hash // - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); + rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); goto done; @@ -305,7 +305,7 @@ // outer hash // - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); + rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); goto done; @@ -364,7 +364,8 @@ memset(&hmac_ctx, 0, sizeof(SIGN_VERIFY_CONTEXT)); - rc = sign_mgr_init(tokdata, sess, &hmac_ctx, &ctx->mech, FALSE, ctx->key); + rc = sign_mgr_init(tokdata, sess, &hmac_ctx, &ctx->mech, FALSE, ctx->key, + FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Sign Mgr Init failed.\n"); return rc; diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/mech_md5.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/mech_md5.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/mech_md5.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/mech_md5.c 2022-02-02 15:05:41.000000000 +0100 @@ -20,30 +20,53 @@ #include "tok_spec_struct.h" #include "trace.h" -#include +#include #include // // Software MD5 implementation (OpenSSL based) // -void sw_md5_init(DIGEST_CONTEXT *ctx) +static void sw_md5_free(STDLL_TokData_t *tokdata, SESSION *sess, + CK_BYTE *context, CK_ULONG context_len) { - ctx->context_len = sizeof(MD5_CTX); - ctx->context = (CK_BYTE *) malloc(sizeof(MD5_CTX)); + UNUSED(tokdata); + UNUSED(sess); + UNUSED(context_len); + + EVP_MD_CTX_free((EVP_MD_CTX *)context); +} + +CK_RV sw_md5_init(DIGEST_CONTEXT *ctx) +{ + ctx->context_len = 1; + ctx->context = (CK_BYTE *)EVP_MD_CTX_new(); if (ctx->context == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - // TODO: propagate error up? - return; + ctx->context_len = 0; + return CKR_HOST_MEMORY; } - MD5_Init((MD5_CTX *)ctx->context); + if (!EVP_DigestInit_ex((EVP_MD_CTX *)ctx->context, EVP_md5(), NULL)) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + EVP_MD_CTX_free((EVP_MD_CTX *)ctx->context); + ctx->context = NULL; + ctx->context_len = 0; + return CKR_FUNCTION_FAILED; + } + + ctx->state_unsaveable = CK_TRUE; + ctx->context_free_func = sw_md5_free; + + return CKR_OK; } CK_RV sw_md5_hash(DIGEST_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { + unsigned int len; + if (!ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __func__); return CKR_FUNCTION_FAILED; @@ -57,37 +80,60 @@ if (ctx->context == NULL) return CKR_OPERATION_NOT_INITIALIZED; - MD5_Update((MD5_CTX *)ctx->context, in_data, in_data_len); - MD5_Final(out_data, (MD5_CTX *)ctx->context); - *out_data_len = MD5_HASH_SIZE; + len = *out_data_len; + if (!EVP_DigestUpdate((EVP_MD_CTX *)ctx->context, in_data, in_data_len) || + !EVP_DigestFinal((EVP_MD_CTX *)ctx->context, out_data, &len)) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + return CKR_FUNCTION_FAILED; + } - free(ctx->context); + *out_data_len = len; + + EVP_MD_CTX_free((EVP_MD_CTX *)ctx->context); ctx->context = NULL; + ctx->context_free_func = NULL; return CKR_OK; } -CK_RV sw_MD5_Update(DIGEST_CONTEXT *ctx, CK_BYTE *in_data, - CK_ULONG in_data_len) +static CK_RV sw_md5_update(DIGEST_CONTEXT *ctx, CK_BYTE *in_data, + CK_ULONG in_data_len) { if (ctx->context == NULL) return CKR_OPERATION_NOT_INITIALIZED; - MD5_Update((MD5_CTX *)ctx->context, in_data, in_data_len); + if (!EVP_DigestUpdate((EVP_MD_CTX *)ctx->context, in_data, in_data_len)) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + return CKR_FUNCTION_FAILED; + } + return CKR_OK; } -CK_RV sw_MD5_Final(DIGEST_CONTEXT *ctx, CK_BYTE *out_data, - CK_ULONG *out_data_len) +static CK_RV sw_md5_final(DIGEST_CONTEXT *ctx, CK_BYTE *out_data, + CK_ULONG *out_data_len) { + unsigned int len; + if (ctx->context == NULL) return CKR_OPERATION_NOT_INITIALIZED; - MD5_Final(out_data, (MD5_CTX *)ctx->context); - *out_data_len = MD5_HASH_SIZE; + if (*out_data_len < MD5_HASH_SIZE) { + TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); + return CKR_BUFFER_TOO_SMALL; + } + + len = *out_data_len; + if (!EVP_DigestFinal((EVP_MD_CTX *)ctx->context, out_data, &len)) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + return CKR_FUNCTION_FAILED; + } + + *out_data_len = len; - free(ctx->context); + EVP_MD_CTX_free((EVP_MD_CTX *)ctx->context); ctx->context = NULL; + ctx->context_free_func = NULL; return CKR_OK; } @@ -99,8 +145,7 @@ UNUSED(sess); if (mech->mechanism == CKM_MD5) { - sw_md5_init(ctx); - return CKR_OK; + return sw_md5_init(ctx); } else { return CKR_MECHANISM_INVALID; } @@ -153,7 +198,7 @@ return CKR_OK; if (ctx->mech.mechanism == CKM_MD5) - return sw_MD5_Update(ctx, in_data, in_data_len); + return sw_md5_update(ctx, in_data, in_data_len); else return CKR_MECHANISM_INVALID; } @@ -182,7 +227,7 @@ } if (ctx->mech.mechanism == CKM_MD5) - return sw_MD5_Final(ctx, out_data, out_data_len); + return sw_md5_final(ctx, out_data, out_data_len); else return CKR_MECHANISM_INVALID; } @@ -256,7 +301,7 @@ digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); + rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); goto done; @@ -267,7 +312,7 @@ attr->pValue, attr->ulValueLen, hash, &hash_len); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Digest failed.\n"); - digest_mgr_cleanup(&digest_ctx); + digest_mgr_cleanup(tokdata, sess, &digest_ctx); goto done; } @@ -298,7 +343,7 @@ // inner hash // - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); + rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); goto done; @@ -330,7 +375,7 @@ // outer hash // - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); + rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); goto done; @@ -389,7 +434,8 @@ memset(&hmac_ctx, 0, sizeof(SIGN_VERIFY_CONTEXT)); - rc = sign_mgr_init(tokdata, sess, &hmac_ctx, &ctx->mech, FALSE, ctx->key); + rc = sign_mgr_init(tokdata, sess, &hmac_ctx, &ctx->mech, FALSE, ctx->key, + FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Sign Mgr Init failed.\n"); goto done; @@ -413,6 +459,6 @@ } done: - sign_mgr_cleanup(&hmac_ctx); + sign_mgr_cleanup(tokdata, sess, &hmac_ctx); return rc; } diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/mech_openssl.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/mech_openssl.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/mech_openssl.c 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/mech_openssl.c 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,4596 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ + + +#include +#include +#include +#include + +#include + +#include "pkcs11types.h" +#include "defs.h" +#include "host_defs.h" +#include "h_extern.h" +#include "tok_spec_struct.h" +#include "trace.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if OPENSSL_VERSION_PREREQ(3, 0) +#include +#include +#endif + +CK_RV openssl_specific_rsa_keygen(TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl) +{ + CK_ATTRIBUTE *publ_exp = NULL; + CK_ATTRIBUTE *attr = NULL; + CK_ULONG mod_bits; + CK_BBOOL flag; + CK_RV rc; + CK_ULONG BNLength; +#if !OPENSSL_VERSION_PREREQ(3, 0) + const RSA *rsa = NULL; + const BIGNUM *bignum = NULL; +#else + BIGNUM *bignum = NULL; +#endif + CK_BYTE *ssl_ptr = NULL; + BIGNUM *e = NULL; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *ctx = NULL; + + rc = template_attribute_get_ulong(publ_tmpl, CKA_MODULUS_BITS, &mod_bits); + if (rc != CKR_OK) { + TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); + return CKR_TEMPLATE_INCOMPLETE; // should never happen + } + + // we don't support less than 512 bit keys in the sw + if (mod_bits < 512 || mod_bits > OPENSSL_RSA_MAX_MODULUS_BITS) { + TRACE_ERROR("%s\n", ock_err(ERR_KEY_SIZE_RANGE)); + return CKR_KEY_SIZE_RANGE; + } + + rc = template_attribute_get_non_empty(publ_tmpl, CKA_PUBLIC_EXPONENT, + &publ_exp); + if (rc != CKR_OK) { + TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); + return CKR_TEMPLATE_INCOMPLETE; + } + + if (publ_exp->ulValueLen > sizeof(CK_ULONG)) { + TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); + return CKR_ATTRIBUTE_VALUE_INVALID; + } + + e = BN_new(); + if (e == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + return CKR_HOST_MEMORY; + } + BN_bin2bn(publ_exp->pValue, publ_exp->ulValueLen, e); + + ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); + if (ctx == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + rc = CKR_HOST_MEMORY; + goto done; + } + + if (EVP_PKEY_keygen_init(ctx) != 1) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rc = CKR_FUNCTION_FAILED; + goto done; + } + if (mod_bits > INT_MAX + || EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, mod_bits) != 1) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rc = CKR_FUNCTION_FAILED; + goto done; + } +#if !OPENSSL_VERSION_PREREQ(3, 0) + if (EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, e) != 1) { +#else + if (EVP_PKEY_CTX_set1_rsa_keygen_pubexp(ctx, e) != 1) { +#endif + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rc = CKR_FUNCTION_FAILED; + goto done; + } +#if !OPENSSL_VERSION_PREREQ(3, 0) + e = NULL; // will be freed as part of the context +#endif + if (EVP_PKEY_keygen(ctx, &pkey) != 1) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rc = CKR_FUNCTION_FAILED; + goto done; + } +#if !OPENSSL_VERSION_PREREQ(3, 0) + if ((rsa = EVP_PKEY_get0_RSA(pkey)) == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rc = CKR_FUNCTION_FAILED; + goto done; + } + RSA_get0_key(rsa, &bignum, NULL, NULL); +#else + if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, &bignum)) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rc = CKR_FUNCTION_FAILED; + goto done; + } +#endif + BNLength = BN_num_bytes(bignum); + ssl_ptr = malloc(BNLength); + if (ssl_ptr == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + rc = CKR_HOST_MEMORY; + goto done; + } + BNLength = BN_bn2bin(bignum, ssl_ptr); + rc = build_attribute(CKA_MODULUS, ssl_ptr, BNLength, &attr); // in bytes + if (rc != CKR_OK) { + TRACE_DEVEL("build_attribute failed\n"); + goto done; + } + rc = template_update_attribute(publ_tmpl, attr); + if (rc != CKR_OK) { + TRACE_ERROR("template_update_attribute failed\n"); + free(attr); + goto done; + } + free(ssl_ptr); + ssl_ptr = NULL; +#if OPENSSL_VERSION_PREREQ(3, 0) + BN_free(bignum); + bignum = NULL; +#endif + + // Public Exponent +#if !OPENSSL_VERSION_PREREQ(3, 0) + RSA_get0_key(rsa, NULL, &bignum, NULL); +#else + if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_E, &bignum)) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rc = CKR_FUNCTION_FAILED; + goto done; + } +#endif + BNLength = BN_num_bytes(bignum); + ssl_ptr = malloc(BNLength); + if (ssl_ptr == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + rc = CKR_HOST_MEMORY; + goto done; + } + BNLength = BN_bn2bin(bignum, ssl_ptr); + // in bytes + rc = build_attribute(CKA_PUBLIC_EXPONENT, ssl_ptr, BNLength, &attr); + if (rc != CKR_OK) { + TRACE_DEVEL("build_attribute failed\n"); + goto done; + } + rc = template_update_attribute(publ_tmpl, attr); + if (rc != CKR_OK) { + TRACE_ERROR("template_update_attribute failed\n"); + free(attr); + goto done; + } + + /* add public exponent to the private template. Its already an attribute in + * the private template at this point, we're just making its value correct + */ + rc = build_attribute(CKA_PUBLIC_EXPONENT, ssl_ptr, BNLength, &attr); + if (rc != CKR_OK) { + TRACE_DEVEL("build_attribute failed\n"); + goto done; + } + rc = template_update_attribute(priv_tmpl, attr); + if (rc != CKR_OK) { + TRACE_ERROR("template_update_attribute failed\n"); + free(attr); + goto done; + } + free(ssl_ptr); + ssl_ptr = NULL; +#if OPENSSL_VERSION_PREREQ(3, 0) + BN_free(bignum); + bignum = NULL; +#endif + + // local = TRUE + // + flag = TRUE; + rc = build_attribute(CKA_LOCAL, &flag, sizeof(CK_BBOOL), &attr); + if (rc != CKR_OK) { + TRACE_DEVEL("build_attribute failed\n"); + goto done; + } + rc = template_update_attribute(publ_tmpl, attr); + if (rc != CKR_OK) { + TRACE_ERROR("template_update_attribute failed\n"); + free(attr); + goto done; + } + + // + // now, do the private key + // + // Cheat here and put the whole original key into the CKA_VALUE... remember + // to force the system to not return this for RSA keys.. + + // Add the modulus to the private key information +#if !OPENSSL_VERSION_PREREQ(3, 0) + RSA_get0_key(rsa, &bignum, NULL, NULL); +#else + if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, &bignum)) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rc = CKR_FUNCTION_FAILED; + goto done; + } +#endif + BNLength = BN_num_bytes(bignum); + ssl_ptr = malloc(BNLength); + if (ssl_ptr == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + rc = CKR_HOST_MEMORY; + goto done; + } + BNLength = BN_bn2bin(bignum, ssl_ptr); + rc = build_attribute(CKA_MODULUS, ssl_ptr, BNLength, &attr); // in bytes + if (rc != CKR_OK) { + TRACE_DEVEL("build_attribute failed\n"); + goto done; + } + rc = template_update_attribute(priv_tmpl, attr); + if (rc != CKR_OK) { + TRACE_ERROR("template_update_attribute failed\n"); + free(attr); + goto done; + } + free(ssl_ptr); + ssl_ptr = NULL; +#if OPENSSL_VERSION_PREREQ(3, 0) + BN_free(bignum); + bignum = NULL; +#endif + + // Private Exponent +#if !OPENSSL_VERSION_PREREQ(3, 0) + RSA_get0_key(rsa, NULL, NULL, &bignum); +#else + if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_D, &bignum)) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rc = CKR_FUNCTION_FAILED; + goto done; + } +#endif + BNLength = BN_num_bytes(bignum); + ssl_ptr = malloc(BNLength); + if (ssl_ptr == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + rc = CKR_HOST_MEMORY; + goto done; + } + BNLength = BN_bn2bin(bignum, ssl_ptr); + rc = build_attribute(CKA_PRIVATE_EXPONENT, ssl_ptr, BNLength, &attr); + if (rc != CKR_OK) { + TRACE_DEVEL("build_attribute failed\n"); + goto done; + } + rc = template_update_attribute(priv_tmpl, attr); + if (rc != CKR_OK) { + TRACE_ERROR("template_update_attribute failed\n"); + OPENSSL_cleanse(attr, sizeof(CK_ATTRIBUTE) + attr->ulValueLen); + free(attr); + goto done; + } + OPENSSL_cleanse(ssl_ptr, BNLength); + free(ssl_ptr); + ssl_ptr = NULL; +#if OPENSSL_VERSION_PREREQ(3, 0) + BN_free(bignum); + bignum = NULL; +#endif + + // prime #1: p +#if !OPENSSL_VERSION_PREREQ(3, 0) + RSA_get0_factors(rsa, &bignum, NULL); +#else + if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_FACTOR1, &bignum)) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rc = CKR_FUNCTION_FAILED; + goto done; + } +#endif + BNLength = BN_num_bytes(bignum); + ssl_ptr = malloc(BNLength); + if (ssl_ptr == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + rc = CKR_HOST_MEMORY; + goto done; + } + BNLength = BN_bn2bin(bignum, ssl_ptr); + rc = build_attribute(CKA_PRIME_1, ssl_ptr, BNLength, &attr); + if (rc != CKR_OK) { + TRACE_DEVEL("build_attribute failed\n"); + goto done; + } + rc = template_update_attribute(priv_tmpl, attr); + if (rc != CKR_OK) { + TRACE_ERROR("template_update_attribute failed\n"); + OPENSSL_cleanse(attr, sizeof(CK_ATTRIBUTE) + attr->ulValueLen); + free(attr); + goto done; + } + OPENSSL_cleanse(ssl_ptr, BNLength); + free(ssl_ptr); + ssl_ptr = NULL; +#if OPENSSL_VERSION_PREREQ(3, 0) + BN_free(bignum); + bignum = NULL; +#endif + + // prime #2: q +#if !OPENSSL_VERSION_PREREQ(3, 0) + RSA_get0_factors(rsa, NULL, &bignum); +#else + if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_FACTOR2, &bignum)) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rc = CKR_FUNCTION_FAILED; + goto done; + } +#endif + BNLength = BN_num_bytes(bignum); + ssl_ptr = malloc(BNLength); + if (ssl_ptr == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + rc = CKR_HOST_MEMORY; + goto done; + } + BNLength = BN_bn2bin(bignum, ssl_ptr); + rc = build_attribute(CKA_PRIME_2, ssl_ptr, BNLength, &attr); + if (rc != CKR_OK) { + TRACE_DEVEL("build_attribute failed\n"); + goto done; + } + rc = template_update_attribute(priv_tmpl, attr); + if (rc != CKR_OK) { + TRACE_ERROR("template_update_attribute failed\n"); + OPENSSL_cleanse(attr, sizeof(CK_ATTRIBUTE) + attr->ulValueLen); + free(attr); + goto done; + } + OPENSSL_cleanse(ssl_ptr, BNLength); + free(ssl_ptr); + ssl_ptr = NULL; +#if OPENSSL_VERSION_PREREQ(3, 0) + BN_free(bignum); + bignum = NULL; +#endif + + // exponent 1: d mod(p-1) +#if !OPENSSL_VERSION_PREREQ(3, 0) + RSA_get0_crt_params(rsa, &bignum, NULL, NULL); +#else + if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_EXPONENT1, &bignum)) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rc = CKR_FUNCTION_FAILED; + goto done; + } +#endif + BNLength = BN_num_bytes(bignum); + ssl_ptr = malloc(BNLength); + if (ssl_ptr == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + rc = CKR_HOST_MEMORY; + goto done; + } + BNLength = BN_bn2bin(bignum, ssl_ptr); + rc = build_attribute(CKA_EXPONENT_1, ssl_ptr, BNLength, &attr); + if (rc != CKR_OK) { + TRACE_DEVEL("build_attribute failed\n"); + goto done; + } + rc = template_update_attribute(priv_tmpl, attr); + if (rc != CKR_OK) { + TRACE_ERROR("template_update_attribute failed\n"); + OPENSSL_cleanse(attr, sizeof(CK_ATTRIBUTE) + attr->ulValueLen); + free(attr); + goto done; + } + OPENSSL_cleanse(ssl_ptr, BNLength); + free(ssl_ptr); + ssl_ptr = NULL; +#if OPENSSL_VERSION_PREREQ(3, 0) + BN_free(bignum); + bignum = NULL; +#endif + + // exponent 2: d mod(q-1) +#if !OPENSSL_VERSION_PREREQ(3, 0) + RSA_get0_crt_params(rsa, NULL, &bignum, NULL); +#else + if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_EXPONENT2, &bignum)) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rc = CKR_FUNCTION_FAILED; + goto done; + } +#endif + BNLength = BN_num_bytes(bignum); + ssl_ptr = malloc(BNLength); + if (ssl_ptr == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + rc = CKR_HOST_MEMORY; + goto done; + } + BNLength = BN_bn2bin(bignum, ssl_ptr); + rc = build_attribute(CKA_EXPONENT_2, ssl_ptr, BNLength, &attr); + if (rc != CKR_OK) { + TRACE_DEVEL("build_attribute failed\n"); + goto done; + } + rc = template_update_attribute(priv_tmpl, attr); + if (rc != CKR_OK) { + TRACE_ERROR("template_update_attribute failed\n"); + OPENSSL_cleanse(attr, sizeof(CK_ATTRIBUTE) + attr->ulValueLen); + free(attr); + goto done; + } + OPENSSL_cleanse(ssl_ptr, BNLength); + free(ssl_ptr); + ssl_ptr = NULL; +#if OPENSSL_VERSION_PREREQ(3, 0) + BN_free(bignum); + bignum = NULL; +#endif + + // CRT coefficient: q_inverse mod(p) +#if !OPENSSL_VERSION_PREREQ(3, 0) + RSA_get0_crt_params(rsa, NULL, NULL, &bignum); +#else + if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_COEFFICIENT1, + &bignum)) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rc = CKR_FUNCTION_FAILED; + goto done; + } +#endif + BNLength = BN_num_bytes(bignum); + ssl_ptr = malloc(BNLength); + if (ssl_ptr == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + rc = CKR_HOST_MEMORY; + goto done; + } + BNLength = BN_bn2bin(bignum, ssl_ptr); + rc = build_attribute(CKA_COEFFICIENT, ssl_ptr, BNLength, &attr); + if (rc != CKR_OK) { + TRACE_DEVEL("build_attribute failed\n"); + goto done; + } + rc = template_update_attribute(priv_tmpl, attr); + if (rc != CKR_OK) { + TRACE_ERROR("template_update_attribute failed\n"); + OPENSSL_cleanse(attr, sizeof(CK_ATTRIBUTE) + attr->ulValueLen); + free(attr); + goto done; + } + OPENSSL_cleanse(ssl_ptr, BNLength); + free(ssl_ptr); + ssl_ptr = NULL; +#if OPENSSL_VERSION_PREREQ(3, 0) + BN_free(bignum); + bignum = NULL; +#endif + + flag = TRUE; + rc = build_attribute(CKA_LOCAL, &flag, sizeof(CK_BBOOL), &attr); + if (rc != CKR_OK) { + TRACE_DEVEL("build_attribute failed\n"); + goto done; + } + rc = template_update_attribute(priv_tmpl, attr); + if (rc != CKR_OK) { + TRACE_ERROR("template_update_attribute failed\n"); + free(attr); + goto done; + } + +done: + if (ssl_ptr != NULL) { + OPENSSL_cleanse(ssl_ptr, BNLength); + free(ssl_ptr); + } + if (pkey != NULL) + EVP_PKEY_free(pkey); + if (ctx != NULL) + EVP_PKEY_CTX_free(ctx); + if (e != NULL) + BN_free(e); +#if OPENSSL_VERSION_PREREQ(3, 0) + if (bignum != NULL) + BN_free(bignum); +#endif + return rc; +} + +// convert from the local PKCS11 template representation to +// the underlying requirement +// returns the pointer to the local key representation +static EVP_PKEY *rsa_convert_public_key(OBJECT *key_obj) +{ + CK_BBOOL rc; + CK_ATTRIBUTE *modulus = NULL; + CK_ATTRIBUTE *pub_exp = NULL; + EVP_PKEY *pkey = NULL; + BIGNUM *bn_mod, *bn_exp; +#if OPENSSL_VERSION_PREREQ(3, 0) + EVP_PKEY_CTX *pctx = NULL; + OSSL_PARAM_BLD *tmpl = NULL; + OSSL_PARAM *params = NULL; +#else + RSA *rsa; +#endif + + rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, + &modulus); + if (rc != CKR_OK) + return NULL; + rc = template_attribute_get_non_empty(key_obj->template, + CKA_PUBLIC_EXPONENT, &pub_exp); + if (rc != CKR_OK) + return NULL; + + // Create and init BIGNUM structs + bn_mod = BN_new(); + bn_exp = BN_new(); + + if (bn_exp == NULL || bn_mod == NULL) { + if (bn_mod) + free(bn_mod); + if (bn_exp) + free(bn_exp); + return NULL; + } + // Convert from strings to BIGNUMs + BN_bin2bn((unsigned char *) modulus->pValue, modulus->ulValueLen, bn_mod); + BN_bin2bn((unsigned char *) pub_exp->pValue, pub_exp->ulValueLen, bn_exp); + +#if !OPENSSL_VERSION_PREREQ(3, 0) + // Create an RSA key struct to return + rsa = RSA_new(); + if (rsa == NULL) { + if (bn_mod) + free(bn_mod); + if (bn_exp) + free(bn_exp); + return NULL; + } + + RSA_set0_key(rsa, bn_mod, bn_exp, NULL); + + pkey = EVP_PKEY_new(); + if (pkey == NULL) { + RSA_free(rsa); + return NULL; + } + + if (EVP_PKEY_assign_RSA(pkey, rsa) != 1) { + RSA_free(rsa); + EVP_PKEY_free(pkey); + return NULL; + } +#else + tmpl = OSSL_PARAM_BLD_new(); + if (tmpl == NULL) + goto out; + + if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_N, bn_mod) || + !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_E, bn_exp)) + goto out; + + params = OSSL_PARAM_BLD_to_param(tmpl); + if (params == NULL) + goto out; + + pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); + if (pctx == NULL) + goto out; + + if (!EVP_PKEY_fromdata_init(pctx) || + !EVP_PKEY_fromdata(pctx, &pkey, EVP_PKEY_PUBLIC_KEY, params)) + goto out; + +out: + if (pctx != NULL) + EVP_PKEY_CTX_free(pctx); + if (tmpl != NULL) + OSSL_PARAM_BLD_free(tmpl); + if (params != NULL) + OSSL_PARAM_free(params); + if (bn_mod != NULL) + BN_free(bn_mod); + if (bn_exp != NULL) + BN_free(bn_exp); +#endif + + return pkey; +} + +static EVP_PKEY *rsa_convert_private_key(OBJECT *key_obj) +{ + CK_ATTRIBUTE *modulus = NULL; + CK_ATTRIBUTE *pub_exp = NULL; + CK_ATTRIBUTE *priv_exp = NULL; + CK_ATTRIBUTE *prime1 = NULL; + CK_ATTRIBUTE *prime2 = NULL; + CK_ATTRIBUTE *exp_1 = NULL; + CK_ATTRIBUTE *exp_2 = NULL; + CK_ATTRIBUTE *coeff = NULL; + EVP_PKEY *pkey = NULL; +#if OPENSSL_VERSION_PREREQ(3, 0) + EVP_PKEY_CTX *pctx = NULL; + OSSL_PARAM_BLD *tmpl = NULL; + OSSL_PARAM *params = NULL; +#else + RSA *rsa; +#endif + BIGNUM *bn_mod, *bn_pub_exp, *bn_priv_exp, *bn_p1, *bn_p2, *bn_e1, *bn_e2, + *bn_cf; + + template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, &modulus); + template_attribute_get_non_empty(key_obj->template, CKA_PUBLIC_EXPONENT, + &pub_exp); + template_attribute_find(key_obj->template, CKA_PRIVATE_EXPONENT, &priv_exp); + template_attribute_find(key_obj->template, CKA_PRIME_1, &prime1); + template_attribute_find(key_obj->template, CKA_PRIME_2, &prime2); + template_attribute_find(key_obj->template, CKA_EXPONENT_1, &exp_1); + template_attribute_find(key_obj->template, CKA_EXPONENT_2,&exp_2); + template_attribute_find(key_obj->template, CKA_COEFFICIENT, &coeff); + + if (!prime2 && !modulus) { + return NULL; + } + +#if !OPENSSL_VERSION_PREREQ(3, 0) + // Create and init all the RSA and BIGNUM structs we need. + rsa = RSA_new(); + if (rsa == NULL) + return NULL; + + /* + * Depending if an engine is loaded on OpenSSL and define its own + * RSA_METHOD, we can end up having an infinite loop as the SOFT + * Token doesn't implement RSA and, instead, calls OpenSSL for it. + * So to avoid it we set RSA methods to the default rsa methods. + */ + RSA_set_method(rsa, RSA_PKCS1_OpenSSL()); +#endif + + bn_mod = BN_new(); + bn_pub_exp = BN_new(); + bn_priv_exp = BN_new(); + bn_p1 = BN_new(); + bn_p2 = BN_new(); + bn_e1 = BN_new(); + bn_e2 = BN_new(); + bn_cf = BN_new(); + + if ((bn_cf == NULL) || (bn_e2 == NULL) || (bn_e1 == NULL) || + (bn_p2 == NULL) || (bn_p1 == NULL) || (bn_priv_exp == NULL) || + (bn_pub_exp == NULL) || (bn_mod == NULL)) + goto out; + + // CRT key? + if (prime1) { + if (!prime2 || !exp_1 || !exp_2 || !coeff) + goto out; + + // Even though this is CRT key, OpenSSL requires the + // modulus and exponents filled in or encrypt and decrypt will + // not work + BN_bin2bn((unsigned char *) modulus->pValue, modulus->ulValueLen, + bn_mod); + BN_bin2bn((unsigned char *) pub_exp->pValue, pub_exp->ulValueLen, + bn_pub_exp); + BN_bin2bn((unsigned char *) priv_exp->pValue, priv_exp->ulValueLen, + bn_priv_exp); + + BN_bin2bn((unsigned char *) prime1->pValue, prime1->ulValueLen, bn_p1); + BN_bin2bn((unsigned char *) prime2->pValue, prime2->ulValueLen, bn_p2); + + BN_bin2bn((unsigned char *) exp_1->pValue, exp_1->ulValueLen, bn_e1); + BN_bin2bn((unsigned char *) exp_2->pValue, exp_2->ulValueLen, bn_e2); + BN_bin2bn((unsigned char *) coeff->pValue, coeff->ulValueLen, bn_cf); + +#if !OPENSSL_VERSION_PREREQ(3, 0) + RSA_set0_key(rsa, bn_mod, bn_pub_exp, bn_priv_exp); + bn_mod = NULL; + bn_pub_exp = NULL; + bn_priv_exp = NULL; + RSA_set0_factors(rsa, bn_p1, bn_p2); + bn_p1 = NULL; + bn_p2 = NULL; + RSA_set0_crt_params(rsa, bn_e1, bn_e2, bn_cf); + bn_e1 = NULL; + bn_e2 = NULL; + bn_cf = NULL; + + pkey = EVP_PKEY_new(); + if (pkey == NULL) + goto out; + + if (EVP_PKEY_assign_RSA(pkey, rsa) != 1) + goto out; +#else + tmpl = OSSL_PARAM_BLD_new(); + if (tmpl == NULL) + goto out; + + if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_N, bn_mod) || + !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_E, bn_pub_exp) || + !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_D, bn_priv_exp) || + !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_FACTOR1, bn_p1) || + !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_FACTOR2, bn_p2) || + !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_EXPONENT1, + bn_e1) || + !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_EXPONENT2, + bn_e2) || + !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_COEFFICIENT1, + bn_cf)) + goto out; +#endif + } else { // must be a non-CRT key + if (!priv_exp) { + return NULL; + } + BN_bin2bn((unsigned char *) modulus->pValue, modulus->ulValueLen, + bn_mod); + BN_bin2bn((unsigned char *) pub_exp->pValue, pub_exp->ulValueLen, + bn_pub_exp); + BN_bin2bn((unsigned char *) priv_exp->pValue, priv_exp->ulValueLen, + bn_priv_exp); + +#if !OPENSSL_VERSION_PREREQ(3, 0) + RSA_set0_key(rsa, bn_mod, bn_pub_exp, bn_priv_exp); + bn_mod = NULL; + bn_pub_exp = NULL; + bn_priv_exp = NULL; + + pkey = EVP_PKEY_new(); + if (pkey == NULL) + goto out; + + if (EVP_PKEY_assign_RSA(pkey, rsa) != 1) + goto out; +#else + tmpl = OSSL_PARAM_BLD_new(); + if (tmpl == NULL) + goto out; + + if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_N, bn_mod) || + !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_E, bn_pub_exp) || + !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_D, bn_priv_exp)) + goto out; +#endif + } + +#if OPENSSL_VERSION_PREREQ(3, 0) + params = OSSL_PARAM_BLD_to_param(tmpl); + if (params == NULL) + goto out; + + pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); + if (pctx == NULL) + goto out; + + if (!EVP_PKEY_fromdata_init(pctx) || + !EVP_PKEY_fromdata(pctx, &pkey, EVP_PKEY_PUBLIC_KEY, params)) + goto out; + + EVP_PKEY_CTX_free(pctx); + OSSL_PARAM_BLD_free(tmpl); + OSSL_PARAM_free(params); + BN_free(bn_mod); + BN_free(bn_pub_exp); + BN_free(bn_priv_exp); + BN_free(bn_p1); + BN_free(bn_p2); + BN_free(bn_e1); + BN_free(bn_e2); + BN_free(bn_cf); +#endif + + return pkey; +out: +#if !OPENSSL_VERSION_PREREQ(3, 0) + if (rsa) + RSA_free(rsa); +#else + if (pctx != NULL) + EVP_PKEY_CTX_free(pctx); + if (tmpl != NULL) + OSSL_PARAM_BLD_free(tmpl); + if (params != NULL) + OSSL_PARAM_free(params); +#endif + if (pkey) + EVP_PKEY_free(pkey); + if (bn_mod) + BN_free(bn_mod); + if (bn_pub_exp) + BN_free(bn_pub_exp); + if (bn_priv_exp) + BN_free(bn_priv_exp); + if (bn_p1) + BN_free(bn_p1); + if (bn_p2) + BN_free(bn_p2); + if (bn_e1) + BN_free(bn_e1); + if (bn_e2) + BN_free(bn_e2); + if (bn_cf) + BN_free(bn_cf); + + return NULL; +} + +CK_RV openssl_specific_rsa_encrypt(STDLL_TokData_t *tokdata, CK_BYTE *in_data, + CK_ULONG in_data_len, CK_BYTE *out_data, + OBJECT *key_obj) +{ + EVP_PKEY_CTX *ctx = NULL; + EVP_PKEY *pkey = NULL; + CK_RV rc; + size_t outlen = in_data_len; + + UNUSED(tokdata); + + pkey = rsa_convert_public_key(key_obj); + if (pkey == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rc = CKR_FUNCTION_FAILED; + return rc; + } + + ctx = EVP_PKEY_CTX_new(pkey, NULL); + if (ctx == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + rc = CKR_HOST_MEMORY; + goto done; + } + + if (EVP_PKEY_encrypt_init(ctx) != 1) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rc = CKR_FUNCTION_FAILED; + goto done; + } + if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_NO_PADDING) != 1) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rc = CKR_FUNCTION_FAILED; + goto done; + } + if (EVP_PKEY_encrypt(ctx, out_data, &outlen, + in_data, in_data_len) != 1) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rc = CKR_FUNCTION_FAILED; + goto done; + } + + rc = CKR_OK; +done: + if (pkey != NULL) + EVP_PKEY_free(pkey); + if (ctx != NULL) + EVP_PKEY_CTX_free(ctx); + return rc; +} + +CK_RV openssl_specific_rsa_decrypt(STDLL_TokData_t *tokdata, CK_BYTE *in_data, + CK_ULONG in_data_len, CK_BYTE *out_data, + OBJECT *key_obj) +{ + EVP_PKEY_CTX *ctx = NULL; + EVP_PKEY *pkey = NULL; + size_t outlen = in_data_len; + CK_RV rc; + + UNUSED(tokdata); + + pkey = rsa_convert_private_key(key_obj); + if (pkey == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rc = CKR_FUNCTION_FAILED; + return rc; + } + + ctx = EVP_PKEY_CTX_new(pkey, NULL); + if (ctx == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + rc = CKR_HOST_MEMORY; + goto done; + } + + if (EVP_PKEY_decrypt_init(ctx) != 1) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rc = CKR_FUNCTION_FAILED; + goto done; + } + if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_NO_PADDING) != 1) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rc = CKR_FUNCTION_FAILED; + goto done; + } + if (EVP_PKEY_decrypt(ctx, out_data, &outlen, + in_data, in_data_len) != 1) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rc = CKR_FUNCTION_FAILED; + goto done; + } + + rc = CKR_OK; +done: + if (pkey != NULL) + EVP_PKEY_free(pkey); + if (ctx != NULL) + EVP_PKEY_CTX_free(ctx); + return rc; +} + +CK_RV openssl_specific_rsa_pkcs_encrypt(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, CK_ULONG in_data_len, + CK_BYTE *out_data, + CK_ULONG *out_data_len, + OBJECT *key_obj, + t_rsa_encrypt rsa_encrypt_func) +{ + CK_RV rc; + CK_ULONG modulus_bytes; + CK_BYTE clear[MAX_RSA_KEYLEN], cipher[MAX_RSA_KEYLEN]; + CK_ATTRIBUTE *attr = NULL; + + /* format the data */ + rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, + &attr); + if (rc != CKR_OK) { + TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); + return rc; + } + modulus_bytes = attr->ulValueLen; + + rc = rsa_format_block(tokdata, in_data, in_data_len, clear, + modulus_bytes, PKCS_BT_2); + if (rc != CKR_OK) { + TRACE_DEVEL("rsa_format_block failed\n"); + goto done; + } + // Do an RSA public encryption + rc = rsa_encrypt_func(tokdata, clear, modulus_bytes, cipher, key_obj); + + if (rc == CKR_OK) { + memcpy(out_data, cipher, modulus_bytes); + *out_data_len = modulus_bytes; + } else { + TRACE_DEVEL("openssl_specific_rsa_encrypt failed\n"); + } + +done: + OPENSSL_cleanse(clear, sizeof(clear)); + return rc; +} + +CK_RV openssl_specific_rsa_pkcs_decrypt(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, CK_ULONG in_data_len, + CK_BYTE *out_data, + CK_ULONG *out_data_len, OBJECT *key_obj, + t_rsa_decrypt rsa_decrypt_func) +{ + CK_RV rc; + CK_BYTE out[MAX_RSA_KEYLEN]; + CK_ULONG modulus_bytes; + + modulus_bytes = in_data_len; + + rc = rsa_decrypt_func(tokdata, in_data, modulus_bytes, out, key_obj); + if (rc != CKR_OK) { + TRACE_DEVEL("openssl_specific_rsa_decrypt failed\n"); + goto done; + } + + rc = rsa_parse_block(out, modulus_bytes, out_data, out_data_len, PKCS_BT_2); + if (rc != CKR_OK) { + TRACE_DEVEL("rsa_parse_block failed\n"); + goto done; + } + + /* + * For PKCS #1 v1.5 padding, out_data_len must be less than + * modulus_bytes - 11. + */ + if (*out_data_len > (modulus_bytes - 11)) { + TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE)); + rc = CKR_ENCRYPTED_DATA_LEN_RANGE; + } + +done: + OPENSSL_cleanse(out, sizeof(out)); + return rc; +} + + +CK_RV openssl_specific_rsa_pkcs_sign(STDLL_TokData_t *tokdata, SESSION *sess, + CK_BYTE *in_data, CK_ULONG in_data_len, + CK_BYTE *signature, CK_ULONG *sig_len, + OBJECT *key_obj, + t_rsa_decrypt rsa_decrypt_func) +{ + CK_BYTE data[MAX_RSA_KEYLEN], sig[MAX_RSA_KEYLEN]; + CK_ULONG modulus_bytes; + CK_RV rc; + CK_ATTRIBUTE *attr = NULL; + + UNUSED(sess); + + /* format the data */ + rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, + &attr); + if (rc != CKR_OK) { + TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); + return rc; + } + modulus_bytes = attr->ulValueLen; + rc = rsa_format_block(tokdata, in_data, in_data_len, data, + modulus_bytes, PKCS_BT_1); + if (rc != CKR_OK) { + TRACE_DEVEL("rsa_format_block failed\n"); + return rc; + } + + /* signing is a private key operation --> decrypt */ + rc = rsa_decrypt_func(tokdata, data, modulus_bytes, sig, key_obj); + if (rc == CKR_OK) { + memcpy(signature, sig, modulus_bytes); + *sig_len = modulus_bytes; + } else { + TRACE_DEVEL("openssl_specific_rsa_decrypt failed\n"); + } + + return rc; +} + +CK_RV openssl_specific_rsa_pkcs_verify(STDLL_TokData_t *tokdata, SESSION *sess, + CK_BYTE *in_data, CK_ULONG in_data_len, + CK_BYTE *signature, CK_ULONG sig_len, + OBJECT *key_obj, + t_rsa_encrypt rsa_encrypt_func) +{ + CK_ATTRIBUTE *attr = NULL; + CK_BYTE out[MAX_RSA_KEYLEN], out_data[MAX_RSA_KEYLEN]; + CK_ULONG modulus_bytes, out_data_len; + CK_RV rc; + + UNUSED(sess); + UNUSED(sig_len); + + out_data_len = MAX_RSA_KEYLEN; + rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, + &attr); + if (rc != CKR_OK) { + TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); + return rc; + } else { + modulus_bytes = attr->ulValueLen; + } + + // verifying is a public key operation --> encrypt + // + rc = rsa_encrypt_func(tokdata, signature, modulus_bytes, out, key_obj); + if (rc != CKR_OK) { + TRACE_DEVEL("openssl_specific_rsa_encrypt failed: %lx\n", rc); + /* + * Return CKR_SIGNATURE_INVALID in case of CKR_ARGUMENTS_BAD or + * CKR_FUNCTION_FAILED because we dont know why the RSA op failed and + * it may have failed due to a tampered signature being greater or equal + * to the modulus. + */ + if (rc == CKR_ARGUMENTS_BAD || rc == CKR_FUNCTION_FAILED) { + TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); + rc = CKR_SIGNATURE_INVALID; + } + return rc; + } + + rc = rsa_parse_block(out, modulus_bytes, out_data, &out_data_len, + PKCS_BT_1); + if (rc == CKR_ENCRYPTED_DATA_INVALID) { + TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); + return CKR_SIGNATURE_INVALID; + } else if (rc != CKR_OK) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + return CKR_FUNCTION_FAILED; + } + + if (in_data_len != out_data_len) { + TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); + return CKR_SIGNATURE_INVALID; + } + + if (CRYPTO_memcmp(in_data, out_data, out_data_len) != 0) { + TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); + return CKR_SIGNATURE_INVALID; + } + + return rc; +} + +CK_RV openssl_specific_rsa_pkcs_verify_recover(STDLL_TokData_t *tokdata, + CK_BYTE *signature, + CK_ULONG sig_len, + CK_BYTE *out_data, + CK_ULONG *out_data_len, + OBJECT *key_obj, + t_rsa_encrypt rsa_encrypt_func) +{ + CK_ATTRIBUTE *attr = NULL; + CK_BYTE out[MAX_RSA_KEYLEN]; + CK_ULONG modulus_bytes; + CK_RV rc; + + UNUSED(sig_len); + + rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, + &attr); + if (rc != CKR_OK) { + TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); + return rc; + } else { + modulus_bytes = attr->ulValueLen; + } + + // verifying is a public key operation --> encrypt + // + rc = rsa_encrypt_func(tokdata, signature, modulus_bytes, out, key_obj); + if (rc != CKR_OK) { + TRACE_DEVEL("openssl_specific_rsa_encrypt failed: %lx\n", rc); + /* + * Return CKR_SIGNATURE_INVALID in case of CKR_ARGUMENTS_BAD or + * CKR_FUNCTION_FAILED because we dont know why the RSA op failed and + * it may have failed due to a tampered signature being greater or equal + * to the modulus. + */ + if (rc == CKR_ARGUMENTS_BAD || rc == CKR_FUNCTION_FAILED) { + TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); + rc = CKR_SIGNATURE_INVALID; + } + return rc; + } + + rc = rsa_parse_block(out, modulus_bytes, out_data, out_data_len, PKCS_BT_1); + if (rc == CKR_ENCRYPTED_DATA_INVALID) { + TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); + return CKR_SIGNATURE_INVALID; + } else if (rc != CKR_OK) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + } + + return rc; +} + +CK_RV openssl_specific_rsa_pss_sign(STDLL_TokData_t *tokdata, SESSION *sess, + SIGN_VERIFY_CONTEXT *ctx, + CK_BYTE *in_data, CK_ULONG in_data_len, + CK_BYTE *sig, CK_ULONG *sig_len, + t_rsa_decrypt rsa_decrypt_func) +{ + CK_RV rc; + CK_ULONG modbytes; + CK_ATTRIBUTE *attr = NULL; + OBJECT *key_obj = NULL; + CK_BYTE *emdata = NULL; + CK_RSA_PKCS_PSS_PARAMS *pssParms = NULL; + + UNUSED(sess); + + /* check the arguments */ + if (!in_data || !sig) { + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + return CKR_ARGUMENTS_BAD; + } + + if (!ctx) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + return CKR_FUNCTION_FAILED; + } + + pssParms = (CK_RSA_PKCS_PSS_PARAMS *) ctx->mech.pParameter; + + /* get the key */ + rc = object_mgr_find_in_map1(tokdata, ctx->key, &key_obj, READ_LOCK); + if (rc != CKR_OK) { + TRACE_DEVEL("object_mgr_find_in_map1 failed\n"); + return rc; + } + + rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, + &attr); + if (rc != CKR_OK) { + TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); + goto done; + } else { + modbytes = attr->ulValueLen; + } + + emdata = (CK_BYTE *) malloc(modbytes); + if (emdata == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + rc = CKR_HOST_MEMORY; + goto done; + } + + rc = emsa_pss_encode(tokdata, pssParms, in_data, in_data_len, emdata, + &modbytes); + if (rc != CKR_OK) + goto done; + + /* signing is a private key operation --> decrypt */ + rc = rsa_decrypt_func(tokdata, emdata, modbytes, sig, key_obj); + if (rc == CKR_OK) + *sig_len = modbytes; + else + TRACE_DEVEL("openssl_specific_rsa_decrypt failed\n"); + +done: + if (emdata) + free(emdata); + + object_put(tokdata, key_obj, TRUE); + key_obj = NULL; + + return rc; +} + + +CK_RV openssl_specific_rsa_pss_verify(STDLL_TokData_t *tokdata, SESSION *sess, + SIGN_VERIFY_CONTEXT *ctx, + CK_BYTE *in_data, CK_ULONG in_data_len, + CK_BYTE *signature, CK_ULONG sig_len, + t_rsa_encrypt rsa_encrypt_func) +{ + CK_RV rc; + CK_ULONG modbytes; + OBJECT *key_obj = NULL; + CK_ATTRIBUTE *attr = NULL; + CK_BYTE out[MAX_RSA_KEYLEN]; + CK_RSA_PKCS_PSS_PARAMS *pssParms = NULL; + + UNUSED(sess); + + /* check the arguments */ + if (!in_data || !signature) { + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + return CKR_ARGUMENTS_BAD; + } + + if (!ctx) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + return CKR_FUNCTION_FAILED; + } + + pssParms = (CK_RSA_PKCS_PSS_PARAMS *) ctx->mech.pParameter; + + /* get the key */ + rc = object_mgr_find_in_map1(tokdata, ctx->key, &key_obj, READ_LOCK); + if (rc != CKR_OK) { + TRACE_DEVEL("object_mgr_find_in_map1 failed\n"); + return rc; + } + + /* verify is a public key operation ... encrypt */ + rc = rsa_encrypt_func(tokdata, signature, sig_len, out, key_obj); + if (rc != CKR_OK) { + TRACE_DEVEL("openssl_specific_rsa_encrypt failed: %lx\n", rc); + /* + * Return CKR_SIGNATURE_INVALID in case of CKR_ARGUMENTS_BAD or + * CKR_FUNCTION_FAILED because we dont know why the RSA op failed and + * it may have failed due to a tampered signature being greater or equal + * to the modulus. + */ + if (rc == CKR_ARGUMENTS_BAD || rc == CKR_FUNCTION_FAILED) { + TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); + rc = CKR_SIGNATURE_INVALID; + } + goto done; + } + + rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, + &attr); + if (rc != CKR_OK) { + TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); + goto done; + } else { + modbytes = attr->ulValueLen; + } + + /* call the pss verify scheme */ + rc = emsa_pss_verify(tokdata, pssParms, in_data, in_data_len, out, + modbytes); + +done: + object_put(tokdata, key_obj, TRUE); + key_obj = NULL; + + return rc; +} + + +CK_RV openssl_specific_rsa_x509_encrypt(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, CK_ULONG in_data_len, + CK_BYTE *out_data, + CK_ULONG *out_data_len, OBJECT *key_obj, + t_rsa_encrypt rsa_encrypt_func) +{ + CK_ATTRIBUTE *attr = NULL; + CK_BYTE clear[MAX_RSA_KEYLEN], cipher[MAX_RSA_KEYLEN]; + CK_ULONG modulus_bytes; + CK_RV rc; + + rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, + &attr); + if (rc != CKR_OK) { + TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); + goto done; + } + + modulus_bytes = attr->ulValueLen; + + // prepad with zeros + // + memset(clear, 0, modulus_bytes - in_data_len); + memcpy(&clear[modulus_bytes - in_data_len], in_data, in_data_len); + + rc = rsa_encrypt_func(tokdata, clear, modulus_bytes, cipher, key_obj); + if (rc == CKR_OK) { + memcpy(out_data, cipher, modulus_bytes); + *out_data_len = modulus_bytes; + } else { + TRACE_DEVEL("openssl_specific_rsa_encrypt failed\n"); + } + +done: + OPENSSL_cleanse(clear, sizeof(clear)); + return rc; +} + +CK_RV openssl_specific_rsa_x509_decrypt(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, CK_ULONG in_data_len, + CK_BYTE *out_data, + CK_ULONG *out_data_len, OBJECT *key_obj, + t_rsa_decrypt rsa_decrypt_func) +{ + CK_ATTRIBUTE *attr = NULL; + CK_BYTE out[MAX_RSA_KEYLEN]; + CK_ULONG modulus_bytes; + CK_RV rc; + + UNUSED(in_data_len); + + rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, + &attr); + if (rc != CKR_OK) { + TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); + goto done; + } + + modulus_bytes = attr->ulValueLen; + + rc = rsa_decrypt_func(tokdata, in_data, modulus_bytes, out, key_obj); + if (rc == CKR_OK) { + memcpy(out_data, out, modulus_bytes); + *out_data_len = modulus_bytes; + } else { + TRACE_DEVEL("openssl_specific_rsa_decrypt failed\n"); + } + +done: + OPENSSL_cleanse(out, sizeof(out)); + return rc; +} + + +CK_RV openssl_specific_rsa_x509_sign(STDLL_TokData_t *tokdata, CK_BYTE *in_data, + CK_ULONG in_data_len, CK_BYTE *signature, + CK_ULONG *sig_len, OBJECT *key_obj, + t_rsa_decrypt rsa_decrypt_func) +{ + CK_ATTRIBUTE *attr = NULL; + CK_BYTE data[MAX_RSA_KEYLEN], sig[MAX_RSA_KEYLEN]; + CK_ULONG modulus_bytes; + CK_RV rc; + + rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, + &attr); + if (rc != CKR_OK) { + TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); + return rc; + } else { + modulus_bytes = attr->ulValueLen; + } + + // prepad with zeros + // + + memset(data, 0x0, modulus_bytes - in_data_len); + memcpy(&data[modulus_bytes - in_data_len], in_data, in_data_len); + + rc = rsa_decrypt_func(tokdata, data, modulus_bytes, sig, key_obj); + if (rc == CKR_OK) { + memcpy(signature, sig, modulus_bytes); + *sig_len = modulus_bytes; + } else { + TRACE_DEVEL("openssl_specific_rsa_encrypt failed: %lx\n", rc); + /* + * Return CKR_SIGNATURE_INVALID in case of CKR_ARGUMENTS_BAD or + * CKR_FUNCTION_FAILED because we dont know why the RSA op failed and + * it may have failed due to a tampered signature being greater or equal + * to the modulus. + */ + if (rc == CKR_ARGUMENTS_BAD || rc == CKR_FUNCTION_FAILED) { + TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); + rc = CKR_SIGNATURE_INVALID; + } + } + + return rc; +} + +CK_RV openssl_specific_rsa_x509_verify(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, CK_ULONG in_data_len, + CK_BYTE *signature, CK_ULONG sig_len, + OBJECT *key_obj, + t_rsa_encrypt rsa_encrypt_func) +{ + CK_ATTRIBUTE *attr = NULL; + CK_BYTE out[MAX_RSA_KEYLEN]; + CK_ULONG modulus_bytes; + CK_RV rc; + + UNUSED(sig_len); + + rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, + &attr); + if (rc != CKR_OK) { + TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); + return rc; + } else { + modulus_bytes = attr->ulValueLen; + } + + rc = rsa_encrypt_func(tokdata, signature, modulus_bytes, out, key_obj); + if (rc == CKR_OK) { + CK_ULONG pos1, pos2, len; + // it should be noted that in_data_len is not necessarily + // the same as the modulus length + // + for (pos1 = 0; pos1 < in_data_len; pos1++) + if (in_data[pos1] != 0) + break; + + for (pos2 = 0; pos2 < modulus_bytes; pos2++) + if (out[pos2] != 0) + break; + + // at this point, pos1 and pos2 point to the first non-zero + // bytes in the input data and the decrypted signature + // (the recovered data), respectively. + if ((in_data_len - pos1) != (modulus_bytes - pos2)) { + TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); + return CKR_SIGNATURE_INVALID; + } + len = in_data_len - pos1; + + if (CRYPTO_memcmp(&in_data[pos1], &out[pos2], len) != 0) { + TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); + return CKR_SIGNATURE_INVALID; + } + return CKR_OK; + } else { + TRACE_DEVEL("openssl_specific_rsa_encrypt failed: %lx\n", rc); + /* + * Return CKR_SIGNATURE_INVALID in case of CKR_ARGUMENTS_BAD or + * CKR_FUNCTION_FAILED because we dont know why the RSA op failed and + * it may have failed due to a tampered signature being greater or equal + * to the modulus. + */ + if (rc == CKR_ARGUMENTS_BAD || rc == CKR_FUNCTION_FAILED) { + TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); + rc = CKR_SIGNATURE_INVALID; + } + } + + return rc; +} + +CK_RV openssl_specific_rsa_x509_verify_recover(STDLL_TokData_t *tokdata, + CK_BYTE *signature, + CK_ULONG sig_len, + CK_BYTE *out_data, + CK_ULONG *out_data_len, + OBJECT *key_obj, + t_rsa_encrypt rsa_encrypt_func) +{ + CK_ATTRIBUTE *attr = NULL; + CK_BYTE out[MAX_RSA_KEYLEN]; + CK_ULONG modulus_bytes; + CK_RV rc; + + UNUSED(sig_len); + + rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, + &attr); + if (rc != CKR_OK) { + TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); + return rc; + } else { + modulus_bytes = attr->ulValueLen; + } + + rc = rsa_encrypt_func(tokdata, signature, modulus_bytes, out, key_obj); + if (rc == CKR_OK) { + memcpy(out_data, out, modulus_bytes); + *out_data_len = modulus_bytes; + } else { + TRACE_DEVEL("openssl_specific_rsa_encrypt failed\n"); + } + + return rc; +} + +CK_RV openssl_specific_rsa_oaep_encrypt(STDLL_TokData_t *tokdata, + ENCR_DECR_CONTEXT *ctx, + CK_BYTE *in_data, CK_ULONG in_data_len, + CK_BYTE *out_data, + CK_ULONG *out_data_len, CK_BYTE *hash, + CK_ULONG hlen, + t_rsa_encrypt rsa_encrypt_func) +{ + CK_RV rc; + CK_BYTE cipher[MAX_RSA_KEYLEN]; + CK_ULONG modulus_bytes; + CK_ATTRIBUTE *attr = NULL; + CK_BYTE *em_data = NULL; + OBJECT *key_obj = NULL; + CK_RSA_PKCS_OAEP_PARAMS_PTR oaepParms = NULL; + + if (!in_data || !out_data || !hash) { + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + return CKR_ARGUMENTS_BAD; + } + + oaepParms = (CK_RSA_PKCS_OAEP_PARAMS_PTR) ctx->mech.pParameter; + + rc = object_mgr_find_in_map1(tokdata, ctx->key, &key_obj, READ_LOCK); + if (rc != CKR_OK) { + TRACE_DEVEL("object_mgr_find_in_map1 failed\n"); + return rc; + } + + rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, + &attr); + if (rc != CKR_OK) { + TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); + goto done; + } + + modulus_bytes = attr->ulValueLen; + + /* pkcs1v2.2, section 7.1.1 Step 2: + * EME-OAEP encoding. + */ + em_data = (CK_BYTE *) malloc(modulus_bytes * sizeof(CK_BYTE)); + if (em_data == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + rc = CKR_HOST_MEMORY; + goto done; + } + + rc = encode_eme_oaep(tokdata, in_data, in_data_len, em_data, + modulus_bytes, oaepParms->mgf, hash, hlen); + if (rc != CKR_OK) + goto done; + + rc = rsa_encrypt_func(tokdata, em_data, modulus_bytes, cipher, key_obj); + if (rc == CKR_OK) { + memcpy(out_data, cipher, modulus_bytes); + *out_data_len = modulus_bytes; + } else { + TRACE_DEVEL("openssl_specific_rsa_encrypt failed\n"); + } + +done: + if (em_data) { + OPENSSL_cleanse(em_data, modulus_bytes * sizeof(CK_BYTE)); + free(em_data); + } + + object_put(tokdata, key_obj, TRUE); + key_obj = NULL; + + return rc; +} + +CK_RV openssl_specific_rsa_oaep_decrypt(STDLL_TokData_t *tokdata, + ENCR_DECR_CONTEXT *ctx, + CK_BYTE *in_data, CK_ULONG in_data_len, + CK_BYTE *out_data, + CK_ULONG *out_data_len, CK_BYTE *hash, + CK_ULONG hlen, + t_rsa_encrypt rsa_decrypt_func) +{ + CK_RV rc; + CK_BYTE *decr_data = NULL; + OBJECT *key_obj = NULL; + CK_ATTRIBUTE *attr = NULL; + CK_RSA_PKCS_OAEP_PARAMS_PTR oaepParms = NULL; + + if (!in_data || !out_data || !hash) { + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + return CKR_ARGUMENTS_BAD; + } + + oaepParms = (CK_RSA_PKCS_OAEP_PARAMS_PTR) ctx->mech.pParameter; + + rc = object_mgr_find_in_map1(tokdata, ctx->key, &key_obj, READ_LOCK); + if (rc != CKR_OK) { + TRACE_DEVEL("object_mgr_find_in_map1 failed\n"); + return rc; + } + + rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, + &attr); + if (rc != CKR_OK) { + TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); + goto error; + } + + *out_data_len = attr->ulValueLen; + + decr_data = (CK_BYTE *) malloc(in_data_len); + if (decr_data == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + rc = CKR_HOST_MEMORY; + goto error; + } + + rc = rsa_decrypt_func(tokdata, in_data, in_data_len, decr_data, key_obj); + if (rc != CKR_OK) + goto error; + + /* pkcs1v2.2, section 7.1.2 Step 2: + * EME-OAEP decoding. + */ + rc = decode_eme_oaep(tokdata, decr_data, in_data_len, out_data, + out_data_len, oaepParms->mgf, hash, hlen); + +error: + if (decr_data) { + OPENSSL_cleanse(decr_data, in_data_len); + free(decr_data); + } + + object_put(tokdata, key_obj, TRUE); + key_obj = NULL; + + return rc; +} + + +#ifndef NO_EC + +static int curve_nid_from_params(const CK_BYTE *params, CK_ULONG params_len) +{ + const unsigned char *oid; + ASN1_OBJECT *obj = NULL; + int nid; + + oid = params; + obj = d2i_ASN1_OBJECT(NULL, &oid, params_len); + if (obj == NULL || oid != params + params_len) { + TRACE_ERROR("curve not supported by OpenSSL.\n"); + return NID_undef; + } + + nid = OBJ_obj2nid(obj); + ASN1_OBJECT_free(obj); + + return nid; +} + +static int ec_prime_len_from_nid(int nid) +{ + EC_GROUP *group; + int primelen; + + group = EC_GROUP_new_by_curve_name(nid); + if (group == NULL) + return -1; + + primelen = EC_GROUP_order_bits(group); + + EC_GROUP_free(group); + + return (primelen + 7) / 8; +} + +static int ec_prime_len_from_pkey(EVP_PKEY *pkey) +{ +#if !OPENSSL_VERSION_PREREQ(3, 0) + return (EC_GROUP_order_bits(EC_KEY_get0_group( + EVP_PKEY_get0_EC_KEY(pkey))) + 7) / 8; +#else + size_t curve_len; + char curve[80]; + + if (!EVP_PKEY_get_utf8_string_param(pkey, OSSL_PKEY_PARAM_GROUP_NAME, + curve, sizeof(curve), &curve_len)) + return -1; + + return ec_prime_len_from_nid(OBJ_sn2nid(curve)); +#endif +} + + +#if !OPENSSL_VERSION_PREREQ(3, 0) +static CK_RV make_ec_key_from_params(const CK_BYTE *params, CK_ULONG params_len, + EC_KEY **key) +{ + EC_KEY *ec_key = NULL; + int nid; + CK_RV rc = CKR_OK; + + nid = curve_nid_from_params(params, params_len); + if (nid == NID_undef) { + TRACE_ERROR("curve not supported by OpenSSL.\n"); + rc = CKR_CURVE_NOT_SUPPORTED; + goto out; + } + + ec_key = EC_KEY_new_by_curve_name(nid); + if (ec_key == NULL) { + TRACE_ERROR("curve not supported by OpenSSL.\n"); + rc = CKR_CURVE_NOT_SUPPORTED; + goto out; + } + +out: + if (rc != CKR_OK) { + if (ec_key != NULL) + EC_KEY_free(ec_key); + + return rc; + } + + *key = ec_key; + + return CKR_OK; +} +#endif + +#if OPENSSL_VERSION_PREREQ(3, 0) +static CK_RV build_pkey_from_params(OSSL_PARAM_BLD *tmpl, int selection, + EVP_PKEY **pkey) +{ + + OSSL_PARAM *params = NULL; + EVP_PKEY_CTX *pctx = NULL; + CK_RV rc = CKR_OK; + + params = OSSL_PARAM_BLD_to_param(tmpl); + if (params == NULL) { + TRACE_ERROR("OSSL_PARAM_BLD_to_param failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); + if (pctx == NULL) { + TRACE_ERROR("EVP_PKEY_CTX_new_id failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + if (!EVP_PKEY_fromdata_init(pctx) || + !EVP_PKEY_fromdata(pctx, pkey, selection, params)) { + TRACE_ERROR("EVP_PKEY_fromdata failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + EVP_PKEY_CTX_free(pctx); + pctx = EVP_PKEY_CTX_new(*pkey, NULL); + if (pctx == NULL) { + TRACE_ERROR("EVP_PKEY_CTX_new failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + if (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) { + if (EVP_PKEY_check(pctx) != 1) { + TRACE_ERROR("EVP_PKEY_check failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + } else { + if (EVP_PKEY_public_check(pctx) != 1) { + TRACE_ERROR("EVP_PKEY_public_check failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + } + +out: + if (pctx != NULL) + EVP_PKEY_CTX_free(pctx); + if (params != NULL) + OSSL_PARAM_free(params); + + if (rc != 0 && *pkey != NULL) { + EVP_PKEY_free(*pkey); + *pkey = NULL; + } + + return rc; +} +#endif + +#if !OPENSSL_VERSION_PREREQ(3, 0) +static CK_RV fill_ec_key_from_pubkey(EC_KEY *ec_key, const CK_BYTE *data, + CK_ULONG data_len, CK_BBOOL allow_raw, + int nid, EVP_PKEY **ec_pkey) +#else +static CK_RV fill_ec_key_from_pubkey(OSSL_PARAM_BLD *tmpl, const CK_BYTE *data, + CK_ULONG data_len, CK_BBOOL allow_raw, + int nid, EVP_PKEY **ec_pkey) +#endif +{ + CK_BYTE *ecpoint = NULL; + CK_ULONG ecpoint_len, privlen; + CK_BBOOL allocated = FALSE; + + CK_RV rc; + + privlen = ec_prime_len_from_nid(nid); + if (privlen <= 0) { + TRACE_ERROR("ec_prime_len_from_nid failed\n"); + rc = CKR_CURVE_NOT_SUPPORTED; + goto out; + } + + rc = ec_point_from_public_data(data, data_len, privlen, allow_raw, + &allocated, &ecpoint, &ecpoint_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ec_point_from_public_data failed\n"); + goto out; + } + +#if !OPENSSL_VERSION_PREREQ(3, 0) + if (!EC_KEY_oct2key(ec_key, ecpoint, ecpoint_len, NULL)) { + TRACE_ERROR("EC_KEY_oct2key failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + if (!EC_KEY_check_key(ec_key)) { + TRACE_ERROR("EC_KEY_check_key failed\n"); + rc = CKR_PUBLIC_KEY_INVALID; + goto out; + } + + *ec_pkey = EVP_PKEY_new(); + if (*ec_pkey == NULL) { + TRACE_ERROR("EVP_PKEY_CTX_new failed.\n"); + rc = CKR_HOST_MEMORY; + goto out; + } + + if (!EVP_PKEY_assign_EC_KEY(*ec_pkey, ec_key)) { + TRACE_ERROR("EVP_PKEY_assign_EC_KEY failed.\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } +#else + if (!OSSL_PARAM_BLD_push_octet_string(tmpl, + OSSL_PKEY_PARAM_PUB_KEY, + ecpoint, ecpoint_len)) { + TRACE_ERROR("OSSL_PARAM_BLD_push_octet_string failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + rc = build_pkey_from_params(tmpl, EVP_PKEY_PUBLIC_KEY, ec_pkey); + if (rc != CKR_OK) { + TRACE_ERROR("build_pkey_from_params failed\n"); + goto out; + } + #endif + +out: + if (allocated && ecpoint != NULL) + free(ecpoint); + + return rc; +} + +#if !OPENSSL_VERSION_PREREQ(3, 0) +static CK_RV fill_ec_key_from_privkey(EC_KEY *ec_key, const CK_BYTE *data, + CK_ULONG data_len, EVP_PKEY **ec_pkey) +#else +static CK_RV fill_ec_key_from_privkey(OSSL_PARAM_BLD *tmpl, const CK_BYTE *data, + CK_ULONG data_len, int nid, + EVP_PKEY **ec_pkey) +#endif +{ + EC_POINT *point = NULL; +#if OPENSSL_VERSION_PREREQ(3, 0) + EC_GROUP *group = NULL; + BIGNUM *bn_priv = NULL; + unsigned char *pub_key = NULL; + unsigned int pub_key_len; + point_conversion_form_t form; +#endif + CK_RV rc = CKR_OK; + +#if !OPENSSL_VERSION_PREREQ(3, 0) + if (!EC_KEY_oct2priv(ec_key, data, data_len)) { + TRACE_ERROR("EC_KEY_oct2priv failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + point = EC_POINT_new(EC_KEY_get0_group(ec_key)); + if (point == NULL) { + TRACE_ERROR("EC_POINT_new failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + if (!EC_POINT_mul(EC_KEY_get0_group(ec_key), point, + EC_KEY_get0_private_key(ec_key), NULL, NULL, NULL)) { + TRACE_ERROR("EC_POINT_mul failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + if (!EC_KEY_set_public_key(ec_key, point)) { + TRACE_ERROR("EC_KEY_set_public_key failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + if (!EC_KEY_check_key(ec_key)) { + TRACE_ERROR("EC_KEY_check_key failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + *ec_pkey = EVP_PKEY_new(); + if (*ec_pkey == NULL) { + TRACE_ERROR("EVP_PKEY_CTX_new failed.\n"); + rc = CKR_HOST_MEMORY; + goto out; + } + + if (!EVP_PKEY_assign_EC_KEY(*ec_pkey, ec_key)) { + TRACE_ERROR("EVP_PKEY_assign_EC_KEY failed.\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } +#else + group = EC_GROUP_new_by_curve_name(nid); + if (group == NULL) { + TRACE_ERROR("EC_GROUP_new_by_curve_name failed\n"); + rc = CKR_CURVE_NOT_SUPPORTED; + goto out; + } + + point = EC_POINT_new(group); + if (point == NULL) { + TRACE_ERROR("EC_POINT_new failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + bn_priv = BN_bin2bn(data, data_len, NULL); + if (bn_priv == NULL) { + rc = CKR_FUNCTION_FAILED; + goto out; + } + + if (!EC_POINT_mul(group, point, bn_priv, NULL, NULL, NULL)) { + TRACE_ERROR("EC_POINT_mul failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + form = EC_GROUP_get_point_conversion_form(group); + pub_key_len = EC_POINT_point2buf(group, point, form, &pub_key, + NULL); + if (pub_key_len == 0) { + TRACE_ERROR("EC_POINT_point2buf failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + if (!OSSL_PARAM_BLD_push_octet_string(tmpl, OSSL_PKEY_PARAM_PUB_KEY, + pub_key, pub_key_len)) { + TRACE_ERROR("OSSL_PARAM_BLD_push_octet_string failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PRIV_KEY, bn_priv)) { + TRACE_ERROR("OSSL_PARAM_BLD_push_BN failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + rc = build_pkey_from_params(tmpl, EVP_PKEY_KEYPAIR, ec_pkey); + if (rc != CKR_OK) { + TRACE_ERROR("build_pkey_from_params failed\n"); + goto out; + } +#endif + +out: + if (point != NULL) + EC_POINT_free(point); +#if OPENSSL_VERSION_PREREQ(3, 0) + if (group != NULL) + EC_GROUP_free(group); + if (bn_priv != NULL) + BN_free(bn_priv); + if (pub_key != NULL) + OPENSSL_free(pub_key); +#endif + + return rc; +} + +CK_RV openssl_make_ec_key_from_template(TEMPLATE *template, EVP_PKEY **pkey) +{ + CK_ATTRIBUTE *attr = NULL; + CK_OBJECT_CLASS keyclass; + EVP_PKEY *ec_pkey = NULL; + int nid; +#if !OPENSSL_VERSION_PREREQ(3, 0) + EC_KEY *ec_key = NULL; +#else + OSSL_PARAM_BLD *tmpl = NULL; +#endif + CK_RV rc; + + rc = template_attribute_get_ulong(template, CKA_CLASS, &keyclass); + if (rc != CKR_OK) { + TRACE_ERROR("Could not find CKA_CLASS in the template\n"); + goto out; + } + + rc = template_attribute_get_non_empty(template, CKA_ECDSA_PARAMS, &attr); + if (rc != CKR_OK) { + TRACE_ERROR("Could not find CKA_ECDSA_PARAMS in the template\n"); + goto out; + } + + nid = curve_nid_from_params(attr->pValue, attr->ulValueLen); + if (nid == NID_undef) { + TRACE_ERROR("curve not supported by OpenSSL.\n"); + rc = CKR_CURVE_NOT_SUPPORTED; + goto out; + } + +#if !OPENSSL_VERSION_PREREQ(3, 0) + rc = make_ec_key_from_params(attr->pValue, attr->ulValueLen, &ec_key); + if (rc != CKR_OK) + goto out; +#else + tmpl = OSSL_PARAM_BLD_new(); + if (tmpl == NULL) { + TRACE_ERROR("OSSL_PARAM_BLD_new failed\n"); + rc = CKR_HOST_MEMORY; + goto out; + } + + if (!OSSL_PARAM_BLD_push_utf8_string(tmpl, OSSL_PKEY_PARAM_GROUP_NAME, + OBJ_nid2sn(nid), 0)) { + TRACE_ERROR("OSSL_PARAM_BLD_push_utf8_string failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } +#endif + + switch (keyclass) { + case CKO_PUBLIC_KEY: + rc = template_attribute_get_non_empty(template, CKA_EC_POINT, &attr); + if (rc != CKR_OK) { + TRACE_ERROR("Could not find CKA_EC_POINT in the template\n"); + goto out; + } + +#if !OPENSSL_VERSION_PREREQ(3, 0) + rc = fill_ec_key_from_pubkey(ec_key, attr->pValue, attr->ulValueLen, + FALSE, nid, &ec_pkey); +#else + rc = fill_ec_key_from_pubkey(tmpl, attr->pValue, attr->ulValueLen, + FALSE, nid, &ec_pkey); +#endif + if (rc != CKR_OK) { + TRACE_DEVEL("fill_ec_key_from_pubkey failed\n"); + goto out; + } + break; + + case CKO_PRIVATE_KEY: + rc = template_attribute_get_non_empty(template, CKA_VALUE, &attr); + if (rc != CKR_OK) { + TRACE_ERROR("Could not find CKA_VALUE in the template\n"); + goto out; + } + +#if !OPENSSL_VERSION_PREREQ(3, 0) + rc = fill_ec_key_from_privkey(ec_key, attr->pValue, attr->ulValueLen, + &ec_pkey); +#else + rc = fill_ec_key_from_privkey(tmpl, attr->pValue, attr->ulValueLen, + nid, &ec_pkey); + +#endif + if (rc != CKR_OK) { + TRACE_DEVEL("fill_ec_key_from_privkey failed\n"); + goto out; + } + break; + + default: + rc = CKR_KEY_FUNCTION_NOT_PERMITTED; + goto out; + } + +#if !OPENSSL_VERSION_PREREQ(3, 0) + ec_key = NULL; +#endif + + rc = CKR_OK; + +out: +#if OPENSSL_VERSION_PREREQ(3, 0) + if (tmpl != NULL) + OSSL_PARAM_BLD_free(tmpl); +#endif + + if (rc != CKR_OK) { + if (ec_pkey != NULL) + EVP_PKEY_free(ec_pkey); +#if !OPENSSL_VERSION_PREREQ(3, 0) + if (ec_key != NULL) + EC_KEY_free(ec_key); +#endif + + return rc; + } + + *pkey = ec_pkey; + + return CKR_OK; +} + +CK_RV openssl_specific_ec_generate_keypair(STDLL_TokData_t *tokdata, + TEMPLATE *publ_tmpl, + TEMPLATE *priv_tmpl) +{ + + CK_ATTRIBUTE *attr = NULL, *ec_point_attr, *value_attr, *parms_attr; +#if !OPENSSL_VERSION_PREREQ(3, 0) + const EC_KEY *ec_key = NULL; + BN_CTX *bnctx = NULL; +#else + BIGNUM *bn_d = NULL; +#endif + CK_BYTE *ecpoint = NULL, *enc_ecpoint = NULL, *d = NULL; + CK_ULONG ecpoint_len, enc_ecpoint_len, d_len; + EVP_PKEY_CTX *ctx = NULL; + EVP_PKEY *ec_pkey = NULL; + int nid; + CK_RV rc; + + UNUSED(tokdata); + + rc = template_attribute_get_non_empty(publ_tmpl, CKA_ECDSA_PARAMS, &attr); + if (rc != CKR_OK) + goto out; + + nid = curve_nid_from_params(attr->pValue, attr->ulValueLen); + if (nid == NID_undef) { + TRACE_ERROR("curve not supported by OpenSSL.\n"); + rc = CKR_CURVE_NOT_SUPPORTED; + goto out; + } + + ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); + if (ctx == NULL) { + TRACE_ERROR("EVP_PKEY_CTX_new failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + if (EVP_PKEY_keygen_init(ctx) <= 0) { + TRACE_ERROR("EVP_PKEY_keygen_init failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid) <= 0) { + TRACE_ERROR("EVP_PKEY_CTX_set_ec_paramgen_curve_nid failed\n"); + rc = CKR_CURVE_NOT_SUPPORTED; + goto out; + } + + if (EVP_PKEY_keygen(ctx, &ec_pkey) <= 0) { + TRACE_ERROR("EVP_PKEY_keygen failed\n"); + if (ERR_GET_REASON(ERR_peek_last_error()) == EC_R_INVALID_CURVE) + rc = CKR_CURVE_NOT_SUPPORTED; + else + rc = CKR_FUNCTION_FAILED; + goto out; + } + +#if !OPENSSL_VERSION_PREREQ(3, 0) + ec_key = EVP_PKEY_get0_EC_KEY(ec_pkey); + if (ec_key == NULL) { + TRACE_ERROR("EVP_PKEY_get0_EC_KEY failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + bnctx = BN_CTX_new(); + if (bnctx == NULL) { + rc = CKR_HOST_MEMORY; + goto out; + } + + ecpoint_len = EC_KEY_key2buf(ec_key, POINT_CONVERSION_UNCOMPRESSED, + &ecpoint, bnctx); + if (ecpoint_len == 0) { + TRACE_ERROR("Failed to get the EC Point compressed.\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } +#else + if (!EVP_PKEY_get_octet_string_param(ec_pkey, + OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, + NULL, 0, &ecpoint_len)) { + TRACE_ERROR("EVP_PKEY_get_octet_string_param failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + ecpoint = OPENSSL_zalloc(ecpoint_len); + if (ecpoint == NULL) { + TRACE_ERROR("OPENSSL_zalloc failed\n"); + rc = CKR_HOST_MEMORY; + goto out; + } + + if (!EVP_PKEY_get_octet_string_param(ec_pkey, + OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, + ecpoint, ecpoint_len, &ecpoint_len)) { + TRACE_ERROR("EVP_PKEY_get_octet_string_param failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } +#endif + + rc = ber_encode_OCTET_STRING(FALSE, &enc_ecpoint, &enc_ecpoint_len, + ecpoint, ecpoint_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_encode_OCTET_STRING failed\n"); + goto out; + } + + rc = build_attribute(CKA_EC_POINT, enc_ecpoint, enc_ecpoint_len, + &ec_point_attr); + if (rc != CKR_OK) { + TRACE_ERROR("build_attribute for CKA_EC_POINT failed rc=0x%lx\n", rc); + goto out; + } + rc = template_update_attribute(publ_tmpl, ec_point_attr); + if (rc != CKR_OK) { + TRACE_ERROR("template_update_attribute failed\n"); + free(ec_point_attr); + goto out; + } + +#if !OPENSSL_VERSION_PREREQ(3, 0) + d_len = EC_KEY_priv2buf(ec_key, &d); + if (d_len == 0) { + TRACE_ERROR("Failed to get the EC private key.\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } +#else + if (!EVP_PKEY_get_bn_param(ec_pkey, OSSL_PKEY_PARAM_PRIV_KEY, &bn_d)) { + TRACE_ERROR("EVP_PKEY_get_bn_param failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + d_len = ec_prime_len_from_nid(nid); + d = OPENSSL_zalloc(d_len); + if (d == NULL) { + TRACE_ERROR("OPENSSL_zalloc failed\n"); + rc = CKR_HOST_MEMORY; + goto out; + } + + BN_bn2binpad(bn_d, d, d_len); +#endif + + rc = build_attribute(CKA_VALUE, d, d_len, &value_attr); + if (rc != CKR_OK) { + TRACE_ERROR("build_attribute for CKA_VALUE failed, rc=0x%lx\n", rc); + goto out; + } + rc = template_update_attribute(priv_tmpl, value_attr); + if (rc != CKR_OK) { + TRACE_ERROR("template_update_attribute failed\n"); + free(value_attr); + goto out; + } + + + /* Add CKA_ECDSA_PARAMS to private template also */ + rc = build_attribute(CKA_ECDSA_PARAMS, attr->pValue, attr->ulValueLen, + &parms_attr); + if (rc != CKR_OK) { + TRACE_ERROR("build_attribute for CKA_ECDSA_PARAMS failed, rc=0x%lx\n", + rc); + goto out; + } + rc = template_update_attribute(priv_tmpl, parms_attr); + if (rc != CKR_OK) { + TRACE_ERROR("template_update_attribute failed\n"); + free(parms_attr); + goto out; + } + + rc = CKR_OK; + +out: + if (ctx != NULL) + EVP_PKEY_CTX_free(ctx); +#if !OPENSSL_VERSION_PREREQ(3, 0) + if (bnctx != NULL) + BN_CTX_free(bnctx); +#else + if (bn_d != NULL) + BN_free(bn_d); +#endif + if (ec_pkey != NULL) + EVP_PKEY_free(ec_pkey); + if (ecpoint != NULL) + OPENSSL_free(ecpoint); + if (enc_ecpoint != NULL) + free(enc_ecpoint); + if (d != NULL) + OPENSSL_free(d); + + return rc; +} + +CK_RV openssl_specific_ec_sign(STDLL_TokData_t *tokdata, SESSION *sess, + CK_BYTE *in_data, CK_ULONG in_data_len, + CK_BYTE *out_data, CK_ULONG *out_data_len, + OBJECT *key_obj) +{ + EVP_PKEY *ec_key; + ECDSA_SIG *sig = NULL; + const BIGNUM *r, *s; + CK_ULONG privlen, n; + CK_RV rc = CKR_OK; + EVP_PKEY_CTX *ctx = NULL; + size_t siglen; + CK_BYTE *sigbuf = NULL; + const unsigned char *p; + + UNUSED(tokdata); + UNUSED(sess); + + *out_data_len = 0; + + rc = openssl_make_ec_key_from_template(key_obj->template, &ec_key); + if (rc != CKR_OK) + return rc; + + ctx = EVP_PKEY_CTX_new(ec_key, NULL); + if (ctx == NULL) { + TRACE_ERROR("EVP_PKEY_CTX_new failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + if (EVP_PKEY_sign_init(ctx) <= 0) { + TRACE_ERROR("EVP_PKEY_sign_init failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + if (EVP_PKEY_sign(ctx, NULL, &siglen, in_data, in_data_len) <= 0) { + TRACE_ERROR("EVP_PKEY_sign failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + sigbuf = malloc(siglen); + if (sigbuf == NULL) { + TRACE_ERROR("malloc failed\n"); + rc = CKR_HOST_MEMORY; + goto out; + } + + if (EVP_PKEY_sign(ctx, sigbuf, &siglen, in_data, in_data_len) <= 0) { + TRACE_ERROR("EVP_PKEY_sign failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + p = sigbuf; + sig = d2i_ECDSA_SIG(NULL, &p, siglen); + if (sig == NULL) { + TRACE_ERROR("d2i_ECDSA_SIG failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + ECDSA_SIG_get0(sig, &r, &s); + + privlen = ec_prime_len_from_pkey(ec_key); + if (privlen <= 0) { + TRACE_ERROR("ec_prime_len_from_pkey failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + /* Insert leading 0's if r or s shorter than privlen */ + n = privlen - BN_num_bytes(r); + memset(out_data, 0, n); + BN_bn2bin(r, &out_data[n]); + + n = privlen - BN_num_bytes(s); + memset(out_data + privlen, 0x00, n); + BN_bn2bin(s, &out_data[privlen + n]); + + *out_data_len = 2 * privlen; + +out: + if (sig != NULL) + ECDSA_SIG_free(sig); + if (ec_key != NULL) + EVP_PKEY_free(ec_key); + if (sigbuf != NULL) + free(sigbuf); + if (ctx != NULL) + EVP_PKEY_CTX_free(ctx); + + return rc; +} + +CK_RV openssl_specific_ec_verify(STDLL_TokData_t *tokdata, + SESSION *sess, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *signature, + CK_ULONG signature_len, OBJECT *key_obj) +{ + EVP_PKEY *ec_key; + CK_ULONG privlen; + ECDSA_SIG *sig = NULL; + BIGNUM *r = NULL, *s = NULL; + CK_RV rc = CKR_OK; + size_t siglen; + CK_BYTE *sigbuf = NULL; + EVP_PKEY_CTX *ctx = NULL; + + UNUSED(tokdata); + UNUSED(sess); + + rc = openssl_make_ec_key_from_template(key_obj->template, &ec_key); + if (rc != CKR_OK) + return rc; + + privlen = ec_prime_len_from_pkey(ec_key); + if (privlen <= 0) { + TRACE_ERROR("ec_prime_len_from_pkey failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + if (signature_len < 2 * privlen) { + TRACE_ERROR("Signature is too short\n"); + rc = CKR_SIGNATURE_LEN_RANGE; + goto out; + } + + sig = ECDSA_SIG_new(); + if (sig == NULL) { + rc = CKR_HOST_MEMORY; + goto out; + } + + r = BN_bin2bn(signature, privlen, NULL); + s = BN_bin2bn(signature + privlen, privlen, NULL); + if (r == NULL || s == NULL) { + TRACE_ERROR("BN_bin2bn failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + if (!ECDSA_SIG_set0(sig, r, s)) { + TRACE_ERROR("ECDSA_SIG_set0 failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + siglen = i2d_ECDSA_SIG(sig, &sigbuf); + if (siglen <= 0) { + TRACE_ERROR("i2d_ECDSA_SIG failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + ctx = EVP_PKEY_CTX_new(ec_key, NULL); + if (ctx == NULL) { + TRACE_ERROR("EVP_PKEY_CTX_new failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + if (EVP_PKEY_verify_init(ctx) <= 0) { + TRACE_ERROR("EVP_PKEY_verify_init failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + rc = EVP_PKEY_verify(ctx, sigbuf, siglen, in_data, in_data_len); + switch (rc) { + case 0: + rc = CKR_SIGNATURE_INVALID; + break; + case 1: + rc = CKR_OK; + break; + default: + rc = CKR_FUNCTION_FAILED; + break; + } + +out: + if (sig != NULL) + ECDSA_SIG_free(sig); + if (ec_key != NULL) + EVP_PKEY_free(ec_key); + if (sigbuf != NULL) + OPENSSL_free(sigbuf); + if (ctx != NULL) + EVP_PKEY_CTX_free(ctx); + + return rc; +} + +CK_RV openssl_specific_ecdh_pkcs_derive(STDLL_TokData_t *tokdata, + CK_BYTE *priv_bytes, + CK_ULONG priv_length, + CK_BYTE *pub_bytes, + CK_ULONG pub_length, + CK_BYTE *secret_value, + CK_ULONG *secret_value_len, + CK_BYTE *oid, CK_ULONG oid_length) +{ +#if !OPENSSL_VERSION_PREREQ(3, 0) + EC_KEY *pub = NULL, *priv = NULL; +#else + OSSL_PARAM_BLD *tmpl = NULL; +#endif + EVP_PKEY *ec_pub = NULL, *ec_priv = NULL; + EVP_PKEY_CTX *ctx = NULL; + size_t secret_len; + int nid; + CK_RV rc; + + UNUSED(tokdata); + + nid = curve_nid_from_params(oid, oid_length); + if (nid == NID_undef) { + TRACE_ERROR("curve not supported by OpenSSL.\n"); + rc = CKR_CURVE_NOT_SUPPORTED; + goto out; + } + +#if !OPENSSL_VERSION_PREREQ(3, 0) + rc = make_ec_key_from_params(oid, oid_length, &priv); + if (rc != CKR_OK) { + TRACE_DEVEL("make_ec_key_from_params failed\n"); + goto out; + } +#else + tmpl = OSSL_PARAM_BLD_new(); + if (tmpl == NULL) { + TRACE_ERROR("OSSL_PARAM_BLD_new failed\n"); + rc = CKR_HOST_MEMORY; + goto out; + } + + if (!OSSL_PARAM_BLD_push_utf8_string(tmpl, OSSL_PKEY_PARAM_GROUP_NAME, + OBJ_nid2sn(nid), 0)) { + TRACE_ERROR("OSSL_PARAM_BLD_push_utf8_string failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } +#endif + +#if !OPENSSL_VERSION_PREREQ(3, 0) + rc = fill_ec_key_from_privkey(priv, priv_bytes, priv_length, &ec_priv); +#else + rc = fill_ec_key_from_privkey(tmpl, priv_bytes, priv_length, nid, &ec_priv); +#endif + if (rc != CKR_OK) { + TRACE_DEVEL("fill_ec_key_from_privkey failed\n"); + goto out; + } +#if !OPENSSL_VERSION_PREREQ(3, 0) + priv = NULL; +#else + OSSL_PARAM_BLD_free(tmpl); + tmpl = NULL; +#endif + +#if !OPENSSL_VERSION_PREREQ(3, 0) + rc = make_ec_key_from_params(oid, oid_length, &pub); + if (rc != CKR_OK) { + TRACE_DEVEL("make_ec_key_from_params failed\n"); + goto out; + } +#else + tmpl = OSSL_PARAM_BLD_new(); + if (tmpl == NULL) { + TRACE_ERROR("OSSL_PARAM_BLD_new failed\n"); + rc = CKR_HOST_MEMORY; + goto out; + } + + if (!OSSL_PARAM_BLD_push_utf8_string(tmpl, OSSL_PKEY_PARAM_GROUP_NAME, + OBJ_nid2sn(nid), 0)) { + TRACE_ERROR("OSSL_PARAM_BLD_push_utf8_string failed\n"); + rc = CKR_FUNCTION_FAILED; + goto out; + } +#endif + +#if !OPENSSL_VERSION_PREREQ(3, 0) + rc = fill_ec_key_from_pubkey(pub, pub_bytes, pub_length, TRUE, nid, + &ec_pub); +#else + rc = fill_ec_key_from_pubkey(tmpl, pub_bytes, pub_length, TRUE, nid, + &ec_pub); +#endif + if (rc != CKR_OK) { + TRACE_DEVEL("fill_ec_key_from_pubkey failed\n"); + goto out; + } +#if !OPENSSL_VERSION_PREREQ(3, 0) + pub = NULL; +#else + OSSL_PARAM_BLD_free(tmpl); + tmpl = NULL; +#endif + + ctx = EVP_PKEY_CTX_new(ec_priv, NULL); + if (ctx == NULL) { + TRACE_DEVEL("EVP_PKEY_CTX_new failed\n"); + goto out; + } + + if (EVP_PKEY_derive_init(ctx) <= 0 || + EVP_PKEY_derive_set_peer(ctx, ec_pub) <= 0) { + TRACE_DEVEL("EVP_PKEY_derive_init/EVP_PKEY_derive_set_peer failed\n"); + goto out; + } + + secret_len = ec_prime_len_from_nid(nid); + if (EVP_PKEY_derive(ctx, secret_value, &secret_len) <= 0) { + TRACE_DEVEL("ECDH_compute_key failed\n"); + rc = CKR_FUNCTION_FAILED; + *secret_value_len = 0; + goto out; + } + + *secret_value_len = secret_len; + +out: +#if !OPENSSL_VERSION_PREREQ(3, 0) + if (priv != NULL) + EC_KEY_free(priv); + if (pub != NULL) + EC_KEY_free(pub); +#else + if (tmpl != NULL) + OSSL_PARAM_BLD_free(tmpl); +#endif + if (ec_priv != NULL) + EVP_PKEY_free(ec_priv); + if (ec_pub != NULL) + EVP_PKEY_free(ec_pub); + if (ctx != NULL) + EVP_PKEY_CTX_free(ctx); + + return rc; +} + +#endif + +static const EVP_MD *md_from_mech(CK_MECHANISM *mech) +{ + const EVP_MD *md = NULL; + + switch (mech->mechanism) { + case CKM_SHA_1: + md = EVP_sha1(); + break; + case CKM_SHA224: + md = EVP_sha224(); + break; + case CKM_SHA256: + md = EVP_sha256(); + break; + case CKM_SHA384: + md = EVP_sha384(); + break; + case CKM_SHA512: + md = EVP_sha512(); + break; +#ifdef NID_sha512_224WithRSAEncryption + case CKM_SHA512_224: + md = EVP_sha512_224(); + break; +#endif +#ifdef NID_sha512_256WithRSAEncryption + case CKM_SHA512_256: + md = EVP_sha512_256(); + break; +#endif +#ifdef NID_sha3_224 + case CKM_IBM_SHA3_224: + md = EVP_sha3_224(); + break; +#endif +#ifdef NID_sha3_256 + case CKM_IBM_SHA3_256: + md = EVP_sha3_256(); + break; +#endif +#ifdef NID_sha3_384 + case CKM_IBM_SHA3_384: + md = EVP_sha3_384(); + break; +#endif +#ifdef NID_sha3_512 + case CKM_IBM_SHA3_512: + md = EVP_sha3_512(); + break; +#endif + default: + break; + } + + return md; +} + +#if !OPENSSL_VERSION_PREREQ(3, 0) +static EVP_MD_CTX *md_ctx_from_context(DIGEST_CONTEXT *ctx) +{ + const EVP_MD *md; + EVP_MD_CTX *md_ctx; + + md_ctx = EVP_MD_CTX_new(); + if (md_ctx == NULL) + return NULL; + + md = md_from_mech(&ctx->mech); + if (md == NULL || + !EVP_DigestInit_ex(md_ctx, md, NULL)) { + TRACE_ERROR("md_from_mech or EVP_DigestInit_ex failed\n"); + EVP_MD_CTX_free(md_ctx); + return NULL; + } + + if (ctx->context_len == 0) { + ctx->context_len = EVP_MD_meth_get_app_datasize(EVP_MD_CTX_md(md_ctx)); + ctx->context = malloc(ctx->context_len); + if (ctx->context == NULL) { + TRACE_ERROR("malloc failed\n"); + EVP_MD_CTX_free(md_ctx); + ctx->context_len = 0; + return NULL; + } + + /* Save context data for later use */ + memcpy(ctx->context, EVP_MD_CTX_md_data(md_ctx), ctx->context_len); + } else { + if (ctx->context_len != + (CK_ULONG)EVP_MD_meth_get_app_datasize(EVP_MD_CTX_md(md_ctx))) { + TRACE_ERROR("context size mismatcht\n"); + return NULL; + } + /* restore the MD context data */ + memcpy(EVP_MD_CTX_md_data(md_ctx), ctx->context, ctx->context_len); + } + + return md_ctx; +} +#endif + +#if OPENSSL_VERSION_PREREQ(3, 0) +static void openssl_specific_sha_free(STDLL_TokData_t *tokdata, SESSION *sess, + CK_BYTE *context, CK_ULONG context_len) +{ + UNUSED(tokdata); + UNUSED(sess); + UNUSED(context_len); + + EVP_MD_CTX_free((EVP_MD_CTX *)context); +} +#endif + +CK_RV openssl_specific_sha_init(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx, + CK_MECHANISM *mech) +{ +#if !OPENSSL_VERSION_PREREQ(3, 0) + EVP_MD_CTX *md_ctx; +#else + const EVP_MD *md; +#endif + + UNUSED(tokdata); + + ctx->mech.ulParameterLen = mech->ulParameterLen; + ctx->mech.mechanism = mech->mechanism; + +#if !OPENSSL_VERSION_PREREQ(3, 0) + md_ctx = md_ctx_from_context(ctx); + if (md_ctx == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + return CKR_HOST_MEMORY; + } + + EVP_MD_CTX_free(md_ctx); +#else + ctx->context_len = 1; + ctx->context = (CK_BYTE *)EVP_MD_CTX_new(); + if (ctx->context == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + return CKR_HOST_MEMORY; + } + + md = md_from_mech(&ctx->mech); + if (md == NULL || + !EVP_DigestInit_ex((EVP_MD_CTX *)ctx->context, md, NULL)) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + EVP_MD_CTX_free((EVP_MD_CTX *)ctx->context); + return CKR_FUNCTION_FAILED; + } + + ctx->state_unsaveable = CK_TRUE; + ctx->context_free_func = openssl_specific_sha_free; +#endif + + return CKR_OK; +} + +CK_RV openssl_specific_sha(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx, + CK_BYTE *in_data, CK_ULONG in_data_len, + CK_BYTE *out_data, CK_ULONG *out_data_len) +{ + unsigned int len; + CK_RV rc = CKR_OK; +#if !OPENSSL_VERSION_PREREQ(3, 0) + EVP_MD_CTX *md_ctx; +#endif + + UNUSED(tokdata); + + if (!ctx || !ctx->context) + return CKR_OPERATION_NOT_INITIALIZED; + + if (!in_data || !out_data) + return CKR_ARGUMENTS_BAD; + +#if !OPENSSL_VERSION_PREREQ(3, 0) + /* Recreate the OpenSSL MD context from the saved context */ + md_ctx = md_ctx_from_context(ctx); + if (md_ctx == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + return CKR_HOST_MEMORY; + } + + if (*out_data_len < (CK_ULONG)EVP_MD_CTX_size(md_ctx)) + return CKR_BUFFER_TOO_SMALL; + + if (!EVP_DigestUpdate(md_ctx, in_data, in_data_len) || + !EVP_DigestFinal(md_ctx, out_data, &len)) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rc = CKR_FUNCTION_FAILED; + goto out; + } + + *out_data_len = len; +#else + if (*out_data_len < (CK_ULONG)EVP_MD_CTX_size((EVP_MD_CTX *)ctx->context)) { + TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); + return CKR_BUFFER_TOO_SMALL; + } + + len = *out_data_len; + if (!EVP_DigestUpdate((EVP_MD_CTX *)ctx->context, in_data, in_data_len) || + !EVP_DigestFinal((EVP_MD_CTX *)ctx->context, out_data, &len)) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + return CKR_FUNCTION_FAILED; + } + + *out_data_len = len; +#endif + +#if !OPENSSL_VERSION_PREREQ(3, 0) +out: + EVP_MD_CTX_free(md_ctx); + free(ctx->context); +#else + EVP_MD_CTX_free((EVP_MD_CTX *)ctx->context); +#endif + ctx->context = NULL; + ctx->context_len = 0; + ctx->context_free_func = NULL; + + return rc; +} + +CK_RV openssl_specific_sha_update(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx, + CK_BYTE *in_data, CK_ULONG in_data_len) +{ +#if !OPENSSL_VERSION_PREREQ(3, 0) + EVP_MD_CTX *md_ctx; +#endif + + UNUSED(tokdata); + + if (!ctx || !ctx->context) + return CKR_OPERATION_NOT_INITIALIZED; + + if (!in_data) + return CKR_ARGUMENTS_BAD; + +#if !OPENSSL_VERSION_PREREQ(3, 0) + /* Recreate the OpenSSL MD context from the saved context */ + md_ctx = md_ctx_from_context(ctx); + if (md_ctx == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + return CKR_HOST_MEMORY; + } + + if (!EVP_DigestUpdate(md_ctx, in_data, in_data_len)) { + EVP_MD_CTX_free(md_ctx); + free(ctx->context); + ctx->context = NULL; + ctx->context_len = 0; + ctx->context_free_func = NULL; + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + return CKR_FUNCTION_FAILED; + } + + /* Save context data for later use */ + memcpy(ctx->context, EVP_MD_CTX_md_data(md_ctx), ctx->context_len); + + EVP_MD_CTX_free(md_ctx); +#else + if (!EVP_DigestUpdate((EVP_MD_CTX *)ctx->context, in_data, in_data_len)) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + return CKR_FUNCTION_FAILED; + } +#endif + + return CKR_OK; +} + +CK_RV openssl_specific_sha_final(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx, + CK_BYTE *out_data, CK_ULONG *out_data_len) +{ + unsigned int len; + CK_RV rc = CKR_OK; +#if !OPENSSL_VERSION_PREREQ(3, 0) + EVP_MD_CTX *md_ctx; +#endif + + UNUSED(tokdata); + + if (!ctx || !ctx->context) + return CKR_OPERATION_NOT_INITIALIZED; + + if (!out_data) + return CKR_ARGUMENTS_BAD; + +#if !OPENSSL_VERSION_PREREQ(3, 0) + /* Recreate the OpenSSL MD context from the saved context */ + md_ctx = md_ctx_from_context(ctx); + if (md_ctx == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + return CKR_HOST_MEMORY; + } + + if (*out_data_len < (CK_ULONG)EVP_MD_CTX_size(md_ctx)) + return CKR_BUFFER_TOO_SMALL; + + if (!EVP_DigestFinal(md_ctx, out_data, &len)) { + rc = CKR_FUNCTION_FAILED; + goto out; + } + *out_data_len = len; + +out: + EVP_MD_CTX_free(md_ctx); + free(ctx->context); + ctx->context = NULL; + ctx->context_len = 0; + ctx->context_free_func = NULL; +#else + if (*out_data_len < (CK_ULONG)EVP_MD_CTX_size((EVP_MD_CTX *)ctx->context)) { + TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); + return CKR_BUFFER_TOO_SMALL; + } + + len = *out_data_len; + if (!EVP_DigestFinal((EVP_MD_CTX *)ctx->context, out_data, &len)) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + return CKR_FUNCTION_FAILED; + } + + *out_data_len = len; + + EVP_MD_CTX_free((EVP_MD_CTX *)ctx->context); + ctx->context = NULL; + ctx->context_len = 0; + ctx->context_free_func = NULL; +#endif + + return rc; +} + +static const EVP_CIPHER *openssl_cipher_from_mech(CK_MECHANISM_TYPE mech, + CK_ULONG keylen, + CK_KEY_TYPE keytype) +{ + switch (mech) { + case CKM_DES_ECB: + if (keytype == CKK_DES && keylen == DES_KEY_SIZE) + return EVP_des_ecb(); + break; + case CKM_DES_CBC: + if (keytype == CKK_DES && keylen == DES_KEY_SIZE) + return EVP_des_cbc(); + break; + case CKM_DES3_ECB: + if (keytype == CKK_DES2 && keylen == DES_KEY_SIZE * 2) + return EVP_des_ede_ecb(); + if (keytype == CKK_DES3 && keylen == DES_KEY_SIZE * 3) + return EVP_des_ede3_ecb(); + break; + case CKM_DES3_CBC: + if (keytype == CKK_DES2 && keylen == DES_KEY_SIZE * 2) + return EVP_des_ede_cbc(); + if (keytype == CKK_DES3 && keylen == DES_KEY_SIZE * 3) + return EVP_des_ede3_cbc(); + break; + case CKM_DES_OFB64: + if (keytype == CKK_DES && keylen == DES_KEY_SIZE) + return EVP_des_ofb(); + if (keytype == CKK_DES2 && keylen == DES_KEY_SIZE * 2) + return EVP_des_ede_ofb(); + if (keytype == CKK_DES3 && keylen == DES_KEY_SIZE * 3) + return EVP_des_ede3_ofb(); + break; + case CKM_DES_CFB8: + if (keytype == CKK_DES && keylen == DES_KEY_SIZE) + return EVP_des_cfb8(); + if (keytype == CKK_DES3 && keylen == DES_KEY_SIZE * 3) + return EVP_des_ede3_cfb8(); + break; + case CKM_DES_CFB64: + if (keytype == CKK_DES && keylen == DES_KEY_SIZE) + return EVP_des_cfb64(); + if (keytype == CKK_DES2 && keylen == DES_KEY_SIZE * 2) + return EVP_des_ede_cfb64(); + if (keytype == CKK_DES3 && keylen == DES_KEY_SIZE * 3) + return EVP_des_ede3_cfb64(); + break; +#ifndef NOAES + case CKM_AES_ECB: + if (keytype != CKK_AES) + break; + switch (keylen * 8) { + case 128: + return EVP_aes_128_ecb(); + case 192: + return EVP_aes_192_ecb(); + case 256: + return EVP_aes_256_ecb(); + default: + break; + } + break; + case CKM_AES_CBC: + if (keytype != CKK_AES) + break; + switch (keylen * 8) { + case 128: + return EVP_aes_128_cbc(); + case 192: + return EVP_aes_192_cbc(); + case 256: + return EVP_aes_256_cbc(); + default: + break; + } + break; + case CKM_AES_CTR: + if (keytype != CKK_AES) + break; + switch (keylen * 8) { + case 128: + return EVP_aes_128_ctr(); + case 192: + return EVP_aes_192_ctr(); + case 256: + return EVP_aes_256_ctr(); + default: + break; + } + break; + case CKM_AES_OFB: + if (keytype != CKK_AES) + break; + switch (keylen * 8) { + case 128: + return EVP_aes_128_ofb(); + case 192: + return EVP_aes_192_ofb(); + case 256: + return EVP_aes_256_ofb(); + default: + break; + } + break; + case CKM_AES_CFB8: + if (keytype != CKK_AES) + break; + switch (keylen * 8) { + case 128: + return EVP_aes_128_cfb8(); + case 192: + return EVP_aes_192_cfb8(); + case 256: + return EVP_aes_256_cfb8(); + default: + break; + } + break; + case CKM_AES_CFB128: + if (keytype != CKK_AES) + break; + switch (keylen * 8) { + case 128: + return EVP_aes_128_cfb128(); + case 192: + return EVP_aes_192_cfb128(); + case 256: + return EVP_aes_256_cfb128(); + default: + break; + } + break; + case CKM_AES_GCM: + if (keytype != CKK_AES) + break; + switch (keylen * 8) { + case 128: + return EVP_aes_128_gcm(); + case 192: + return EVP_aes_192_gcm(); + case 256: + return EVP_aes_256_gcm(); + default: + break; + } + break; +#endif + default: + TRACE_ERROR("mechanism 0x%lx not supported\n", mech); + return NULL; + } + + TRACE_ERROR("key length %lu or key type %lu not supported for mech 0x%lx\n", + keylen, keytype, mech); + return NULL; +} + +static CK_RV openssl_cipher_perform(OBJECT *key, CK_MECHANISM_TYPE mech, + CK_BYTE *in_data, CK_ULONG in_data_len, + CK_BYTE *out_data, CK_ULONG *out_data_len, + CK_BYTE *init_v, CK_BYTE *out_v, + CK_BYTE encrypt) +{ + const EVP_CIPHER *cipher = NULL; + CK_ATTRIBUTE *key_attr = NULL; + EVP_CIPHER_CTX *ctx = NULL; + CK_KEY_TYPE keytype = 0; + int blocksize, outlen; + CK_RV rc; + + rc = template_attribute_get_ulong(key->template, CKA_KEY_TYPE, &keytype); + if (rc != CKR_OK) { + TRACE_ERROR("Could not find CKA_KEY_TYPE for the key\n"); + return rc; + } + + rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &key_attr); + if (rc != CKR_OK) { + TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); + return rc; + } + + cipher = openssl_cipher_from_mech(mech, key_attr->ulValueLen, keytype); + if (cipher == NULL) { + TRACE_ERROR("Cipher not supported.\n"); + return CKR_MECHANISM_INVALID; + } + +#if !OPENSSL_VERSION_PREREQ(3, 0) + blocksize = EVP_CIPHER_block_size(cipher); +#else + blocksize = EVP_CIPHER_get_block_size(cipher); +#endif + if (in_data_len % blocksize || in_data_len > INT_MAX) { + TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); + return CKR_DATA_LEN_RANGE; + } + + ctx = EVP_CIPHER_CTX_new(); + if (ctx == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + return CKR_HOST_MEMORY; + } + + if (EVP_CipherInit_ex(ctx, cipher, NULL, key_attr->pValue, + init_v, encrypt ? 1 : 0) != 1 + || EVP_CIPHER_CTX_set_padding(ctx, 0) != 1 + || EVP_CipherUpdate(ctx, out_data, &outlen, in_data, in_data_len) != 1 + || EVP_CipherFinal_ex(ctx, out_data, &outlen) != 1) { + TRACE_ERROR("%s\n", ock_err(ERR_GENERAL_ERROR)); + rc = CKR_GENERAL_ERROR; + goto done; + } + + if (out_v != NULL) { +#if !OPENSSL_VERSION_PREREQ(3, 0) + memcpy(out_v, EVP_CIPHER_CTX_iv(ctx), EVP_CIPHER_CTX_iv_length(ctx)); +#else + if (EVP_CIPHER_CTX_get_updated_iv(ctx, out_v, + EVP_CIPHER_CTX_get_iv_length(ctx)) != 1) { + TRACE_ERROR("%s\n", ock_err(ERR_GENERAL_ERROR)); + rc = CKR_GENERAL_ERROR; + goto done; + } +#endif + } + + *out_data_len = in_data_len; + rc = CKR_OK; + +done: + EVP_CIPHER_CTX_free(ctx); + return rc; +} + +CK_RV openssl_cmac_perform(CK_MECHANISM_TYPE mech, CK_BYTE *message, + CK_ULONG message_len, OBJECT *key, CK_BYTE *mac, + CK_BBOOL first, CK_BBOOL last, CK_VOID_PTR *ctx) +{ + int rc; + size_t maclen; + CK_RV rv = CKR_OK; + CK_ATTRIBUTE *key_attr = NULL; + const EVP_CIPHER *cipher; + CK_KEY_TYPE keytype = 0; + struct cmac_ctx { +#if !OPENSSL_VERSION_PREREQ(3, 0) + EVP_MD_CTX *mctx; + EVP_PKEY_CTX *pctx; + EVP_PKEY *pkey; +#else + EVP_MAC *mac; + EVP_MAC_CTX *mctx; +#endif + int macsize; + }; + struct cmac_ctx *cmac = NULL; +#if OPENSSL_VERSION_PREREQ(3, 0) + OSSL_PARAM params[2]; +#endif + + if (first) { + if (key == NULL) + return CKR_ARGUMENTS_BAD; + + rv = template_attribute_get_ulong(key->template, CKA_KEY_TYPE, + &keytype); + if (rv != CKR_OK) { + TRACE_ERROR("Could not find CKA_KEY_TYPE for the key\n"); + goto err; + } + + rv = template_attribute_get_non_empty(key->template, CKA_VALUE, + &key_attr); + if (rv != CKR_OK) { + TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); + goto err; + } + + switch (mech) { + case CKM_AES_CMAC: + cipher = openssl_cipher_from_mech(CKM_AES_CBC, + key_attr->ulValueLen, keytype); + break; + case CKM_DES3_CMAC: + cipher = openssl_cipher_from_mech(CKM_DES3_CBC, + key_attr->ulValueLen, + keytype); + break; + default: + TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); + rv = CKR_MECHANISM_INVALID; + goto err; + } + + if (cipher == NULL) { + TRACE_ERROR("Cipher not supported.\n"); + rv = CKR_MECHANISM_INVALID; + goto err; + } + + cmac = calloc(1, sizeof(*cmac)); + if (cmac == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + rv = CKR_HOST_MEMORY; + goto err; + } + + cmac->macsize = EVP_CIPHER_block_size(cipher); + +#if !OPENSSL_VERSION_PREREQ(3, 0) + cmac->mctx = EVP_MD_CTX_new(); + if (cmac->mctx == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + rv = CKR_HOST_MEMORY; + goto err; + } + + cmac->pkey = EVP_PKEY_new_CMAC_key(NULL, key_attr->pValue, + key_attr->ulValueLen, cipher); + if (cmac->pkey == NULL) { + TRACE_ERROR("EVP_DigestSignInit failed\n"); + rv = CKR_FUNCTION_FAILED; + goto err; + } + + if (EVP_DigestSignInit(cmac->mctx, &cmac->pctx, + NULL, NULL, cmac->pkey) != 1) { + TRACE_ERROR("EVP_DigestSignInit failed\n"); + rv = CKR_FUNCTION_FAILED; + goto err; + } +#else + cmac->mac = EVP_MAC_fetch(NULL, "CMAC", NULL); + if (cmac->mac == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rv = CKR_FUNCTION_FAILED; + goto err; + } + + cmac->mctx = EVP_MAC_CTX_new(cmac->mac); + if (cmac->mctx == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + rv = CKR_HOST_MEMORY; + goto err; + } + + params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER, + (char *)EVP_CIPHER_get0_name(cipher), 0); + params[1] = OSSL_PARAM_construct_end(); + + if (!EVP_MAC_init(cmac->mctx, key_attr->pValue, key_attr->ulValueLen, + params)) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rv = CKR_FUNCTION_FAILED; + goto err; + } +#endif + + *ctx = cmac; + } + + cmac = (struct cmac_ctx *)*ctx; + if (cmac == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rv = CKR_FUNCTION_FAILED; + goto err; + } + +#if !OPENSSL_VERSION_PREREQ(3, 0) + rc = EVP_DigestSignUpdate(cmac->mctx, message, message_len); +#else + rc = EVP_MAC_update(cmac->mctx, message, message_len); +#endif + if (rc != 1 || message_len > INT_MAX) { +#if !OPENSSL_VERSION_PREREQ(3, 0) + TRACE_ERROR("EVP_DigestSignUpdate failed\n"); +#else + TRACE_ERROR("EVP_MAC_update failed\n"); +#endif + rv = CKR_FUNCTION_FAILED; + goto err; + } + + if (last) { + maclen = cmac->macsize; +#if !OPENSSL_VERSION_PREREQ(3, 0) + rc = EVP_DigestSignFinal(cmac->mctx, mac, &maclen); +#else + rc = EVP_MAC_final(cmac->mctx, mac, &maclen, maclen); +#endif + if (rc != 1) { +#if !OPENSSL_VERSION_PREREQ(3, 0) + TRACE_ERROR("EVP_DigestSignFinal failed\n"); +#else + TRACE_ERROR("EVP_MAC_final failed\n"); +#endif + rv = CKR_FUNCTION_FAILED; + goto err; + } + +#if !OPENSSL_VERSION_PREREQ(3, 0) + EVP_MD_CTX_free(cmac->mctx); /* frees pctx */ + EVP_PKEY_free(cmac->pkey); +#else + EVP_MAC_CTX_free(cmac->mctx); + EVP_MAC_free(cmac->mac); +#endif + free(cmac); + *ctx = NULL; + } + + return CKR_OK; +err: + if (cmac != NULL) { +#if !OPENSSL_VERSION_PREREQ(3, 0) + if (cmac->mctx != NULL) + EVP_MD_CTX_free(cmac->mctx); /* frees pctx */ + if (cmac->pkey != NULL) + EVP_PKEY_free(cmac->pkey); +#else + if (cmac->mctx != NULL) + EVP_MAC_CTX_free(cmac->mctx); + if (cmac->mac != NULL) + EVP_MAC_free(cmac->mac); +#endif + free(cmac); + } + *ctx = NULL; + return rv; +} + + +#ifndef NOAES + +CK_RV openssl_specific_aes_ecb(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, + CK_ULONG *out_data_len, + OBJECT *key, CK_BYTE encrypt) +{ + UNUSED(tokdata); + + return openssl_cipher_perform(key, CKM_AES_ECB, in_data, in_data_len, + out_data, out_data_len, NULL, NULL, + encrypt); +} + +CK_RV openssl_specific_aes_cbc(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, + CK_ULONG *out_data_len, + OBJECT *key, CK_BYTE *init_v, CK_BYTE encrypt) +{ + UNUSED(tokdata); + + return openssl_cipher_perform(key, CKM_AES_CBC, in_data, in_data_len, + out_data, out_data_len, init_v, NULL, + encrypt); +} + +CK_RV openssl_specific_aes_ctr(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, + CK_ULONG *out_data_len, + OBJECT *key, + CK_BYTE *counterblock, + CK_ULONG counter_width, CK_BYTE encrypt) +{ + unsigned char init_v[AES_BLOCK_SIZE]; + CK_RV rc; + + UNUSED(tokdata); + + if (counter_width > AES_BLOCK_SIZE || counter_width == 0) { + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + return CKR_ARGUMENTS_BAD; + } + + memset(init_v, 0, sizeof(init_v)); + memcpy(init_v, counterblock + AES_BLOCK_SIZE - counter_width, + counter_width); + + rc = openssl_cipher_perform(key, CKM_AES_CTR, in_data, in_data_len, + out_data, out_data_len, init_v, init_v, + encrypt); + + if (rc == CKR_OK) + memcpy(counterblock, init_v + AES_BLOCK_SIZE - counter_width, + counter_width); + + return rc; +} + +CK_RV openssl_specific_aes_ofb(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, + OBJECT *key, + CK_BYTE *init_v, CK_BYTE encrypt) +{ + CK_ULONG out_data_len; + + UNUSED(tokdata); + + return openssl_cipher_perform(key, CKM_AES_OFB, in_data, in_data_len, + out_data, &out_data_len, init_v, init_v, + encrypt); +} + +CK_RV openssl_specific_aes_cfb(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, + OBJECT *key, + CK_BYTE *init_v, CK_ULONG cfb_len, + CK_BYTE encrypt) +{ + CK_ULONG out_data_len; + CK_MECHANISM_TYPE mech; + + UNUSED(tokdata); + + switch (cfb_len * 8) { + case 8: + mech = CKM_AES_CFB8; + break; + case 128: + mech = CKM_AES_CFB128; + break; + default: + TRACE_ERROR("CFB length %lu not supported\n", cfb_len); + return CKR_MECHANISM_INVALID; + } + + return openssl_cipher_perform(key, mech, in_data, in_data_len, + out_data, &out_data_len, init_v, init_v, + encrypt); +} + +static void openssl_specific_aes_gcm_free(STDLL_TokData_t *tokdata, + struct _SESSION *sess, + CK_BYTE *context, + CK_ULONG context_len) +{ + AES_GCM_CONTEXT *ctx = (AES_GCM_CONTEXT *)context; + + UNUSED(tokdata); + UNUSED(sess); + UNUSED(context_len); + + if (ctx == NULL) + return; + + if ((EVP_CIPHER_CTX *)ctx->ulClen != NULL) + EVP_CIPHER_CTX_free((EVP_CIPHER_CTX *)ctx->ulClen); + + free(context); +} + +CK_RV openssl_specific_aes_gcm_init(STDLL_TokData_t *tokdata, SESSION *sess, + ENCR_DECR_CONTEXT *ctx, CK_MECHANISM *mech, + CK_OBJECT_HANDLE hkey, CK_BYTE encrypt) +{ + CK_GCM_PARAMS *aes_gcm_param = NULL; + AES_GCM_CONTEXT *context = NULL; + OBJECT *key = NULL; + EVP_CIPHER_CTX *gcm_ctx = NULL; + CK_ATTRIBUTE *attr = NULL; + unsigned char akey[32]; + const EVP_CIPHER *cipher = NULL; + CK_ULONG keylen, tag_len; + int outlen; + CK_RV rc; + + UNUSED(sess); + + context = (AES_GCM_CONTEXT *)ctx->context; + aes_gcm_param = (CK_GCM_PARAMS *)mech->pParameter; + + tag_len = (aes_gcm_param->ulTagBits + 7) / 8; + if (tag_len > AES_BLOCK_SIZE) { + TRACE_ERROR("Tag len too large.\n"); + return CKR_MECHANISM_PARAM_INVALID; + } + + // get the key value + rc = object_mgr_find_in_map_nocache(tokdata, hkey, &key, READ_LOCK); + if (rc != CKR_OK) { + TRACE_ERROR("Failed to find specified object.\n"); + return rc; + } + rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); + if (rc != CKR_OK) { + TRACE_ERROR("Could not find CKA_VALUE for the key\n"); + goto done; + } + + keylen = attr->ulValueLen; + cipher = openssl_cipher_from_mech(mech->mechanism, keylen, CKK_AES); + if (cipher == NULL) { + rc = CKR_MECHANISM_INVALID; + goto done; + } + + memcpy(akey, attr->pValue, keylen); + + gcm_ctx = EVP_CIPHER_CTX_new(); + if (gcm_ctx == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + rc = CKR_HOST_MEMORY; + goto done; + } + + if (EVP_CipherInit_ex(gcm_ctx, cipher, NULL, NULL, NULL, + encrypt ? 1 : 0) != 1 || + EVP_CIPHER_CTX_ctrl(gcm_ctx, EVP_CTRL_AEAD_SET_IVLEN, + aes_gcm_param->ulIvLen, NULL) != 1 || + EVP_CipherInit_ex(gcm_ctx, NULL, NULL, akey, aes_gcm_param->pIv, + encrypt ? 1 : 0) != 1) { + TRACE_ERROR("GCM context initialization failed\n"); + rc = CKR_GENERAL_ERROR; + goto done; + } + + if (aes_gcm_param->ulAADLen > 0) { + if (EVP_CipherUpdate(gcm_ctx, NULL, &outlen, aes_gcm_param->pAAD, + aes_gcm_param->ulAADLen) != 1) { + TRACE_ERROR("GCM add AAD data failed\n"); + rc = CKR_GENERAL_ERROR; + goto done; + } + } + + /* (Miss-)use the ulClen of AES_GCM_CONTEXT to store the context */ + context->ulClen = (CK_ULONG)gcm_ctx; + ctx->state_unsaveable = CK_TRUE; + ctx->context_free_func = openssl_specific_aes_gcm_free; + +done: + object_put(tokdata, key, TRUE); + key = NULL; + + if (rc != CKR_OK) + EVP_CIPHER_CTX_free(gcm_ctx); + + return rc; +} + +CK_RV openssl_specific_aes_gcm(STDLL_TokData_t *tokdata, SESSION *sess, + ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, + CK_ULONG in_data_len, CK_BYTE *out_data, + CK_ULONG *out_data_len, CK_BYTE encrypt) +{ + AES_GCM_CONTEXT *context = NULL; + CK_GCM_PARAMS *aes_gcm_param = NULL; + EVP_CIPHER_CTX *gcm_ctx = NULL; + CK_RV rc = CKR_OK; + CK_ULONG tag_len; + int outlen, finlen; + + UNUSED(tokdata); + UNUSED(sess); + + context = (AES_GCM_CONTEXT *)ctx->context; + gcm_ctx = (EVP_CIPHER_CTX *)context->ulClen; + aes_gcm_param = (CK_GCM_PARAMS *)ctx->mech.pParameter; + + tag_len = (aes_gcm_param->ulTagBits + 7) / 8; + + if (encrypt) { + /* encrypt */ + if (EVP_CipherUpdate(gcm_ctx, out_data, &outlen, + in_data, in_data_len) != 1 || + EVP_CipherFinal_ex(gcm_ctx, out_data + outlen, &finlen) != 1) { + TRACE_ERROR("GCM add plaintext data failed\n"); + rc = CKR_GENERAL_ERROR; + goto done; + } + + /* Append the tag to the output */ + if (EVP_CIPHER_CTX_ctrl(gcm_ctx, EVP_CTRL_AEAD_GET_TAG, tag_len, + out_data + outlen + finlen) != 1) { + TRACE_ERROR("GCM get tag failed\n"); + rc = CKR_GENERAL_ERROR; + goto done; + } + + *out_data_len = outlen + finlen + tag_len; + } else { + /* decrypt data exluding the tag */ + if (EVP_CipherUpdate(gcm_ctx, out_data, &outlen, + in_data, in_data_len - tag_len) != 1) { + TRACE_ERROR("GCM add ciphertext data failed\n"); + rc = CKR_GENERAL_ERROR; + goto done; + } + + /* Set the expected tag */ + if (EVP_CIPHER_CTX_ctrl(gcm_ctx, EVP_CTRL_AEAD_SET_TAG, tag_len, + in_data + in_data_len - tag_len) != 1) { + TRACE_ERROR("GCM set tag failed\n"); + rc = CKR_GENERAL_ERROR; + goto done; + } + + /* Finalize the decryption */ + if(EVP_CipherFinal_ex(gcm_ctx, out_data + outlen, &finlen) != 1) { + TRACE_ERROR("GCM finalize decryption failed\n"); + rc = CKR_ENCRYPTED_DATA_INVALID; + goto done; + } + + *out_data_len = outlen + finlen; + } + +done: + EVP_CIPHER_CTX_free(gcm_ctx); + context->ulClen = (CK_ULONG)NULL; + + return rc; +} + +CK_RV openssl_specific_aes_gcm_update(STDLL_TokData_t *tokdata, SESSION *sess, + ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, + CK_ULONG in_data_len, CK_BYTE *out_data, + CK_ULONG *out_data_len, CK_BYTE encrypt) +{ + AES_GCM_CONTEXT *context = NULL; + CK_GCM_PARAMS *aes_gcm_param = NULL; + EVP_CIPHER_CTX *gcm_ctx = NULL; + CK_RV rc = CKR_OK; + CK_ULONG tag_len, len, out_buf_len; + int outlen; + + UNUSED(tokdata); + UNUSED(sess); + + context = (AES_GCM_CONTEXT *)ctx->context; + gcm_ctx = (EVP_CIPHER_CTX *)context->ulClen; + aes_gcm_param = (CK_GCM_PARAMS *)ctx->mech.pParameter; + + if (gcm_ctx == NULL) + return CKR_OPERATION_NOT_INITIALIZED; + + tag_len = (aes_gcm_param->ulTagBits + 7) / 8; + + if (encrypt) { + /* encrypt */ + if (*out_data_len < in_data_len) { + TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); + *out_data_len = in_data_len; + rc = CKR_BUFFER_TOO_SMALL; + goto done; + } + + if (EVP_CipherUpdate(gcm_ctx, out_data, &outlen, + in_data, in_data_len) != 1) { + TRACE_ERROR("GCM update failed\n"); + rc = CKR_GENERAL_ERROR; + goto done; + } + + *out_data_len = outlen; + } else { + /* decrypt */ + out_buf_len = *out_data_len; + *out_data_len = 0; + + /* Buffer the last tag_len input bytes */ + if (in_data_len >= tag_len) { + if (out_buf_len < context->len + (in_data_len - tag_len)) { + TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); + *out_data_len = context->len + (in_data_len - tag_len); + rc = CKR_BUFFER_TOO_SMALL; + goto done; + } + + /* push buffered data */ + if (context->len > 0) { + if (EVP_CipherUpdate(gcm_ctx, out_data, &outlen, + context->data, context->len) != 1) { + TRACE_ERROR("GCM update failed\n"); + rc = CKR_GENERAL_ERROR; + goto done; + } + context->len = 0; + *out_data_len += outlen; + out_data += outlen; + } + + /* push input data except tag_len last bytes */ + if (EVP_CipherUpdate(gcm_ctx, out_data, &outlen, + in_data, in_data_len - tag_len) != 1) { + TRACE_ERROR("GCM update failed\n"); + rc = CKR_GENERAL_ERROR; + goto done; + } + *out_data_len += outlen; + out_data += outlen; + + /* save tag in buffer */ + memcpy(context->data, in_data + in_data_len - tag_len, tag_len); + context->len = tag_len; + } else if (context->len + in_data_len > tag_len) { + /* push first bytes of buffer */ + len = context->len + in_data_len - tag_len; + if (out_buf_len < len) { + TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); + *out_data_len = len; + rc = CKR_BUFFER_TOO_SMALL; + goto done; + } + + if (EVP_CipherUpdate(gcm_ctx, out_data, &outlen, + context->data, len) != 1) { + TRACE_ERROR("GCM update failed\n"); + rc = CKR_GENERAL_ERROR; + goto done; + } + *out_data_len += outlen; + out_data += outlen; + + /* move remaining to beginning of buffer */ + memmove(context->data, &context->data[len], context->len - len); + context->len = context->len - len; + + /* append input data to buffer */ + memcpy(&context->data[context->len], in_data, in_data_len); + context->len += in_data_len; + } else { + /* append input data to buffer */ + memcpy(&context->data[context->len], in_data, in_data_len); + context->len += in_data_len; + } + } + +done: + return rc; +} + +CK_RV openssl_specific_aes_gcm_final(STDLL_TokData_t *tokdata, SESSION *sess, + ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, + CK_ULONG *out_data_len, CK_BYTE encrypt) +{ + AES_GCM_CONTEXT *context = NULL; + CK_GCM_PARAMS *aes_gcm_param = NULL; + EVP_CIPHER_CTX *gcm_ctx = NULL; + CK_RV rc = CKR_OK; + CK_ULONG tag_len; + int outlen; + + UNUSED(tokdata); + UNUSED(sess); + UNUSED(encrypt); + + context = (AES_GCM_CONTEXT *)ctx->context; + gcm_ctx = (EVP_CIPHER_CTX *)context->ulClen; + aes_gcm_param = (CK_GCM_PARAMS *)ctx->mech.pParameter; + + if (gcm_ctx == NULL) + return CKR_OPERATION_NOT_INITIALIZED; + + tag_len = (aes_gcm_param->ulTagBits + 7) / 8; + + if (encrypt) { + /* encrypt */ + if (context->len == 0) { + if (EVP_CipherFinal_ex(gcm_ctx, context->data, &outlen) != 1) { + TRACE_ERROR("GCM finalize encryption failed\n"); + rc = CKR_GENERAL_ERROR; + goto done; + } + if (outlen > 0) + context->len = outlen; + else + context->len = (CK_ULONG)-1; /* no EVP_CipherFinal again */ + } + + outlen = (context->len == (CK_ULONG)-1 ? 0 : context->len); + if (outlen + tag_len > *out_data_len) { + TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); + /* Return here, do not cleanup the context */ + *out_data_len = outlen + tag_len; + return CKR_BUFFER_TOO_SMALL; + } + + memcpy(out_data, context->data, outlen); + + /* Append the tag to the output */ + if (EVP_CIPHER_CTX_ctrl(gcm_ctx, EVP_CTRL_AEAD_GET_TAG, tag_len, + out_data + outlen) != 1) { + TRACE_ERROR("GCM get tag failed\n"); + rc = CKR_GENERAL_ERROR; + goto done; + } + + *out_data_len = outlen + tag_len; + } else { + if (context->len < tag_len) { + TRACE_ERROR("GCM ciphertext does not contain tag data\n"); + rc = CKR_ENCRYPTED_DATA_INVALID; + goto done; + } + + if (*out_data_len < AES_BLOCK_SIZE) { + TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); + /* Return here, do not cleanup the context */ + *out_data_len = AES_BLOCK_SIZE; + return CKR_BUFFER_TOO_SMALL; + } + + /* Set the expected tag */ + if (EVP_CIPHER_CTX_ctrl(gcm_ctx, EVP_CTRL_AEAD_SET_TAG, tag_len, + context->data) != 1) { + TRACE_ERROR("GCM set tag failed\n"); + rc = CKR_GENERAL_ERROR; + goto done; + } + + /* Finalize the decryption */ + if(EVP_CipherFinal_ex(gcm_ctx, out_data, &outlen) != 1) { + TRACE_ERROR("GCM finalize decryption failed\n"); + rc = CKR_ENCRYPTED_DATA_INVALID; + goto done; + } + + *out_data_len = outlen; + } + +done: + EVP_CIPHER_CTX_free(gcm_ctx); + context->ulClen = (CK_ULONG)NULL; + + return rc; +} + +CK_RV openssl_specific_aes_mac(STDLL_TokData_t *tokdata, CK_BYTE *message, + CK_ULONG message_len, OBJECT *key, CK_BYTE *mac) +{ + CK_BYTE *out_buf; + CK_ULONG out_len; + CK_RV rc; + + out_buf = malloc(message_len); + if (out_buf == NULL) { + TRACE_ERROR("Malloc failed.\n"); + return CKR_HOST_MEMORY; + } + + rc = openssl_specific_aes_cbc(tokdata, message, message_len, out_buf, + &out_len, key, mac, 1); + + if (rc == CKR_OK && out_len >= AES_BLOCK_SIZE) + memcpy(mac, out_buf + out_len - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + + free(out_buf); + + return rc; +} + +CK_RV openssl_specific_aes_cmac(STDLL_TokData_t *tokdata, CK_BYTE *message, + CK_ULONG message_len, OBJECT *key, CK_BYTE *mac, + CK_BBOOL first, CK_BBOOL last, CK_VOID_PTR *ctx) +{ + UNUSED(tokdata); + + return openssl_cmac_perform(CKM_AES_CMAC, message, message_len, key, mac, + first, last, ctx); +} + +#endif + +CK_RV openssl_specific_des_ecb(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, + CK_ULONG *out_data_len, + OBJECT *key, CK_BYTE encrypt) +{ + UNUSED(tokdata); + + return openssl_cipher_perform(key, CKM_DES_ECB, in_data, in_data_len, + out_data, out_data_len, NULL, NULL, + encrypt); +} + +CK_RV openssl_specific_des_cbc(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, + CK_ULONG *out_data_len, + OBJECT *key, CK_BYTE *init_v, CK_BYTE encrypt) +{ + UNUSED(tokdata); + + return openssl_cipher_perform(key, CKM_DES_CBC, in_data, in_data_len, + out_data, out_data_len, init_v, NULL, + encrypt); +} + +CK_RV openssl_specific_tdes_ecb(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, + CK_ULONG *out_data_len, + OBJECT *key, CK_BYTE encrypt) +{ + UNUSED(tokdata); + + return openssl_cipher_perform(key, CKM_DES3_ECB, in_data, in_data_len, + out_data, out_data_len, NULL, NULL, + encrypt); +} + +CK_RV openssl_specific_tdes_cbc(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, + CK_ULONG *out_data_len, + OBJECT *key, CK_BYTE *init_v, CK_BYTE encrypt) +{ + UNUSED(tokdata); + + return openssl_cipher_perform(key, CKM_DES3_CBC, in_data, in_data_len, + out_data, out_data_len, init_v, NULL, + encrypt); +} + +CK_RV openssl_specific_tdes_ofb(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, + OBJECT *key, CK_BYTE *init_v, CK_BYTE encrypt) +{ + CK_ULONG out_data_len; + + UNUSED(tokdata); + + return openssl_cipher_perform(key, CKM_DES_OFB64, in_data, in_data_len, + out_data, &out_data_len, init_v, init_v, + encrypt); + +} + +CK_RV openssl_specific_tdes_cfb(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, + OBJECT *key, + CK_BYTE *init_v, CK_ULONG cfb_len, + CK_BYTE encrypt) +{ + CK_ULONG out_data_len; + CK_MECHANISM_TYPE mech; + + UNUSED(tokdata); + + switch (cfb_len * 8) { + case 8: + mech = CKM_DES_CFB8; + break; + case 64: + mech = CKM_DES_CFB64; + break; + default: + TRACE_ERROR("CFB length %lu not supported\n", cfb_len); + return CKR_MECHANISM_INVALID; + } + + return openssl_cipher_perform(key, mech, in_data, in_data_len, + out_data, &out_data_len, init_v, init_v, + encrypt); +} + +CK_RV openssl_specific_tdes_mac(STDLL_TokData_t *tokdata, CK_BYTE *message, + CK_ULONG message_len, OBJECT *key, CK_BYTE *mac) +{ + CK_BYTE *out_buf; + CK_ULONG out_len; + CK_RV rc; + + out_buf = malloc(message_len); + if (out_buf == NULL) { + TRACE_ERROR("Malloc failed.\n"); + return CKR_HOST_MEMORY; + } + + rc = openssl_specific_tdes_cbc(tokdata, message, message_len, out_buf, + &out_len, key, mac, 1); + + if (rc == CKR_OK && out_len >= DES_BLOCK_SIZE) + memcpy(mac, out_buf + out_len - DES_BLOCK_SIZE, DES_BLOCK_SIZE); + + free(out_buf); + + return rc; +} + +CK_RV openssl_specific_tdes_cmac(STDLL_TokData_t *tokdata, CK_BYTE *message, + CK_ULONG message_len, OBJECT *key, CK_BYTE *mac, + CK_BBOOL first, CK_BBOOL last, CK_VOID_PTR *ctx) +{ + UNUSED(tokdata); + + return openssl_cmac_perform(CKM_DES3_CMAC, message, message_len, key, mac, + first, last, ctx); +} + +CK_RV openssl_specific_hmac_init(STDLL_TokData_t *tokdata, + SIGN_VERIFY_CONTEXT *ctx, + CK_MECHANISM_PTR mech, + CK_OBJECT_HANDLE Hkey) +{ + int rc; + OBJECT *key = NULL; + CK_ATTRIBUTE *attr = NULL; + EVP_MD_CTX *mdctx = NULL; + EVP_PKEY *pkey = NULL; + + rc = object_mgr_find_in_map1(tokdata, Hkey, &key, READ_LOCK); + if (rc != CKR_OK) { + TRACE_ERROR("Failed to find specified object.\n"); + return rc; + } + + rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); + if (rc != CKR_OK) { + TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); + goto done; + } + + pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, attr->pValue, + attr->ulValueLen); + if (pkey == NULL) { + TRACE_ERROR("EVP_PKEY_new_mac_key() failed.\n"); + rc = CKR_FUNCTION_FAILED; + goto done; + } + + mdctx = EVP_MD_CTX_create(); + if (mdctx == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + rc = CKR_HOST_MEMORY; + goto done; + } + + switch (mech->mechanism) { + case CKM_SHA_1_HMAC_GENERAL: + case CKM_SHA_1_HMAC: + rc = EVP_DigestSignInit(mdctx, NULL, EVP_sha1(), NULL, pkey); + break; + case CKM_SHA224_HMAC_GENERAL: + case CKM_SHA224_HMAC: + rc = EVP_DigestSignInit(mdctx, NULL, EVP_sha224(), NULL, pkey); + break; + case CKM_SHA256_HMAC_GENERAL: + case CKM_SHA256_HMAC: + rc = EVP_DigestSignInit(mdctx, NULL, EVP_sha256(), NULL, pkey); + break; + case CKM_SHA384_HMAC_GENERAL: + case CKM_SHA384_HMAC: + rc = EVP_DigestSignInit(mdctx, NULL, EVP_sha384(), NULL, pkey); + break; + case CKM_SHA512_HMAC_GENERAL: + case CKM_SHA512_HMAC: + rc = EVP_DigestSignInit(mdctx, NULL, EVP_sha512(), NULL, pkey); + break; +#ifdef NID_sha512_224WithRSAEncryption + case CKM_SHA512_224_HMAC_GENERAL: + case CKM_SHA512_224_HMAC: + rc = EVP_DigestSignInit(mdctx, NULL, EVP_sha512_224(), NULL, pkey); + break; +#endif +#ifdef NID_sha512_256WithRSAEncryption + case CKM_SHA512_256_HMAC_GENERAL: + case CKM_SHA512_256_HMAC: + rc = EVP_DigestSignInit(mdctx, NULL, EVP_sha512_256(), NULL, pkey); + break; +#endif +#ifdef NID_sha3_224 + case CKM_IBM_SHA3_224_HMAC: + rc = EVP_DigestSignInit(mdctx, NULL, EVP_sha3_224(), NULL, pkey); + break; +#endif +#ifdef NID_sha3_256 + case CKM_IBM_SHA3_256_HMAC: + rc = EVP_DigestSignInit(mdctx, NULL, EVP_sha3_256(), NULL, pkey); + break; +#endif +#ifdef NID_sha3_384 + case CKM_IBM_SHA3_384_HMAC: + rc = EVP_DigestSignInit(mdctx, NULL, EVP_sha3_384(), NULL, pkey); + break; +#endif +#ifdef NID_sha3_512 + case CKM_IBM_SHA3_512_HMAC: + rc = EVP_DigestSignInit(mdctx, NULL, EVP_sha3_512(), NULL, pkey); + break; +#endif + default: + EVP_MD_CTX_destroy(mdctx); + TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); + rc = CKR_MECHANISM_INVALID; + goto done; + } + + if (rc != 1) { + EVP_MD_CTX_destroy(mdctx); + ctx->context = NULL; + TRACE_ERROR("EVP_DigestSignInit failed.\n"); + rc = CKR_FUNCTION_FAILED; + goto done; + } else { + ctx->context = (CK_BYTE *) mdctx; + } + + rc = CKR_OK; +done: + if (pkey != NULL) + EVP_PKEY_free(pkey); + + object_put(tokdata, key, TRUE); + key = NULL; + return rc; +} + +CK_RV openssl_specific_hmac(SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, + CK_ULONG in_data_len, CK_BYTE *signature, + CK_ULONG *sig_len, CK_BBOOL sign) +{ + int rc; + size_t mac_len, len; + unsigned char mac[MAX_SHA_HASH_SIZE]; + EVP_MD_CTX *mdctx = NULL; + CK_RV rv = CKR_OK; + CK_BBOOL general = FALSE; + + if (!ctx || !ctx->context) { + TRACE_ERROR("%s received bad argument(s)\n", __func__); + return CKR_FUNCTION_FAILED; + } + + if (sign && !sig_len) { + TRACE_ERROR("%s received bad argument(s)\n", __func__); + return CKR_FUNCTION_FAILED; + } + + switch (ctx->mech.mechanism) { + case CKM_SHA_1_HMAC_GENERAL: + general = TRUE; + /* fallthrough */ + case CKM_SHA_1_HMAC: + mac_len = SHA1_HASH_SIZE; + break; + case CKM_SHA224_HMAC_GENERAL: +#ifdef NID_sha512_224WithRSAEncryption + case CKM_SHA512_224_HMAC_GENERAL: +#endif + general = TRUE; + /* fallthrough */ + case CKM_SHA224_HMAC: +#ifdef NID_sha512_224WithRSAEncryption + case CKM_SHA512_224_HMAC: +#endif + mac_len = SHA224_HASH_SIZE; + break; + case CKM_SHA256_HMAC_GENERAL: +#ifdef NID_sha512_256WithRSAEncryption + case CKM_SHA512_256_HMAC_GENERAL: +#endif + general = TRUE; + /* fallthrough */ + case CKM_SHA256_HMAC: +#ifdef NID_sha512_256WithRSAEncryption + case CKM_SHA512_256_HMAC: +#endif + mac_len = SHA256_HASH_SIZE; + break; + case CKM_SHA384_HMAC_GENERAL: + general = TRUE; + /* fallthrough */ + case CKM_SHA384_HMAC: + mac_len = SHA384_HASH_SIZE; + break; + case CKM_SHA512_HMAC_GENERAL: + general = TRUE; + /* fallthrough */ + case CKM_SHA512_HMAC: + mac_len = SHA512_HASH_SIZE; + break; +#ifdef NID_sha3_224 + case CKM_IBM_SHA3_224_HMAC: + mac_len = SHA3_224_HASH_SIZE; + break; +#endif +#ifdef NID_sha3_256 + case CKM_IBM_SHA3_256_HMAC: + mac_len = SHA3_256_HASH_SIZE; + break; +#endif +#ifdef NID_sha3_384 + case CKM_IBM_SHA3_384_HMAC: + mac_len = SHA3_384_HASH_SIZE; + break; +#endif +#ifdef NID_sha3_512 + case CKM_IBM_SHA3_512_HMAC: + mac_len = SHA3_512_HASH_SIZE; + break; +#endif + default: + TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); + return CKR_MECHANISM_INVALID; + } + + mdctx = (EVP_MD_CTX *) ctx->context; + + rc = EVP_DigestSignUpdate(mdctx, in_data, in_data_len); + if (rc != 1) { + TRACE_ERROR("EVP_DigestSignUpdate failed.\n"); + rv = CKR_FUNCTION_FAILED; + goto done; + } + + rc = EVP_DigestSignFinal(mdctx, mac, &mac_len); + if (rc != 1) { + TRACE_ERROR("EVP_DigestSignFinal failed.\n"); + rv = CKR_FUNCTION_FAILED; + goto done; + } + + if (sign) { + if (general) + *sig_len = *(CK_ULONG *) ctx->mech.pParameter; + else + *sig_len = mac_len; + + memcpy(signature, mac, *sig_len); + + } else { + if (general) + len = *(CK_ULONG *) ctx->mech.pParameter; + else + len = mac_len; + + if (CRYPTO_memcmp(signature, mac, len) != 0) { + TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); + rv = CKR_SIGNATURE_INVALID; + } + } +done: + EVP_MD_CTX_destroy(mdctx); + ctx->context = NULL; + + return rv; +} + +CK_RV openssl_specific_hmac_update(SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, + CK_ULONG in_data_len, CK_BBOOL sign) +{ + int rc; + EVP_MD_CTX *mdctx = NULL; + CK_RV rv = CKR_OK; + + UNUSED(sign); + + if (!ctx || !ctx->context) + return CKR_OPERATION_NOT_INITIALIZED; + + mdctx = (EVP_MD_CTX *) ctx->context; + + rc = EVP_DigestSignUpdate(mdctx, in_data, in_data_len); + if (rc != 1) { + TRACE_ERROR("EVP_DigestSignUpdate failed.\n"); + rv = CKR_FUNCTION_FAILED; + } else { + ctx->context = (CK_BYTE *) mdctx; + return CKR_OK; + } + + EVP_MD_CTX_destroy(mdctx); + ctx->context = NULL; + return rv; +} + +CK_RV openssl_specific_hmac_final(SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *signature, + CK_ULONG *sig_len, CK_BBOOL sign) +{ + int rc; + size_t mac_len, len; + unsigned char mac[MAX_SHA_HASH_SIZE]; + EVP_MD_CTX *mdctx = NULL; + CK_RV rv = CKR_OK; + CK_BBOOL general = FALSE; + + if (!ctx || !ctx->context) + return CKR_OPERATION_NOT_INITIALIZED; + + if (sign && !sig_len) { + TRACE_ERROR("%s received bad argument(s)\n", __func__); + return CKR_FUNCTION_FAILED; + } + + switch (ctx->mech.mechanism) { + case CKM_SHA_1_HMAC_GENERAL: + general = TRUE; + /* fallthrough */ + case CKM_SHA_1_HMAC: + mac_len = SHA1_HASH_SIZE; + break; + case CKM_SHA224_HMAC_GENERAL: + general = TRUE; + /* fallthrough */ + case CKM_SHA224_HMAC: + mac_len = SHA224_HASH_SIZE; + break; + case CKM_SHA256_HMAC_GENERAL: + general = TRUE; + /* fallthrough */ + case CKM_SHA256_HMAC: + mac_len = SHA256_HASH_SIZE; + break; + case CKM_SHA384_HMAC_GENERAL: + general = TRUE; + /* fallthrough */ + case CKM_SHA384_HMAC: + mac_len = SHA384_HASH_SIZE; + break; + case CKM_SHA512_HMAC_GENERAL: + general = TRUE; + /* fallthrough */ + case CKM_SHA512_HMAC: + mac_len = SHA512_HASH_SIZE; + break; +#ifdef NID_sha3_224 + case CKM_IBM_SHA3_224_HMAC: + mac_len = SHA3_224_HASH_SIZE; + break; +#endif +#ifdef NID_sha3_256 + case CKM_IBM_SHA3_256_HMAC: + mac_len = SHA3_256_HASH_SIZE; + break; +#endif +#ifdef NID_sha3_384 + case CKM_IBM_SHA3_384_HMAC: + mac_len = SHA3_384_HASH_SIZE; + break; +#endif +#ifdef NID_sha3_512 + case CKM_IBM_SHA3_512_HMAC: + mac_len = SHA3_512_HASH_SIZE; + break; +#endif + default: + TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); + return CKR_MECHANISM_INVALID; + } + + if (signature == NULL) { + if (sign) { + if (general) + *sig_len = *(CK_ULONG *) ctx->mech.pParameter; + else + *sig_len = (CK_ULONG) mac_len; + } + return CKR_OK; + } + + mdctx = (EVP_MD_CTX *) ctx->context; + + rc = EVP_DigestSignFinal(mdctx, mac, &mac_len); + if (rc != 1) { + TRACE_ERROR("EVP_DigestSignFinal failed.\n"); + rv = CKR_FUNCTION_FAILED; + goto done; + } + + if (sign) { + if (general) + *sig_len = *(CK_ULONG *) ctx->mech.pParameter; + else + *sig_len = mac_len; + + memcpy(signature, mac, *sig_len); + + } else { + if (general) + len = *(CK_ULONG *) ctx->mech.pParameter; + else + len = mac_len; + + if (CRYPTO_memcmp(signature, mac, len) != 0) { + TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); + rv = CKR_SIGNATURE_INVALID; + } + } +done: + EVP_MD_CTX_destroy(mdctx); + ctx->context = NULL; + return rv; +} diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/mech_rsa.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/mech_rsa.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/mech_rsa.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/mech_rsa.c 2022-02-02 15:05:41.000000000 +0100 @@ -307,32 +307,6 @@ return rc; } -/* helper function for rsa-oaep */ -CK_RV get_mgf_mech(CK_RSA_PKCS_MGF_TYPE mgf, CK_MECHANISM_TYPE *mech) -{ - switch (mgf) { - case CKG_MGF1_SHA1: - *mech = CKM_SHA_1; - break; - case CKG_MGF1_SHA224: - *mech = CKM_SHA224; - break; - case CKG_MGF1_SHA256: - *mech = CKM_SHA256; - break; - case CKG_MGF1_SHA384: - *mech = CKM_SHA384; - break; - case CKG_MGF1_SHA512: - *mech = CKM_SHA512; - break; - default: - return CKR_MECHANISM_INVALID; - } - - return CKR_OK; -} - // // CK_RV rsa_pkcs_encrypt(STDLL_TokData_t *tokdata, @@ -602,6 +576,10 @@ goto done; } + /* Release obj lock, token specific rsa-oaep may re-acquire the lock */ + object_put(tokdata, key_obj, TRUE); + key_obj = NULL; + rc = token_specific.t_rsa_oaep_encrypt(tokdata, ctx, in_data, in_data_len, out_data, out_data_len, hash, hlen); @@ -625,6 +603,10 @@ goto done; } + /* Release obj lock, token specific rsa-oaep may re-acquire the lock */ + object_put(tokdata, key_obj, TRUE); + key_obj = NULL; + rc = token_specific.t_rsa_oaep_decrypt(tokdata, ctx, in_data, in_data_len, out_data, out_data_len, hash, hlen); @@ -1331,6 +1313,10 @@ goto done; } + /* Release obj lock, token specific rsa_pss may re-acquire the lock */ + object_put(tokdata, key_obj, TRUE); + key_obj = NULL; + rc = token_specific.t_rsa_pss_sign(tokdata, sess, ctx, in_data, in_data_len, out_data, out_data_len); if (rc != CKR_OK) @@ -1389,6 +1375,10 @@ goto done; } + /* Release obj lock, token specific rsa_pss may re-acquire the lock */ + object_put(tokdata, key_obj, TRUE); + key_obj = NULL; + rc = token_specific.t_rsa_pss_verify(tokdata, sess, ctx, in_data, in_data_len, signature, sig_len); if (rc != CKR_OK) @@ -1450,7 +1440,7 @@ return CKR_MECHANISM_PARAM_INVALID; } - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); + rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; @@ -1460,7 +1450,7 @@ in_data, in_data_len, hash, &hlen); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Digest failed.\n"); - digest_mgr_cleanup(&digest_ctx); + digest_mgr_cleanup(tokdata, sess, &digest_ctx); return rc; } @@ -1469,7 +1459,8 @@ sign_mech.ulParameterLen = ctx->mech.ulParameterLen; sign_mech.pParameter = ctx->mech.pParameter; - rc = sign_mgr_init(tokdata, sess, &sign_ctx, &sign_mech, FALSE, ctx->key); + rc = sign_mgr_init(tokdata, sess, &sign_ctx, &sign_mech, FALSE, ctx->key, + FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Sign Mgr Init failed.\n"); goto done; @@ -1481,7 +1472,7 @@ TRACE_DEVEL("Sign Mgr Sign failed.\n"); done: - sign_mgr_cleanup(&sign_ctx); + sign_mgr_cleanup(tokdata, sess, &sign_ctx); return rc; } @@ -1525,11 +1516,12 @@ digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; - rc = digest_mgr_init(tokdata, sess, digest_ctx, &digest_mech); + rc = digest_mgr_init(tokdata, sess, digest_ctx, &digest_mech, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } + ctx->state_unsaveable |= digest_ctx->state_unsaveable; } rc = digest_mgr_digest_update(tokdata, sess, digest_ctx, in_data, @@ -1585,7 +1577,8 @@ sign_mech.ulParameterLen = ctx->mech.ulParameterLen; sign_mech.pParameter = ctx->mech.pParameter; - rc = sign_mgr_init(tokdata, sess, &sign_ctx, &sign_mech, FALSE, ctx->key); + rc = sign_mgr_init(tokdata, sess, &sign_ctx, &sign_mech, FALSE, ctx->key, + FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Sign Mgr Init failed.\n"); goto done; @@ -1597,7 +1590,7 @@ TRACE_DEVEL("Sign Mgr Sign failed.\n"); done: - sign_mgr_cleanup(&sign_ctx); + sign_mgr_cleanup(tokdata, sess, &sign_ctx); return rc; } @@ -1650,7 +1643,7 @@ return CKR_MECHANISM_PARAM_INVALID; } - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); + rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; @@ -1660,7 +1653,7 @@ in_data_len, hash, &hlen); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Digest failed.\n"); - digest_mgr_cleanup(&digest_ctx); + digest_mgr_cleanup(tokdata, sess, &digest_ctx); return rc; } @@ -1670,7 +1663,7 @@ verify_mech.pParameter = ctx->mech.pParameter; rc = verify_mgr_init(tokdata, sess, &verify_ctx, &verify_mech, FALSE, - ctx->key); + ctx->key, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Verify Mgr Init failed.\n"); goto done; @@ -1682,7 +1675,7 @@ TRACE_DEVEL("Verify Mgr Verify failed.\n"); done: - verify_mgr_cleanup(&verify_ctx); + verify_mgr_cleanup(tokdata, sess, &verify_ctx); return rc; } @@ -1732,7 +1725,7 @@ verify_mech.pParameter = ctx->mech.pParameter; rc = verify_mgr_init(tokdata, sess, &verify_ctx, &verify_mech, FALSE, - ctx->key); + ctx->key, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Verify Mgr Init failed.\n"); goto done; @@ -1744,7 +1737,7 @@ TRACE_DEVEL("Verify Mgr Verify failed.\n"); done: - verify_mgr_cleanup(&verify_ctx); + verify_mgr_cleanup(tokdata, sess, &verify_ctx); return rc; } @@ -1816,7 +1809,7 @@ digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); + rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; @@ -1826,7 +1819,7 @@ in_data_len, hash, &hash_len); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Digest failed.\n"); - digest_mgr_cleanup(&digest_ctx); + digest_mgr_cleanup(tokdata, sess, &digest_ctx); return rc; } // build the BER-encodings @@ -1854,7 +1847,8 @@ sign_mech.ulParameterLen = 0; sign_mech.pParameter = NULL; - rc = sign_mgr_init(tokdata, sess, &sign_ctx, &sign_mech, FALSE, ctx->key); + rc = sign_mgr_init(tokdata, sess, &sign_ctx, &sign_mech, FALSE, ctx->key, + FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Sign Mgr Init failed.\n"); goto error; @@ -1869,7 +1863,7 @@ free(octet_str); if (ber_data) free(ber_data); - sign_mgr_cleanup(&sign_ctx); + sign_mgr_cleanup(tokdata, sess, &sign_ctx); return rc; } @@ -1912,12 +1906,13 @@ digest_mech.pParameter = NULL; rc = digest_mgr_init(tokdata, sess, &context->hash_context, - &digest_mech); + &digest_mech, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } context->flag = TRUE; + ctx->state_unsaveable |= context->hash_context.state_unsaveable; } rc = digest_mgr_digest_update(tokdata, sess, &context->hash_context, @@ -1995,7 +1990,7 @@ digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); + rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; @@ -2005,7 +2000,7 @@ in_data_len, hash, &hash_len); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Digest failed.\n"); - digest_mgr_cleanup(&digest_ctx); + digest_mgr_cleanup(tokdata, sess, &digest_ctx); return rc; } // Build the BER encoding @@ -2033,7 +2028,7 @@ verify_mech.pParameter = NULL; rc = verify_mgr_init(tokdata, sess, &verify_ctx, &verify_mech, FALSE, - ctx->key); + ctx->key, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Verify Mgr Init failed.\n"); goto done; @@ -2047,7 +2042,7 @@ free(octet_str); if (ber_data) free(ber_data); - sign_mgr_cleanup(&verify_ctx); + sign_mgr_cleanup(tokdata, sess, &verify_ctx); return rc; } @@ -2089,12 +2084,13 @@ digest_mech.pParameter = NULL; rc = digest_mgr_init(tokdata, sess, &context->hash_context, - &digest_mech); + &digest_mech, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } context->flag = TRUE; + ctx->state_unsaveable |= context->hash_context.state_unsaveable; } rc = digest_mgr_digest_update(tokdata, sess, &context->hash_context, @@ -2201,7 +2197,8 @@ sign_mech.ulParameterLen = 0; sign_mech.pParameter = NULL; - rc = sign_mgr_init(tokdata, sess, &sign_ctx, &sign_mech, FALSE, ctx->key); + rc = sign_mgr_init(tokdata, sess, &sign_ctx, &sign_mech, FALSE, ctx->key, + FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Sign Mgr Init failed.\n"); goto done; @@ -2220,7 +2217,7 @@ free(octet_str); if (ber_data) free(ber_data); - sign_mgr_cleanup(&sign_ctx); + sign_mgr_cleanup(tokdata, sess, &sign_ctx); return rc; } @@ -2317,7 +2314,7 @@ verify_mech.pParameter = NULL; rc = verify_mgr_init(tokdata, sess, &verify_ctx, &verify_mech, FALSE, - ctx->key); + ctx->key, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Verify Mgr Init failed.\n"); goto done; @@ -2331,7 +2328,7 @@ free(octet_str); if (ber_data) free(ber_data); - verify_mgr_cleanup(&verify_ctx); + verify_mgr_cleanup(tokdata, sess, &verify_ctx); return rc; } diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/mech_sha.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/mech_sha.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/mech_sha.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/mech_sha.c 2022-02-02 15:05:41.000000000 +0100 @@ -38,30 +38,52 @@ #include "tok_spec_struct.h" #include "trace.h" -#include +#include #include // // Software SHA-1 implementation (OpenSSL based) // -void sw_sha1_init(DIGEST_CONTEXT *ctx) +static void sw_sha1_free(STDLL_TokData_t *tokdata, SESSION *sess, + CK_BYTE *context, CK_ULONG context_len) { - ctx->context_len = sizeof(SHA_CTX); - ctx->context = (CK_BYTE *) malloc(sizeof(SHA_CTX)); + UNUSED(tokdata); + UNUSED(sess); + UNUSED(context_len); + + EVP_MD_CTX_free((EVP_MD_CTX *)context); +} + +CK_RV sw_sha1_init(DIGEST_CONTEXT *ctx) +{ + ctx->context_len = 1; + ctx->context = (CK_BYTE *)EVP_MD_CTX_new(); if (ctx->context == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - // TODO: propagate error up? - return; + ctx->context_len = 0; + return CKR_HOST_MEMORY; + } + + if (!EVP_DigestInit_ex((EVP_MD_CTX *)ctx->context, EVP_sha1(), NULL)) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + EVP_MD_CTX_free((EVP_MD_CTX *)ctx->context); + ctx->context = NULL; + ctx->context_len = 0; + return CKR_FUNCTION_FAILED; } - SHA1_Init((SHA_CTX *)ctx->context); + ctx->state_unsaveable = CK_TRUE; + ctx->context_free_func = sw_sha1_free; + + return CKR_OK; } CK_RV sw_sha1_hash(DIGEST_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { + unsigned int len; if (!ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __func__); @@ -76,37 +98,60 @@ if (ctx->context == NULL) return CKR_OPERATION_NOT_INITIALIZED; - SHA1_Update((SHA_CTX *)ctx->context, in_data, in_data_len); - SHA1_Final(out_data, (SHA_CTX *)ctx->context); - *out_data_len = SHA1_HASH_SIZE; + len = *out_data_len; + if (!EVP_DigestUpdate((EVP_MD_CTX *)ctx->context, in_data, in_data_len) || + !EVP_DigestFinal((EVP_MD_CTX *)ctx->context, out_data, &len)) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + return CKR_FUNCTION_FAILED; + } + + *out_data_len = len; - free(ctx->context); + EVP_MD_CTX_free((EVP_MD_CTX *)ctx->context); ctx->context = NULL; + ctx->context_free_func = NULL; return CKR_OK; } -CK_RV sw_sha1_update(DIGEST_CONTEXT *ctx, CK_BYTE *in_data, - CK_ULONG in_data_len) +static CK_RV sw_sha1_update(DIGEST_CONTEXT *ctx, CK_BYTE *in_data, + CK_ULONG in_data_len) { if (ctx->context == NULL) return CKR_OPERATION_NOT_INITIALIZED; - SHA1_Update((SHA_CTX *)ctx->context, in_data, in_data_len); + if (!EVP_DigestUpdate((EVP_MD_CTX *)ctx->context, in_data, in_data_len)) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + return CKR_FUNCTION_FAILED; + } + return CKR_OK; } -CK_RV sw_sha1_final(DIGEST_CONTEXT *ctx, CK_BYTE *out_data, - CK_ULONG *out_data_len) +static CK_RV sw_sha1_final(DIGEST_CONTEXT *ctx, CK_BYTE *out_data, + CK_ULONG *out_data_len) { + unsigned int len; + if (ctx->context == NULL) return CKR_OPERATION_NOT_INITIALIZED; - SHA1_Final(out_data, (SHA_CTX *)ctx->context); - *out_data_len = SHA1_HASH_SIZE; + if (*out_data_len < SHA1_HASH_SIZE) { + TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); + return CKR_BUFFER_TOO_SMALL; + } + + len = *out_data_len; + if (!EVP_DigestFinal((EVP_MD_CTX *)ctx->context, out_data, &len)) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + return CKR_FUNCTION_FAILED; + } + + *out_data_len = len; - free(ctx->context); + EVP_MD_CTX_free((EVP_MD_CTX *)ctx->context); ctx->context = NULL; + ctx->context_free_func = NULL; return CKR_OK; } @@ -128,8 +173,7 @@ * supported. JML */ if (mech->mechanism == CKM_SHA_1) { - sw_sha1_init(ctx); - return CKR_OK; + return sw_sha1_init(ctx); } else { return CKR_MECHANISM_INVALID; } @@ -410,7 +454,7 @@ // build (K XOR ipad), (K XOR opad) // if (key_bytes > digest_block_size) { - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); + rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); goto done; @@ -421,7 +465,7 @@ attr->pValue, attr->ulValueLen, hash, &hash_len); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Digest failed.\n"); - digest_mgr_cleanup(&digest_ctx); + digest_mgr_cleanup(tokdata, sess, &digest_ctx); goto done; } @@ -448,7 +492,7 @@ // inner hash // - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); + rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); goto done; @@ -480,7 +524,7 @@ // outer hash // - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); + rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); goto done; @@ -583,7 +627,8 @@ memset(&hmac_ctx, 0, sizeof(SIGN_VERIFY_CONTEXT)); - rc = sign_mgr_init(tokdata, sess, &hmac_ctx, &ctx->mech, FALSE, ctx->key); + rc = sign_mgr_init(tokdata, sess, &hmac_ctx, &ctx->mech, FALSE, ctx->key, + FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Sign Mgr Init failed.\n"); goto done; @@ -607,7 +652,7 @@ } done: - sign_mgr_cleanup(&hmac_ctx); + sign_mgr_cleanup(tokdata, sess, &hmac_ctx); return rc; } diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/mech_ssl3.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/mech_ssl3.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/mech_ssl3.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/mech_ssl3.c 2022-02-02 15:05:41.000000000 +0100 @@ -128,7 +128,7 @@ // inner hash // - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); + rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Init failed.\n"); goto done; @@ -166,7 +166,7 @@ // outer hash // - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); + rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Init failed.\n"); goto done; @@ -267,7 +267,7 @@ // inner hash // rc = digest_mgr_init(tokdata, sess, &context->hash_context, - &digest_mech); + &digest_mech, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Init failed.\n"); goto done; @@ -289,6 +289,7 @@ goto done; } context->flag = TRUE; + ctx->state_unsaveable |= context->hash_context.state_unsaveable; } @@ -393,7 +394,8 @@ digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; - rc = digest_mgr_init(tokdata, sess, &context->hash_context, &digest_mech); + rc = digest_mgr_init(tokdata, sess, &context->hash_context, &digest_mech, + FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Init failed.\n"); goto done; @@ -462,7 +464,8 @@ memset(&mac_ctx, 0, sizeof(SIGN_VERIFY_CONTEXT)); - rc = sign_mgr_init(tokdata, sess, &mac_ctx, &ctx->mech, FALSE, ctx->key); + rc = sign_mgr_init(tokdata, sess, &mac_ctx, &ctx->mech, FALSE, ctx->key, + FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Sign Init failed.\n"); goto error; @@ -485,7 +488,7 @@ rc = CKR_SIGNATURE_INVALID; } error: - sign_mgr_cleanup(&mac_ctx); + sign_mgr_cleanup(tokdata, sess, &mac_ctx); return rc; } @@ -551,7 +554,7 @@ // inner hash // rc = digest_mgr_init(tokdata, sess, &context->hash_context, - &digest_mech); + &digest_mech, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Init failed.\n"); goto done; @@ -573,6 +576,7 @@ goto done; } context->flag = TRUE; + ctx->state_unsaveable |= context->hash_context.state_unsaveable; } rc = digest_mgr_digest_update(tokdata, sess, &context->hash_context, @@ -664,7 +668,8 @@ digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; - rc = digest_mgr_init(tokdata, sess, &context->hash_context, &digest_mech); + rc = digest_mgr_init(tokdata, sess, &context->hash_context, &digest_mech, + FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Init failed.\n"); goto done; @@ -871,7 +876,7 @@ digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); + rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Init failed.\n"); return rc; @@ -912,7 +917,7 @@ digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); + rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Init failed.\n"); return rc; @@ -967,7 +972,7 @@ digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); + rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech, FALSE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Init failed.\n"); return rc; @@ -1047,6 +1052,14 @@ else return rc; } + rc = tokdata->policy->is_mech_allowed(tokdata->policy, mech, + &base_key_obj->strength, + POLICY_CHECK_DERIVE, + sess); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: derive key\n"); + goto error; + } if (!key_object_is_mechanism_allowed(base_key_obj->template, CKM_SSL3_MASTER_KEY_DERIVE)) { @@ -1290,6 +1303,8 @@ // occur in a separate call to C_DestroyObject // + INC_COUNTER(tokdata, sess, mech, base_key_obj, POLICY_STRENGTH_IDX_0); + object_put(tokdata, base_key_obj, TRUE); base_key_obj = NULL; @@ -1377,6 +1392,14 @@ return rc; } + rc = tokdata->policy->is_mech_allowed(tokdata->policy, mech, + &base_key_obj->strength, + POLICY_CHECK_DERIVE, + sess); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: derive wrap\n"); + goto error; + } if (!key_object_is_mechanism_allowed(base_key_obj->template, CKM_SSL3_KEY_AND_MAC_DERIVE)) { TRACE_ERROR("Mechanism not allwed per CKA_ALLOWED_MECHANISMS.\n"); @@ -1663,6 +1686,8 @@ #endif } + INC_COUNTER(tokdata, sess, mech, base_key_obj, POLICY_STRENGTH_IDX_0); + error: object_put(tokdata, base_key_obj, TRUE); base_key_obj = NULL; @@ -1702,7 +1727,7 @@ // at the beginning so that they may be overridden by caller-specified // values. // - new_attrs = (CK_ATTRIBUTE *) malloc((ulCount + 7) * (sizeof(CK_ATTRIBUTE))); + new_attrs = (CK_ATTRIBUTE *) calloc(ulCount + 7, sizeof(CK_ATTRIBUTE)); if (!new_attrs) goto error; @@ -1920,7 +1945,7 @@ // at the beginning so that they may be overridden by caller-specified // values. // - new_attrs = (CK_ATTRIBUTE *) malloc((ulCount + 7) * (sizeof(CK_ATTRIBUTE))); + new_attrs = (CK_ATTRIBUTE *) calloc(ulCount + 7, sizeof(CK_ATTRIBUTE)); if (!new_attrs) goto error; @@ -2013,6 +2038,7 @@ goto error; } switch (keytype) { + case CKK_AES: case CKK_GENERIC_SECRET: case CKK_DES: case CKK_DES2: diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/mgf_translation.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/mgf_translation.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/mgf_translation.c 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/mgf_translation.c 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,61 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ +#include +#include + +CK_RV translate_string_to_mgf(const char *str, size_t len, CK_ULONG* mgf) +{ + switch(len) { + case 13: + if (strcmp("CKG_MGF1_SHA1", str) == 0) { + *mgf = CKG_MGF1_SHA1; + return CKR_OK; + } + return CKR_FUNCTION_FAILED; + case 15: + if (strcmp("CKG_MGF1_SHA224", str) == 0) { + *mgf = CKG_MGF1_SHA224; + return CKR_OK; + } + if (strcmp("CKG_MGF1_SHA256", str) == 0) { + *mgf = CKG_MGF1_SHA256; + return CKR_OK; + } + if (strcmp("CKG_MGF1_SHA384", str) == 0) { + *mgf = CKG_MGF1_SHA384; + return CKR_OK; + } + if (strcmp("CKG_MGF1_SHA512", str) == 0) { + *mgf = CKG_MGF1_SHA512; + return CKR_OK; + } + return CKR_FUNCTION_FAILED; + case 21: + if (strcmp("CKG_IBM_MGF1_SHA3_224", str) == 0) { + *mgf = CKG_IBM_MGF1_SHA3_224; + return CKR_OK; + } + if (strcmp("CKG_IBM_MGF1_SHA3_256", str) == 0) { + *mgf = CKG_IBM_MGF1_SHA3_256; + return CKR_OK; + } + if (strcmp("CKG_IBM_MGF1_SHA3_384", str) == 0) { + *mgf = CKG_IBM_MGF1_SHA3_384; + return CKR_OK; + } + if (strcmp("CKG_IBM_MGF1_SHA3_512", str) == 0) { + *mgf = CKG_IBM_MGF1_SHA3_512; + return CKR_OK; + } + return CKR_FUNCTION_FAILED; + default: + return CKR_FUNCTION_FAILED; + } +} diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/new_host.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/new_host.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/new_host.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/new_host.c 2022-02-02 15:05:41.000000000 +0100 @@ -49,6 +49,7 @@ #include "attributes.h" #include "../api/apiproto.h" +#include "../api/policy.h" void SC_SetFunctionList(void); CK_RV SC_Finalize(STDLL_TokData_t *tokdata, CK_SLOT_ID sid, SLOT_INFO *sinfp, @@ -81,34 +82,12 @@ { CK_RV rc = CKR_OK; char abs_tokdir_name[PATH_MAX]; - - if ((rc = check_user_and_group()) != CKR_OK) - return rc; + CK_BBOOL newdatastore; + policy_t policy = sltp->TokData->policy; /* set trace info */ set_trace(t); - if (sltp->TokData != NULL) { - TRACE_ERROR("Already initialized.\n"); - return CKR_CRYPTOKI_ALREADY_INITIALIZED; - } - - /* - * Create separate memory area for each token specific data - */ - sltp->TokData = (STDLL_TokData_t *) calloc(1, sizeof(STDLL_TokData_t)); - if (!sltp->TokData) { - TRACE_ERROR("Allocating host memory failed.\n"); - return CKR_HOST_MEMORY; - } - - sltp->TokData->ro_session_count = 0; - sltp->TokData->global_login_state = CKS_RO_PUBLIC_SESSION; -#ifdef ENABLE_LOCKS - pthread_rwlock_init(&sltp->TokData->sess_list_rwlock, NULL); -#endif - pthread_mutex_init(&sltp->TokData->login_mutex, NULL); - bt_init(&sltp->TokData->sess_btree, free); bt_init(&sltp->TokData->object_map_btree, free); bt_init(&sltp->TokData->sess_obj_btree, call_object_free); @@ -140,6 +119,15 @@ TRACE_DEVEL("Token version: %u.%u\n", (unsigned int)(sinfp->version >> 16), (unsigned int)(sinfp->version & 0xffff)); + /* Check token store encryption against policy */ + newdatastore = sinfp->version >= TOK_NEW_DATA_STORE ? CK_TRUE : CK_FALSE; + rc = policy->check_token_store(policy, newdatastore, + token_specific.data_store.encryption_algorithm, + SlotNumber, &sltp->TokData->store_strength); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Token cannot load since data store encryption is too weak for policy.\n"); + goto done; + } /* Initialize Lock */ if (XProcLock_Init(sltp->TokData) != CKR_OK) { @@ -174,9 +162,7 @@ if (rc != 0) { sltp->FcnList = NULL; detach_shm(sltp->TokData, 0); - if (sltp->TokData) - free(sltp->TokData); - sltp->TokData = NULL; + final_data_store(sltp->TokData); TRACE_DEVEL("Token Specific Init failed.\n"); goto done; } @@ -186,9 +172,7 @@ rc = load_token_data(sltp->TokData, SlotNumber); if (rc != CKR_OK) { sltp->FcnList = NULL; - if (sltp->TokData) - free(sltp->TokData); - sltp->TokData = NULL; + final_data_store(sltp->TokData); TRACE_DEVEL("Failed to load token data. (rc=0x%02lx)\n", rc); goto done; } @@ -218,8 +202,7 @@ SC_Finalize(sltp->TokData, SlotNumber, sinfp, NULL, 0); } else { CloseXProcLock(sltp->TokData); - free(sltp->TokData); - sltp->TokData = NULL; + final_data_store(sltp->TokData); } } @@ -258,11 +241,6 @@ bt_destroy(&tokdata->priv_token_obj_btree); bt_destroy(&tokdata->publ_token_obj_btree); -#ifdef ENABLE_LOCKS - pthread_rwlock_destroy(&tokdata->sess_list_rwlock); -#endif - pthread_mutex_destroy(&tokdata->login_mutex); - detach_shm(tokdata, in_fork_initializer); /* close spin lock file */ CloseXProcLock(tokdata); @@ -276,9 +254,6 @@ final_data_store(tokdata); - if (tokdata) - free(tokdata); - return rc; } @@ -463,6 +438,10 @@ dat = &tokdata->nv_token_data->dat; if (tokdata->version < TOK_NEW_DATA_STORE) { rc = compute_sha1(tokdata, pPin, ulPinLen, hash_sha); + if (rc != CKR_OK) { + TRACE_DEVEL("compute_sha1 failed.\n"); + goto done; + } if (memcmp(tokdata->nv_token_data->so_pin_sha, hash_sha, SHA1_HASH_SIZE) != 0) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT)); @@ -470,13 +449,12 @@ goto done; } } else { - rc = PKCS5_PBKDF2_HMAC((char *)pPin, ulPinLen, - dat->so_login_salt, 64, - dat->so_login_it, EVP_sha512(), - 256 / 8, login_key); - if (rc != 1) { + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pPin, ulPinLen, + dat->so_login_salt, 64, + dat->so_login_it, EVP_sha512(), + 256 / 8, login_key); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - rc = CKR_FUNCTION_FAILED; goto done; } if (CRYPTO_memcmp(dat->so_login_key, login_key, 32) != 0) { @@ -546,7 +524,7 @@ return CKR_FUNCTION_FAILED; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -602,13 +580,13 @@ memcpy(login_salt, USER_KDF_LOGIN_PURPOSE, 32); rng_generate(tokdata, login_salt + 32, 32); - rc = PKCS5_PBKDF2_HMAC((char *)pPin, ulPinLen, - login_salt, 64, - login_it, EVP_sha512(), - 256 / 8, login_key); - if (rc != 1) { + + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pPin, ulPinLen, + login_salt, 64, + login_it, EVP_sha512(), + 256 / 8, login_key); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - rc = CKR_FUNCTION_FAILED; goto done; } @@ -616,13 +594,12 @@ memcpy(wrap_salt, USER_KDF_WRAP_PURPOSE, 32); rng_generate(tokdata, wrap_salt + 32, 32); - rc = PKCS5_PBKDF2_HMAC((char *)pPin, ulPinLen, - wrap_salt, 64, - wrap_it, EVP_sha512(), - 256 / 8, wrap_key); - if (rc != 1) { + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pPin, ulPinLen, + wrap_salt, 64, + wrap_it, EVP_sha512(), + 256 / 8, wrap_key); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - rc = CKR_FUNCTION_FAILED; goto done; } } @@ -705,7 +682,7 @@ return CKR_FUNCTION_FAILED; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -777,13 +754,12 @@ memcpy(login_salt, USER_KDF_LOGIN_PURPOSE, 32); rng_generate(tokdata, login_salt + 32, 32); - rc = PKCS5_PBKDF2_HMAC((char *)pNewPin, ulNewLen, - login_salt, 64, - login_it, EVP_sha512(), - 256 / 8, new_login_key); - if (rc != 1) { + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pNewPin, ulNewLen, + login_salt, 64, + login_it, EVP_sha512(), + 256 / 8, new_login_key); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - rc = CKR_FUNCTION_FAILED; goto done; } @@ -791,32 +767,30 @@ memcpy(wrap_salt, USER_KDF_WRAP_PURPOSE, 32); rng_generate(tokdata, wrap_salt + 32, 32); - rc = PKCS5_PBKDF2_HMAC((char *)pNewPin, ulNewLen, - wrap_salt, 64, - wrap_it, EVP_sha512(), - 256 / 8, new_wrap_key); - if (rc != 1) { + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pNewPin, ulNewLen, + wrap_salt, 64, + wrap_it, EVP_sha512(), + 256 / 8, new_wrap_key); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - rc = CKR_FUNCTION_FAILED; goto done; } - rc = PKCS5_PBKDF2_HMAC((char *)pOldPin, ulOldLen, - dat->user_login_salt, 64, - dat->user_login_it, EVP_sha512(), - 256 / 8, old_login_key); - if (rc != 1) { + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pOldPin, ulOldLen, + dat->user_login_salt, 64, + dat->user_login_it, EVP_sha512(), + 256 / 8, old_login_key); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - rc = CKR_FUNCTION_FAILED; goto done; } - rc = PKCS5_PBKDF2_HMAC((char *)pNewPin, ulNewLen, - dat->user_login_salt, 64, - dat->user_login_it, EVP_sha512(), - 256 / 8, new_login_key_old_salt); - if (rc != 1) { + + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pNewPin, ulNewLen, + dat->user_login_salt, 64, + dat->user_login_it, EVP_sha512(), + 256 / 8, new_login_key_old_salt); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - rc = CKR_FUNCTION_FAILED; goto done; } @@ -901,13 +875,12 @@ memcpy(login_salt, SO_KDF_LOGIN_PURPOSE, 32); rng_generate(tokdata, login_salt + 32, 32); - rc = PKCS5_PBKDF2_HMAC((char *)pNewPin, ulNewLen, - login_salt, 64, - login_it, EVP_sha512(), - 256 / 8, new_login_key); - if (rc != 1) { + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pNewPin, ulNewLen, + login_salt, 64, + login_it, EVP_sha512(), + 256 / 8, new_login_key); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - rc = CKR_FUNCTION_FAILED; goto done; } @@ -915,32 +888,30 @@ memcpy(wrap_salt, SO_KDF_WRAP_PURPOSE, 32); rng_generate(tokdata, wrap_salt + 32, 32); - rc = PKCS5_PBKDF2_HMAC((char *)pNewPin, ulNewLen, - wrap_salt, 64, - wrap_it, EVP_sha512(), - 256 / 8, new_wrap_key); - if (rc != 1) { + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pNewPin, ulNewLen, + wrap_salt, 64, + wrap_it, EVP_sha512(), + 256 / 8, new_wrap_key); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - rc = CKR_FUNCTION_FAILED; goto done; } - rc = PKCS5_PBKDF2_HMAC((char *)pOldPin, ulOldLen, - dat->so_login_salt, 64, - dat->so_login_it, EVP_sha512(), - 256 / 8, old_login_key); - if (rc != 1) { + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pOldPin, ulOldLen, + dat->so_login_salt, 64, + dat->so_login_it, EVP_sha512(), + 256 / 8, old_login_key); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - rc = CKR_FUNCTION_FAILED; goto done; } - rc = PKCS5_PBKDF2_HMAC((char *)pNewPin, ulNewLen, - dat->so_login_salt, 64, - dat->so_login_it, EVP_sha512(), - 256 / 8, new_login_key_old_salt); - if (rc != 1) { + + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pNewPin, ulNewLen, + dat->so_login_salt, 64, + dat->so_login_it, EVP_sha512(), + 256 / 8, new_login_key_old_salt); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - rc = CKR_FUNCTION_FAILED; goto done; } @@ -1046,7 +1017,7 @@ return rc; } - sess = session_mgr_find(tokdata, *phSession); + sess = session_mgr_find_reset_error(tokdata, *phSession); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; @@ -1163,7 +1134,7 @@ if (!pOperationState) length_only = TRUE; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1208,15 +1179,16 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } - rc = session_mgr_set_op_state(sess, hEncryptionKey, hAuthenticationKey, - pOperationState, ulOperationStateLen); + rc = session_mgr_set_op_state(tokdata, sess, hEncryptionKey, + hAuthenticationKey, pOperationState, + ulOperationStateLen); if (rc != CKR_OK) TRACE_DEVEL("session_mgr_set_op_state() failed.\n"); @@ -1256,7 +1228,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1343,6 +1315,10 @@ } rc = compute_sha1(tokdata, pPin, ulPinLen, hash_sha); + if (rc != CKR_OK) { + TRACE_DEVEL("compute_sha1 failed.\n"); + goto done; + } if (memcmp(tokdata->nv_token_data->user_pin_sha, hash_sha, SHA1_HASH_SIZE) != 0) { set_login_flags(userType, flags); @@ -1357,22 +1333,21 @@ compute_md5(tokdata, pPin, ulPinLen, tokdata->user_pin_md5); memset(tokdata->so_pin_md5, 0x0, MD5_HASH_SIZE); } else { - rc = PKCS5_PBKDF2_HMAC((char *)pPin, ulPinLen, - dat->user_login_salt, 64, - dat->user_login_it, EVP_sha512(), - 256 / 8, login_key); - if (rc != 1) { + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pPin, ulPinLen, + dat->user_login_salt, 64, + dat->user_login_it, EVP_sha512(), + 256 / 8, login_key); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - rc = CKR_FUNCTION_FAILED; goto done; } - rc = PKCS5_PBKDF2_HMAC((char *)pPin, ulPinLen, - dat->user_wrap_salt, 64, - dat->user_wrap_it, EVP_sha512(), - 256 / 8, wrap_key); - if (rc != 1) { + + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pPin, ulPinLen, + dat->user_wrap_salt, 64, + dat->user_wrap_it, EVP_sha512(), + 256 / 8, wrap_key); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - rc = CKR_FUNCTION_FAILED; goto done; } @@ -1441,6 +1416,10 @@ if (tokdata->version < TOK_NEW_DATA_STORE) { rc = compute_sha1(tokdata, pPin, ulPinLen, hash_sha); + if (rc != CKR_OK) { + TRACE_DEVEL("compute_sha1 failed.\n"); + goto done; + } if (memcmp(tokdata->nv_token_data->so_pin_sha, hash_sha, SHA1_HASH_SIZE) != 0) { set_login_flags(userType, flags); @@ -1455,22 +1434,21 @@ compute_md5(tokdata, pPin, ulPinLen, tokdata->so_pin_md5); memset(tokdata->user_pin_md5, 0x0, MD5_HASH_SIZE); } else { - rc = PKCS5_PBKDF2_HMAC((char *)pPin, ulPinLen, - dat->so_login_salt, 64, - dat->so_login_it, EVP_sha512(), - 256 / 8, login_key); - if (rc != 1) { + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pPin, ulPinLen, + dat->so_login_salt, 64, + dat->so_login_it, EVP_sha512(), + 256 / 8, login_key); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - rc = CKR_FUNCTION_FAILED; goto done; } - rc = PKCS5_PBKDF2_HMAC((char *)pPin, ulPinLen, - dat->so_wrap_salt, 64, - dat->so_wrap_it, EVP_sha512(), - 256 / 8, wrap_key); - if (rc != 1) { + + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pPin, ulPinLen, + dat->so_wrap_salt, 64, + dat->so_wrap_it, EVP_sha512(), + 256 / 8, wrap_key); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - rc = CKR_FUNCTION_FAILED; goto done; } @@ -1530,7 +1508,7 @@ return CKR_FUNCTION_FAILED; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1586,7 +1564,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1600,6 +1578,7 @@ goto done; } + /* Enforces policy */ rc = object_mgr_add(tokdata, sess, pTemplate, ulCount, phObject); if (rc != CKR_OK) TRACE_DEVEL("object_mgr_add() failed.\n"); @@ -1642,7 +1621,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1656,6 +1635,7 @@ goto done; } + /* Enforces policy */ rc = object_mgr_copy(tokdata, sess, pTemplate, ulCount, hObject, phNewObject); if (rc != CKR_OK) @@ -1684,7 +1664,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1724,7 +1704,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1759,7 +1739,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1787,13 +1767,14 @@ for (i = 0; i < ulCount; i++, attr++) { TRACE_DEBUG("%lu: Attribute type: 0x%08lx, Value Length: %lu\n", i, attr->type, attr->ulValueLen); - - if (attr->ulValueLen >= sizeof(val) && attr->pValue != NULL) { - memset(val, 0, sizeof(val)); - memcpy(val, attr->pValue, attr->ulValueLen > sizeof(val) ? - sizeof(val) : attr->ulValueLen); - TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n", - val[0], val[1], val[2], val[3]); + if (rc == CKR_OK && attr->ulValueLen != CK_UNAVAILABLE_INFORMATION) { + if (attr->ulValueLen >= sizeof(val) && attr->pValue != NULL) { + memset(val, 0, sizeof(val)); + memcpy(val, attr->pValue, attr->ulValueLen > sizeof(val) ? + sizeof(val) : attr->ulValueLen); + TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n", + val[0], val[1], val[2], val[3]); + } } } #endif @@ -1816,7 +1797,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1872,7 +1853,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1944,7 +1925,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1994,7 +1975,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2049,7 +2030,7 @@ if (rc != CKR_OK) goto done; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2069,8 +2050,9 @@ goto done; } + sess->encr_ctx.count_statistics = TRUE; rc = encr_mgr_init(tokdata, sess, &sess->encr_ctx, OP_ENCRYPT_INIT, - pMechanism, hKey); + pMechanism, hKey, TRUE); done: TRACE_INFO("C_EncryptInit: rc = 0x%08lx, sess = %ld, mech = 0x%lx\n", @@ -2098,7 +2080,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2128,7 +2110,7 @@ done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) { if (sess) - encr_mgr_cleanup(&sess->encr_ctx); + encr_mgr_cleanup(tokdata, sess, &sess->encr_ctx); } TRACE_INFO("C_Encrypt: rc = 0x%08lx, sess = %ld, amount = %lu\n", @@ -2156,7 +2138,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2187,7 +2169,7 @@ done: if (rc != CKR_OK && rc != CKR_BUFFER_TOO_SMALL) { if (sess) - encr_mgr_cleanup(&sess->encr_ctx); + encr_mgr_cleanup(tokdata, sess, &sess->encr_ctx); } TRACE_INFO("C_EncryptUpdate: rc = 0x%08lx, sess = %ld, amount = %lu\n", @@ -2214,7 +2196,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2244,7 +2226,7 @@ done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) { if (sess) - encr_mgr_cleanup(&sess->encr_ctx); + encr_mgr_cleanup(tokdata, sess, &sess->encr_ctx); } TRACE_INFO("C_EncryptFinal: rc = 0x%08lx, sess = %ld\n", @@ -2279,7 +2261,7 @@ if (rc != CKR_OK) goto done; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2299,8 +2281,9 @@ goto done; } + sess->decr_ctx.count_statistics = TRUE; rc = decr_mgr_init(tokdata, sess, &sess->decr_ctx, OP_DECRYPT_INIT, - pMechanism, hKey); + pMechanism, hKey, TRUE); if (rc != CKR_OK) TRACE_DEVEL("decr_mgr_init() failed.\n"); @@ -2330,7 +2313,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2361,7 +2344,7 @@ done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) { if (sess) - decr_mgr_cleanup(&sess->decr_ctx); + decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx); } TRACE_INFO("C_Decrypt: rc = 0x%08lx, sess = %ld, amount = %lu\n", @@ -2389,7 +2372,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2420,7 +2403,7 @@ done: if (rc != CKR_OK && rc != CKR_BUFFER_TOO_SMALL && sess != NULL) { if (sess) - decr_mgr_cleanup(&sess->decr_ctx); + decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx); } TRACE_INFO("C_DecryptUpdate: rc = 0x%08lx, sess = %ld, amount = %lu\n", @@ -2447,7 +2430,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2477,7 +2460,7 @@ done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) { if (sess) - decr_mgr_cleanup(&sess->decr_ctx); + decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx); } TRACE_INFO("C_DecryptFinal: rc = 0x%08lx, sess = %ld, amount = %lu\n", @@ -2512,7 +2495,7 @@ if (rc != CKR_OK) goto done; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2532,7 +2515,8 @@ goto done; } - rc = digest_mgr_init(tokdata, sess, &sess->digest_ctx, pMechanism); + sess->digest_ctx.count_statistics = TRUE; + rc = digest_mgr_init(tokdata, sess, &sess->digest_ctx, pMechanism, TRUE); if (rc != CKR_OK) TRACE_DEVEL("digest_mgr_init() failed.\n"); @@ -2562,7 +2546,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2606,7 +2590,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2650,7 +2634,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2691,7 +2675,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2741,7 +2725,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2765,7 +2749,9 @@ goto done; } - rc = sign_mgr_init(tokdata, sess, &sess->sign_ctx, pMechanism, FALSE, hKey); + sess->sign_ctx.count_statistics = TRUE; + rc = sign_mgr_init(tokdata, sess, &sess->sign_ctx, pMechanism, FALSE, hKey, + TRUE); if (rc != CKR_OK) TRACE_DEVEL("sign_mgr_init() failed.\n"); @@ -2795,7 +2781,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2825,7 +2811,7 @@ done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) { if (sess != NULL) - sign_mgr_cleanup(&sess->sign_ctx); + sign_mgr_cleanup(tokdata, sess, &sess->sign_ctx); } TRACE_INFO("C_Sign: rc = 0x%08lx, sess = %ld, datalen = %lu\n", @@ -2850,7 +2836,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2875,7 +2861,7 @@ done: if (rc != CKR_OK && sess != NULL) - sign_mgr_cleanup(&sess->sign_ctx); + sign_mgr_cleanup(tokdata, sess, &sess->sign_ctx); TRACE_INFO("C_SignUpdate: rc = 0x%08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulPartLen); @@ -2900,7 +2886,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2930,7 +2916,7 @@ done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) { if (sess != NULL) - sign_mgr_cleanup(&sess->sign_ctx); + sign_mgr_cleanup(tokdata, sess, &sess->sign_ctx); } TRACE_INFO("C_SignFinal: rc = 0x%08lx, sess = %ld\n", @@ -2965,7 +2951,7 @@ if (rc != CKR_OK) goto done; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2985,7 +2971,8 @@ goto done; } - rc = sign_mgr_init(tokdata, sess, &sess->sign_ctx, pMechanism, TRUE, hKey); + rc = sign_mgr_init(tokdata, sess, &sess->sign_ctx, pMechanism, TRUE, hKey, + TRUE); if (rc != CKR_OK) TRACE_DEVEL("sign_mgr_init() failed.\n"); @@ -3015,7 +3002,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -3045,7 +3032,7 @@ done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) { if (sess != NULL) - sign_mgr_cleanup(&sess->sign_ctx); + sign_mgr_cleanup(tokdata, sess, &sess->sign_ctx); } TRACE_INFO("C_SignRecover: rc = 0x%08lx, sess = %ld, datalen = %lu\n", @@ -3079,7 +3066,7 @@ if (rc != CKR_OK) goto done; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -3099,8 +3086,9 @@ goto done; } + sess->verify_ctx.count_statistics = TRUE; rc = verify_mgr_init(tokdata, sess, &sess->verify_ctx, pMechanism, - FALSE, hKey); + FALSE, hKey, TRUE); if (rc != CKR_OK) TRACE_DEVEL("verify_mgr_init() failed.\n"); @@ -3129,7 +3117,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -3155,7 +3143,7 @@ done: if (sess != NULL) - verify_mgr_cleanup(&sess->verify_ctx); + verify_mgr_cleanup(tokdata, sess, &sess->verify_ctx); TRACE_INFO("C_Verify: rc = 0x%08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulDataLen); @@ -3179,7 +3167,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -3205,7 +3193,7 @@ done: if (rc != CKR_OK && sess != NULL) - verify_mgr_cleanup(&sess->verify_ctx); + verify_mgr_cleanup(tokdata, sess, &sess->verify_ctx); TRACE_INFO("C_VerifyUpdate: rc = 0x%08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulPartLen); @@ -3229,7 +3217,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -3255,7 +3243,7 @@ done: if (sess != NULL) - verify_mgr_cleanup(&sess->verify_ctx); + verify_mgr_cleanup(tokdata, sess, &sess->verify_ctx); TRACE_INFO("C_VerifyFinal: rc = 0x%08lx, sess = %ld\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle); @@ -3289,7 +3277,7 @@ if (rc != CKR_OK) goto done; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -3310,7 +3298,7 @@ } rc = verify_mgr_init(tokdata, sess, &sess->verify_ctx, pMechanism, - TRUE, hKey); + TRUE, hKey, TRUE); if (rc != CKR_OK) TRACE_DEVEL("verify_mgr_init() failed.\n"); @@ -3340,7 +3328,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -3372,7 +3360,7 @@ done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) { if (sess != NULL) - verify_mgr_cleanup(&sess->verify_ctx); + verify_mgr_cleanup(tokdata, sess, &sess->verify_ctx); } TRACE_INFO("C_VerifyRecover: rc = 0x%08lx, sess = %ld, recover len = %lu, " @@ -3500,12 +3488,18 @@ if (rc != CKR_OK) goto done; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } + rc = tokdata->policy->is_mech_allowed(tokdata->policy, pMechanism, NULL, + POLICY_CHECK_KEYGEN, sess); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Key generation mechanism not allowed\n"); + goto done; + } if (pin_expired(&sess->session_info, tokdata->nv_token_data->token_info.flags) == TRUE) { @@ -3582,12 +3576,18 @@ if (rc != CKR_OK) goto done; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } + rc = tokdata->policy->is_mech_allowed(tokdata->policy, pMechanism, NULL, + POLICY_CHECK_KEYGEN, sess); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Keypair generation mechanism not allowed\n"); + goto done; + } if (pin_expired(&sess->session_info, tokdata->nv_token_data->token_info.flags) == TRUE) { @@ -3667,7 +3667,7 @@ if (!pWrappedKey) length_only = TRUE; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -3724,7 +3724,7 @@ if (rc != CKR_OK) goto done; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -3806,7 +3806,7 @@ if (rc != CKR_OK) goto done; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -3916,7 +3916,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -3992,7 +3992,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -4019,6 +4019,8 @@ goto done; } + sess->decr_ctx.count_statistics = TRUE; + sess->encr_ctx.count_statistics = TRUE; rc = encr_mgr_reencrypt_single(tokdata, sess, &sess->decr_ctx, pDecrMech, hDecrKey, &sess->encr_ctx, pEncrMech, hEncrKey, pEncryptedData, ulEncryptedDataLen, @@ -4039,6 +4041,24 @@ return rc; } +CK_RV SC_HandleEvent(STDLL_TokData_t *tokdata, unsigned int event_type, + unsigned int event_flags, const char *payload, + unsigned int payload_len) +{ + CK_RV rc; + + if (token_specific.t_handle_event == NULL) + return CKR_FUNCTION_NOT_SUPPORTED; + + rc = token_specific.t_handle_event(tokdata, event_type, event_flags, + payload, payload_len); + + TRACE_INFO("SC_HandleEvent: rc = 0x%08lx, event_type = 0x%08x, " + "event_flags = 0x%08x\n", rc, event_type, event_flags); + + return rc; +} + void SC_SetFunctionList(void) { function_list.ST_Initialize = ST_Initialize; @@ -4104,4 +4124,6 @@ function_list.ST_CancelFunction = NULL; // SC_CancelFunction; function_list.ST_IBM_ReencryptSingle = SC_IBM_ReencryptSingle; + + function_list.ST_HandleEvent = SC_HandleEvent; } diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/object.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/object.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/object.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/object.c 2022-02-02 15:05:41.000000000 +0100 @@ -36,6 +36,7 @@ #include "tok_spec_struct.h" #include "pkcs32.h" #include "trace.h" +#include "../api/policy.h" // object_create() // @@ -698,16 +699,10 @@ // -// -CK_RV object_restore(CK_BYTE * data, OBJECT ** new_obj, CK_BBOOL replace) -{ - return object_restore_withSize(data, new_obj, replace, -1); -} - -// //Modified object_restore to prevent buffer overflow //If data_size=-1, won't do bounds checking -CK_RV object_restore_withSize(CK_BYTE * data, OBJECT ** new_obj, +CK_RV object_restore_withSize(struct policy *policy, + CK_BYTE * data, OBJECT ** new_obj, CK_BBOOL replace, int data_size) { TEMPLATE *tmpl = NULL; @@ -747,6 +742,17 @@ TRACE_DEVEL("template_unflatten_withSize failed.\n"); goto error; } + /* External tools (e.g., pkcscca) might use this function and not + be aware of any policy. Allow them to pass NULL. */ + if (policy) { + /* Ignore policy violations here since the point is to get the + correct strength classification for the usage scenario + which will then allow or block key usage. */ + policy->store_object_strength(policy, &obj->strength, + policy_get_attr_from_template, + tmpl, NULL, NULL); + } + obj->template = tmpl; tmpl = NULL; @@ -760,6 +766,9 @@ /* Reload of existing object only changes the template */ template_free((*new_obj)->template); (*new_obj)->template = obj->template; + (*new_obj)->strength.strength = obj->strength.strength; + (*new_obj)->strength.siglen = obj->strength.siglen; + (*new_obj)->strength.allowed = obj->strength.allowed; free(obj); // don't want to do object_free() here! } diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/obj_mgr.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/obj_mgr.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/obj_mgr.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/obj_mgr.c 2022-02-02 15:05:41.000000000 +0100 @@ -28,6 +28,7 @@ #include "trace.h" #include "../api/apiproto.h" +#include "../api/policy.h" static CK_RV object_mgr_check_session(SESSION *sess, CK_BBOOL priv_obj, CK_BBOOL sess_obj) @@ -84,14 +85,13 @@ CK_ULONG ulCount, CK_OBJECT_HANDLE *handle) { OBJECT *o = NULL; - CK_BBOOL priv_obj, sess_obj, added = FALSE, locked = FALSE; + CK_BBOOL priv_obj, sess_obj, locked = FALSE; CK_RV rc; CK_OBJECT_CLASS class; CK_KEY_TYPE keytype; CK_BYTE *spki = NULL; CK_ULONG spki_len = 0; - CK_ATTRIBUTE *spki_attr = NULL; - unsigned long obj_handle; + CK_ATTRIBUTE *spki_attr = NULL, *value_attr = NULL, *vallen_attr = NULL; if (!sess || !pTemplate || !handle) { TRACE_ERROR("Invalid function arguments.\n"); @@ -148,6 +148,40 @@ } } break; + case CKO_SECRET_KEY: + rc = template_attribute_get_ulong(o->template, CKA_KEY_TYPE, &keytype); + if (rc != CKR_OK) { + TRACE_ERROR("Could not find CKA_KEY_TYPE for the key object.\n"); + goto done; + } + + switch (keytype) { + case CKK_GENERIC_SECRET: + case CKK_AES: + rc = template_attribute_get_non_empty(o->template, CKA_VALUE, + &value_attr); + if (rc != CKR_OK) { + TRACE_ERROR("Could not find CKA_VALUE for the key object.\n"); + goto done; + } + rc = build_attribute(CKA_VALUE_LEN, + (CK_BYTE *)&value_attr->ulValueLen, + sizeof(CK_ULONG), &vallen_attr); + if (rc != CKR_OK) { + TRACE_DEVEL("build_attribute failed\n"); + goto done; + } + rc = template_update_attribute(o->template, vallen_attr); + if (rc != CKR_OK) { + TRACE_ERROR("template_update_attribute failed\n"); + free(vallen_attr); + goto done; + } + break; + default: + break; + } + break; default: break; } @@ -162,126 +196,11 @@ // okay, object is created and the session permissions look okay. // add the object to the appropriate list and assign an object handle // - - if (sess_obj) { - o->session = sess; - memset(o->name, 0x00, sizeof(CK_BYTE) * 8); - - if ((obj_handle = bt_node_add(&tokdata->sess_obj_btree, o)) == 0) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - } else { - CK_BYTE current[8]; - CK_BYTE next[8]; - - // we'll be modifying nv_token_data so we should protect this part with - // the 'XProcLock' - // - rc = XProcLock(tokdata); - if (rc != CKR_OK) { - TRACE_ERROR("Failed to get Process Lock.\n"); - goto done; - } - locked = TRUE; - - // Determine if we have already reached our Max Token Objects - // - if (priv_obj) { - if (tokdata->global_shm->num_priv_tok_obj >= MAX_TOK_OBJS) { - rc = CKR_HOST_MEMORY; - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - goto done; - } - } else { - if (tokdata->global_shm->num_publ_tok_obj >= MAX_TOK_OBJS) { - rc = CKR_HOST_MEMORY; - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - goto done; - } - } - - memcpy(current, &tokdata->nv_token_data->next_token_object_name, 8); - - o->session = NULL; - memcpy(&o->name, current, 8); - - rc = compute_next_token_obj_name(current, next); - if (rc != CKR_OK) { - // TODO: handle error, check if rc is a valid per spec - goto done; - } - memcpy(&tokdata->nv_token_data->next_token_object_name, next, 8); - - rc = save_token_object(tokdata, o); - if (rc != CKR_OK) { - // TODO: handle error, check if rc is a valid per spec - goto done; - } - // add the object identifier to the shared memory segment - // - object_mgr_add_to_shm(o, tokdata->global_shm); - - // save_token_data has to lock the mutex itself because it's used - // elsewhere - rc = save_token_data(tokdata, sess->session_info.slotID); - if (rc != CKR_OK) { - // TODO: handle error, check if rc is a valid per spec - goto done; - } - - // now, store the object in the appropriate btree - // - if (priv_obj) - obj_handle = bt_node_add(&tokdata->priv_token_obj_btree, o); - else - obj_handle = bt_node_add(&tokdata->publ_token_obj_btree, o); - - if (!obj_handle) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - } - added = TRUE; - - rc = object_mgr_add_to_map(tokdata, sess, o, obj_handle, handle); - if (rc != CKR_OK) { - // we need to remove the object from whatever btree we just added it to - if (sess_obj) { - // put the binary tree node which holds o on the free list, but - // pass NULL here, so that o (the binary tree node's value pointer) - // isn't touched. It is free'd below - bt_node_free(&tokdata->sess_obj_btree, obj_handle, FALSE); - } else { - // we'll want to delete the token object file too! - // - delete_token_object(tokdata, o); - - if (priv_obj) { - // put the binary tree node which holds o on the free list, but - // pass NULL here, so that o (the binary tree node's value - // pointer) isn't touched. It is free'd below - bt_node_free(&tokdata->priv_token_obj_btree, obj_handle, FALSE); - } else { - // put the binary tree node which holds o on the free list, but - // pass NULL here, so that o (the binary tree node's value - // pointer) isn't touched. It is free'd below - bt_node_free(&tokdata->publ_token_obj_btree, obj_handle, FALSE); - } - - object_mgr_del_from_shm(o, tokdata->global_shm); - } - } - + rc = object_mgr_create_final(tokdata, sess, o, handle); done: if ((rc != CKR_OK) && (o != NULL)) { - if (!added) - object_free(o); - else - object_put(tokdata, o, FALSE); + object_free(o); o = NULL; } if (spki != NULL) @@ -383,9 +302,8 @@ OBJECT *new_obj = NULL; CK_BBOOL priv_obj; CK_BBOOL sess_obj; - CK_BBOOL added = FALSE, locked = FALSE; + CK_BBOOL locked = FALSE; CK_RV rc; - unsigned long obj_handle; if (!sess || (!pTemplate && ulCount) || !new_handle) { TRACE_ERROR("Invalid function arguments.\n"); @@ -420,113 +338,11 @@ // okay, object is created and the session permissions look okay. // add the object to the appropriate list and assign an object handle // - - if (sess_obj) { - new_obj->session = sess; - memset(&new_obj->name, 0x00, sizeof(CK_BYTE) * 8); - - if ((obj_handle = bt_node_add(&tokdata->sess_obj_btree, new_obj)) == 0) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - } else { - CK_BYTE current[8]; - CK_BYTE next[8]; - - // we'll be modifying nv_token_data so we should protect this part - // with 'XProcLock' - // - rc = XProcLock(tokdata); - if (rc != CKR_OK) { - TRACE_ERROR("Failed to get Process Lock.\n"); - goto done; - } - locked = TRUE; - - // Determine if we have already reached our Max Token Objects - // - if (priv_obj) { - if (tokdata->global_shm->num_priv_tok_obj >= MAX_TOK_OBJS) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - } else { - if (tokdata->global_shm->num_publ_tok_obj >= MAX_TOK_OBJS) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - } - memcpy(current, &tokdata->nv_token_data->next_token_object_name, 8); - - new_obj->session = NULL; - memcpy(&new_obj->name, current, 8); - - compute_next_token_obj_name(current, next); - memcpy(&tokdata->nv_token_data->next_token_object_name, next, 8); - - save_token_object(tokdata, new_obj); - - // add the object identifier to the shared memory segment - // - object_mgr_add_to_shm(new_obj, tokdata->global_shm); - - save_token_data(tokdata, sess->session_info.slotID); - - // now, store the object in the token object btree - // - if (priv_obj) - obj_handle = bt_node_add(&tokdata->priv_token_obj_btree, new_obj); - else - obj_handle = bt_node_add(&tokdata->publ_token_obj_btree, new_obj); - - if (!obj_handle) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - } - added = TRUE; - - rc = object_mgr_add_to_map(tokdata, sess, new_obj, obj_handle, new_handle); - if (rc != CKR_OK) { - TRACE_DEVEL("object_mgr_add_to_map failed.\n"); - - // this is messy but we need to remove the object from whatever - // list we just added it to - // - if (sess_obj) { - // put the binary tree node which holds new_obj on the free list, - // but pass NULL here, so that new_obj (the binary tree node's value - // pointer) isn't touched. It is free'd below - bt_node_free(&tokdata->sess_obj_btree, obj_handle, FALSE); - } else { - delete_token_object(tokdata, new_obj); - - if (priv_obj) { - // put the binary tree node which holds new_obj on the free - // list, but pass NULL here, so that new_obj (the binary tree - // node's value pointer) isn't touched. It is free'd below - bt_node_free(&tokdata->priv_token_obj_btree, obj_handle, FALSE); - } else { - // put the binary tree node which holds new_obj on the free - // list, but pass NULL here, so that new_obj (the binary tree - // node's value pointer) isn't touched. It is free'd below - bt_node_free(&tokdata->publ_token_obj_btree, obj_handle, FALSE); - } - - object_mgr_del_from_shm(new_obj, tokdata->global_shm); - } - } + rc = object_mgr_create_final(tokdata, sess, new_obj, new_handle); done: if ((rc != CKR_OK) && (new_obj != NULL)) { - if (!added) - object_free(new_obj); - else - object_put(tokdata, new_obj, FALSE); + object_free(new_obj); new_obj = NULL; } object_put(tokdata, old_obj, TRUE); @@ -653,6 +469,14 @@ return CKR_FUNCTION_FAILED; } + rc = tokdata->policy->store_object_strength(tokdata->policy, &obj->strength, + policy_get_attr_from_template, + obj->template, NULL, sess); + if (rc != CKR_OK) { + TRACE_ERROR("Failed to store acceptable object strength.\n"); + return rc; + } + sess_obj = object_is_session_object(obj); priv_obj = object_is_private(obj); @@ -1639,13 +1463,16 @@ if (oldObj != NULL) { obj = oldObj; - rc = object_restore_withSize(data, &obj, TRUE, data_size); + rc = object_restore_withSize(tokdata->policy, + data, &obj, TRUE, data_size); } else { - rc = object_restore_withSize(data, &obj, FALSE, data_size); + rc = object_restore_withSize(tokdata->policy, + data, &obj, FALSE, data_size); if (rc == CKR_OK) { rc = XProcLock(tokdata); if (rc != CKR_OK) { TRACE_ERROR("Failed to get Process Lock.\n"); + object_free(obj); return rc; } @@ -1655,12 +1482,14 @@ if (!bt_node_add(&tokdata->priv_token_obj_btree, obj)) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; + object_free(obj); goto unlock; } } else { if (!bt_node_add(&tokdata->publ_token_obj_btree, obj)) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; + object_free(obj); goto unlock; } } @@ -2000,7 +1829,7 @@ rc = XProcLock(tokdata); if (rc != CKR_OK) { TRACE_ERROR("Failed to get Process Lock.\n"); - return rc; + goto done_no_xproc_unlock; } if (priv) { @@ -2110,6 +1939,7 @@ XProcUnLock(tokdata); } +done_no_xproc_unlock: if (wr_locked) object_unlock(obj); if (!rd_locked) { @@ -2277,6 +2107,8 @@ /* we didn't find it in the btree, so add it */ if (fa.done == FALSE) { new_obj = (OBJECT *) malloc(sizeof(OBJECT)); + if (new_obj == NULL) + return CKR_HOST_MEMORY; memset(new_obj, 0x0, sizeof(OBJECT)); rc = object_init_lock(new_obj); @@ -2332,6 +2164,8 @@ /* we didn't find it in the btree, so add it */ if (fa.done == FALSE) { new_obj = (OBJECT *) malloc(sizeof(OBJECT)); + if (new_obj == NULL) + return CKR_HOST_MEMORY; memset(new_obj, 0x0, sizeof(OBJECT)); rc = object_init_lock(new_obj); diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/p11util.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/p11util.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/p11util.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/p11util.c 2022-02-02 15:05:41.000000000 +0100 @@ -12,6 +12,7 @@ #include #include #include "pkcs11types.h" +#include "mechtable.h" #define _sym2str(X) case X: return #X @@ -216,6 +217,17 @@ _sym2str(CKA_IBM_USE_AS_DATA); _sym2str(CKA_IBM_STRUCT_PARAMS); _sym2str(CKA_IBM_STD_COMPLIANCE1); + _sym2str(CKA_IBM_PROTKEY_EXTRACTABLE); + _sym2str(CKA_IBM_PROTKEY_NEVER_EXTRACTABLE); + _sym2str(CKA_IBM_OPAQUE_PKEY); + _sym2str(CKA_IBM_DILITHIUM_KEYFORM); + _sym2str(CKA_IBM_DILITHIUM_RHO); + _sym2str(CKA_IBM_DILITHIUM_SEED); + _sym2str(CKA_IBM_DILITHIUM_TR); + _sym2str(CKA_IBM_DILITHIUM_S1); + _sym2str(CKA_IBM_DILITHIUM_S2); + _sym2str(CKA_IBM_DILITHIUM_T0); + _sym2str(CKA_IBM_DILITHIUM_T1); default: sprintf(buf, "unknown attribute type 0x%08lx", atype); return buf; @@ -329,233 +341,13 @@ } -const char *p11_get_ckm(CK_ULONG mechanism) +const char *p11_get_ckm(const struct mechtable_funcs *f, CK_ULONG mechanism) { - switch (mechanism) { - _sym2str(CKM_RSA_PKCS_KEY_PAIR_GEN); - _sym2str(CKM_RSA_PKCS); - _sym2str(CKM_RSA_9796); - _sym2str(CKM_RSA_X_509); - _sym2str(CKM_MD2_RSA_PKCS); - _sym2str(CKM_MD5_RSA_PKCS); - _sym2str(CKM_SHA1_RSA_PKCS); - _sym2str(CKM_RIPEMD128_RSA_PKCS); - _sym2str(CKM_RIPEMD160_RSA_PKCS); - _sym2str(CKM_RSA_PKCS_OAEP); - _sym2str(CKM_RSA_X9_31_KEY_PAIR_GEN); - _sym2str(CKM_RSA_X9_31); - _sym2str(CKM_SHA1_RSA_X9_31); - _sym2str(CKM_RSA_PKCS_PSS); - _sym2str(CKM_SHA1_RSA_PKCS_PSS); - _sym2str(CKM_DSA_KEY_PAIR_GEN); - _sym2str(CKM_DSA); - _sym2str(CKM_DSA_SHA1); - _sym2str(CKM_DH_PKCS_KEY_PAIR_GEN); - _sym2str(CKM_DH_PKCS_DERIVE); - _sym2str(CKM_X9_42_DH_KEY_PAIR_GEN); - _sym2str(CKM_X9_42_DH_DERIVE); - _sym2str(CKM_X9_42_DH_HYBRID_DERIVE); - _sym2str(CKM_X9_42_MQV_DERIVE); - _sym2str(CKM_SHA224_RSA_PKCS); - _sym2str(CKM_SHA256_RSA_PKCS); - _sym2str(CKM_SHA384_RSA_PKCS); - _sym2str(CKM_SHA512_RSA_PKCS); - _sym2str(CKM_RC2_KEY_GEN); - _sym2str(CKM_RC2_ECB); - _sym2str(CKM_RC2_CBC); - _sym2str(CKM_RC2_MAC); - _sym2str(CKM_RC2_MAC_GENERAL); - _sym2str(CKM_RC2_CBC_PAD); - _sym2str(CKM_RC4_KEY_GEN); - _sym2str(CKM_RC4); - _sym2str(CKM_DES_KEY_GEN); - _sym2str(CKM_DES_ECB); - _sym2str(CKM_DES_CBC); - _sym2str(CKM_DES_MAC); - _sym2str(CKM_DES_MAC_GENERAL); - _sym2str(CKM_DES_CBC_PAD); - _sym2str(CKM_DES2_KEY_GEN); - _sym2str(CKM_DES3_KEY_GEN); - _sym2str(CKM_DES3_ECB); - _sym2str(CKM_DES3_CBC); - _sym2str(CKM_DES3_MAC); - _sym2str(CKM_DES3_MAC_GENERAL); - _sym2str(CKM_DES3_CBC_PAD); - _sym2str(CKM_CDMF_KEY_GEN); - _sym2str(CKM_CDMF_ECB); - _sym2str(CKM_CDMF_CBC); - _sym2str(CKM_CDMF_MAC); - _sym2str(CKM_CDMF_MAC_GENERAL); - _sym2str(CKM_CDMF_CBC_PAD); - _sym2str(CKM_MD2); - _sym2str(CKM_MD2_HMAC); - _sym2str(CKM_MD2_HMAC_GENERAL); - _sym2str(CKM_MD5); - _sym2str(CKM_MD5_HMAC); - _sym2str(CKM_MD5_HMAC_GENERAL); - _sym2str(CKM_SHA_1); - _sym2str(CKM_SHA_1_HMAC); - _sym2str(CKM_SHA_1_HMAC_GENERAL); - _sym2str(CKM_RIPEMD128); - _sym2str(CKM_RIPEMD128_HMAC); - _sym2str(CKM_RIPEMD128_HMAC_GENERAL); - _sym2str(CKM_RIPEMD160); - _sym2str(CKM_RIPEMD160_HMAC); - _sym2str(CKM_RIPEMD160_HMAC_GENERAL); - _sym2str(CKM_SHA224); - _sym2str(CKM_SHA224_HMAC); - _sym2str(CKM_SHA224_HMAC_GENERAL); - _sym2str(CKM_SHA256); - _sym2str(CKM_SHA256_HMAC); - _sym2str(CKM_SHA256_HMAC_GENERAL); - _sym2str(CKM_SHA384); - _sym2str(CKM_SHA384_HMAC); - _sym2str(CKM_SHA384_HMAC_GENERAL); - _sym2str(CKM_SHA512); - _sym2str(CKM_SHA512_HMAC); - _sym2str(CKM_SHA512_HMAC_GENERAL); - _sym2str(CKM_SHA512_224); - _sym2str(CKM_SHA512_224_HMAC); - _sym2str(CKM_SHA512_224_HMAC_GENERAL); - _sym2str(CKM_SHA512_256); - _sym2str(CKM_SHA512_256_HMAC); - _sym2str(CKM_SHA512_256_HMAC_GENERAL); - _sym2str(CKM_CAST_KEY_GEN); - _sym2str(CKM_CAST_ECB); - _sym2str(CKM_CAST_CBC); - _sym2str(CKM_CAST_MAC); - _sym2str(CKM_CAST_MAC_GENERAL); - _sym2str(CKM_CAST_CBC_PAD); - _sym2str(CKM_CAST3_KEY_GEN); - _sym2str(CKM_CAST3_ECB); - _sym2str(CKM_CAST3_CBC); - _sym2str(CKM_CAST3_MAC); - _sym2str(CKM_CAST3_MAC_GENERAL); - _sym2str(CKM_CAST3_CBC_PAD); - _sym2str(CKM_CAST5_KEY_GEN); - _sym2str(CKM_CAST5_ECB); - _sym2str(CKM_CAST5_CBC); - _sym2str(CKM_CAST5_MAC); - _sym2str(CKM_CAST5_MAC_GENERAL); - _sym2str(CKM_CAST5_CBC_PAD); - _sym2str(CKM_RC5_KEY_GEN); - _sym2str(CKM_RC5_ECB); - _sym2str(CKM_RC5_CBC); - _sym2str(CKM_RC5_MAC); - _sym2str(CKM_RC5_MAC_GENERAL); - _sym2str(CKM_RC5_CBC_PAD); - _sym2str(CKM_IDEA_KEY_GEN); - _sym2str(CKM_IDEA_ECB); - _sym2str(CKM_IDEA_CBC); - _sym2str(CKM_IDEA_MAC); - _sym2str(CKM_IDEA_MAC_GENERAL); - _sym2str(CKM_IDEA_CBC_PAD); - _sym2str(CKM_GENERIC_SECRET_KEY_GEN); - _sym2str(CKM_CONCATENATE_BASE_AND_KEY); - _sym2str(CKM_CONCATENATE_BASE_AND_DATA); - _sym2str(CKM_CONCATENATE_DATA_AND_BASE); - _sym2str(CKM_XOR_BASE_AND_DATA); - _sym2str(CKM_EXTRACT_KEY_FROM_KEY); - _sym2str(CKM_SSL3_PRE_MASTER_KEY_GEN); - _sym2str(CKM_SSL3_MASTER_KEY_DERIVE); - _sym2str(CKM_SSL3_KEY_AND_MAC_DERIVE); - _sym2str(CKM_SSL3_MASTER_KEY_DERIVE_DH); - _sym2str(CKM_TLS_PRE_MASTER_KEY_GEN); - _sym2str(CKM_TLS_MASTER_KEY_DERIVE); - _sym2str(CKM_TLS_KEY_AND_MAC_DERIVE); - _sym2str(CKM_TLS_MASTER_KEY_DERIVE_DH); - _sym2str(CKM_SSL3_MD5_MAC); - _sym2str(CKM_SSL3_SHA1_MAC); - _sym2str(CKM_MD5_KEY_DERIVATION); - _sym2str(CKM_MD2_KEY_DERIVATION); - _sym2str(CKM_SHA1_KEY_DERIVATION); - _sym2str(CKM_SHA224_KEY_DERIVATION); - _sym2str(CKM_SHA256_KEY_DERIVATION); - _sym2str(CKM_SHA384_KEY_DERIVATION); - _sym2str(CKM_SHA512_KEY_DERIVATION); - _sym2str(CKM_PBE_MD2_DES_CBC); - _sym2str(CKM_PBE_MD5_DES_CBC); - _sym2str(CKM_PBE_MD5_CAST_CBC); - _sym2str(CKM_PBE_MD5_CAST3_CBC); - _sym2str(CKM_PBE_MD5_CAST5_CBC); - _sym2str(CKM_PBE_SHA1_CAST5_CBC); - _sym2str(CKM_PBE_SHA1_RC4_128); - _sym2str(CKM_PBE_SHA1_RC4_40); - _sym2str(CKM_PBE_SHA1_DES3_EDE_CBC); - _sym2str(CKM_PBE_SHA1_DES2_EDE_CBC); - _sym2str(CKM_PBE_SHA1_RC2_128_CBC); - _sym2str(CKM_PBE_SHA1_RC2_40_CBC); - _sym2str(CKM_PKCS5_PBKD2); - _sym2str(CKM_PBA_SHA1_WITH_SHA1_HMAC); - _sym2str(CKM_KEY_WRAP_LYNKS); - _sym2str(CKM_KEY_WRAP_SET_OAEP); - _sym2str(CKM_SKIPJACK_KEY_GEN); - _sym2str(CKM_SKIPJACK_ECB64); - _sym2str(CKM_SKIPJACK_CBC64); - _sym2str(CKM_SKIPJACK_OFB64); - _sym2str(CKM_SKIPJACK_CFB64); - _sym2str(CKM_SKIPJACK_CFB32); - _sym2str(CKM_SKIPJACK_CFB16); - _sym2str(CKM_SKIPJACK_CFB8); - _sym2str(CKM_SKIPJACK_WRAP); - _sym2str(CKM_SKIPJACK_PRIVATE_WRAP); - _sym2str(CKM_SKIPJACK_RELAYX); - _sym2str(CKM_KEA_KEY_PAIR_GEN); - _sym2str(CKM_KEA_KEY_DERIVE); - _sym2str(CKM_FORTEZZA_TIMESTAMP); - _sym2str(CKM_BATON_KEY_GEN); - _sym2str(CKM_BATON_ECB128); - _sym2str(CKM_BATON_ECB96); - _sym2str(CKM_BATON_CBC128); - _sym2str(CKM_BATON_COUNTER); - _sym2str(CKM_BATON_SHUFFLE); - _sym2str(CKM_BATON_WRAP); - _sym2str(CKM_EC_KEY_PAIR_GEN); - _sym2str(CKM_ECDSA); - _sym2str(CKM_ECDSA_SHA1); - _sym2str(CKM_ECDSA_SHA224); - _sym2str(CKM_ECDSA_SHA256); - _sym2str(CKM_ECDSA_SHA384); - _sym2str(CKM_ECDSA_SHA512); - _sym2str(CKM_ECDH1_DERIVE); - _sym2str(CKM_ECDH1_COFACTOR_DERIVE); - _sym2str(CKM_ECMQV_DERIVE); - _sym2str(CKM_JUNIPER_KEY_GEN); - _sym2str(CKM_JUNIPER_ECB128); - _sym2str(CKM_JUNIPER_CBC128); - _sym2str(CKM_JUNIPER_COUNTER); - _sym2str(CKM_JUNIPER_SHUFFLE); - _sym2str(CKM_JUNIPER_WRAP); - _sym2str(CKM_FASTHASH); - _sym2str(CKM_AES_KEY_GEN); - _sym2str(CKM_AES_ECB); - _sym2str(CKM_AES_CBC); - _sym2str(CKM_AES_MAC); - _sym2str(CKM_AES_MAC_GENERAL); - _sym2str(CKM_AES_CBC_PAD); - _sym2str(CKM_AES_CTR); - _sym2str(CKM_DSA_PARAMETER_GEN); - _sym2str(CKM_DH_PKCS_PARAMETER_GEN); - _sym2str(CKM_X9_42_DH_PARAMETER_GEN); - _sym2str(CKM_VENDOR_DEFINED); - _sym2str(CKM_IBM_SHA3_224); - _sym2str(CKM_IBM_SHA3_256); - _sym2str(CKM_IBM_SHA3_384); - _sym2str(CKM_IBM_SHA3_512); - _sym2str(CKM_IBM_CMAC); - _sym2str(CKM_IBM_SHA3_224_HMAC); - _sym2str(CKM_IBM_SHA3_256_HMAC); - _sym2str(CKM_IBM_SHA3_384_HMAC); - _sym2str(CKM_IBM_SHA3_512_HMAC); - _sym2str(CKM_IBM_EC_X25519); - _sym2str(CKM_IBM_ED25519_SHA512); - _sym2str(CKM_IBM_EC_X448); - _sym2str(CKM_IBM_ED448_SHA3); - _sym2str(CKM_IBM_DILITHIUM); - _sym2str(CKM_IBM_ATTRIBUTEBOUND_WRAP); - default: - return "UNKNOWN"; - } + const struct mechrow *row = f->p_row_from_num(mechanism); + + if (row) + return row->string; + return "UNKNOWN"; } // Allocates memory on *dst and puts hex dump from ptr diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/p11util.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/p11util.h --- opencryptoki-3.16.0+dfsg/usr/lib/common/p11util.h 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/p11util.h 2022-02-02 15:05:41.000000000 +0100 @@ -14,6 +14,8 @@ #include "pkcs11types.h" +struct mechtable_funcs; + // // p11_get_ckr - return textual interpretation of a CKR_ error code // @rc is the CKR_.. error @@ -23,7 +25,7 @@ // p11_get_ckm - return textual interpretation of a CKM_ mechanism code // @rc is the CKM_.. as a string // -const char *p11_get_ckm(CK_ULONG); +const char *p11_get_ckm(const struct mechtable_funcs *,CK_ULONG); // // p11_get_cka - return textual interpretation of an attribute type diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/parser.y opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/parser.y --- opencryptoki-3.16.0+dfsg/usr/lib/common/parser.y 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/parser.y 1970-01-01 01:00:00.000000000 +0100 @@ -1,304 +0,0 @@ -/* - * COPYRIGHT (c) International Business Machines Corp. 2013-2017 - * - * This program is provided under the terms of the Common Public License, - * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this - * software constitutes recipient's acceptance of CPL-1.0 terms which can be - * found in the file LICENSE file or at - * https://opensource.org/licenses/cpl1.0.php - */ - -%{ -/* - * Parse openCryptoki's config file. - */ - -#include -#include -#include -#include -#include - -#include "slotmgr.h" -#include "configparser.h" - -static struct strholder { - struct strholder *prev; - char *str; -} *strroot; - -struct parsefuncs *parsefuncs; -void *parsedata; - -extern FILE *yyin; -extern int yyparse(); -extern void yyerror(const char *s); -extern int line_num; -extern int yylex(); - -static void configparse_freestrings(void); -static void configparse_freestringsfrom(char *str); - -struct ock_key { - char *name; - keyword_token token; -}; - -static const struct ock_key ock_keywords[] = { - {"stdll", KW_STDLL}, - {"description", KW_SLOTDESC}, - {"manufacturer", KW_MANUFID}, - {"hwversion", KW_HWVERSION}, - {"firmwareversion", KW_FWVERSION}, - {"confname", KW_CONFNAME}, - {"tokname", KW_TOKNAME}, - {"tokversion", KW_TOKVERSION} -}; - -int lookup_keyword(const char *key); - -%} - -%union { - char *str; - unsigned int num; - int err; -} - -%token EQUAL DOT SLOT EOL OCKVERSION BEGIN_DEF END_DEF -%token STRING -%token KEYWORD -%token INTEGER -%token TOKVERSION -%token COMMENT - -%% - -config_file: - config_file sections - | - ; - -sections: - version_def eolcomment - | SLOT INTEGER BEGIN_DEF - { - if (parsefuncs->begin_slot && parsefuncs->begin_slot(parsedata, $2, 0)) { - if (parsefuncs->parseerror) - parsefuncs->parseerror(parsedata, line_num, NULL); - YYERROR; - } - } eolcomment keyword_defs END_DEF - { - if (parsefuncs->end_slot && parsefuncs->end_slot(parsedata)) { - if (parsefuncs->parseerror) - parsefuncs->parseerror(parsedata, line_num, NULL); - YYERROR; - } - } - | SLOT INTEGER EOL BEGIN_DEF - { - if (parsefuncs->begin_slot && parsefuncs->begin_slot(parsedata, $2, 1)) { - if (parsefuncs->parseerror) - parsefuncs->parseerror(parsedata, line_num, NULL); - YYERROR; - } - } eolcomment keyword_defs END_DEF - { - if (parsefuncs->end_slot && parsefuncs->end_slot(parsedata)) { - if (parsefuncs->parseerror) - parsefuncs->parseerror(parsedata, line_num, NULL); - YYERROR; - } - } - | eolcomment - ; - -version_def: - OCKVERSION STRING - { - if (parsefuncs->version && parsefuncs->version(parsedata, $2)) { - if (parsefuncs->parseerror) - parsefuncs->parseerror(parsedata, line_num, NULL); - configparse_freestringsfrom($2); - YYERROR; - } - configparse_freestringsfrom($2); - } - -line_def: - STRING EQUAL TOKVERSION - { - int kw; - char errbuf[256]; - - kw = lookup_keyword($1); - if (kw == -1) { - if (parsefuncs->parseerror) { - snprintf(errbuf, sizeof(errbuf), "Unknown keyword: \"%s\"", $1); - parsefuncs->parseerror(parsedata, line_num, errbuf); - } - configparse_freestringsfrom($1); - YYERROR; - } - configparse_freestringsfrom($1); - if (parsefuncs->key_vers) { - if(parsefuncs->key_vers(parsedata, kw, $3)) { - if (parsefuncs->parseerror) - parsefuncs->parseerror(parsedata, line_num, NULL); - YYERROR; - } - } - } - | - STRING EQUAL STRING - { - int kw; - char errbuf[256]; - - kw = lookup_keyword($1); - if (kw == -1) { - if (parsefuncs->parseerror) { - snprintf(errbuf, sizeof(errbuf), "Unknown keyword: \"%s\"", $1); - parsefuncs->parseerror(parsedata, line_num, errbuf); - } - configparse_freestringsfrom($3); - YYERROR; - } - if (parsefuncs->key_str && parsefuncs->key_str(parsedata, kw, $3)) { - if (parsefuncs->parseerror) - parsefuncs->parseerror(parsedata, line_num, NULL); - configparse_freestringsfrom($3); - YYERROR; - } - configparse_freestringsfrom($3); // Will also free $1 - } - -keyword_defs: - line_def eolcomment keyword_defs - | - eolcomment keyword_defs - | - /* empty */ - -eolcomment: - COMMENT EOL - { - if (parsefuncs->eolcomment) - parsefuncs->eolcomment(parsedata, $1); - if (parsefuncs->eol) - parsefuncs->eol(parsedata); - configparse_freestringsfrom($1); - } - | - EOL - { - if (parsefuncs->eol) - parsefuncs->eol(parsedata); - } - -%% - -char *configparse_strdup(char *val) -{ - struct strholder *holder; - char *res = NULL; - - holder = (struct strholder *)malloc(sizeof(struct strholder)); - if (holder) { - holder->prev = strroot; - strroot = holder; - holder->str = res = strdup(val); - } - return res; -} - -static void configparse_freestrings() -{ - struct strholder *cur, *next; - - cur = strroot; - while (cur) { - next = cur->prev; - free(cur->str); - free(cur); - cur = next; - } - strroot = NULL; -} - -static void configparse_freestringsfrom(char *str) -{ - struct strholder *cur, *next, **anchor; - - anchor = &strroot; - cur = strroot; - while (cur && cur->str != str) { - anchor = &cur->prev; - cur = cur->prev; - } - while (cur) { - next = cur->prev; - free(cur->str); - free(cur); - cur = next; - } - *anchor = NULL; -} - -void -yyerror(const char *s) -{ - if (parsefuncs->parseerror) - parsefuncs->parseerror(parsedata, line_num, s); -} - -int -lookup_keyword(const char *key) -{ - int i; - - for (i = 0; i < KW_MAX ; i++ ) { - if (strncmp(key, ock_keywords[i].name, strlen(key)) == 0) - return ock_keywords[i].token; - } - /* if we get here that means did not find a match... */ - return -1; -} - -const char *keyword_token_to_str(int tok) -{ - return tok < KW_MAX ? ock_keywords[tok].name : ""; -} - -int -load_and_parse(const char *configfile, struct parsefuncs *funcs, void *private) -{ - - FILE *conf; - int res; - - extern FILE *yyin; - - conf = fopen(configfile, "r"); - - if (!conf) { - fprintf(stderr, "Failed to open %s: %s\n", configfile, strerror(errno)); - return -1; - } - - line_num = 1; - yyin = conf; - parsefuncs = funcs; - parsedata = private; - strroot = NULL; - - res = yyparse(); - - fclose(conf); - parsefuncs = NULL; - parsedata = NULL; - configparse_freestrings(); - - return res; -} diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/pkey_utils.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/pkey_utils.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/pkey_utils.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/pkey_utils.c 2022-02-02 15:05:41.000000000 +0100 @@ -398,11 +398,16 @@ ec_params = (CK_BYTE *) attr->pValue; - if (memcmp(ec_params, p256, sizeof(p256)) == 0 || - memcmp(ec_params, p384, sizeof(p384)) == 0 || - memcmp(ec_params, p521, sizeof(p521)) == 0 || - memcmp(ec_params, ed25519, sizeof(ed25519)) == 0 || - memcmp(ec_params, ed448, sizeof(ed448)) == 0) { + if ((attr->ulValueLen == sizeof(p256) && + memcmp(ec_params, p256, sizeof(p256)) == 0) || + (attr->ulValueLen == sizeof(p384) && + memcmp(ec_params, p384, sizeof(p384)) == 0) || + (attr->ulValueLen == sizeof(p521) && + memcmp(ec_params, p521, sizeof(p521)) == 0) || + (attr->ulValueLen == sizeof(ed25519) && + memcmp(ec_params, ed25519, sizeof(ed25519)) == 0) || + (attr->ulValueLen == sizeof(ed448) && + memcmp(ec_params, ed448, sizeof(ed448)) == 0)) { return CK_TRUE; } @@ -763,15 +768,20 @@ } ec_params = (CK_BYTE *) attr->pValue; - if (memcmp(ec_params, p256, sizeof(p256)) == 0) + if (attr->ulValueLen == sizeof(p256) && + memcmp(ec_params, p256, sizeof(p256)) == 0) curve_type = curve_p256; - else if (memcmp(ec_params, p384, sizeof(p384)) == 0) + else if (attr->ulValueLen == sizeof(p384) && + memcmp(ec_params, p384, sizeof(p384)) == 0) curve_type = curve_p384; - else if (memcmp(ec_params, p521, sizeof(p521)) == 0) + else if (attr->ulValueLen == sizeof(p521) && + memcmp(ec_params, p521, sizeof(p521)) == 0) curve_type = curve_p521; - else if (memcmp(ec_params, ed25519, sizeof(ed25519)) == 0) + else if (attr->ulValueLen == sizeof(ed25519) && + memcmp(ec_params, ed25519, sizeof(ed25519)) == 0) curve_type = curve_ed25519; - else if (memcmp(ec_params, ed448, sizeof(ed448)) == 0) + else if (attr->ulValueLen == sizeof(ed448) && + memcmp(ec_params, ed448, sizeof(ed448)) == 0) curve_type = curve_ed448; else curve_type = curve_invalid; diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/sess_mgr.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/sess_mgr.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/sess_mgr.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/sess_mgr.c 2022-02-02 15:05:41.000000000 +0100 @@ -47,6 +47,27 @@ return result; } +// session_mgr_find_reset_error() +// +// search for the specified session and reset the ulDeviceError field +// in the session info. returning a pointer to the session might be +// dangerous, but performs well +// +// The returned session must be put back (using bt_put_node_value()) by the +// caller to decrease the reference count! +// +// Returns: SESSION * or NULL +// +SESSION *session_mgr_find_reset_error(STDLL_TokData_t *tokdata, + CK_SESSION_HANDLE handle) +{ + SESSION *res = session_mgr_find(tokdata, handle); + + if (res) + res->session_info.ulDeviceError = 0; + return res; +} + void session_mgr_put(STDLL_TokData_t *tokdata, SESSION *session) { bt_put_node_value(&tokdata->sess_btree, session); @@ -243,32 +264,62 @@ if (sess->find_list) free(sess->find_list); - if (sess->encr_ctx.context) - free(sess->encr_ctx.context); + if (sess->encr_ctx.context) { + if (sess->encr_ctx.context_free_func != NULL) + sess->encr_ctx.context_free_func(tokdata, sess, + sess->encr_ctx.context, + sess->encr_ctx.context_len); + else + free(sess->encr_ctx.context); + } if (sess->encr_ctx.mech.pParameter) free(sess->encr_ctx.mech.pParameter); - if (sess->decr_ctx.context) - free(sess->decr_ctx.context); + if (sess->decr_ctx.context) { + if (sess->decr_ctx.context_free_func != NULL) + sess->decr_ctx.context_free_func(tokdata, sess, + sess->decr_ctx.context, + sess->decr_ctx.context_len); + else + free(sess->decr_ctx.context); + } if (sess->decr_ctx.mech.pParameter) free(sess->decr_ctx.mech.pParameter); - if (sess->digest_ctx.context) - free(sess->digest_ctx.context); + if (sess->digest_ctx.context) { + if (sess->digest_ctx.context_free_func != NULL) + sess->digest_ctx.context_free_func(tokdata, sess, + sess->digest_ctx.context, + sess->digest_ctx.context_len); + else + free(sess->digest_ctx.context); + } if (sess->digest_ctx.mech.pParameter) free(sess->digest_ctx.mech.pParameter); - if (sess->sign_ctx.context) - free(sess->sign_ctx.context); + if (sess->sign_ctx.context) { + if (sess->sign_ctx.context_free_func != NULL) + sess->sign_ctx.context_free_func(tokdata, sess, + sess->sign_ctx.context, + sess->sign_ctx.context_len); + else + free(sess->sign_ctx.context); + } if (sess->sign_ctx.mech.pParameter) free(sess->sign_ctx.mech.pParameter); - if (sess->verify_ctx.context) - free(sess->verify_ctx.context); + if (sess->verify_ctx.context) { + if (sess->verify_ctx.context_free_func != NULL) + sess->verify_ctx.context_free_func(tokdata, sess, + sess->verify_ctx.context, + sess->verify_ctx.context_len); + else + free(sess->verify_ctx.context); + } if (sess->verify_ctx.mech.pParameter) free(sess->verify_ctx.mech.pParameter); @@ -323,32 +374,62 @@ if (sess->find_list) free(sess->find_list); - if (sess->encr_ctx.context) - free(sess->encr_ctx.context); + if (sess->encr_ctx.context) { + if (sess->encr_ctx.context_free_func != NULL) + sess->encr_ctx.context_free_func(tokdata, sess, + sess->encr_ctx.context, + sess->encr_ctx.context_len); + else + free(sess->encr_ctx.context); + } if (sess->encr_ctx.mech.pParameter) free(sess->encr_ctx.mech.pParameter); - if (sess->decr_ctx.context) - free(sess->decr_ctx.context); + if (sess->decr_ctx.context) { + if (sess->decr_ctx.context_free_func != NULL) + sess->decr_ctx.context_free_func(tokdata, sess, + sess->decr_ctx.context, + sess->decr_ctx.context_len); + else + free(sess->decr_ctx.context); + } if (sess->decr_ctx.mech.pParameter) free(sess->decr_ctx.mech.pParameter); - if (sess->digest_ctx.context) - free(sess->digest_ctx.context); + if (sess->digest_ctx.context) { + if (sess->digest_ctx.context_free_func != NULL) + sess->digest_ctx.context_free_func(tokdata, sess, + sess->digest_ctx.context, + sess->digest_ctx.context_len); + else + free(sess->digest_ctx.context); + } if (sess->digest_ctx.mech.pParameter) free(sess->digest_ctx.mech.pParameter); - if (sess->sign_ctx.context) - free(sess->sign_ctx.context); + if (sess->sign_ctx.context) { + if (sess->sign_ctx.context_free_func != NULL) + sess->sign_ctx.context_free_func(tokdata, sess, + sess->sign_ctx.context, + sess->sign_ctx.context_len); + else + free(sess->sign_ctx.context); + } if (sess->sign_ctx.mech.pParameter) free(sess->sign_ctx.mech.pParameter); - if (sess->verify_ctx.context) - free(sess->verify_ctx.context); + if (sess->verify_ctx.context) { + if (sess->verify_ctx.context_free_func != NULL) + sess->verify_ctx.context_free_func(tokdata, sess, + sess->verify_ctx.context, + sess->verify_ctx.context_len); + else + free(sess->verify_ctx.context); + } if (sess->verify_ctx.mech.pParameter) free(sess->verify_ctx.mech.pParameter); @@ -480,6 +561,10 @@ active_ops = 0; if (sess->encr_ctx.active == TRUE) { + if (sess->encr_ctx.state_unsaveable) { + TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE)); + return CKR_STATE_UNSAVEABLE; + } active_ops++; if (op_data != NULL) { TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE)); @@ -524,6 +609,10 @@ } if (sess->decr_ctx.active == TRUE) { + if (sess->decr_ctx.state_unsaveable) { + TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE)); + return CKR_STATE_UNSAVEABLE; + } active_ops++; if (op_data != NULL) { TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE)); @@ -568,6 +657,10 @@ } if (sess->digest_ctx.active == TRUE) { + if (sess->digest_ctx.state_unsaveable) { + TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE)); + return CKR_STATE_UNSAVEABLE; + } active_ops++; if (op_data != NULL) { TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE)); @@ -612,6 +705,10 @@ } if (sess->sign_ctx.active == TRUE) { + if (sess->sign_ctx.state_unsaveable) { + TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE)); + return CKR_STATE_UNSAVEABLE; + } active_ops++; if (op_data != NULL) { TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE)); @@ -656,6 +753,10 @@ } if (sess->verify_ctx.active == TRUE) { + if (sess->verify_ctx.state_unsaveable) { + TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE)); + return CKR_STATE_UNSAVEABLE; + } active_ops++; if (op_data != NULL) { TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE)); @@ -711,7 +812,7 @@ // // -CK_RV session_mgr_set_op_state(SESSION *sess, +CK_RV session_mgr_set_op_state(STDLL_TokData_t *tokdata, SESSION *sess, CK_OBJECT_HANDLE encr_key, CK_OBJECT_HANDLE auth_key, CK_BYTE *data, CK_ULONG data_len) @@ -891,19 +992,19 @@ // state information looks okay. cleanup the current session state, first // if (sess->encr_ctx.active) - encr_mgr_cleanup(&sess->encr_ctx); + encr_mgr_cleanup(tokdata, sess, &sess->encr_ctx); if (sess->decr_ctx.active) - decr_mgr_cleanup(&sess->decr_ctx); + decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx); if (sess->digest_ctx.active) - digest_mgr_cleanup(&sess->digest_ctx); + digest_mgr_cleanup(tokdata, sess, &sess->digest_ctx); if (sess->sign_ctx.active) - sign_mgr_cleanup(&sess->sign_ctx); + sign_mgr_cleanup(tokdata, sess, &sess->sign_ctx); if (sess->verify_ctx.active) - verify_mgr_cleanup(&sess->verify_ctx); + verify_mgr_cleanup(tokdata, sess, &sess->verify_ctx); // copy the new state information diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/shared_memory.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/shared_memory.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/shared_memory.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/shared_memory.c 2022-02-02 15:05:41.000000000 +0100 @@ -29,6 +29,7 @@ #include #include #include +#include /* For logging functions: */ #include "pkcs11types.h" @@ -36,6 +37,7 @@ #include "host_defs.h" #include "h_extern.h" #include "trace.h" +#include "ock_syslog.h" #include "shared_memory.h" @@ -159,6 +161,7 @@ struct shm_context *ctx = NULL; size_t real_len = sizeof(*ctx) + len; int created = 0; + struct group *grp; /* * This is used for portability purpose. Please check `shm_open` @@ -169,6 +172,14 @@ goto done; } + grp = getgrnam("pkcs11"); + if (!grp) { + rc = -errno; + SYS_ERROR(errno, "getgrname(\"pkcs11\"): %s\n", + strerror(errno)); + goto done; + } + /* try and open first... */ fd = shm_open(name, O_RDWR, mode); if (fd < 0) { @@ -188,6 +199,12 @@ SYS_ERROR(errno, "fchmod(%s): %s\n", name, strerror(errno)); goto done; } + if (fchown(fd, -1, grp->gr_gid) != 0) { + rc = -errno; + SYS_ERROR(errno, "fchown of token shm segment: %s\n", + strerror(errno)); + goto done; + } } } @@ -203,6 +220,21 @@ } /* + * If the shared memory segment does not belong to the pkcs11 group or does + * not have correct permissions, do not use it. + */ + if (stat_buf.st_gid != grp->gr_gid || + (stat_buf.st_mode & ~S_IFMT) != (unsigned int)mode) { + TRACE_ERROR("SHM segment has wrong gid/mode combination (expected: %u/0%o; got: %u/0%o)\n", + grp->gr_gid, mode, stat_buf.st_gid, stat_buf.st_mode); + OCK_SYSLOG(LOG_ERR, + "SHM segment has wrong gid/mode combination (expected: %u/0%o; got: %u/0%o)\n", + grp->gr_gid, mode, stat_buf.st_gid, stat_buf.st_mode); + rc = -EINVAL; + goto done; + } + + /* * The shared memory needs to be extended when created (when its length * is zero). When its length is not zero and is not equal to the * expected size, an error is returned if `force` is not set. If `force` @@ -281,7 +313,8 @@ */ ctx = addr; if (created) { - strcpy(ctx->name, name); + strncpy(ctx->name, name, SM_NAME_LEN); + ctx->name[SM_NAME_LEN] = '\0'; ctx->data_len = len; memset(ctx->data, 0, ctx->data_len); ctx->ref = 0; @@ -326,7 +359,7 @@ { int rc; int ref; - char name[SM_NAME_LEN + 2] = { 0, }; + char name[SM_NAME_LEN + 1] = { 0, }; struct shm_context *ctx = get_shm_context(addr); if (ctx->ref <= 0) { @@ -341,7 +374,7 @@ TRACE_DEVEL("close: ref = %d\n", ref); if (ref == 0 && destroy) { - strncpy(name, ctx->name, SM_NAME_LEN + 2); + memcpy(name, ctx->name, SM_NAME_LEN); name[SM_NAME_LEN] = '\0'; } diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/sign_mgr.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/sign_mgr.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/sign_mgr.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/sign_mgr.c 2022-02-02 15:05:41.000000000 +0100 @@ -25,13 +25,17 @@ #include "tok_spec_struct.h" #include "trace.h" +#include "../api/policy.h" +#include "../api/statistics.h" + // // CK_RV sign_mgr_init(STDLL_TokData_t *tokdata, SESSION *sess, SIGN_VERIFY_CONTEXT *ctx, CK_MECHANISM *mech, - CK_BBOOL recover_mode, CK_OBJECT_HANDLE key) + CK_BBOOL recover_mode, CK_OBJECT_HANDLE key, + CK_BBOOL checkpolicy) { OBJECT *key_obj = NULL; CK_ATTRIBUTE *attr = NULL; @@ -40,7 +44,7 @@ CK_OBJECT_CLASS class; CK_BBOOL flag; CK_RV rc; - + CK_ULONG strength = POLICY_STRENGTH_IDX_0; if (!sess || !ctx) { TRACE_ERROR("Invalid function arguments.\n"); @@ -60,6 +64,15 @@ else return rc; } + if (checkpolicy) { + rc = tokdata->policy->is_mech_allowed(tokdata->policy, mech, + &key_obj->strength, + POLICY_CHECK_SIGNATURE, sess); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Sign init\n"); + goto done; + } + } if (recover_mode) { // is key allowed to generate signatures where the data can be @@ -424,6 +437,12 @@ ctx->context_len = 0; ctx->context = NULL; + strength = key_obj->strength.strength; + + /* Release obj lock, token specific hmac-sign may re-acquire the lock */ + object_put(tokdata, key_obj, TRUE); + key_obj = NULL; + rc = hmac_sign_init(tokdata, sess, mech, key); if (rc != CKR_OK) { TRACE_ERROR("Failed to initialize hmac.\n"); @@ -792,6 +811,9 @@ rc = CKR_OK; done: + if (ctx->count_statistics == TRUE && rc == CKR_OK) + INC_COUNTER(tokdata, sess, mech, key_obj, strength); + object_put(tokdata, key_obj, TRUE); key_obj = NULL; @@ -801,7 +823,8 @@ // // -CK_RV sign_mgr_cleanup(SIGN_VERIFY_CONTEXT *ctx) +CK_RV sign_mgr_cleanup(STDLL_TokData_t *tokdata, SESSION *sess, + SIGN_VERIFY_CONTEXT *ctx) { if (!ctx) { TRACE_ERROR("Invalid function argument.\n"); @@ -817,6 +840,8 @@ ctx->recover = FALSE; ctx->context_len = 0; ctx->pkey_active = FALSE; + ctx->state_unsaveable = FALSE; + ctx->count_statistics = FALSE; if (ctx->mech.pParameter) { free(ctx->mech.pParameter); @@ -824,9 +849,14 @@ } if (ctx->context) { - free(ctx->context); + if (ctx->context_free_func != NULL) + ctx->context_free_func(tokdata, sess, ctx->context, + ctx->context_len); + else + free(ctx->context); ctx->context = NULL; } + ctx->context_free_func = NULL; return CKR_OK; } diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/stringtranslations.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/stringtranslations.h --- opencryptoki-3.16.0+dfsg/usr/lib/common/stringtranslations.h 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/stringtranslations.h 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,60 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ +#ifndef OCK_STRINGTRANSLATIONS_H +#define OCK_STRINGTRANSLATIONS_H + +#include +#include +#include "ec_defs.h" +#include "mechtable.h" + +/* + * Translate a string of a given length CK_RVo a mechanism id. + */ +static inline CK_RV translate_string_to_mech(const char *str, size_t len, + CK_ULONG *mech) +{ + (void)len; + const struct mechrow *col = mechrow_from_string(str); + + if (col) { + *mech = col->numeric; + return CKR_OK; + } + return CKR_FUNCTION_FAILED; +} + +/* + * Translate an elliptic curve name (all caps) of a given length CK_RVo + * a struct _ec. + */ +CK_RV translate_string_to_curve(const char *str, size_t len, + const struct _ec **curve); + +CK_RV translate_string_to_mgf(const char *str, size_t len, CK_ULONG* mgf); + +CK_RV translate_string_to_kdf(const char *str, size_t len, CK_ULONG* kdf); + +static inline CK_RV translate_string_to_prf(const char *str, size_t len, + CK_ULONG* prf) +{ + (void)len; + if (strcmp(str, "CKP_PKCS5_PBKD2_HMAC_SHA256") == 0) { + *prf = CKP_PKCS5_PBKD2_HMAC_SHA256; + return CKR_OK; + } + if (strcmp(str, "CKP_PKCS5_PBKD2_HMAC_SHA512") == 0) { + *prf = CKP_PKCS5_PBKD2_HMAC_SHA512; + return CKR_OK; + } + return CKR_FUNCTION_FAILED; +} + +#endif diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/sw_crypt.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/sw_crypt.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/sw_crypt.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/sw_crypt.c 2022-02-02 15:05:41.000000000 +0100 @@ -32,51 +32,6 @@ CK_ULONG *out_data_len, CK_BYTE *init_v, CK_BYTE *key_value, CK_BYTE encrypt) { -#if OPENSSL_VERSION_NUMBER < 0x10100000L - DES_key_schedule des_key1; - DES_key_schedule des_key2; - DES_key_schedule des_key3; - - const_DES_cblock key_SSL1, key_SSL2, key_SSL3; - DES_cblock ivec; - - // the des decrypt will only fail if the data length is not evenly divisible - // by DES_BLOCK_SIZE - if (in_data_len % DES_BLOCK_SIZE) { - TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); - return CKR_DATA_LEN_RANGE; - } - // The key as passed in is a 24 byte string containing 3 keys - // pick it apart and create the key schedules - memcpy(&key_SSL1, key_value, (size_t) 8); - memcpy(&key_SSL2, key_value + 8, (size_t) 8); - memcpy(&key_SSL3, key_value + 16, (size_t) 8); - DES_set_key_unchecked(&key_SSL1, &des_key1); - DES_set_key_unchecked(&key_SSL2, &des_key2); - DES_set_key_unchecked(&key_SSL3, &des_key3); - - memcpy(ivec, init_v, sizeof(ivec)); - - // Encrypt or decrypt the data - if (encrypt) { - DES_ede3_cbc_encrypt(in_data, - out_data, - in_data_len, - &des_key1, - &des_key2, &des_key3, &ivec, DES_ENCRYPT); - *out_data_len = in_data_len; - } else { - DES_ede3_cbc_encrypt(in_data, - out_data, - in_data_len, - &des_key1, - &des_key2, &des_key3, &ivec, DES_DECRYPT); - - *out_data_len = in_data_len; - } - - return CKR_OK; -#else CK_RV rc; int outlen; const EVP_CIPHER *cipher = EVP_des_ede3_cbc(); @@ -109,7 +64,6 @@ done: EVP_CIPHER_CTX_free(ctx); return rc; -#endif } CK_RV sw_aes_cbc(CK_BYTE *in_data, @@ -119,33 +73,6 @@ CK_BYTE *init_v, CK_BYTE *key_value, CK_ULONG keylen, CK_BYTE encrypt) { -#if OPENSSL_VERSION_NUMBER < 0x10100000L - AES_KEY aes_key; - - UNUSED(out_data_len); //XXX can this parameter be removed ? - - memset(&aes_key, 0, sizeof(aes_key)); - - // the aes decrypt will only fail if the data length is not evenly divisible - // by AES_BLOCK_SIZE - if (in_data_len % AES_BLOCK_SIZE) { - TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); - return CKR_DATA_LEN_RANGE; - } - - // Encrypt or decrypt the data - if (encrypt) { - AES_set_encrypt_key(key_value, keylen * 8, &aes_key); - AES_cbc_encrypt(in_data, out_data, in_data_len, &aes_key, - init_v, AES_ENCRYPT); - } else { - AES_set_decrypt_key(key_value, keylen * 8, &aes_key); - AES_cbc_encrypt(in_data, out_data, in_data_len, &aes_key, - init_v, AES_DECRYPT); - } - - return CKR_OK; -#else CK_RV rc; int outlen; const EVP_CIPHER *cipher = NULL; @@ -187,5 +114,4 @@ done: EVP_CIPHER_CTX_free(ctx); return rc; -#endif } diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/tok_specific.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/tok_specific.h --- opencryptoki-3.16.0+dfsg/usr/lib/common/tok_specific.h 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/tok_specific.h 2022-02-02 15:05:41.000000000 +0100 @@ -326,4 +326,10 @@ CK_OBJECT_CLASS, CK_ULONG, TEMPLATE *); +CK_RV token_specific_handle_event(STDLL_TokData_t *tokdata, + unsigned int event_type, + unsigned int event_flags, + const char *payload, + unsigned int payload_len); + #endif diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/tok_spec_struct.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/tok_spec_struct.h --- opencryptoki-3.16.0+dfsg/usr/lib/common/tok_spec_struct.h 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/tok_spec_struct.h 2022-02-02 15:05:41.000000000 +0100 @@ -278,6 +278,10 @@ CK_RV(*t_set_attrs_for_new_object) (STDLL_TokData_t *, CK_OBJECT_CLASS, CK_ULONG, TEMPLATE *); + + CK_RV(*t_handle_event) (STDLL_TokData_t *tokdata, unsigned int event_type, + unsigned int event_flags, const char *payload, + unsigned int payload_len); }; typedef struct token_specific_struct token_spec_t; diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/trace.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/trace.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/trace.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/trace.c 2022-02-02 15:05:41.000000000 +0100 @@ -33,6 +33,8 @@ #ifdef SYS_gettid #define __gettid() syscall(SYS_gettid) +#else +#define __gettid() gettid() #endif pthread_mutex_t tlmtx = PTHREAD_MUTEX_INITIALIZER; @@ -129,7 +131,7 @@ void trace_finalize(void) { - if (trace.fd) + if (trace.fd >= 0) close(trace.fd); trace.fd = -1; trace.level = TRACE_LEVEL_NONE; diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/utility.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/utility.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/utility.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/utility.c 2022-02-02 15:05:41.000000000 +0100 @@ -1,5 +1,5 @@ /* - * COPYRIGHT (c) International Business Machines Corp. 2001-2017 + * COPYRIGHT (c) International Business Machines Corp. 2001-2021 * * This program is provided under the terms of the Common Public License, * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this @@ -40,203 +40,6 @@ #include #include -// Function: dlist_add_as_first() -// -// Adds the specified node to the start of the list -// -// Returns: pointer to the start of the list -// -DL_NODE *dlist_add_as_first(DL_NODE *list, void *data) -{ - DL_NODE *node = NULL; - - if (!data) - return list; - - node = (DL_NODE *) malloc(sizeof(DL_NODE)); - if (!node) - return NULL; - - node->data = data; - node->prev = NULL; - node->next = list; - if (list) - list->prev = node; - - return node; -} - -// Function: dlist_add_as_last() -// -// Adds the specified node to the end of the list -// -// Returns: pointer to the start of the list -// -DL_NODE *dlist_add_as_last(DL_NODE *list, void *data) -{ - DL_NODE *node = NULL; - - if (!data) - return list; - - node = (DL_NODE *) malloc(sizeof(DL_NODE)); - if (!node) - return NULL; - - node->data = data; - node->next = NULL; - - if (!list) { - node->prev = NULL; - return node; - } else { - DL_NODE *temp = dlist_get_last(list); - temp->next = node; - node->prev = temp; - - return list; - } -} - -// Function: dlist_find() -// -DL_NODE *dlist_find(DL_NODE *list, void *data) -{ - DL_NODE *node = list; - - while (node && node->data != data) - node = node->next; - - return node; -} - -// Function: dlist_get_first() -// -// Returns the last node in the list or NULL if list is empty -// -DL_NODE *dlist_get_first(DL_NODE *list) -{ - DL_NODE *temp = list; - - if (!list) - return NULL; - - while (temp->prev != NULL) - temp = temp->prev; - - return temp; -} - -// Function: dlist_get_last() -// -// Returns the last node in the list or NULL if list is empty -// -DL_NODE *dlist_get_last(DL_NODE *list) -{ - DL_NODE *temp = list; - - if (!list) - return NULL; - - while (temp->next != NULL) - temp = temp->next; - - return temp; -} - -// -// -CK_ULONG dlist_length(DL_NODE *list) -{ - DL_NODE *temp = list; - CK_ULONG len = 0; - - while (temp) { - len++; - temp = temp->next; - } - - return len; -} - -// -// -DL_NODE *dlist_next(DL_NODE *node) -{ - if (!node) - return NULL; - - return node->next; -} - -// -// -DL_NODE *dlist_prev(DL_NODE *node) -{ - if (!node) - return NULL; - - return node->prev; -} - -// -// -void dlist_purge(DL_NODE *list) -{ - DL_NODE *node; - - if (!list) - return; - - do { - node = list->next; - free(list); - list = node; - } while (list); -} - -// Function: dlist_remove_node() -// -// Attempts to remove the specified node from the list. The caller is -// responsible for freeing the data associated with the node prior to -// calling this routine -// -DL_NODE *dlist_remove_node(DL_NODE *list, DL_NODE *node) -{ - DL_NODE *temp = list; - - if (!list || !node) - return NULL; - - // special case: removing head of the list - // - if (list == node) { - temp = list->next; - if (temp) - temp->prev = NULL; - - free(list); - return temp; - } - // we have no guarantee that the node is in the list - // so search through the list to find it - // - while ((temp != NULL) && (temp->next != node)) - temp = temp->next; - - if (temp != NULL) { - DL_NODE *next = node->next; - - temp->next = next; - if (next) - next->prev = temp; - - free(node); - } - - return list; -} - CK_RV CreateXProcLock(char *tokname, STDLL_TokData_t *tokdata) { char lockfile[PATH_MAX]; @@ -382,12 +185,14 @@ if (tokdata->spinxplfd < 0) { TRACE_DEVEL("No file descriptor to lock with.\n"); + pthread_mutex_unlock(&tokdata->spinxplfd_mutex); return CKR_CANT_LOCK; } if (tokdata->spinxplfd_count == 0) { if (flock(tokdata->spinxplfd, LOCK_EX) != 0) { TRACE_DEVEL("flock has failed.\n"); + pthread_mutex_unlock(&tokdata->spinxplfd_mutex); return CKR_CANT_LOCK; } } @@ -543,8 +348,6 @@ memset(tokdata->user_pin_md5, 0x0, MD5_HASH_SIZE); memcpy(tokdata->so_pin_md5, default_so_pin_md5, MD5_HASH_SIZE); } else { - int rv; - dat->version = tokdata->version; /* SO login key */ @@ -552,13 +355,14 @@ memcpy(dat->so_login_salt, SO_KDF_LOGIN_PURPOSE, 32); rng_generate(tokdata, dat->so_login_salt + 32, 32); - rv = PKCS5_PBKDF2_HMAC(SO_PIN_DEFAULT, strlen(SO_PIN_DEFAULT), - dat->so_login_salt, 64, - dat->so_login_it, EVP_sha512(), - 256 / 8, dat->so_login_key); - if (rv != 1) { + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, (CK_BYTE *)SO_PIN_DEFAULT, + strlen(SO_PIN_DEFAULT), + dat->so_login_salt, 64, + dat->so_login_it, EVP_sha512(), + 256 / 8, dat->so_login_key); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - return CKR_FUNCTION_FAILED; + return rc; } /* SO wrap key */ @@ -566,13 +370,14 @@ memcpy(dat->so_wrap_salt, SO_KDF_WRAP_PURPOSE, 32); rng_generate(tokdata, dat->so_wrap_salt + 32, 32); - rv = PKCS5_PBKDF2_HMAC(SO_PIN_DEFAULT, strlen(SO_PIN_DEFAULT), - dat->so_wrap_salt, 64, - dat->so_wrap_it, EVP_sha512(), - 256 / 8, tokdata->so_wrap_key); - if (rv != 1) { + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, (CK_BYTE *)SO_PIN_DEFAULT, + strlen(SO_PIN_DEFAULT), + dat->so_wrap_salt, 64, + dat->so_wrap_it, EVP_sha512(), + 256 / 8, tokdata->so_wrap_key); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - return CKR_FUNCTION_FAILED; + return rc; } /* User login key */ @@ -580,13 +385,14 @@ memcpy(dat->user_login_salt, USER_KDF_LOGIN_PURPOSE, 32); rng_generate(tokdata, dat->user_login_salt + 32, 32); - rv = PKCS5_PBKDF2_HMAC(USER_PIN_DEFAULT, strlen(USER_PIN_DEFAULT), - dat->user_login_salt, 64, - dat->user_login_it, EVP_sha512(), - 256 / 8, dat->user_login_key); - if (rv != 1) { + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, (CK_BYTE *)USER_PIN_DEFAULT, + strlen(USER_PIN_DEFAULT), + dat->user_login_salt, 64, + dat->user_login_it, EVP_sha512(), + 256 / 8, dat->user_login_key); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - return CKR_FUNCTION_FAILED; + return rc; } /* User wrap key */ @@ -594,13 +400,14 @@ memcpy(dat->user_wrap_salt, USER_KDF_WRAP_PURPOSE, 32); rng_generate(tokdata, dat->user_wrap_salt + 32, 32); - rv = PKCS5_PBKDF2_HMAC(USER_PIN_DEFAULT, strlen(USER_PIN_DEFAULT), - dat->user_wrap_salt, 64, - dat->user_wrap_it, EVP_sha512(), - 256 / 8, tokdata->user_wrap_key); - if (rv != 1) { + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, (CK_BYTE *)USER_PIN_DEFAULT, + strlen(USER_PIN_DEFAULT), + dat->user_wrap_salt, 64, + dat->user_wrap_it, EVP_sha512(), + 256 / 8, tokdata->user_wrap_key); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - return CKR_FUNCTION_FAILED; + return rc; } } @@ -860,7 +667,7 @@ rc = CKR_FUNCTION_FAILED; goto err; } - ret = sm_open(buf, 0666, (void **) shm, sizeof(**shm), 0); + ret = sm_open(buf, 0660, (void **) shm, sizeof(**shm), 0); if (ret < 0) { TRACE_DEVEL("sm_open failed.\n"); rc = CKR_FUNCTION_FAILED; @@ -895,219 +702,171 @@ return rc; } -CK_RV get_sha_size(CK_ULONG mech, CK_ULONG *hsize) +/* Compute specified SHA or MD5 using software */ +CK_RV compute_sha(STDLL_TokData_t *tokdata, CK_BYTE *data, CK_ULONG len, + CK_BYTE *hash, CK_ULONG mech) { + const EVP_MD *md; + unsigned int hash_len; + + UNUSED(tokdata); + switch (mech) { + case CKM_MD5: + hash_len = MD5_HASH_SIZE; + md = EVP_md5(); + break; case CKM_SHA_1: - *hsize = SHA1_HASH_SIZE; + hash_len = SHA1_HASH_SIZE; + md = EVP_sha1(); break; case CKM_SHA224: case CKM_SHA512_224: - *hsize = SHA224_HASH_SIZE; + hash_len = SHA224_HASH_SIZE; + md = EVP_sha224(); break; case CKM_SHA256: case CKM_SHA512_256: - *hsize = SHA256_HASH_SIZE; + hash_len = SHA256_HASH_SIZE; + md = EVP_sha256(); break; case CKM_SHA384: - *hsize = SHA384_HASH_SIZE; + hash_len = SHA384_HASH_SIZE; + md = EVP_sha384(); break; case CKM_SHA512: - *hsize = SHA512_HASH_SIZE; + hash_len = SHA512_HASH_SIZE; + md = EVP_sha512(); break; +#ifdef NID_sha3_224 case CKM_IBM_SHA3_224: - *hsize = SHA3_224_HASH_SIZE; + hash_len = SHA3_224_HASH_SIZE; + md = EVP_sha3_224(); break; +#endif +#ifdef NID_sha3_256 case CKM_IBM_SHA3_256: - *hsize = SHA3_256_HASH_SIZE; + hash_len = SHA3_256_HASH_SIZE; + md = EVP_sha3_256(); break; +#endif +#ifdef NID_sha3_384 case CKM_IBM_SHA3_384: - *hsize = SHA3_384_HASH_SIZE; + hash_len = SHA3_384_HASH_SIZE; + md = EVP_sha3_384(); break; +#endif +#ifdef NID_sha3_512 case CKM_IBM_SHA3_512: - *hsize = SHA3_512_HASH_SIZE; + hash_len = SHA3_512_HASH_SIZE; + md = EVP_sha3_512(); break; +#endif default: return CKR_MECHANISM_INVALID; } - return CKR_OK; -} -CK_RV get_sha_block_size(CK_ULONG mech, CK_ULONG *bsize) -{ - switch (mech) { - case CKM_SHA_1: - *bsize = SHA1_BLOCK_SIZE; - break; - case CKM_SHA224: - *bsize = SHA224_BLOCK_SIZE; - break; - case CKM_SHA256: - *bsize = SHA256_BLOCK_SIZE; - break; - case CKM_SHA384: - *bsize = SHA384_BLOCK_SIZE; - break; - case CKM_SHA512: - case CKM_SHA512_224: - case CKM_SHA512_256: - *bsize = SHA512_BLOCK_SIZE; - break; - case CKM_IBM_SHA3_224: - *bsize = SHA3_224_BLOCK_SIZE; - break; - case CKM_IBM_SHA3_256: - *bsize = SHA3_256_BLOCK_SIZE; - break; - case CKM_IBM_SHA3_384: - *bsize = SHA3_384_BLOCK_SIZE; - break; - case CKM_IBM_SHA3_512: - *bsize = SHA3_512_BLOCK_SIZE; - break; - default: - return CKR_MECHANISM_INVALID; + if (EVP_Digest(data, len, hash, &hash_len, md, NULL) != 1) { + TRACE_ERROR("%s EVP_Digest failed\n", __func__); + return CKR_FUNCTION_FAILED; } - return CKR_OK; -} -CK_RV get_hmac_digest(CK_ULONG mech, CK_ULONG *digest_mech, CK_BBOOL *general) -{ - switch (mech) { - case CKM_MD2_HMAC: - case CKM_MD2_HMAC_GENERAL: - *digest_mech = CKM_MD2; - *general = (mech == CKM_MD2_HMAC_GENERAL); - break; - case CKM_MD5_HMAC: - case CKM_MD5_HMAC_GENERAL: - *digest_mech = CKM_MD5; - *general = (mech == CKM_MD5_HMAC_GENERAL); - break; - case CKM_RIPEMD128_HMAC: - case CKM_RIPEMD128_HMAC_GENERAL: - *digest_mech = CKM_RIPEMD128; - *general = (mech == CKM_RIPEMD128_HMAC_GENERAL); - break; - case CKM_SHA_1_HMAC: - case CKM_SHA_1_HMAC_GENERAL: - *digest_mech = CKM_SHA_1; - *general = (mech == CKM_SHA_1_HMAC_GENERAL); - break; - case CKM_SHA224_HMAC: - case CKM_SHA224_HMAC_GENERAL: - *digest_mech = CKM_SHA224; - *general = (mech == CKM_SHA224_HMAC_GENERAL); - break; - case CKM_SHA256_HMAC: - case CKM_SHA256_HMAC_GENERAL: - *digest_mech = CKM_SHA256; - *general = (mech == CKM_SHA256_HMAC_GENERAL); - break; - case CKM_SHA384_HMAC: - case CKM_SHA384_HMAC_GENERAL: - *digest_mech = CKM_SHA384; - *general = (mech == CKM_SHA384_HMAC_GENERAL); - break; - case CKM_SHA512_HMAC: - case CKM_SHA512_HMAC_GENERAL: - *digest_mech = CKM_SHA512; - *general = (mech == CKM_SHA512_HMAC_GENERAL); - break; - case CKM_SHA512_224_HMAC: - case CKM_SHA512_224_HMAC_GENERAL: - *digest_mech = CKM_SHA512_224; - *general = (mech == CKM_SHA512_224_HMAC_GENERAL); - break; - case CKM_SHA512_256_HMAC: - case CKM_SHA512_256_HMAC_GENERAL: - *digest_mech = CKM_SHA512_256; - *general = (mech == CKM_SHA512_256_HMAC_GENERAL); - break; - case CKM_IBM_SHA3_224_HMAC: - *digest_mech = CKM_IBM_SHA3_224; - *general = FALSE; - break; - case CKM_IBM_SHA3_256_HMAC: - *digest_mech = CKM_IBM_SHA3_256; - *general = FALSE; - break; - case CKM_IBM_SHA3_384_HMAC: - *digest_mech = CKM_IBM_SHA3_384; - *general = FALSE; - break; - case CKM_IBM_SHA3_512_HMAC: - *digest_mech = CKM_IBM_SHA3_512; - *general = FALSE; - break; - default: - return CKR_MECHANISM_INVALID; - } return CKR_OK; } -/* Compute specified SHA using either software or token implementation */ -CK_RV compute_sha(STDLL_TokData_t *tokdata, CK_BYTE *data, CK_ULONG len, - CK_BYTE *hash, CK_ULONG mech) -{ - DIGEST_CONTEXT ctx; - CK_ULONG hash_len; - CK_RV rv; - - memset(&ctx, 0x0, sizeof(ctx)); - ctx.mech.mechanism = mech; - - rv = get_sha_size(mech, &hash_len); - if (rv != CKR_OK) - return rv; - - rv = sha_init(tokdata, NULL, &ctx, &ctx.mech); - if (rv != CKR_OK) { - TRACE_DEBUG("failed to create digest.\n"); - return rv; - } - rv = sha_hash(tokdata, NULL, FALSE, &ctx, data, len, hash, &hash_len); - - digest_mgr_cleanup(&ctx); - return rv; -} - /* Compute SHA1 using software implementation */ CK_RV compute_sha1(STDLL_TokData_t *tokdata, CK_BYTE *data, CK_ULONG len, CK_BYTE *hash) { - // XXX KEY - DIGEST_CONTEXT ctx; - CK_ULONG hash_len = SHA1_HASH_SIZE; - - UNUSED(tokdata); + CK_RV rc; + const CK_MECHANISM mech = { CKM_SHA_1, NULL, 0 }; - memset(&ctx, 0x0, sizeof(ctx)); + rc = compute_sha(tokdata, data, len, hash, CKM_SHA_1); - sw_sha1_init(&ctx); - if (ctx.context == NULL) - return CKR_HOST_MEMORY; + if (rc == CKR_OK && + (tokdata->statistics->flags & STATISTICS_FLAG_COUNT_INTERNAL) != 0) + tokdata->statistics->increment_func(tokdata->statistics, + tokdata->slot_id, &mech, + POLICY_STRENGTH_IDX_0); - return sw_sha1_hash(&ctx, data, len, hash, &hash_len); + return rc; } CK_RV compute_md5(STDLL_TokData_t *tokdata, CK_BYTE *data, CK_ULONG len, CK_BYTE *hash) { - DIGEST_CONTEXT ctx; - CK_ULONG hash_len = MD5_HASH_SIZE; + CK_RV rc; + const CK_MECHANISM mech = { CKM_MD5, NULL, 0 }; - UNUSED(tokdata); + rc = compute_sha(tokdata, data, len, hash, CKM_MD5); - memset(&ctx, 0x0, sizeof(ctx)); + if (rc == CKR_OK && + (tokdata->statistics->flags & STATISTICS_FLAG_COUNT_INTERNAL) != 0) + tokdata->statistics->increment_func(tokdata->statistics, + tokdata->slot_id, &mech, + POLICY_STRENGTH_IDX_0); - sw_md5_init(&ctx); - if (ctx.context == NULL) - return CKR_HOST_MEMORY; + return rc; +} + +CK_RV compute_PKCS5_PBKDF2_HMAC(STDLL_TokData_t *tokdata, + CK_CHAR *pPin, CK_ULONG ulPinLen, + CK_BYTE *salt, CK_ULONG salt_len, + CK_ULONG it_count, const EVP_MD *digest, + CK_ULONG key_len, CK_BYTE *key) +{ + CK_RV rc = CKR_OK; + const CK_MECHANISM mech = { CKM_PKCS5_PBKD2, NULL, 0 }; + CK_MECHANISM mech2 = { 0, NULL, 0 }; + + if (PKCS5_PBKDF2_HMAC((char *)pPin, ulPinLen, salt, salt_len, + it_count, digest, key_len, key) != 1) { + TRACE_DEVEL("PKCS5_PBKDF2_HMAC failed.\n"); + rc = CKR_FUNCTION_FAILED; + } - return sw_md5_hash(&ctx, data, len, hash, &hash_len); + if (rc == CKR_OK && + (tokdata->statistics->flags & STATISTICS_FLAG_COUNT_INTERNAL) != 0) { + tokdata->statistics->increment_func(tokdata->statistics, + tokdata->slot_id, &mech, + POLICY_STRENGTH_IDX_0); + if ((tokdata->statistics->flags & STATISTICS_FLAG_COUNT_IMPLICIT) != 0) { + /* We use CKM_PKCS5_PBKD2 with CKP_PKCS5_PBKD2_HMAC_SHAxxx */ + switch (EVP_MD_type(digest)) { + case NID_sha1: + mech2.mechanism = CKM_SHA_1_HMAC; + break; + case NID_sha224: + mech2.mechanism = CKM_SHA224_HMAC; + break; + case NID_sha256: + mech2.mechanism = CKM_SHA256_HMAC; + break; + case NID_sha384: + mech2.mechanism = CKM_SHA384_HMAC; + break; + case NID_sha512: + mech2.mechanism = CKM_SHA512_HMAC; + break; + default: + return rc; + } + /* + * Use strength 0 because the HMAC key is the pin, and it is max + * 8 char (i.e. 64 bit) long, which is way below 112 bit anyway. + */ + tokdata->statistics->increment_func(tokdata->statistics, + tokdata->slot_id, &mech2, + POLICY_STRENGTH_IDX_0); + } + } + + return rc; } + + + CK_RV get_keytype(STDLL_TokData_t *tokdata, CK_OBJECT_HANDLE hkey, CK_KEY_TYPE *keytype) { @@ -1129,55 +888,6 @@ return rc; } -CK_RV check_user_and_group() -{ - int i; - uid_t uid, euid; - struct passwd *pw, *epw; - struct group *grp; - - /* - * Check for root user or Group PKCS#11 Membershp. - * Only these are allowed. - */ - uid = getuid(); - euid = geteuid(); - - /* Root or effective Root is ok */ - if (uid == 0 || euid == 0) - return CKR_OK; - - /* - * Check for member of group. SAB get login seems to not work - * with some instances of application invocations (particularly - * when forked). So we need to get the group information. - * Really need to take the uid and map it to a name. - */ - grp = getgrnam("pkcs11"); - if (grp == NULL) { - OCK_SYSLOG(LOG_ERR, "getgrnam() failed: %s\n", strerror(errno)); - goto error; - } - - if (getgid() == grp->gr_gid || getegid() == grp->gr_gid) - return CKR_OK; - /* Check if user or effective user is member of pkcs11 group */ - pw = getpwuid(uid); - epw = getpwuid(euid); - for (i = 0; grp->gr_mem[i]; i++) { - if ((pw && (strncmp(pw->pw_name, grp->gr_mem[i], - strlen(pw->pw_name)) == 0)) || - (epw && (strncmp(epw->pw_name, grp->gr_mem[i], - strlen(epw->pw_name)) == 0))) - return CKR_OK; - } - -error: - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - - return CKR_FUNCTION_FAILED; -} - void copy_token_contents_sensibly(CK_TOKEN_INFO_PTR pInfo, TOKEN_DATA *nv_token_data) { diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/utility_common.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/utility_common.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/utility_common.c 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/utility_common.c 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,228 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ + +#include "pkcs11types.h" +#include "defs.h" +#include "trace.h" + +CK_RV get_sha_size(CK_ULONG mech, CK_ULONG *hsize) +{ + switch (mech) { + case CKM_SHA_1: + *hsize = SHA1_HASH_SIZE; + break; + case CKM_SHA224: + case CKM_SHA512_224: + *hsize = SHA224_HASH_SIZE; + break; + case CKM_SHA256: + case CKM_SHA512_256: + *hsize = SHA256_HASH_SIZE; + break; + case CKM_SHA384: + *hsize = SHA384_HASH_SIZE; + break; + case CKM_SHA512: + *hsize = SHA512_HASH_SIZE; + break; + case CKM_IBM_SHA3_224: + *hsize = SHA3_224_HASH_SIZE; + break; + case CKM_IBM_SHA3_256: + *hsize = SHA3_256_HASH_SIZE; + break; + case CKM_IBM_SHA3_384: + *hsize = SHA3_384_HASH_SIZE; + break; + case CKM_IBM_SHA3_512: + *hsize = SHA3_512_HASH_SIZE; + break; + default: + return CKR_MECHANISM_INVALID; + } + return CKR_OK; +} + +CK_RV get_sha_block_size(CK_ULONG mech, CK_ULONG *bsize) +{ + switch (mech) { + case CKM_SHA_1: + *bsize = SHA1_BLOCK_SIZE; + break; + case CKM_SHA224: + *bsize = SHA224_BLOCK_SIZE; + break; + case CKM_SHA256: + *bsize = SHA256_BLOCK_SIZE; + break; + case CKM_SHA384: + *bsize = SHA384_BLOCK_SIZE; + break; + case CKM_SHA512: + case CKM_SHA512_224: + case CKM_SHA512_256: + *bsize = SHA512_BLOCK_SIZE; + break; + case CKM_IBM_SHA3_224: + *bsize = SHA3_224_BLOCK_SIZE; + break; + case CKM_IBM_SHA3_256: + *bsize = SHA3_256_BLOCK_SIZE; + break; + case CKM_IBM_SHA3_384: + *bsize = SHA3_384_BLOCK_SIZE; + break; + case CKM_IBM_SHA3_512: + *bsize = SHA3_512_BLOCK_SIZE; + break; + default: + return CKR_MECHANISM_INVALID; + } + return CKR_OK; +} + +CK_RV get_hmac_digest(CK_ULONG mech, CK_ULONG *digest_mech, CK_BBOOL *general) +{ + switch (mech) { + case CKM_MD2_HMAC: + case CKM_MD2_HMAC_GENERAL: + *digest_mech = CKM_MD2; + *general = (mech == CKM_MD2_HMAC_GENERAL); + break; + case CKM_MD5_HMAC: + case CKM_MD5_HMAC_GENERAL: + *digest_mech = CKM_MD5; + *general = (mech == CKM_MD5_HMAC_GENERAL); + break; + case CKM_RIPEMD128_HMAC: + case CKM_RIPEMD128_HMAC_GENERAL: + *digest_mech = CKM_RIPEMD128; + *general = (mech == CKM_RIPEMD128_HMAC_GENERAL); + break; + case CKM_SHA_1_HMAC: + case CKM_SHA_1_HMAC_GENERAL: + *digest_mech = CKM_SHA_1; + *general = (mech == CKM_SHA_1_HMAC_GENERAL); + break; + case CKM_SHA224_HMAC: + case CKM_SHA224_HMAC_GENERAL: + *digest_mech = CKM_SHA224; + *general = (mech == CKM_SHA224_HMAC_GENERAL); + break; + case CKM_SHA256_HMAC: + case CKM_SHA256_HMAC_GENERAL: + *digest_mech = CKM_SHA256; + *general = (mech == CKM_SHA256_HMAC_GENERAL); + break; + case CKM_SHA384_HMAC: + case CKM_SHA384_HMAC_GENERAL: + *digest_mech = CKM_SHA384; + *general = (mech == CKM_SHA384_HMAC_GENERAL); + break; + case CKM_SHA512_HMAC: + case CKM_SHA512_HMAC_GENERAL: + *digest_mech = CKM_SHA512; + *general = (mech == CKM_SHA512_HMAC_GENERAL); + break; + case CKM_SHA512_224_HMAC: + case CKM_SHA512_224_HMAC_GENERAL: + *digest_mech = CKM_SHA512_224; + *general = (mech == CKM_SHA512_224_HMAC_GENERAL); + break; + case CKM_SHA512_256_HMAC: + case CKM_SHA512_256_HMAC_GENERAL: + *digest_mech = CKM_SHA512_256; + *general = (mech == CKM_SHA512_256_HMAC_GENERAL); + break; + case CKM_IBM_SHA3_224_HMAC: + *digest_mech = CKM_IBM_SHA3_224; + *general = FALSE; + break; + case CKM_IBM_SHA3_256_HMAC: + *digest_mech = CKM_IBM_SHA3_256; + *general = FALSE; + break; + case CKM_IBM_SHA3_384_HMAC: + *digest_mech = CKM_IBM_SHA3_384; + *general = FALSE; + break; + case CKM_IBM_SHA3_512_HMAC: + *digest_mech = CKM_IBM_SHA3_512; + *general = FALSE; + break; + default: + return CKR_MECHANISM_INVALID; + } + return CKR_OK; +} + +CK_RV digest_from_kdf(CK_EC_KDF_TYPE kdf, CK_MECHANISM_TYPE *mech) +{ + switch (kdf) { + case CKD_SHA1_KDF: + *mech = CKM_SHA_1; + break; + case CKD_SHA224_KDF: + *mech = CKM_SHA224; + break; + case CKD_SHA256_KDF: + *mech = CKM_SHA256; + break; + case CKD_SHA384_KDF: + *mech = CKM_SHA384; + break; + case CKD_SHA512_KDF: + *mech = CKM_SHA512; + break; + default: + TRACE_ERROR("Error unsupported KDF %ld.\n", kdf); + return CKR_FUNCTION_FAILED; + } + + return CKR_OK; +} + +/* helper function for rsa-oaep and rsa-pss */ +CK_RV get_mgf_mech(CK_RSA_PKCS_MGF_TYPE mgf, CK_MECHANISM_TYPE *mech) +{ + switch (mgf) { + case CKG_MGF1_SHA1: + *mech = CKM_SHA_1; + break; + case CKG_MGF1_SHA224: + *mech = CKM_SHA224; + break; + case CKG_MGF1_SHA256: + *mech = CKM_SHA256; + break; + case CKG_MGF1_SHA384: + *mech = CKM_SHA384; + break; + case CKG_MGF1_SHA512: + *mech = CKM_SHA512; + break; + case CKG_IBM_MGF1_SHA3_224: + *mech = CKM_IBM_SHA3_224; + break; + case CKG_IBM_MGF1_SHA3_256: + *mech = CKM_IBM_SHA3_256; + break; + case CKG_IBM_MGF1_SHA3_384: + *mech = CKM_IBM_SHA3_384; + break; + case CKG_IBM_MGF1_SHA3_512: + *mech = CKM_IBM_SHA3_512; + break; + default: + return CKR_MECHANISM_INVALID; + } + + return CKR_OK; +} diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/common/verify_mgr.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/verify_mgr.c --- opencryptoki-3.16.0+dfsg/usr/lib/common/verify_mgr.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/common/verify_mgr.c 2022-02-02 15:05:41.000000000 +0100 @@ -25,6 +25,8 @@ #include "tok_spec_struct.h" #include "trace.h" +#include "../api/policy.h" +#include "../api/statistics.h" // // @@ -32,7 +34,8 @@ SESSION *sess, SIGN_VERIFY_CONTEXT *ctx, CK_MECHANISM *mech, - CK_BBOOL recover_mode, CK_OBJECT_HANDLE key) + CK_BBOOL recover_mode, CK_OBJECT_HANDLE key, + CK_BBOOL checkpolicy) { OBJECT *key_obj = NULL; CK_ATTRIBUTE *attr = NULL; @@ -61,6 +64,15 @@ else return rc; } + if (checkpolicy) { + rc = tokdata->policy->is_mech_allowed(tokdata->policy, mech, + &key_obj->strength, + POLICY_CHECK_VERIFY, sess); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Verify init\n"); + goto done; + } + } if (recover_mode) { // is key allowed to verify signatures where the data can be @@ -789,6 +801,9 @@ rc = CKR_OK; done: + if (ctx->count_statistics == TRUE && rc == CKR_OK) + INC_COUNTER(tokdata, sess, mech, key_obj, POLICY_STRENGTH_IDX_0); + object_put(tokdata, key_obj, TRUE); key_obj = NULL; @@ -798,7 +813,8 @@ // // -CK_RV verify_mgr_cleanup(SIGN_VERIFY_CONTEXT *ctx) +CK_RV verify_mgr_cleanup(STDLL_TokData_t *tokdata, SESSION *sess, + SIGN_VERIFY_CONTEXT *ctx) { if (!ctx) { TRACE_ERROR("Invalid function argument.\n"); @@ -814,6 +830,8 @@ ctx->recover = FALSE; ctx->context_len = 0; ctx->pkey_active = FALSE; + ctx->state_unsaveable = FALSE; + ctx->count_statistics = FALSE; if (ctx->mech.pParameter) { free(ctx->mech.pParameter); @@ -821,9 +839,14 @@ } if (ctx->context) { - free(ctx->context); + if (ctx->context_free_func != NULL) + ctx->context_free_func(tokdata, sess, ctx->context, + ctx->context_len); + else + free(ctx->context); ctx->context = NULL; } + ctx->context_free_func = NULL; return CKR_OK; } diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/config/cfglex.l opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/config/cfglex.l --- opencryptoki-3.16.0+dfsg/usr/lib/config/cfglex.l 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/config/cfglex.l 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,102 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ +%{ +/* Generic Config Parser */ + +#include +#include +#include + +#include "cfgparse.h" +#include "configuration.h" + +/* Ignore -Wsign-compare for autogenerated code. */ +#pragma GCC diagnostic ignored "-Wsign-compare" + +#define YY_USER_ACTION \ + yylloc->first_line = yylloc->last_line; \ + yylloc->first_column = yylloc->last_column; \ + for(int i = 0; yytext[i] != '\0'; i++) { \ + if(yytext[i] == '\n') { \ + yylloc->last_line++; \ + yylloc->last_column = 0; \ + } \ + else { \ + yylloc->last_column++; \ + } \ + } + +#define YYSTYPE CONFIGSTYPE +#define YYLTYPE CONFIGLTYPE +%} + +%option reentrant +%option noyywrap nounput noinput yylineno stack bison-bridge bison-locations noyy_top_state +%option prefix="config" +/* Option only relevant if speed is preferred over size. Typically not the case for DSOs. */ +/* %option full */ +%option warn +%option extra-type="int" +%option header-file="cfglex.h" +%x COMMENT STRING MAIN + +%% + +version { yy_push_state(MAIN, yyscanner); return FILEVERSION; } + +[\t ]+ /* ignore spaces */; + +\n return EOL; + +
= return EQUAL; + +
\{ return BEGIN_DEF; + +
\} return END_DEF; + +
\( return BEGIN_LIST; + +
\) return END_LIST; + +# yy_push_state(COMMENT, yyscanner); + +
\" yy_push_state(STRING, yyscanner); + +
0|[1-9][0-9]* { yylval->num = strtoul(yytext, NULL, 10); return NUMBER; } + +
0x[0-9a-fA-F]+ { yylval->num = strtoul(yytext, NULL, 16); return NUMBER; } + +
[0-9]+"."[0-9]+ { /* version */ + unsigned long major, minor; + char *dot = strchr(yytext, '.'); + + *dot = '\0'; + major = strtoul(yytext, NULL, 10); + minor = strtoul(dot + 1, NULL, 10); + + yylval->num = (uint32_t)major << 16 | (uint32_t)minor; + return VERSION_TOK; + } + +
, { return COMMA; } + +
[a-zA-Z./][a-zA-Z0-9_\-./]* { yylval->str = strdup(yytext); return BARE; } + +\n { yy_pop_state(yyscanner); return EOL; } + +[^\n]+ { if (yyextra) { yylval->str = strdup(yytext); return COMMENT_TOK; } } + +\" yy_pop_state(yyscanner); + +[^\"]+ { yylval->str = strdup(yytext); return STRING_TOK; } + +. { yy_push_state(MAIN, yyscanner); yyless(0); } + +%% diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/config/cfgparser.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/config/cfgparser.h --- opencryptoki-3.16.0+dfsg/usr/lib/config/cfgparser.h 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/config/cfgparser.h 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,21 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ +#ifndef CFGPARSER_H +#define CFGPARSER_H + +#include +#include "configuration.h" + +typedef void (*error_hook_f)(int line, int col, const char *msg); + +int parse_configlib_file(FILE *conf, struct ConfigBaseNode **res, + error_hook_f error_hook, int trackComments); + +#endif diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/config/cfgparse.y opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/config/cfgparse.y --- opencryptoki-3.16.0+dfsg/usr/lib/config/cfgparse.y 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/config/cfgparse.y 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,307 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ + +%{ +/* + * Generic config file parser. + */ +#include +%} + +%code requires { +#include "configuration.h" +typedef void* configscan_t; + +typedef void (*error_hook_f)(int line, int col, const char *msg); +} + +%code provides +{ + // Tell Flex the expected prototype of yylex. + #define YY_DECL \ + int configlex (CONFIGSTYPE *yylval_param, CONFIGLTYPE *yylloc_param, configscan_t yyscanner) + + // Declare the scanner. + YY_DECL; + + + static inline void configerror(CONFIGLTYPE *lloc, configscan_t scanner, + struct ConfigBaseNode **res, + error_hook_f error_hook, + int trackComments, + const char *msg) + { + (void)scanner; + (void)res; + (void)trackComments; + if (error_hook) { + error_hook(lloc->first_line, lloc->first_column, msg); + } + } +} + +%union { + char *str; + unsigned long num; + struct ConfigBaseNode *node; +} + +%token + EOL + EQUAL + BEGIN_DEF + END_DEF + BEGIN_LIST + END_LIST + COMMA + FILEVERSION + NUMBER + VERSION_TOK + BARE + COMMENT_TOK + STRING_TOK + +%type configelemstar configelem barelist barelist_ne + eoc eocstar eocplus commentedconfigelemstar + +%defines +%destructor { free($$); } +%destructor { confignode_deepfree($$); } +%define api.pure full +%locations +%define api.prefix {config} +%lex-param { configscan_t scanner } +%parse-param { configscan_t scanner } +%parse-param { struct ConfigBaseNode **res } +%parse-param { error_hook_f error_hook } +%parse-param { int trackComments } +%define parse.trace +%define parse.error verbose +%define parse.lac full +%% + +/* Parse the whole config file: +configfile ::= commentedconfigelem* +*/ +configfile: + commentedconfigelemstar { *res = $1; $1 = NULL; } + +/* Parse configelemstar that might start with an arbitrary number of + initial comments. This is used to take care of comments before the + first configelem. The rules for configelem take care of comments + after the configelem. Since "after configelem i" is "before + configelem (i+1)", we cannot add comment tracking to before and + after a configelem. So we use this rule to fill the vacant + position before the first configelem. +*/ +commentedconfigelemstar : + eocstar configelemstar { $$ = confignode_append($1, $2); $1 = $2 = NULL; } + +/* 0-n configuration elements with comments between them. */ +configelemstar: + configelem configelemstar { $$ = confignode_append($1, $2); $1 = $2 = NULL; } + | + /* empty */ { $$ = NULL; } + +/* Valid configuration elements: +- "version" BARE +- BARE = NUMBER +- BARE = VERSION +- BARE = STRING +- BARE = BARE +- BARE NUMBER { configelemstar } +- BARE { configelemstar } +- BARE ( barelist ) + +Special care has to be taken for newlines and comments. They are +supported before and after {, }, (, and ), but not before or after = +or the special keyword "version". + +Note: the lexer only emits the FILEVERSION token as first "active" +configuration element. You may have an arbitrary number of comments and +newlines before, but the first keyword can either be version (in which case it +is seen as FILEVERSION and not BARE), or any other BARE to start a different +alternative. + +Every config elem has to end with eocstar to allow an arbitrary number +of comments at the end of the element. The element also has to take +care of all the positions where it wants to allow comments. +*/ +configelem: + /* version somestring*/ + FILEVERSION BARE eocstar { + struct ConfigFileVersionNode *n = confignode_allocfileversion($2, @1.first_line); + if (!n) { YYERROR; } + $$ = confignode_append(&(n->base), $3); + $2 = NULL; + $3 = NULL; + } + | + /* conf = 42 */ + BARE EQUAL NUMBER eocstar { + struct ConfigIntValNode *n = confignode_allocintval($1, $3, @1.first_line); + if (!n) { YYERROR; } + $$ = confignode_append(&(n->base), $4); + $1 = NULL; + $4 = NULL; + } + | + /* conf = 1.0 */ + BARE EQUAL VERSION_TOK eocstar { + struct ConfigVersionValNode *n = confignode_allocversionval($1, $3, @1.first_line); + if (!n) { YYERROR; } + $$ = confignode_append(&(n->base), $4); + $1 = NULL; + $4 = NULL; + } + | + /* conf = "A string" */ + BARE EQUAL STRING_TOK eocstar { + struct ConfigStringValNode *n = confignode_allocstringval($1, $3, @1.first_line); + if (!n) { YYERROR; } + $$ = confignode_append(&(n->base), $4); + $1 = NULL; + $3 = NULL; + $4 = NULL; + } + | + /* conf = configuration */ + BARE EQUAL BARE eocstar { + struct ConfigBareValNode *n = confignode_allocbareval($1, $3, @1.first_line); + if (!n) { YYERROR; } + $$ = confignode_append(&(n->base), $4); + $1 = NULL; + $3 = NULL; + $4 = NULL; + } + | + /* conf 42 { subconf = 73 } */ + BARE NUMBER eocstar BEGIN_DEF commentedconfigelemstar END_DEF eocstar { + struct ConfigIdxStructNode *n = confignode_allocidxstruct($1, $2, $3, $5, @1.first_line); + if (!n) { YYERROR; } + $$ = confignode_append(&(n->base), $7); + $1 = NULL; + $3 = $5 = $7 = NULL; + } + | + /* conf { subconf = 73 } */ + BARE eocstar BEGIN_DEF commentedconfigelemstar END_DEF eocstar { + + struct ConfigStructNode *n = confignode_allocstruct($1, $2, $4, @1.first_line); + if (!n) { YYERROR; } + $$ = confignode_append(&(n->base), $6); + $1 = NULL; + $2 = $4 = $6 = NULL; + } + | + /* conf ( A, B, C ) */ + BARE eocstar BEGIN_LIST barelist END_LIST eocstar { + struct ConfigBareListNode *n = confignode_allocbarelist($1, $2, $4, @1.first_line); + if (!n) { YYERROR; } + $$ = confignode_append(&(n->base), $6); + $1 = NULL; + $2 = $4 = $6 = NULL; + } + | + BARE eocstar { + struct ConfigBareConstNode *n = confignode_allocbareconst($1, @1.first_line); + if (!n) { YYERROR; } + $$ = confignode_append(&(n->base), $2); + $1 = NULL; + $2 = NULL; + } + +/* +A possibly empty list of barewords or comments. Two bare words have to be +separated by a comma (see barelist_ne). +*/ +barelist: + eocstar { $$ = $1; $1 = NULL; } + | + eocstar barelist_ne eocstar { + $$ = confignode_append($1, confignode_append($2, $3)); + $1 = $2 = $3 = NULL; + } + +/* Nonempty list of bare words. If the list contains multiple elements, they +are separated by a comma. After a comma you can optionally add as many +end-of-line comments as you wish (see eocstar). Note that the list may not end +with a comma! +*/ +barelist_ne: + BARE COMMA eocstar barelist_ne { + struct ConfigBareNode *n = confignode_allocbare($1, @1.first_line); + if (!n) { YYERROR; } + $1 = NULL; + $$ = confignode_append(&n->base, confignode_append($3, $4)); + $3 = $4 = NULL; + } + | + BARE { + struct ConfigBareNode *n = confignode_allocbare($1, @1.first_line); + if (!n) { YYERROR; } + $1 = NULL; + $$ = &n->base; + } + +/* Either end of line comment or just end of line token. Either way, a line +ends with this non-terminal. +*/ +eoc: + COMMENT_TOK EOL { + if (trackComments) { + struct ConfigEOCNode *eocn = confignode_alloceoc($1, @1.first_line); + if (!eocn) { YYERROR; }; + $1 = NULL; + $$ = &eocn->base; + } else { + $$ = NULL; + } + } + | + EOL { + if (trackComments) { + struct ConfigEOCNode *eocn = confignode_alloceoc(NULL, @1.first_line); + if (!eocn) { YYERROR; }; + $$ = &eocn->base; + } else { + $$ = NULL; + } + } + +/* BNF form of eoc* */ +eocstar: + eocplus { $$ = $1; $1 = NULL; } + | + /* empty */ { $$ = NULL; } + +/* BNF form of eoc+ */ +eocplus: + eoc { $$ = $1; $1 = NULL; } + | + eoc eocplus { $$ = confignode_append($1, $2); $1 = $2 = NULL; } + +%% + +#include "cfglex.h" + +int parse_configlib_file(FILE *conf, struct ConfigBaseNode **res, + error_hook_f error_hook, int trackComments) +{ + configscan_t scanner; + int ret; + + configlex_init_extra(trackComments, &scanner); + configset_in(conf, scanner); + ret = configparse(scanner, res, error_hook, trackComments) ? -1 : 0; + + configlex_destroy(scanner); + return ret; +} diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/config/config.mk opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/config/config.mk --- opencryptoki-3.16.0+dfsg/usr/lib/config/config.mk 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/config/config.mk 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,19 @@ +noinst_HEADERS += usr/lib/config/configuration.h usr/lib/config/cfglex.h usr/lib/config/cfgparse.h + +EXTRA_DIST += usr/lib/config/cfgparse.y usr/lib/config/cfglex.l + +BUILT_SOURCES += usr/lib/config/cfglex.c usr/lib/config/cfgparse.c + +usr/lib/config/cfglex.$(OBJEXT): usr/lib/config/cfgparse.h +usr/lib/config/cfgparse.$(OBJEXT): usr/lib/config/cfglex.h + +usr/lib/config/cfgparse.c: usr/lib/config/cfgparse.y + $(AM_V_YACC)$(am__skipyacc) $(SHELL) $(YLWRAP) $< cfgparse.tab.c usr/lib/config/cfgparse.c cfgparse.tab.h usr/lib/config/cfgparse.h cfgparse.output usr/lib/config/cfgparse.output -- $(YACCCOMPILE) + +usr/lib/config/cfglex.c: usr/lib/config/cfglex.l + $(AM_V_LEX)$(am__skiplex) $(SHELL) $(YLWRAP) $< lex.config.c usr/lib/config/cfglex.c cfglex.h usr/lib/config/cfglex.h -- $(LEXCOMPILE) + +CLEANFILES += usr/lib/config/cfglex.c usr/lib/config/cfglex.h \ +usr/lib/config/cfgparse.c usr/lib/config/cfgparse.h \ +usr/lib/config/cfgparse.output + diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/config/configuration.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/config/configuration.c --- opencryptoki-3.16.0+dfsg/usr/lib/config/configuration.c 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/config/configuration.c 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,523 @@ +#include "configuration.h" + +void confignode_deepfree(struct ConfigBaseNode *n) +{ + struct ConfigBaseNode *b, *i, *t; + + if (n) { + b = n; + i = n->next; + while (i != b) { + t = i->next; + confignode_free(i); + i = t; + } + confignode_free(n); + } +} + +void confignode_free(struct ConfigBaseNode *n) +{ + if (n) { + switch (n->type) { + case CT_FILEVERSION: + confignode_freefileversion(confignode_to_fileversion(n)); + break; + case CT_INTVAL: + confignode_freeintval(confignode_to_intval(n)); + break; + case CT_STRINGVAL: + confignode_freestringval(confignode_to_stringval(n)); + break; + case CT_VERSIONVAL: + confignode_freeversionval(confignode_to_versionval(n)); + break; + case CT_BAREVAL: + confignode_freebareval(confignode_to_bareval(n)); + break; + case CT_STRUCT: + confignode_freestruct(confignode_to_struct(n)); + break; + case CT_IDX_STRUCT: + confignode_freeidxstruct(confignode_to_idxstruct(n)); + break; + case CT_BARELIST: + confignode_freebarelist(confignode_to_barelist(n)); + break; + case CT_EOC: + confignode_freeeoc(confignode_to_eoc(n)); + break; + case CT_BARE: + confignode_freebare(confignode_to_bare(n)); + break; + case CT_BARECONST: + confignode_freebareconst(confignode_to_bareconst(n)); + break; + default: + break; + } + } +} + +static void confignode_dump_indent(FILE *fp, unsigned indent) +{ + unsigned i; + + for (i = 0; i < indent; ++i) + fputc(' ', fp); +} + +static int confignode_dump_i(FILE *fp, struct ConfigBaseNode *n, + struct ConfigDumpCb *cb, unsigned flags, + unsigned indent, unsigned curindent, + unsigned numbares, int curatbol); + +static void confignode_dumpstruct(FILE *fp, struct ConfigStructNode *n, + struct ConfigDumpCb *cb, + unsigned flags, unsigned indent, + unsigned curindent) +{ + if (n->beforeOpen) { + fputs(n->base.key, fp); + if (confignode_dump_i(fp, n->beforeOpen, cb, flags, indent, curindent, 0, 0)) + confignode_dump_indent(fp, curindent); + fputc('{', fp); + } else { + fprintf(fp, "%s {", n->base.key); + } + if (n->value) + if (confignode_dump_i(fp, n->value, cb, flags, indent, curindent + indent, 0, 0)) + confignode_dump_indent(fp, curindent); + fputc('}', fp); +} + +static void confignode_dumpidxstruct(FILE *fp, struct ConfigIdxStructNode *n, + struct ConfigDumpCb *cb, + unsigned flags, unsigned indent, + unsigned curindent) +{ + if (n->beforeOpen) { + fprintf(fp, "%s %lu", n->base.key, n->idx); + if (confignode_dump_i(fp, n->beforeOpen, cb, flags, indent, curindent, 0, 0)) + confignode_dump_indent(fp, curindent); + fputc('{', fp); + } else { + fprintf(fp, "%s %lu {", n->base.key, n->idx); + } + if (n->value) + if (confignode_dump_i(fp, n->value, cb, flags, indent, curindent + indent, 0, 0)) + confignode_dump_indent(fp, curindent); + fputc('}', fp); +} + +static void confignode_dumpbarelist(FILE *fp, struct ConfigBareListNode *n, + struct ConfigDumpCb *cb, + unsigned flags, unsigned indent, + unsigned curindent) +{ + struct ConfigBaseNode *i; + unsigned num = 0, braceindent = curindent, valindent = 2; + int f; + + if (n->beforeOpen) { + fputs(n->base.key, fp); + if (confignode_dump_i(fp, n->beforeOpen, cb, flags, indent, curindent, 0, 0)) { + confignode_dump_indent(fp, curindent); + valindent = indent; + } else { + braceindent += strlen(n->base.key) + 1; + } + fputc('(', fp); + } else { + fprintf(fp, "%s (", n->base.key); + braceindent += strlen(n->base.key) + 1; + } + if (n->value) { + confignode_foreach(i, n->value, f) + num += (unsigned) confignode_hastype(i, CT_BARE); + if (confignode_dump_i(fp, n->value, cb, flags, indent, + braceindent + valindent, num, 0)) + confignode_dump_indent(fp, braceindent); + } + fputc(')', fp); +} + +static void confignode_dumpintval(FILE *fp, struct ConfigIntValNode *n, + unsigned flags) +{ + if (flags & CONFIG_FLAG_INT_PRINT_MODE_HEX) + fprintf(fp, "%s = 0x%lx", n->base.key, n->value); + else + fprintf(fp, "%s = %lu", n->base.key, n->value); +} + +static int confignode_dump_i(FILE *fp, struct ConfigBaseNode *n, + struct ConfigDumpCb *cb, unsigned flags, + unsigned indent, unsigned curindent, + unsigned numbares, int curatbol) +{ + struct ConfigBaseNode *i; + int atbol = curatbol, newatbol; + + i = n; + do { + newatbol = 0; + if (cb) { + flags = cb->flags(i, flags); + } + if (atbol) + confignode_dump_indent(fp, curindent); + else if (i->type != CT_EOC) + /* In this case, we did not indent, but if a user writes + multiple configurations in one line, we will + concatenate value of previous item with key of new item + producing an invalid configuration. So add a space. */ + fputc(' ', fp); + switch (i->type) { + case CT_FILEVERSION: + fprintf(fp, "version %s", i->key); + break; + case CT_INTVAL: + confignode_dumpintval(fp, confignode_to_intval(i), flags); + break; + case CT_STRINGVAL: + fprintf(fp, "%s = \"%s\"", i->key, + confignode_to_stringval(i)->value); + break; + case CT_VERSIONVAL: + fprintf(fp, "%s = %d.%d", i->key, + (confignode_to_versionval(i)->value & 0xffff0000) >> 16, + confignode_to_versionval(i)->value & 0xffff); + break; + case CT_BAREVAL: + fprintf(fp, "%s = %s", i->key, confignode_to_bareval(i)->value); + break; + case CT_STRUCT: + confignode_dumpstruct(fp, confignode_to_struct(i), cb, flags, + indent, curindent); + break; + case CT_IDX_STRUCT: + confignode_dumpidxstruct(fp, confignode_to_idxstruct(i), cb, flags, + indent, curindent); + break; + case CT_BARELIST: + confignode_dumpbarelist(fp, confignode_to_barelist(i), cb, flags, + indent, curindent); + break; + case CT_EOC: + if (i->key) { + if (atbol) + fprintf(fp, "#%s", i->key); + else + fprintf(fp, " #%s", i->key); + } + fputc('\n', fp); + newatbol = 1; + break; + case CT_BARE: + fputs(i->key, fp); + if (numbares > 1) { + fputc(',', fp); + --numbares; + } else if (i->next == n) { + /* In this case, there is no EOL node after the last + element of the list. Put a blank to separate it + from the closing bracket. */ + fputc(' ', fp); + } + break; + case CT_BARECONST: + fputs(i->key, fp); + break; + default: + break; + } + atbol = newatbol; + i = i->next; + } while (i != n); + return atbol; +} + +void confignode_dump(FILE *fp, struct ConfigBaseNode *n, + struct ConfigDumpCb *cb, unsigned indent) +{ + if (n) + confignode_dump_i(fp, n, cb, 0, indent, 0, 0, 1); +} + +/* dumpable allocations */ +struct ConfigFileVersionNode * +confignode_allocfileversiondumpable(char *version, int line, char *comment) +{ + struct ConfigFileVersionNode *res; + struct ConfigEOCNode *eoc; + char *key; + + key = strdup(version); + if (!key) + return NULL; + res = confignode_allocfileversion(key, line); + if (res) { + eoc = confignode_alloceoc(comment ? strdup(comment) : NULL, line); + if (eoc) { + confignode_append(&(res->base), &(eoc->base)); + } else { + confignode_freefileversion(res); + res = NULL; + } + } else { + free(key); + } + return res; +} + +struct ConfigIntValNode * +confignode_allocintvaldumpable(char *key, unsigned long val, int line, + char *comment) +{ + struct ConfigIntValNode *res; + struct ConfigEOCNode *eoc; + char *dkey; + + dkey = strdup(key); + if (!dkey) + return NULL; + res = confignode_allocintval(dkey, val, line); + if (res) { + eoc = confignode_alloceoc(comment ? strdup(comment) : NULL, line); + if (eoc) { + confignode_append(&(res->base), &(eoc->base)); + } else { + confignode_freeintval(res); + res = NULL; + } + } else { + free(dkey); + } + return res; +} + +struct ConfigVersionValNode * +confignode_allocversionvaldumpable(char *key, unsigned long val, int line, + char *comment) +{ + struct ConfigVersionValNode *res; + struct ConfigEOCNode *eoc; + char *dkey; + + dkey = strdup(key); + if (!dkey) + return NULL; + res = confignode_allocversionval(dkey, val, line); + if (res) { + eoc = confignode_alloceoc(comment ? strdup(comment) : NULL, line); + if (eoc) { + confignode_append(&(res->base), &(eoc->base)); + } else { + confignode_freeversionval(res); + res = NULL; + } + } else { + free(dkey); + } + return res; +} + +struct ConfigStringValNode * +confignode_allocstringvaldumpable(char *key, char *val, int line, char *comment) +{ + struct ConfigStringValNode *res; + struct ConfigEOCNode *eoc; + char *str, *dkey; + + dkey = strdup(key); + str = strdup(val); + if (!str || !dkey) { + free(str); + free(dkey); + return NULL; + } + res = confignode_allocstringval(dkey, str, line); + if (res) { + eoc = confignode_alloceoc(comment ? strdup(comment) : NULL, line); + if (eoc) { + confignode_append(&(res->base), &(eoc->base)); + } else { + confignode_freestringval(res); + res = NULL; + } + } else { + free(str); + free(dkey); + } + return res; +} + +struct ConfigBareValNode * +confignode_allocbarevaldumpable(char *key, char *val, int line, char *comment) +{ + struct ConfigBareValNode *res; + struct ConfigEOCNode *eoc; + char *str, *dkey; + + dkey = strdup(key); + str = strdup(val); + if (!str || !dkey) { + free(str); + free(dkey); + return NULL; + } + res = confignode_allocbareval(dkey, str, line); + if (res) { + eoc = confignode_alloceoc(comment ? strdup(comment) : NULL, line); + if (eoc) { + confignode_append(&(res->base), &(eoc->base)); + } else { + confignode_freebareval(res); + res = NULL; + } + } else { + free(str); + free(dkey); + } + return res; +} + +struct ConfigIdxStructNode * +confignode_allocidxstructdumpable(char *key, unsigned long num, + struct ConfigBaseNode *beforeOpen, + struct ConfigBaseNode *value, + int line, char *comment) +{ + struct ConfigIdxStructNode *res = NULL; + struct ConfigEOCNode *eoc; + char *dkey; + + dkey = strdup(key); + if (!dkey) + return NULL; + /* First allocate eoc node such that if allocating res fails, we do not + take ownership of beforeOpen or value. */ + eoc = confignode_alloceoc(comment ? strdup(comment) : NULL, line); + if (eoc) { + res = confignode_allocidxstruct(dkey, num, beforeOpen, value, line); + if (res) { + confignode_append(&(res->base), &(eoc->base)); + } else { + confignode_freeeoc(eoc); + free(dkey); + } + } else { + free(dkey); + } + return res; +} +struct ConfigStructNode * +confignode_allocstructdumpable(char *key, + struct ConfigBaseNode *beforeOpen, + struct ConfigBaseNode *value, + int line, char *comment) +{ + struct ConfigStructNode *res = NULL; + struct ConfigEOCNode *eoc; + char *dkey; + + dkey = strdup(key); + if (!dkey) + return NULL; + /* First allocate eoc node such that if allocating res fails, we do not + take ownership of beforeOpen or value. */ + eoc = confignode_alloceoc(comment ? strdup(comment) : NULL, line); + if (eoc) { + res = confignode_allocstruct(dkey, beforeOpen, value, line); + if (res) { + confignode_append(&(res->base), &(eoc->base)); + } else { + confignode_freeeoc(eoc); + free(dkey); + } + } else { + free(dkey); + } + return res; +} + +struct ConfigBareListNode * +confignode_allocbarelistdumpable(char *key, + struct ConfigBaseNode *beforeOpen, + struct ConfigBaseNode *value, + int line, char *comment) +{ + struct ConfigBareListNode *res = NULL; + struct ConfigEOCNode *eoc; + char *dkey; + + dkey = strdup(key); + if (!dkey) + return NULL; + /* First allocate eoc node such that if allocating res fails, we do not + take ownership of beforeOpen or value. */ + eoc = confignode_alloceoc(comment ? strdup(comment) : NULL, line); + if (eoc) { + res = confignode_allocbarelist(dkey, beforeOpen, value, line); + if (res) { + confignode_append(&(res->base), &(eoc->base)); + } else { + confignode_freeeoc(eoc); + free(dkey); + } + } else { + free(dkey); + } + return res; +} + +struct ConfigBareNode * +confignode_allocbaredumpable(char *bareval, int line, char *comment) +{ + struct ConfigBareNode *res; + struct ConfigEOCNode *eoc; + char *dkey; + + dkey = strdup(bareval); + if (!dkey) + return NULL; + res = confignode_allocbare(dkey, line); + if (res) { + eoc = confignode_alloceoc(comment ? strdup(comment) : NULL, line); + if (eoc) { + confignode_append(&(res->base), &(eoc->base)); + } else { + confignode_freebare(res); + res = NULL; + } + } else { + free(dkey); + } + return res; +} + +struct ConfigBareConstNode * +confignode_allocbareconstdumpable(char *key, int line, char *comment) +{ + struct ConfigBareConstNode *res; + struct ConfigEOCNode *eoc; + char *dkey; + + dkey = strdup(key); + if (!dkey) + return NULL; + res = confignode_allocbareconst(dkey, line); + if (res) { + eoc = confignode_alloceoc(comment ? strdup(comment) : NULL, line); + if (eoc) { + confignode_append(&(res->base), &(eoc->base)); + } else { + confignode_freebareconst(res); + res = NULL; + } + } else { + free(dkey); + } + return res; +} diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/config/configuration.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/config/configuration.h --- opencryptoki-3.16.0+dfsg/usr/lib/config/configuration.h 1970-01-01 01:00:00.000000000 +0100 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/config/configuration.h 2022-02-02 15:05:41.000000000 +0100 @@ -0,0 +1,690 @@ +/* + * COPYRIGHT (c) International Business Machines Corp. 2021 + * + * This program is provided under the terms of the Common Public License, + * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this + * software constitutes recipient's acceptance of CPL-1.0 terms which can be + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ +#ifndef CONFIGURATION_H +#define CONFIGURATION_H + +#include +#include +#include +#include +#include + +#define MAJOR_FROM_VERSION(V) (((V) >> 16) & 0xffu) +#define MINOR_FROM_VERSION(V) ((V) & 0xffu) + +/* + * A file version node. + */ +#define CT_FILEVERSION (1u << 0u) +/* + * key=value with unsigned long value. + */ +#define CT_INTVAL (1u << 1u) +/* + * key=value with string value. + */ +#define CT_STRINGVAL (1u << 2u) +/* + * key=value with version value (packed as a 16/16 bit unsigned integer). + */ +#define CT_VERSIONVAL (1u << 3u) +/* + * key=value with bare string value. + */ +#define CT_BAREVAL (1u << 4u) +/* + * Structure value. + */ +#define CT_STRUCT (1u << 5u) +/* + * Indexed structure value. + */ +#define CT_IDX_STRUCT (1u << 6u) +/* + * Bare list. List contains bare values. + */ +#define CT_BARELIST (1u << 7u) +/* + * End-of-line comment. + */ +#define CT_EOC (1u << 8u) +/* + * A bare value. + */ +#define CT_BARE (1u << 9u) +/* + * A bare constant, i.e., a bare word outside of a list that + * represents its own configuration element. + */ +#define CT_BARECONST (1u << 10u) + +/* + * Mask for all types that have a key. This excludes FILEVERSION, + * EOC, and BARE which reuse the key field for the value. + */ +#define CT_HAS_KEY_MASK (CT_INTVAL | CT_STRINGVAL | CT_VERSIONVAL | \ + CT_BAREVAL | CT_STRINGVAL | CT_IDX_STRUCT | \ + CT_BARELIST | CT_BARECONST) + +/***** Node Types *****/ +struct ConfigBaseNode; + +struct ConfigBaseNode { + struct ConfigBaseNode *next, *prev; + unsigned int type; + char *key; + uint16_t line; + uint16_t flags; +}; + +struct ConfigFileVersionNode { + struct ConfigBaseNode base; +}; + +struct ConfigIntValNode { + struct ConfigBaseNode base; + unsigned long value; +}; + +struct ConfigStringValNode { + struct ConfigBaseNode base; + char *value; +}; + +struct ConfigVersionValNode { + struct ConfigBaseNode base; + unsigned int value; +}; + +struct ConfigBareValNode { + struct ConfigBaseNode base; + char *value; +}; + +struct ConfigIdxStructNode { + struct ConfigBaseNode base; + unsigned long idx; + struct ConfigBaseNode *beforeOpen; + struct ConfigBaseNode *value; +}; + +struct ConfigStructNode { + struct ConfigBaseNode base; + struct ConfigBaseNode *beforeOpen; + struct ConfigBaseNode *value; +}; + +struct ConfigBareNode { + /* Reuses base.key for bare value. */ + struct ConfigBaseNode base; +}; + +struct ConfigBareListNode { + struct ConfigBaseNode base; + struct ConfigBaseNode *beforeOpen; + /* either a ConfigBareNode or a ConfigEOCNode */ + struct ConfigBaseNode *value; +}; + +struct ConfigEOCNode { + /* Reuses base.key for comment */ + struct ConfigBaseNode base; +}; + +struct ConfigBareConstNode { + struct ConfigBaseNode base; +}; + +/* Casting from base type functions */ +static inline struct ConfigFileVersionNode * +confignode_to_fileversion(struct ConfigBaseNode *n) +{ + return (struct ConfigFileVersionNode *) + (((char *)n) - offsetof(struct ConfigFileVersionNode, base)); +} + +static inline struct ConfigIntValNode * +confignode_to_intval(struct ConfigBaseNode *n) +{ + return (struct ConfigIntValNode *) + (((char *)n) - offsetof(struct ConfigIntValNode, base)); +} + +static inline struct ConfigStringValNode * +confignode_to_stringval(struct ConfigBaseNode *n) +{ + return (struct ConfigStringValNode *) + (((char *)n) - offsetof(struct ConfigStringValNode, base)); +} + +static inline struct ConfigVersionValNode * +confignode_to_versionval(struct ConfigBaseNode *n) +{ + return (struct ConfigVersionValNode *) + (((char *)n) - offsetof(struct ConfigVersionValNode, base)); +} + +static inline struct ConfigBareValNode * +confignode_to_bareval(struct ConfigBaseNode *n) +{ + return (struct ConfigBareValNode *) + (((char *)n) - offsetof(struct ConfigBareValNode, base)); +} + +static inline struct ConfigIdxStructNode * +confignode_to_idxstruct(struct ConfigBaseNode *n) +{ + return (struct ConfigIdxStructNode *) + (((char *)n) - offsetof(struct ConfigIdxStructNode, base)); +} + +static inline struct ConfigStructNode * +confignode_to_struct(struct ConfigBaseNode *n) +{ + return (struct ConfigStructNode *) + (((char *)n) - offsetof(struct ConfigStructNode, base)); +} + +static inline struct ConfigBareNode * +confignode_to_bare(struct ConfigBaseNode *n) +{ + return (struct ConfigBareNode *) + (((char *)n) - offsetof(struct ConfigBareNode, base)); +} + +static inline struct ConfigBareListNode * +confignode_to_barelist(struct ConfigBaseNode *n) +{ + return (struct ConfigBareListNode *) + (((char *)n) - offsetof(struct ConfigBareListNode, base)); +} + +static inline struct ConfigEOCNode * +confignode_to_eoc(struct ConfigBaseNode *n) +{ + return (struct ConfigEOCNode *) + (((char *)n) - offsetof(struct ConfigEOCNode, base)); +} + +static inline struct ConfigBareConstNode * +confignode_to_bareconst(struct ConfigBaseNode *n) +{ + return (struct ConfigBareConstNode *) + (((char *)n) - offsetof(struct ConfigBareConstNode, base)); +} + +/* Freeing functions */ + +/** + * Free a node and all its descendants. + * @param n Node to free. + */ +void confignode_deepfree(struct ConfigBaseNode *n); + +/** + * Free only one node but not its descendants. + * This function basically is a dispatcher based on the node type. + * @param n Node to free. + */ +void confignode_free(struct ConfigBaseNode *n); + +static inline void confignode_freefileversion(struct ConfigFileVersionNode *n) +{ + if (n) { + free(n->base.key); + free(n); + } +} + +static inline void confignode_freeintval(struct ConfigIntValNode *n) +{ + if (n) { + free(n->base.key); + free(n); + } +} + +static inline void confignode_freestringval(struct ConfigStringValNode *n) +{ + if (n) { + free(n->base.key); + free(n->value); + free(n); + } +} + +static inline void confignode_freeversionval(struct ConfigVersionValNode *n) +{ + if (n) { + free(n->base.key); + free(n); + } +} + +static inline void confignode_freebareval(struct ConfigBareValNode *n) +{ + if (n) { + free(n->base.key); + free(n->value); + free(n); + } +} + +static inline void confignode_freeidxstruct(struct ConfigIdxStructNode *n) +{ + if (n) { + free(n->base.key); + confignode_deepfree(n->beforeOpen); + confignode_deepfree(n->value); + free(n); + } +} + +static inline void confignode_freestruct(struct ConfigStructNode *n) +{ + if (n) { + free(n->base.key); + confignode_deepfree(n->beforeOpen); + confignode_deepfree(n->value); + free(n); + } +} + +static inline void confignode_freebare(struct ConfigBareNode *n) +{ + if (n) { + free(n->base.key); + free(n); + } +} + +static inline void confignode_freebarelist(struct ConfigBareListNode *n) +{ + if (n) { + free(n->base.key); + confignode_deepfree(n->beforeOpen); + confignode_deepfree(n->value); + free(n); + } +} + +static inline void confignode_freeeoc(struct ConfigEOCNode *n) +{ + if (n) { + free(n->base.key); + free(n); + } +} + +static inline void confignode_freebareconst(struct ConfigBareConstNode *n) +{ + if (n) { + free(n->base.key); + free(n); + } +} + +/* Allocation functions */ + +static inline struct ConfigFileVersionNode * +confignode_allocfileversion(char *version, int line) +{ + struct ConfigFileVersionNode *res = + malloc(sizeof(struct ConfigFileVersionNode)); + + if (res) { + res->base.next = res->base.prev = &(res->base); + res->base.key = version; + res->base.type = CT_FILEVERSION; + res->base.line = line; + } + return res; +} + +static inline struct ConfigIntValNode * +confignode_allocintval(char *key, unsigned long val, int line) +{ + struct ConfigIntValNode *res = malloc(sizeof(struct ConfigIntValNode)); + + if (res) { + res->base.next = res->base.prev = &(res->base); + res->base.key = key; + res->base.type = CT_INTVAL; + res->base.line = line; + res->base.flags = 0; + res->value = val; + } + return res; +} + +static inline struct ConfigVersionValNode * +confignode_allocversionval(char *key, unsigned long val, int line) +{ + struct ConfigVersionValNode *res = malloc(sizeof(struct ConfigVersionValNode)); + + if (res) { + res->base.next = res->base.prev = &(res->base); + res->base.key = key; + res->base.type = CT_VERSIONVAL; + res->base.line = line; + res->base.flags = 0; + res->value = val; + } + return res; +} + +static inline struct ConfigStringValNode * +confignode_allocstringval(char *key, char *val, int line) +{ + struct ConfigStringValNode *res = malloc(sizeof(struct ConfigStringValNode)); + + if (res) { + res->base.next = res->base.prev = &(res->base); + res->base.key = key; + res->base.type = CT_STRINGVAL; + res->base.line = line; + res->base.flags = 0; + res->value = val; + } + return res; +} + +static inline struct ConfigBareValNode * +confignode_allocbareval(char *key, char *val, int line) +{ + struct ConfigBareValNode *res = malloc(sizeof(struct ConfigBareValNode)); + + if (res) { + res->base.next = res->base.prev = &(res->base); + res->base.key = key; + res->base.type = CT_BAREVAL; + res->base.line = line; + res->base.flags = 0; + res->value = val; + } + return res; +} + +static inline struct ConfigIdxStructNode * +confignode_allocidxstruct(char *key, unsigned long num, + struct ConfigBaseNode *beforeOpen, + struct ConfigBaseNode *value, + int line) +{ + struct ConfigIdxStructNode *res = + malloc(sizeof(struct ConfigIdxStructNode)); + + if (res) { + res->base.next = res->base.prev = &(res->base); + res->base.key = key; + res->base.type = CT_IDX_STRUCT; + res->base.line = line; + res->base.flags = 0; + res->idx = num; + res->beforeOpen = beforeOpen; + res->value = value; + } + return res; +} + +static inline struct ConfigStructNode * +confignode_allocstruct(char *key, + struct ConfigBaseNode *beforeOpen, + struct ConfigBaseNode *value, + int line) +{ + struct ConfigStructNode *res = malloc(sizeof(struct ConfigStructNode)); + + if (res) { + res->base.next = res->base.prev = &(res->base); + res->base.key = key; + res->base.type = CT_STRUCT; + res->beforeOpen = beforeOpen; + res->base.line = line; + res->base.flags = 0; + res->value = value; + } + return res; +} + +static inline struct ConfigBareListNode * +confignode_allocbarelist(char *key, + struct ConfigBaseNode *beforeOpen, + struct ConfigBaseNode *value, + int line) +{ + struct ConfigBareListNode *res = malloc(sizeof(struct ConfigBareListNode)); + + if (res) { + res->base.next = res->base.prev = &(res->base); + res->base.key = key; + res->base.type = CT_BARELIST; + res->base.line = line; + res->base.flags = 0; + res->beforeOpen = beforeOpen; + res->value = value; + } + return res; +} + +static inline struct ConfigBareNode *confignode_allocbare(char *bareval, + int line) +{ + struct ConfigBareNode *res = malloc(sizeof(struct ConfigBareNode)); + + if (res) { + res->base.next = res->base.prev = &(res->base); + res->base.key = bareval; + res->base.type = CT_BARE; + res->base.line = line; + res->base.flags = 0; + } + return res; +} + +static inline struct ConfigEOCNode *confignode_alloceoc(char *comment, int line) +{ + struct ConfigEOCNode *res = malloc(sizeof(struct ConfigEOCNode)); + + if (res) { + res->base.next = res->base.prev = &(res->base); + res->base.key = comment; + res->base.type = CT_EOC; + res->base.line = line; + res->base.flags = 0; + } + return res; +} + +static inline struct ConfigBareConstNode *confignode_allocbareconst(char *key, + int line) +{ + struct ConfigBareConstNode *res = malloc(sizeof(struct ConfigBareConstNode)); + + if (res) { + res->base.next = res->base.prev = &(res->base); + res->base.key = key; + res->base.type = CT_BARECONST; + res->base.line = line; + res->base.flags = 0; + } + return res; +} + +/* Convenience functions for AST manipulation. These functions + automatically append an EOC-node to the correct node which + optionally includes a comment. If no comment is desired, simply + pass NULL for the comment argument. The dumpable versions below + also strdup all strings (keys, values, and the optional + comment). */ +struct ConfigFileVersionNode * +confignode_allocfileversiondumpable(char *version, int line, char *comment); + +struct ConfigIntValNode * +confignode_allocintvaldumpable(char *key, unsigned long val, int line, + char *comment); + +struct ConfigVersionValNode * +confignode_allocversionvaldumpable(char *key, unsigned long val, int line, + char *comment); + +struct ConfigStringValNode * +confignode_allocstringvaldumpable(char *key, char *val, int line, char *comment); + +struct ConfigBareValNode * +confignode_allocbarevaldumpable(char *key, char *val, int line, char *comment); + +struct ConfigIdxStructNode * +confignode_allocidxstructdumpable(char *key, unsigned long num, + struct ConfigBaseNode *beforeOpen, + struct ConfigBaseNode *value, + int line, char *comment); + +struct ConfigStructNode * +confignode_allocstructdumpable(char *key, + struct ConfigBaseNode *beforeOpen, + struct ConfigBaseNode *value, + int line, char *comment); + +struct ConfigBareListNode * +confignode_allocbarelistdumpable(char *key, + struct ConfigBaseNode *beforeOpen, + struct ConfigBaseNode *value, + int line, char *comment); + +struct ConfigBareNode * +confignode_allocbaredumpable(char *bareval, int line, char *comment); + +struct ConfigBareConstNode * +confignode_allocbareconstdumpable(char *key, int line, char *comment); + +/* Append the list n2 to the end of the list n1. + NULL is considered as empty list. */ +static inline struct ConfigBaseNode *confignode_append(struct ConfigBaseNode *n1, + struct ConfigBaseNode *n2) +{ + struct ConfigBaseNode *tmp; + + if (n1) { + if (n2) { + n1->prev->next = n2; + tmp = n2->prev; + n2->prev = n1->prev; + tmp->next = n1; + n1->prev = tmp; + return n1; + } else { + return n1; + } + } else { + return n2; + } +} + +/* Dumping support */ + +#define CONFIG_FLAG_INT_PRINT_MODE_HEX (1 << 0u) + +struct ConfigDumpCb { + /* Called for every node to update the dump flags. */ + unsigned (*flags)(struct ConfigBaseNode *n, unsigned curflags); +}; + +void confignode_dump(FILE *fp, struct ConfigBaseNode *n, + struct ConfigDumpCb *cb, unsigned indent); + +/* Iteration and searching */ + +/* + * Iterate over a configuration. + * i is the iterator of type struct ConfigBaseNode * + * c is the configuration to iterate over (of type struct ConfigBaseNode *) + * f is an integer + */ +#define confignode_foreach(i,c,f) \ + for((i)=(c),(f)=1;(f)||(i)!=(c);(i)=(i)->next,(f)=0) + +static inline struct ConfigBaseNode * +confignode_find(struct ConfigBaseNode *cfg, const char *key) +{ + struct ConfigBaseNode *i; + + if (cfg) { + i = cfg; + do { + if ((i->type & CT_HAS_KEY_MASK) && strcmp(key, i->key) == 0) + return i; + i = i->next; + } while (i != cfg); + } + return NULL; +} + +static inline struct ConfigIdxStructNode * +confignode_findidx(struct ConfigBaseNode *cfg, const char *key, unsigned idx) +{ + struct ConfigBaseNode *i; + struct ConfigIdxStructNode *res; + + if (cfg) { + i = cfg; + do { + if ((i->type & CT_IDX_STRUCT) && strcmp(key, i->key) == 0) { + res = confignode_to_idxstruct(i); + if (res->idx == idx) + return res; + } + i = i->next; + } while (i != cfg); + } + return NULL; +} + +/* Type checking */ + +static inline int confignode_hastype(struct ConfigBaseNode *n, + unsigned typemask) +{ + return (n->type & typemask) != 0; +} + +/* Convenience functions */ + +static inline char *confignode_getstr(struct ConfigBaseNode *n) +{ + if (n->type & CT_STRINGVAL) + return confignode_to_stringval(n)->value; + if (n->type & CT_BAREVAL) + return confignode_to_bareval(n)->value; + return NULL; +} + +/* Returns 0 if a valid version was found and -1 otherwise. */ +static inline int confignode_getversion(struct ConfigBaseNode *n, + unsigned int *version) +{ + int res = 0; + unsigned int major, minor; + + if (n->type & CT_VERSIONVAL) { + *version = confignode_to_versionval(n)->value; + } else if (n->type & CT_STRINGVAL) { + if (sscanf(confignode_to_stringval(n)->value, "%u.%u", + &major, &minor) == 2) + *version = major << 16 | minor; + else + res = -1; + } else { + res = -1; + } + return res; +} + +#endif diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/ep11_stdll/ep11_specific.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/ep11_stdll/ep11_specific.c --- opencryptoki-3.16.0+dfsg/usr/lib/ep11_stdll/ep11_specific.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/ep11_stdll/ep11_specific.c 2022-02-02 15:05:41.000000000 +0100 @@ -38,6 +38,7 @@ #include "ock_syslog.h" #include "ec_defs.h" #include "p11util.h" +#include "events.h" #include #include @@ -67,7 +68,8 @@ #define EP11SHAREDLIB_V2 "libep11.so.2" #define EP11SHAREDLIB_V1 "libep11.so.1" #define EP11SHAREDLIB "libep11.so" -#define ICASHAREDLIB "libica.so.3" +#define ICASHAREDLIB_V4 "libica.so.4" +#define ICASHAREDLIB_V3 "libica.so.3" CK_RV ep11tok_get_mechanism_list(STDLL_TokData_t * tokdata, CK_MECHANISM_TYPE_PTR mlist, @@ -197,19 +199,30 @@ #define MAX_RETRY_COUNT 100 -#define RETRY_START do { \ +#define RETRY_START(rc, tokdata) \ + do { \ int retry_count; \ + CK_RV rc2; \ + ep11_target_info_t* target_info = \ + get_target_info((tokdata)); \ + if (target_info == NULL) \ + (rc) = CKR_FUNCTION_FAILED; \ for(retry_count = 0; \ + target_info != NULL && \ retry_count < MAX_RETRY_COUNT; \ retry_count ++) { #define RETRY_END(rc, tokdata, session) if ((rc) != CKR_SESSION_CLOSED) \ break; \ - (rc) = ep11tok_relogin_session( \ - tokdata, session); \ - if ((rc) != CKR_OK) \ + rc2 = ep11tok_relogin_session( \ + (tokdata), (session)); \ + if (rc2 != CKR_OK) { \ + (rc) = rc2; \ break; \ + } \ } \ + put_target_info((tokdata), \ + target_info); \ } while (0); #define CKF_EP11_HELPER_SESSION 0x80000000 @@ -232,7 +245,8 @@ static const char *ep11_get_cp(unsigned int cp); #endif static CK_ULONG ep11_get_cp_by_name(const char *name); -static CK_RV check_cps_for_mechanism(cp_config_t * cp_config, +static CK_RV check_cps_for_mechanism(STDLL_TokData_t *tokdata, + cp_config_t * cp_config, CK_MECHANISM_TYPE mech, unsigned char *cp, size_t cp_len, size_t max_cp_index); @@ -248,7 +262,6 @@ } ep11_card_version_t; static CK_RV ep11tok_get_ep11_library_version(CK_VERSION *lib_version); -static CK_RV ep11tok_get_ep11_version(STDLL_TokData_t *tokdata); static void free_card_versions(ep11_card_version_t *card_version); static int check_card_version(STDLL_TokData_t *tokdata, CK_ULONG card_type, const CK_VERSION *ep11_lib_version, @@ -310,6 +323,13 @@ }; #define NUM_OAEP_SHA2_REQ (sizeof(oaep_sha2_req_versions) / sizeof(version_req_t)) +static const CK_VERSION cex6p_oaep_support = { .major = 6, .minor = 7 }; + +static const version_req_t oaep_req_versions[] = { + { .card_type = 6, .min_firmware_version = &cex6p_oaep_support } +}; +#define NUM_OAEP_REQ (sizeof(oaep_req_versions) / sizeof(version_req_t)) + static const CK_VERSION cex7p_edwards_support = { .major = 7, .minor = 15 }; static const version_req_t edwards_req_versions[] = { @@ -476,16 +496,23 @@ #define PKEY_MODE_ENABLE4NONEXTR 2 typedef struct { + volatile unsigned long ref_count; target_t target; + ep11_card_version_t *card_versions; + CK_ULONG used_firmware_API_version; + unsigned char control_points[XCP_CP_BYTES]; + size_t control_points_len; + size_t max_control_point_index; + CK_CHAR serialNumber[16]; +} ep11_target_info_t; + +typedef struct { ep11_target_t target_list; CK_BYTE raw2key_wrap_blob[MAX_BLOBSIZE]; size_t raw2key_wrap_blob_l; int cka_sensitive_default_true; char cp_filter_config_filename[PATH_MAX]; cp_config_t *cp_config; - unsigned char control_points[XCP_CP_BYTES]; - size_t control_points_len; - size_t max_control_point_index; int strict_mode; int vhsm_mode; int optimize_single_ops; @@ -497,16 +524,20 @@ char digest_libica_path[PATH_MAX]; libica_t libica; CK_VERSION ep11_lib_version; - ep11_card_version_t *card_versions; - CK_ULONG used_firmware_API_version; - CK_CHAR serialNumber[16]; + volatile ep11_target_info_t *target_info; + pthread_rwlock_t target_rwlock; } ep11_private_data_t; -static CK_RV ep11tok_setup_target(STDLL_TokData_t *tokdata); +static ep11_target_info_t *get_target_info(STDLL_TokData_t *tokdata); +static void put_target_info(STDLL_TokData_t *tokdata, + ep11_target_info_t *target_info); +static CK_RV refresh_target_info(STDLL_TokData_t *tokdata); static CK_RV get_ep11_target_for_apqn(uint_32 adapter, uint_32 domain, target_t *target, uint64_t flags); static void free_ep11_target_for_apqn(target_t target); +static CK_RV update_ep11_attrs_from_blob(STDLL_TokData_t *tokdata, + TEMPLATE *tmpl); /* defined in the makefile, ep11 library can run standalone (without HW card), @@ -520,6 +551,27 @@ #define CONSTINFO(_X) { (_X), (#_X) } +static void trace_attributes(const char *func, const char *heading, + CK_ATTRIBUTE_PTR attrs, CK_ULONG num_attrs) +{ + CK_ULONG i; + +#ifndef DEBUG + UNUSED(func); + UNUSED(heading); + UNUSED(attrs); + UNUSED(num_attrs); +#endif + + if (trace.level < TRACE_LEVEL_DEBUG) + return; + + TRACE_DEBUG("%s: %s\n", func, heading); + for (i = 0; i < num_attrs; i++) { + TRACE_DEBUG_DUMPATTR(&attrs[i]); + } +} + static CK_RV cleanse_attribute(TEMPLATE *template, CK_ATTRIBUTE_TYPE attr_type) { @@ -704,8 +756,13 @@ CK_BYTE blob[MAX_BLOBSIZE]; size_t blobsize = sizeof(blob); CK_ATTRIBUTE *pkey_attr = NULL, *blob_attr=NULL; + ep11_target_info_t* target_info; CK_RV ret; + target_info = get_target_info(tokdata); + if (target_info == NULL) + return CKR_FUNCTION_FAILED; + /* Check if CPACF_WRAP mech supported */ if (ep11tok_is_mechanism_supported(tokdata, CKM_IBM_CPACF_WRAP) != CKR_OK) { TRACE_INFO("CKM_IBM_CPACF_WRAP not supported on this system.\n"); @@ -715,9 +772,11 @@ memset(&ep11_data->pkey_mk_vp, 0, PKEY_MK_VP_LENGTH); + trace_attributes(__func__, "Generate prot. test key:", tmpl, tmpl_len); + /* Create an AES testkey with CKA_IBM_PROTKEY_EXTRACTABLE */ ret = dll_m_GenerateKey(&mech, tmpl, tmpl_len, NULL, 0, - blob, &blobsize, csum, &csum_l, ep11_data->target); + blob, &blobsize, csum, &csum_l, target_info->target); if (ret != CKR_OK) { TRACE_ERROR("dll_m_GenerateKey failed with rc=0x%lx\n",ret); goto done; @@ -748,6 +807,10 @@ if (blob_attr) free(blob_attr); + if (pkey_attr) + free(pkey_attr); + + put_target_info(tokdata, target_info); return ret; } @@ -1171,7 +1234,7 @@ CK_BYTE **sblob, size_t *sblob_len, OBJECT **sobj, OBJECT *key_obj, OBJECT *wrap_key_obj, - CK_MECHANISM_PTR mech) + CK_MECHANISM_PTR mech, SESSION *sess) { CK_RV rc; CK_BBOOL abkey, abwrapkey, absignkey, signsignkey; @@ -1219,6 +1282,11 @@ TRACE_ERROR("Failed to get sign key for AB wrapping\n"); return rc; } + rc = tokdata->policy->is_key_allowed(tokdata->policy, &(*sobj)->strength, sess); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: AB wrap signing key too weak\n"); + goto out; + } rc = template_attribute_get_bool((*sobj)->template, CKA_IBM_ATTRBOUND, &absignkey); if (rc != CKR_OK || !absignkey) { TRACE_ERROR("AB-Wrap: sign key not AB\n"); @@ -1249,7 +1317,8 @@ CK_BYTE **vblob, size_t *vblob_len, OBJECT **vobj, OBJECT *unwrap_key_obj, CK_ATTRIBUTE_PTR attrs, CK_ULONG attrs_len, - CK_MECHANISM_PTR mech, CK_BBOOL *isab) + CK_MECHANISM_PTR mech, CK_BBOOL *isab, + SESSION *sess) { CK_RV rc; CK_BBOOL abkey, abunwrapkey, abverifykey, verifyverifykey; @@ -1295,6 +1364,11 @@ TRACE_ERROR("Failed to get verification key for AB wrapping\n"); return rc; } + rc = tokdata->policy->is_key_allowed(tokdata->policy, &(*vobj)->strength, sess); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: AB verification key too weak\n"); + goto out; + } rc = template_attribute_get_bool((*vobj)->template, CKA_IBM_ATTRBOUND, &abverifykey); if (rc != CKR_OK || !abverifykey) { TRACE_ERROR("AB-Wrap: verification key not AB\n"); @@ -1337,7 +1411,7 @@ OBJECT *obj, CK_KEY_TYPE keytype) { - ep11_private_data_t *ep11_data = tokdata->private_data; + ep11_target_info_t* target_info; CK_RV rc; CK_BBOOL trusted, encrypt, decrypt, wrap, unwrap, sign, sign_recover, verify, verify_recover, derive, extractable, local, @@ -1367,9 +1441,16 @@ CK_ATTRIBUTE *attr; CK_BBOOL cktrue = TRUE; + target_info = get_target_info(tokdata); + if (target_info == NULL) + return CKR_FUNCTION_FAILED; + rc = dll_m_GetAttributeValue(blob, blob_len, attrs, sizeof(attrs) / sizeof(CK_ATTRIBUTE), - ep11_data->target); + target_info->target); + + put_target_info(tokdata, target_info); + if (rc != CKR_OK) { TRACE_ERROR("Retrieving attributes from AB unwrapped key failed, rc=0x%lx\n", rc); @@ -1502,9 +1583,9 @@ CK_ULONG check_types_sec_sensitive[] = { CKA_ENCRYPT, CKA_DECRYPT, CKA_WRAP, CKA_UNWRAP, CKA_SENSITIVE }; CK_ULONG check_types_gen_sec[] = - { CKA_SIGN, CKA_VERIFY, CKA_ENCRYPT, CKA_DECRYPT }; + { CKA_SIGN, CKA_VERIFY }; CK_ULONG check_types_gen_sec_sensitive[] = - { CKA_SIGN, CKA_VERIFY, CKA_ENCRYPT, CKA_DECRYPT, CKA_SENSITIVE }; + { CKA_SIGN, CKA_VERIFY, CKA_SENSITIVE }; CK_ULONG check_types_derive[] = { CKA_DERIVE }; CK_ULONG *check_types = NULL; CK_BBOOL *check_values[] = { &cktrue, &cktrue, &cktrue, &cktrue, &cktrue }; @@ -1613,299 +1694,29 @@ return CKR_OK; } -static const_info_t ep11_mechanisms[] = { - CONSTINFO(CKM_RSA_PKCS_KEY_PAIR_GEN), - CONSTINFO(CKM_RSA_PKCS), - CONSTINFO(CKM_RSA_9796), - CONSTINFO(CKM_RSA_X_509), - CONSTINFO(CKM_MD2_RSA_PKCS), - CONSTINFO(CKM_MD5_RSA_PKCS), - CONSTINFO(CKM_SHA1_RSA_PKCS), - CONSTINFO(CKM_RIPEMD128_RSA_PKCS), - CONSTINFO(CKM_RIPEMD160_RSA_PKCS), - CONSTINFO(CKM_RSA_PKCS_OAEP), - CONSTINFO(CKM_RSA_X9_31_KEY_PAIR_GEN), - CONSTINFO(CKM_RSA_X9_31), - CONSTINFO(CKM_SHA1_RSA_X9_31), - CONSTINFO(CKM_RSA_PKCS_PSS), - CONSTINFO(CKM_SHA1_RSA_PKCS_PSS), - CONSTINFO(CKM_DSA_KEY_PAIR_GEN), - CONSTINFO(CKM_DSA), - CONSTINFO(CKM_DSA_SHA1), - CONSTINFO(CKM_DH_PKCS_KEY_PAIR_GEN), - CONSTINFO(CKM_DH_PKCS_DERIVE), - CONSTINFO(CKM_X9_42_DH_KEY_PAIR_GEN), - CONSTINFO(CKM_X9_42_DH_DERIVE), - CONSTINFO(CKM_X9_42_DH_HYBRID_DERIVE), - CONSTINFO(CKM_X9_42_MQV_DERIVE), - CONSTINFO(CKM_SHA256_RSA_PKCS), - CONSTINFO(CKM_SHA384_RSA_PKCS), - CONSTINFO(CKM_SHA512_RSA_PKCS), - CONSTINFO(CKM_RC2_KEY_GEN), - CONSTINFO(CKM_RC2_ECB), - CONSTINFO(CKM_RC2_CBC), - CONSTINFO(CKM_RC2_MAC), - CONSTINFO(CKM_RC2_MAC_GENERAL), - CONSTINFO(CKM_RC2_CBC_PAD), - CONSTINFO(CKM_RC4_KEY_GEN), - CONSTINFO(CKM_RC4), - CONSTINFO(CKM_DES_KEY_GEN), - CONSTINFO(CKM_DES_ECB), - CONSTINFO(CKM_DES_CBC), - CONSTINFO(CKM_DES_MAC), - CONSTINFO(CKM_DES_MAC_GENERAL), - CONSTINFO(CKM_DES_CBC_PAD), - CONSTINFO(CKM_DES2_KEY_GEN), - CONSTINFO(CKM_DES3_KEY_GEN), - CONSTINFO(CKM_DES3_ECB), - CONSTINFO(CKM_DES3_CBC), - CONSTINFO(CKM_DES3_MAC), - CONSTINFO(CKM_DES3_MAC_GENERAL), - CONSTINFO(CKM_DES3_CMAC), - CONSTINFO(CKM_DES3_CMAC_GENERAL), - CONSTINFO(CKM_DES3_CBC_PAD), - CONSTINFO(CKM_CDMF_KEY_GEN), - CONSTINFO(CKM_CDMF_ECB), - CONSTINFO(CKM_CDMF_CBC), - CONSTINFO(CKM_CDMF_MAC), - CONSTINFO(CKM_CDMF_MAC_GENERAL), - CONSTINFO(CKM_CDMF_CBC_PAD), - CONSTINFO(CKM_MD2), - CONSTINFO(CKM_MD2_HMAC), - CONSTINFO(CKM_MD2_HMAC_GENERAL), - CONSTINFO(CKM_MD5), - CONSTINFO(CKM_MD5_HMAC), - CONSTINFO(CKM_MD5_HMAC_GENERAL), - CONSTINFO(CKM_SHA_1), - CONSTINFO(CKM_SHA_1_HMAC), - CONSTINFO(CKM_SHA_1_HMAC_GENERAL), - CONSTINFO(CKM_RIPEMD128), - CONSTINFO(CKM_RIPEMD128_HMAC), - CONSTINFO(CKM_RIPEMD128_HMAC_GENERAL), - CONSTINFO(CKM_RIPEMD160), - CONSTINFO(CKM_RIPEMD160_HMAC), - CONSTINFO(CKM_RIPEMD160_HMAC_GENERAL), - CONSTINFO(CKM_SHA224), - CONSTINFO(CKM_SHA224_HMAC), - CONSTINFO(CKM_SHA224_HMAC_GENERAL), - CONSTINFO(CKM_SHA256), - CONSTINFO(CKM_SHA256_HMAC), - CONSTINFO(CKM_SHA256_HMAC_GENERAL), - CONSTINFO(CKM_SHA384), - CONSTINFO(CKM_SHA384_HMAC), - CONSTINFO(CKM_SHA384_HMAC_GENERAL), - CONSTINFO(CKM_SHA512), - CONSTINFO(CKM_SHA512_HMAC), - CONSTINFO(CKM_SHA512_HMAC_GENERAL), - CONSTINFO(CKM_CAST_KEY_GEN), - CONSTINFO(CKM_CAST_ECB), - CONSTINFO(CKM_CAST_CBC), - CONSTINFO(CKM_CAST_MAC), - CONSTINFO(CKM_CAST_MAC_GENERAL), - CONSTINFO(CKM_CAST_CBC_PAD), - CONSTINFO(CKM_CAST3_KEY_GEN), - CONSTINFO(CKM_CAST3_ECB), - CONSTINFO(CKM_CAST3_CBC), - CONSTINFO(CKM_CAST3_MAC), - CONSTINFO(CKM_CAST3_MAC_GENERAL), - CONSTINFO(CKM_CAST3_CBC_PAD), - CONSTINFO(CKM_CAST5_KEY_GEN), - CONSTINFO(CKM_CAST5_ECB), - CONSTINFO(CKM_CAST5_CBC), - CONSTINFO(CKM_CAST5_MAC), - CONSTINFO(CKM_CAST5_MAC_GENERAL), - CONSTINFO(CKM_CAST5_CBC_PAD), - CONSTINFO(CKM_RC5_KEY_GEN), - CONSTINFO(CKM_RC5_ECB), - CONSTINFO(CKM_RC5_CBC), - CONSTINFO(CKM_RC5_MAC), - CONSTINFO(CKM_RC5_MAC_GENERAL), - CONSTINFO(CKM_RC5_CBC_PAD), - CONSTINFO(CKM_IDEA_KEY_GEN), - CONSTINFO(CKM_IDEA_ECB), - CONSTINFO(CKM_IDEA_CBC), - CONSTINFO(CKM_IDEA_MAC), - CONSTINFO(CKM_IDEA_MAC_GENERAL), - CONSTINFO(CKM_IDEA_CBC_PAD), - CONSTINFO(CKM_GENERIC_SECRET_KEY_GEN), - CONSTINFO(CKM_CONCATENATE_BASE_AND_KEY), - CONSTINFO(CKM_CONCATENATE_BASE_AND_DATA), - CONSTINFO(CKM_CONCATENATE_DATA_AND_BASE), - CONSTINFO(CKM_XOR_BASE_AND_DATA), - CONSTINFO(CKM_EXTRACT_KEY_FROM_KEY), - CONSTINFO(CKM_SSL3_PRE_MASTER_KEY_GEN), - CONSTINFO(CKM_SSL3_MASTER_KEY_DERIVE), - CONSTINFO(CKM_SSL3_KEY_AND_MAC_DERIVE), - CONSTINFO(CKM_SSL3_MASTER_KEY_DERIVE_DH), - CONSTINFO(CKM_TLS_PRE_MASTER_KEY_GEN), - CONSTINFO(CKM_TLS_MASTER_KEY_DERIVE), - CONSTINFO(CKM_TLS_KEY_AND_MAC_DERIVE), - CONSTINFO(CKM_TLS_MASTER_KEY_DERIVE_DH), - CONSTINFO(CKM_SSL3_MD5_MAC), - CONSTINFO(CKM_SSL3_SHA1_MAC), - CONSTINFO(CKM_MD5_KEY_DERIVATION), - CONSTINFO(CKM_MD2_KEY_DERIVATION), - CONSTINFO(CKM_SHA1_KEY_DERIVATION), - CONSTINFO(CKM_SHA256_KEY_DERIVATION), - CONSTINFO(CKM_PBE_MD2_DES_CBC), - CONSTINFO(CKM_PBE_MD5_DES_CBC), - CONSTINFO(CKM_PBE_MD5_CAST_CBC), - CONSTINFO(CKM_PBE_MD5_CAST3_CBC), - CONSTINFO(CKM_PBE_MD5_CAST5_CBC), - CONSTINFO(CKM_PBE_SHA1_CAST5_CBC), - CONSTINFO(CKM_PBE_SHA1_RC4_128), - CONSTINFO(CKM_PBE_SHA1_RC4_40), - CONSTINFO(CKM_PBE_SHA1_DES3_EDE_CBC), - CONSTINFO(CKM_PBE_SHA1_DES2_EDE_CBC), - CONSTINFO(CKM_PBE_SHA1_RC2_128_CBC), - CONSTINFO(CKM_PBE_SHA1_RC2_40_CBC), - CONSTINFO(CKM_PKCS5_PBKD2), - CONSTINFO(CKM_PBA_SHA1_WITH_SHA1_HMAC), - CONSTINFO(CKM_KEY_WRAP_LYNKS), - CONSTINFO(CKM_KEY_WRAP_SET_OAEP), - CONSTINFO(CKM_SKIPJACK_KEY_GEN), - CONSTINFO(CKM_SKIPJACK_ECB64), - CONSTINFO(CKM_SKIPJACK_CBC64), - CONSTINFO(CKM_SKIPJACK_OFB64), - CONSTINFO(CKM_SKIPJACK_CFB64), - CONSTINFO(CKM_SKIPJACK_CFB32), - CONSTINFO(CKM_SKIPJACK_CFB16), - CONSTINFO(CKM_SKIPJACK_CFB8), - CONSTINFO(CKM_SKIPJACK_WRAP), - CONSTINFO(CKM_SKIPJACK_PRIVATE_WRAP), - CONSTINFO(CKM_SKIPJACK_RELAYX), - CONSTINFO(CKM_KEA_KEY_PAIR_GEN), - CONSTINFO(CKM_KEA_KEY_DERIVE), - CONSTINFO(CKM_FORTEZZA_TIMESTAMP), - CONSTINFO(CKM_BATON_KEY_GEN), - CONSTINFO(CKM_BATON_ECB128), - CONSTINFO(CKM_BATON_ECB96), - CONSTINFO(CKM_BATON_CBC128), - CONSTINFO(CKM_BATON_COUNTER), - CONSTINFO(CKM_BATON_SHUFFLE), - CONSTINFO(CKM_BATON_WRAP), - CONSTINFO(CKM_EC_KEY_PAIR_GEN), - CONSTINFO(CKM_ECDSA), - CONSTINFO(CKM_ECDSA_SHA1), - CONSTINFO(CKM_ECDSA_SHA224), - CONSTINFO(CKM_ECDSA_SHA256), - CONSTINFO(CKM_ECDSA_SHA384), - CONSTINFO(CKM_ECDSA_SHA512), - CONSTINFO(CKM_ECDH1_DERIVE), - CONSTINFO(CKM_ECDH1_COFACTOR_DERIVE), - CONSTINFO(CKM_ECMQV_DERIVE), - CONSTINFO(CKM_JUNIPER_KEY_GEN), - CONSTINFO(CKM_JUNIPER_ECB128), - CONSTINFO(CKM_JUNIPER_CBC128), - CONSTINFO(CKM_JUNIPER_COUNTER), - CONSTINFO(CKM_JUNIPER_SHUFFLE), - CONSTINFO(CKM_JUNIPER_WRAP), - CONSTINFO(CKM_FASTHASH), - CONSTINFO(CKM_AES_KEY_GEN), - CONSTINFO(CKM_AES_ECB), - CONSTINFO(CKM_AES_CBC), - CONSTINFO(CKM_AES_MAC), - CONSTINFO(CKM_AES_MAC_GENERAL), - CONSTINFO(CKM_AES_CBC_PAD), - CONSTINFO(CKM_AES_CTR), - CONSTINFO(CKM_AES_CMAC), - CONSTINFO(CKM_AES_CMAC_GENERAL), - CONSTINFO(CKM_DSA_PARAMETER_GEN), - CONSTINFO(CKM_DH_PKCS_PARAMETER_GEN), - CONSTINFO(CKM_X9_42_DH_PARAMETER_GEN), - CONSTINFO(CKM_VENDOR_DEFINED), - CONSTINFO(CKM_SHA256_RSA_PKCS_PSS), - CONSTINFO(CKM_SHA224_RSA_PKCS), - CONSTINFO(CKM_SHA224_RSA_PKCS_PSS), - CONSTINFO(CKM_SHA384_RSA_PKCS_PSS), - CONSTINFO(CKM_SHA512_RSA_PKCS_PSS), - CONSTINFO(CKM_SHA224_KEY_DERIVATION), - CONSTINFO(CKM_SHA384_KEY_DERIVATION), - CONSTINFO(CKM_SHA512_KEY_DERIVATION), - CONSTINFO(CKM_SHA512_224), - CONSTINFO(CKM_SHA512_224_HMAC), - CONSTINFO(CKM_SHA512_224_HMAC_GENERAL), - CONSTINFO(CKM_SHA512_256), - CONSTINFO(CKM_SHA512_256_HMAC), - CONSTINFO(CKM_SHA512_256_HMAC_GENERAL), - CONSTINFO(CKM_EP11_SHA512_224), - CONSTINFO(CKM_EP11_SHA512_224_HMAC), - CONSTINFO(CKM_EP11_SHA512_224_HMAC_GENERAL), - CONSTINFO(CKM_EP11_SHA512_256), - CONSTINFO(CKM_EP11_SHA512_256_HMAC), - CONSTINFO(CKM_EP11_SHA512_256_HMAC_GENERAL), - CONSTINFO(CKM_IBM_CMAC), - CONSTINFO(CKM_IBM_ECDSA_SHA224), - CONSTINFO(CKM_IBM_ECDSA_SHA256), - CONSTINFO(CKM_IBM_ECDSA_SHA384), - CONSTINFO(CKM_IBM_ECDSA_SHA512), - CONSTINFO(CKM_IBM_EC_MULTIPLY), - CONSTINFO(CKM_IBM_EAC), - CONSTINFO(CKM_IBM_TESTCODE), - CONSTINFO(CKM_IBM_SHA512_256), - CONSTINFO(CKM_IBM_SHA512_224), - CONSTINFO(CKM_IBM_SHA512_256_HMAC), - CONSTINFO(CKM_IBM_SHA512_224_HMAC), - CONSTINFO(CKM_IBM_SHA512_256_KEY_DERIVATION), - CONSTINFO(CKM_IBM_SHA512_224_KEY_DERIVATION), - CONSTINFO(CKM_IBM_EC_C25519), - CONSTINFO(CKM_IBM_EC_X25519), - CONSTINFO(CKM_IBM_ED25519_SHA512), - CONSTINFO(CKM_IBM_EDDSA_SHA512), - CONSTINFO(CKM_IBM_EDDSA_PH_SHA512), - CONSTINFO(CKM_IBM_EC_C448), - CONSTINFO(CKM_IBM_EC_X448), - CONSTINFO(CKM_IBM_ED448_SHA3), - CONSTINFO(CKM_IBM_SIPHASH), - CONSTINFO(CKM_IBM_CLEARKEY_TRANSPORT), - CONSTINFO(CKM_IBM_ATTRIBUTEBOUND_WRAP), - CONSTINFO(CKM_IBM_TRANSPORTKEY), - CONSTINFO(CKM_IBM_DH_PKCS_DERIVE_RAW), - CONSTINFO(CKM_IBM_ECDH1_DERIVE_RAW), - CONSTINFO(CKM_IBM_WIRETEST), - CONSTINFO(CKM_IBM_RETAINKEY), - CONSTINFO(CKM_IBM_CPACF_WRAP), - CONSTINFO(CKM_IBM_SM3), - CONSTINFO(CKM_IBM_DILITHIUM), - CONSTINFO(CKM_IBM_SHA3_224), - CONSTINFO(CKM_IBM_SHA3_256), - CONSTINFO(CKM_IBM_SHA3_384), - CONSTINFO(CKM_IBM_SHA3_512), - CONSTINFO(CKM_IBM_SHA3_224_HMAC), - CONSTINFO(CKM_IBM_SHA3_256_HMAC), - CONSTINFO(CKM_IBM_SHA3_384_HMAC), - CONSTINFO(CKM_IBM_SHA3_512_HMAC), - CONSTINFO(CKM_IBM_ATTRIBUTEBOUND_WRAP), -}; - #define UNKNOWN_MECHANISM 0xFFFFFFFF /* for logging, debugging */ -static const char *ep11_get_ckm(CK_ULONG mechanism) +static const char *ep11_get_ckm(STDLL_TokData_t *tokdata, CK_ULONG mechanism) { - unsigned int i; + const struct mechrow *row; - for (i = 0; - i < (sizeof(ep11_mechanisms) / sizeof(ep11_mechanisms[0])); - i++) { - if (ep11_mechanisms[i].code == mechanism) - return ep11_mechanisms[i].name; - } + row = tokdata->mechtable_funcs->p_row_from_num(mechanism); + if (row) + return row->string; TRACE_WARNING("%s unknown mechanism %lx\n", __func__, mechanism); return "UNKNOWN"; } -static CK_ULONG ep11_get_mechanisms_by_name(const char *name) +static CK_ULONG ep11_get_mechanisms_by_name(STDLL_TokData_t *tokdata, + const char *name) { - unsigned int i; + const struct mechrow *row; - for (i = 0; - i < (sizeof(ep11_mechanisms) / sizeof(ep11_mechanisms[0])); - i++) { - if (strcmp(ep11_mechanisms[i].name, name) == 0) - return ep11_mechanisms[i].code; - } + row = tokdata->mechtable_funcs->p_row_from_str(name); + if (row) + return row->numeric; TRACE_WARNING("%s unknown mechanism name '%s'\n", __func__, name); return UNKNOWN_MECHANISM; @@ -1935,7 +1746,8 @@ static int read_adapter_config_file(STDLL_TokData_t * tokdata, const char *conf_name); -static int read_cp_filter_config_file(const char *conf_name, +static int read_cp_filter_config_file(STDLL_TokData_t *tokdata, + const char *conf_name, cp_config_t ** cp_config); static CK_RV ep11_error_to_pkcs11_error(CK_RV rc, SESSION *session) @@ -1989,6 +1801,10 @@ ep11_data->pkey_wrap_supported == 0) return CK_FALSE; + /* EP11 does not support sign/verify recover */ + if (attr->type == CKA_SIGN_RECOVER || attr->type == CKA_VERIFY_RECOVER) + return CK_FALSE; + switch (ktype) { case CKK_RSA: if (class == CKO_PRIVATE_KEY && attr->type == CKA_PUBLIC_EXPONENT) @@ -1998,7 +1814,7 @@ if (class == CKO_PRIVATE_KEY && attr->type == CKA_EC_PARAMS) return CK_FALSE; if (attr->type == CKA_ENCRYPT || attr->type == CKA_DECRYPT || - attr->type == CKA_SIGN_RECOVER) + attr->type == CKA_WRAP || attr->type == CKA_UNWRAP) return CK_FALSE; /* Montgomery curves cannot be used for sign/verify */ if (class == CKO_PRIVATE_KEY && curve_type == MONTGOMERY_CURVE && attr->type == CKA_SIGN) @@ -2011,7 +1827,7 @@ break; case CKK_DSA: if (attr->type == CKA_ENCRYPT || attr->type == CKA_DECRYPT || - attr->type == CKA_SIGN_RECOVER) + attr->type == CKA_WRAP || attr->type == CKA_UNWRAP) return CK_FALSE; if (attr->type == CKA_PRIME || attr->type == CKA_SUBPRIME || attr->type == CKA_BASE) @@ -2019,14 +1835,15 @@ break; case CKK_DH: if (attr->type == CKA_ENCRYPT || attr->type == CKA_DECRYPT || - attr->type == CKA_SIGN || attr->type == CKA_SIGN_RECOVER) + attr->type == CKA_WRAP || attr->type == CKA_UNWRAP || + attr->type == CKA_SIGN || attr->type == CKA_VERIFY) return CK_FALSE; if (attr->type == CKA_BASE || attr->type == CKA_PRIME) return CK_FALSE; break; case CKK_IBM_PQC_DILITHIUM: if (attr->type == CKA_ENCRYPT || attr->type == CKA_DECRYPT || - attr->type == CKA_SIGN_RECOVER) + attr->type == CKA_WRAP || attr->type == CKA_UNWRAP) return CK_FALSE; break; default: @@ -2117,10 +1934,10 @@ * calls the ep11 lib (which in turns sends the request to the card), * all m_ function are ep11 functions */ - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_EncryptSingle(ep11_data->raw2key_wrap_blob, ep11_data->raw2key_wrap_blob_l, &mech, key, - ksize, cipher, &clen, ep11_data->target); + ksize, cipher, &clen, target_info->target); RETRY_END(rc, tokdata, sess) if (rc != CKR_OK) { @@ -2140,18 +1957,20 @@ return rc; } + trace_attributes(__func__, "Import sym.:", new_p_attrs, new_attrs_len); + ep11_get_pin_blob(ep11_session, object_is_session_object(key_obj), &ep11_pin_blob, &ep11_pin_blob_len); /* the encrypted key is decrypted and a blob is build, * card accepts only blobs as keys */ - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_UnwrapKey(cipher, clen, ep11_data->raw2key_wrap_blob, ep11_data->raw2key_wrap_blob_l, NULL, ~0, ep11_pin_blob, ep11_pin_blob_len, &mech, new_p_attrs, new_attrs_len, blob, blen, csum, - &cslen, ep11_data->target); + &cslen, target_info->target); RETRY_END(rc, tokdata, sess) if (rc != CKR_OK) { @@ -2194,14 +2013,20 @@ CK_RV token_specific_rng(STDLL_TokData_t * tokdata, CK_BYTE * output, CK_ULONG bytes) { - ep11_private_data_t *ep11_data = tokdata->private_data; + ep11_target_info_t* target_info; + + target_info = get_target_info(tokdata); + if (target_info == NULL) + return CKR_FUNCTION_FAILED; - CK_RV rc = dll_m_GenerateRandom(output, bytes, ep11_data->target); + CK_RV rc = dll_m_GenerateRandom(output, bytes, target_info->target); if (rc != CKR_OK) { rc = ep11_error_to_pkcs11_error(rc, NULL); TRACE_ERROR("%s output=%p bytes=%lu rc=0x%lx\n", __func__, (void *)output, bytes, rc); } + + put_target_info(tokdata, target_info); return rc; } @@ -2215,6 +2040,7 @@ { ep11_private_data_t *ep11_data = tokdata->private_data; CK_MECHANISM mech = { CKM_AES_KEY_GEN, NULL_PTR, 0 }; + ep11_target_info_t* target_info; CK_BYTE csum[MAX_CSUMSIZE]; size_t csum_l = sizeof(csum); CK_RV rc; @@ -2225,11 +2051,17 @@ return CKR_OK; } + trace_attributes(__func__, "Generate wrap blog key:", tmpl_in, tmpl_len); + + target_info = get_target_info(tokdata); + if (target_info == NULL) + return CKR_FUNCTION_FAILED; + ep11_data->raw2key_wrap_blob_l = sizeof(ep11_data->raw2key_wrap_blob); rc = dll_m_GenerateKey(&mech, tmpl_in, tmpl_len, NULL, 0, ep11_data->raw2key_wrap_blob, &ep11_data->raw2key_wrap_blob_l, csum, &csum_l, - ep11_data->target); + target_info->target); if (rc != CKR_OK) { @@ -2240,13 +2072,14 @@ __func__, ep11_data->raw2key_wrap_blob_l, rc); } + put_target_info(tokdata, target_info); return rc; } #ifdef EP11_HSMSIM -#define DLOPEN_FLAGS RTLD_GLOBAL | RTLD_NOW | RTLD_DEEPBIND +#define DLOPEN_FLAGS RTLD_NOW | RTLD_DEEPBIND #else -#define DLOPEN_FLAGS RTLD_GLOBAL | RTLD_NOW +#define DLOPEN_FLAGS RTLD_NOW #endif static void *ep11_load_host_lib() @@ -2409,12 +2242,16 @@ return CKR_OK; if (strcmp(ep11_data->digest_libica_path, "") == 0) { - strcpy(ep11_data->digest_libica_path, ICASHAREDLIB); + strcpy(ep11_data->digest_libica_path, ICASHAREDLIB_V4); default_libica = 1; + libica->library = dlopen(ep11_data->digest_libica_path, RTLD_NOW); + if (libica->library == NULL) { + strcpy(ep11_data->digest_libica_path, ICASHAREDLIB_V3); + libica->library = dlopen(ep11_data->digest_libica_path, RTLD_NOW); + } + } else { + libica->library = dlopen(ep11_data->digest_libica_path, RTLD_NOW); } - - libica->library = dlopen(ep11_data->digest_libica_path, - RTLD_GLOBAL | RTLD_NOW); if (libica->library == NULL) { errstr = dlerror(); OCK_SYSLOG(default_libica ? LOG_WARNING : LOG_ERR, @@ -2479,6 +2316,14 @@ if (ep11_data == NULL) return CKR_HOST_MEMORY; + if (pthread_rwlock_init(&ep11_data->target_rwlock, NULL) != 0) { + TRACE_DEVEL("Target Lock init failed.\n"); + OCK_SYSLOG(LOG_ERR, "%s: Failed to initialize the target lock\n", + __func__); + rc = CKR_CANT_LOCK; + goto error; + } + tokdata->private_data = ep11_data; /* read ep11 specific config file with user specified @@ -2513,13 +2358,28 @@ } #endif - rc = ep11tok_get_ep11_version(tokdata); - if (rc != CKR_OK) + rc = ep11tok_get_ep11_library_version(&ep11_data->ep11_lib_version); + if (rc != CKR_OK) { + TRACE_ERROR("%s Failed to get the Ep11 library version " + "(ep11tok_get_ep11_library_version rc=0x%lx)\n", __func__, + rc); + OCK_SYSLOG(LOG_ERR, "%s: Failed to get the EP11 library version " + "rc=0x%lx\n", __func__, rc); goto error; + } - rc = ep11tok_setup_target(tokdata); - if (rc != CKR_OK) + TRACE_INFO("%s Host library version: %d.%d\n", __func__, + ep11_data->ep11_lib_version.major, + ep11_data->ep11_lib_version.minor); + + rc = refresh_target_info(tokdata); + if (rc != CKR_OK) { + TRACE_ERROR("%s Failed to get the target info (refresh_target_info " + "rc=0x%lx)\n", __func__, rc); + OCK_SYSLOG(LOG_ERR, "%s: Failed to get the target info rc=0x%lx\n", + __func__, rc); goto error; + } if (ep11_data->digest_libica) { rc = ep11tok_load_libica(tokdata); @@ -2530,18 +2390,6 @@ ep11_data->msa_level = get_msa_level(); TRACE_INFO("MSA level = %i\n", ep11_data->msa_level); - ep11_data->control_points_len = sizeof(ep11_data->control_points); - rc = get_control_points(tokdata, ep11_data->control_points, - &ep11_data->control_points_len, - &ep11_data->max_control_point_index); - if (rc != CKR_OK) { - TRACE_ERROR("%s Failed to get the control points (get_control_points " - "rc=0x%lx)\n", __func__, rc); - OCK_SYSLOG(LOG_ERR, "%s: Failed to get the control points rc=0x%lx\n", - __func__, rc); - goto error; - } - /* create an AES key needed for importing keys * (encrypt by wrap_key and m_UnwrapKey by wrap key) */ @@ -2600,10 +2448,14 @@ TRACE_INFO("ep11 %s running\n", __func__); if (ep11_data != NULL) { - if (dll_m_rm_module != NULL) - dll_m_rm_module(NULL, ep11_data->target); + if (ep11_data->target_info != NULL) { + if (dll_m_rm_module != NULL) + dll_m_rm_module(NULL, ep11_data->target_info->target); + free_card_versions(ep11_data->target_info->card_versions); + free((void* )ep11_data->target_info); + } + pthread_rwlock_destroy(&ep11_data->target_rwlock); free_cp_config(ep11_data->cp_config); - free_card_versions(ep11_data->card_versions); free(ep11_data); tokdata->private_data = NULL; } @@ -2617,9 +2469,9 @@ static CK_RV make_maced_spki(STDLL_TokData_t *tokdata, SESSION * sess, OBJECT *pub_key_obj, CK_BYTE *spki, CK_ULONG spki_len, - CK_BYTE *maced_spki, CK_ULONG *maced_spki_len) + CK_BYTE *maced_spki, CK_ULONG *maced_spki_len, + int curve_type) { - ep11_private_data_t *ep11_data = tokdata->private_data; unsigned char *ep11_pin_blob = NULL; CK_ULONG ep11_pin_blob_len = 0; ep11_session_t *ep11_session = (ep11_session_t *) sess->private_data; @@ -2649,6 +2501,10 @@ while (node != NULL) { attr = node->data; + if (!attr_applicable_for_ep11(tokdata, attr, keytype, + CKO_PUBLIC_KEY, curve_type)) + goto make_maced_spki_next; + switch (attr->type) { case CKA_ENCRYPT: case CKA_VERIFY: @@ -2680,11 +2536,9 @@ break; case CKA_EXTRACTABLE: - case CKA_MODIFIABLE: case CKA_DERIVE: case CKA_WRAP: - case CKA_TRUSTED: case CKA_IBM_RESTRICTABLE: case CKA_IBM_NEVER_MODIFIABLE: @@ -2706,17 +2560,20 @@ default: break; } +make_maced_spki_next: node = node->next; } + trace_attributes(__func__, "MACed SPKI import:", p_attrs, attrs_len); + ep11_get_pin_blob(ep11_session, object_is_session_object(pub_key_obj), &ep11_pin_blob, &ep11_pin_blob_len); - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_UnwrapKey(spki, spki_len, NULL, 0, NULL, 0, ep11_pin_blob, ep11_pin_blob_len, &mech, p_attrs, attrs_len, maced_spki, maced_spki_len, - csum, &cslen, ep11_data->target); + csum, &cslen, target_info->target); RETRY_END(rc, tokdata, sess) if (rc != CKR_OK) { @@ -2848,7 +2705,7 @@ * The card expects MACed-SPKIs as public keys. */ rc = make_maced_spki(tokdata, sess, rsa_key_obj, data, data_len, - blob, blob_size); + blob, blob_size, -1); if (rc != CKR_OK) { TRACE_ERROR("%s failed to make a MACed-SPKI rc=0x%lx\n", __func__, rc); @@ -2870,11 +2727,11 @@ } /* encrypt */ - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_EncryptSingle(ep11_data->raw2key_wrap_blob, ep11_data->raw2key_wrap_blob_l, &mech_w, data, data_len, cipher, &cipher_l, - ep11_data->target); + target_info->target); RETRY_END(rc, tokdata, sess) TRACE_INFO("%s wrapping wrap key rc=0x%lx cipher_l=0x%lx\n", @@ -2895,18 +2752,20 @@ goto import_RSA_key_end; } + trace_attributes(__func__, "RSA import:", new_p_attrs, new_attrs_len); + ep11_get_pin_blob(ep11_session, object_is_session_object(rsa_key_obj), &ep11_pin_blob, &ep11_pin_blob_len); /* calls the card, it decrypts the private RSA key, * reads its BER format and builds a blob. */ - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_UnwrapKey(cipher, cipher_l, ep11_data->raw2key_wrap_blob, ep11_data->raw2key_wrap_blob_l, NULL, ~0, ep11_pin_blob, ep11_pin_blob_len, &mech_w, new_p_attrs, new_attrs_len, blob, blob_size, - csum, &cslen, ep11_data->target); + csum, &cslen, target_info->target); RETRY_END(rc, tokdata, sess) if (rc != CKR_OK) { @@ -3057,12 +2916,7 @@ /* * Builds the DER encoding (ansi_x962) SPKI. - * (get the length first) */ - rc = ber_encode_ECPublicKey(TRUE, &data, &data_len, - ec_params, &ec_point_uncompr); - data = malloc(data_len); - rc = ber_encode_ECPublicKey(FALSE, &data, &data_len, ec_params, &ec_point_uncompr); free(ecpoint); @@ -3079,7 +2933,7 @@ * The card expects MACed-SPKIs as public keys. */ rc = make_maced_spki(tokdata, sess, ec_key_obj, data, data_len, - blob, blob_size); + blob, blob_size, (int)curve->curve_type); if (rc != CKR_OK) { TRACE_ERROR("%s failed to make a MACed-SPKI rc=0x%lx\n", __func__, rc); @@ -3101,11 +2955,11 @@ } /* encrypt */ - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_EncryptSingle(ep11_data->raw2key_wrap_blob, ep11_data->raw2key_wrap_blob_l, &mech_w, data, data_len, - cipher, &cipher_l, ep11_data->target); + cipher, &cipher_l, target_info->target); RETRY_END(rc, tokdata, sess) TRACE_INFO("%s wrapping wrap key rc=0x%lx cipher_l=0x%lx\n", @@ -3127,20 +2981,22 @@ goto import_EC_key_end; } + trace_attributes(__func__, "EC import:", new_p_attrs, new_attrs_len); + ep11_get_pin_blob(ep11_session, object_is_session_object(ec_key_obj), &ep11_pin_blob, &ep11_pin_blob_len); /* calls the card, it decrypts the private EC key, * reads its BER format and builds a blob. */ - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_UnwrapKey(cipher, cipher_l, ep11_data->raw2key_wrap_blob, ep11_data->raw2key_wrap_blob_l, NULL, ~0, ep11_pin_blob, ep11_pin_blob_len, &mech_w, new_p_attrs, new_attrs_len, blob, - blob_size, csum, &cslen, ep11_data->target); + blob_size, csum, &cslen, target_info->target); RETRY_END(rc, tokdata, sess) if (rc != CKR_OK) { @@ -3252,12 +3108,7 @@ /* * Builds the DER encoding (ansi_x962) SPKI. - * (get the length first) */ - rc = ber_encode_DSAPublicKey(TRUE, &data, &data_len, - prime, subprime, base, value); - data = malloc(data_len); - rc = ber_encode_DSAPublicKey(FALSE, &data, &data_len, prime, subprime, base, value); if (rc != CKR_OK) { @@ -3273,7 +3124,7 @@ * The card expects MACed-SPKIs as public keys. */ rc = make_maced_spki(tokdata, sess, dsa_key_obj, data, data_len, - blob, blob_size); + blob, blob_size, -1); if (rc != CKR_OK) { TRACE_ERROR("%s failed to make a MACed-SPKI rc=0x%lx\n", __func__, rc); @@ -3295,11 +3146,11 @@ } /* encrypt */ - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_EncryptSingle(ep11_data->raw2key_wrap_blob, ep11_data->raw2key_wrap_blob_l, &mech_w, data, data_len, - cipher, &cipher_l, ep11_data->target); + cipher, &cipher_l, target_info->target); RETRY_END(rc, tokdata, sess) @@ -3321,20 +3172,22 @@ goto import_DSA_key_end; } + trace_attributes(__func__, "DSA import:", new_p_attrs, new_attrs_len); + ep11_get_pin_blob(ep11_session, object_is_session_object(dsa_key_obj), &ep11_pin_blob, &ep11_pin_blob_len); /* calls the card, it decrypts the private EC key, * reads its BER format and builds a blob. */ - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_UnwrapKey(cipher, cipher_l, ep11_data->raw2key_wrap_blob, ep11_data->raw2key_wrap_blob_l, NULL, ~0, ep11_pin_blob, ep11_pin_blob_len, &mech_w, new_p_attrs, new_attrs_len, blob, - blob_size, csum, &cslen, ep11_data->target); + blob_size, csum, &cslen, target_info->target); RETRY_END(rc, tokdata, sess) if (rc != CKR_OK) { @@ -3436,11 +3289,7 @@ /* * Builds the DER encoding (ansi_x962) SPKI. - * (get the length first) */ - rc = ber_encode_DHPublicKey(TRUE, &data, &data_len, prime, base, value); - data = malloc(data_len); - rc = ber_encode_DHPublicKey(FALSE, &data, &data_len, prime, base, value); if (rc != CKR_OK) { @@ -3456,7 +3305,7 @@ * The card expects MACed-SPKIs as public keys. */ rc = make_maced_spki(tokdata, sess, dh_key_obj, data, data_len, - blob, blob_size); + blob, blob_size, -1); if (rc != CKR_OK) { TRACE_ERROR("%s failed to make a MACed-SPKI rc=0x%lx\n", __func__, rc); @@ -3464,6 +3313,9 @@ } } else { + CK_ATTRIBUTE *value; + CK_ATTRIBUTE *value_bits; + CK_ULONG num_bits; /* imported private DH key goes here */ @@ -3477,12 +3329,21 @@ goto import_DH_key_end; } + rc = template_attribute_get_non_empty(dh_key_obj->template, CKA_VALUE, + &value); + if (rc != CKR_OK) { + TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); + goto import_DH_key_end; + } + + num_bits = value->ulValueLen * 8; + /* encrypt */ - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_EncryptSingle(ep11_data->raw2key_wrap_blob, ep11_data->raw2key_wrap_blob_l, &mech_w, data, data_len, - cipher, &cipher_l, ep11_data->target); + cipher, &cipher_l, target_info->target); RETRY_END(rc, tokdata, sess) TRACE_INFO("%s wrapping wrap key rc=0x%lx cipher_l=0x%lx\n", @@ -3503,20 +3364,22 @@ goto import_DH_key_end; } + trace_attributes(__func__, "DH import:", new_p_attrs, new_attrs_len); + ep11_get_pin_blob(ep11_session, object_is_session_object(dh_key_obj), &ep11_pin_blob, &ep11_pin_blob_len); /* calls the card, it decrypts the private EC key, * reads its BER format and builds a blob. */ - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_UnwrapKey(cipher, cipher_l, ep11_data->raw2key_wrap_blob, ep11_data->raw2key_wrap_blob_l, NULL, ~0, ep11_pin_blob, ep11_pin_blob_len, &mech_w, new_p_attrs, new_attrs_len, blob, - blob_size, csum, &cslen, ep11_data->target); + blob_size, csum, &cslen, target_info->target); RETRY_END(rc, tokdata, sess) if (rc != CKR_OK) { @@ -3528,6 +3391,21 @@ __func__, rc, *blob_size); } + rc = build_attribute(CKA_VALUE_BITS, (CK_BYTE *)&num_bits, + sizeof(num_bits), &value_bits); + if (rc != CKR_OK) { + TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", __func__, rc); + goto import_DH_key_end; + } + + rc = template_update_attribute(dh_key_obj->template, value_bits); + if (rc != CKR_OK) { + TRACE_ERROR("%s template_update_attribute failed with rc=0x%lx\n", + __func__, rc); + free(value_bits); + goto import_DH_key_end; + } + cleanse_attribute(dh_key_obj->template, CKA_VALUE); } @@ -3644,7 +3522,7 @@ * The card expects MACed-SPKIs as public keys. */ rc = make_maced_spki(tokdata, sess, dilithium_key_obj, data, data_len, - blob, blob_size); + blob, blob_size, -1); if (rc != CKR_OK) { TRACE_ERROR("%s failed to make a MACed-SPKI rc=0x%lx\n", __func__, rc); @@ -3666,11 +3544,11 @@ } /* encrypt */ - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_EncryptSingle(ep11_data->raw2key_wrap_blob, ep11_data->raw2key_wrap_blob_l, &mech_w, data, data_len, - cipher, &cipher_l, ep11_data->target); + cipher, &cipher_l, target_info->target); RETRY_END(rc, tokdata, sess) TRACE_INFO("%s wrapping wrap key rc=0x%lx cipher_l=0x%lx\n", @@ -3693,20 +3571,22 @@ goto done; } + trace_attributes(__func__, "Dilithium import:", new_p_attrs, new_attrs_len); + ep11_get_pin_blob(ep11_session, object_is_session_object(dilithium_key_obj), &ep11_pin_blob, &ep11_pin_blob_len); /* calls the card, it decrypts the private Dilithium key, * reads its BER format and builds a blob. */ - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_UnwrapKey(cipher, cipher_l, ep11_data->raw2key_wrap_blob, ep11_data->raw2key_wrap_blob_l, NULL, ~0, ep11_pin_blob, ep11_pin_blob_len, &mech_w, new_p_attrs, new_attrs_len, blob, - blob_size, csum, &cslen, ep11_data->target); + blob_size, csum, &cslen, target_info->target); RETRY_END(rc, tokdata, sess) if (rc != CKR_OK) { @@ -3876,6 +3756,13 @@ return rc; } + rc = update_ep11_attrs_from_blob(tokdata, obj->template); + if (rc != CKR_OK) { + TRACE_ERROR("%s update_ep11_attrs_from_blob failed with rc=0x%lx\n", + __func__, rc); + return rc; + } + return CKR_OK; } @@ -3884,7 +3771,6 @@ CK_MECHANISM_PTR mech, CK_ATTRIBUTE_PTR attrs, CK_ULONG attrs_len, CK_OBJECT_HANDLE_PTR handle) { - ep11_private_data_t *ep11_data = tokdata->private_data; CK_BYTE blob[MAX_BLOBSIZE]; size_t blobsize = sizeof(blob); CK_BYTE csum[MAX_CSUMSIZE]; @@ -3933,23 +3819,26 @@ goto error; } + trace_attributes(__func__, "Generate key:", new_attrs2, new_attrs2_len); + ep11_get_pin_blob(ep11_session, ep11_is_session_object(attrs, attrs_len), &ep11_pin_blob, &ep11_pin_blob_len); - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_GenerateKey(mech, new_attrs2, new_attrs2_len, ep11_pin_blob, ep11_pin_blob_len, blob, &blobsize, - csum, &csum_len, ep11_data->target); + csum, &csum_len, target_info->target); RETRY_END(rc, tokdata, session) if (rc != CKR_OK) { rc = ep11_error_to_pkcs11_error(rc, session); TRACE_ERROR("%s m_GenerateKey rc=0x%lx mech='%s' attrs_len=0x%lx\n", - __func__, rc, ep11_get_ckm(mech->mechanism), attrs_len); + __func__, rc, ep11_get_ckm(tokdata, mech->mechanism), + attrs_len); goto done; } TRACE_INFO("%s m_GenerateKey rc=0x%lx mech='%s' attrs_len=0x%lx\n", - __func__, rc, ep11_get_ckm(mech->mechanism), attrs_len); + __func__, rc, ep11_get_ckm(tokdata, mech->mechanism), attrs_len); rc = build_attribute(CKA_IBM_OPAQUE, blob, blobsize, &attr); if (rc != CKR_OK) { @@ -3965,6 +3854,13 @@ } attr = NULL; + rc = update_ep11_attrs_from_blob(tokdata, key_obj->template); + if (rc != CKR_OK) { + TRACE_ERROR("%s update_ep11_attrs_from_blob failed with rc=0x%lx\n", + __func__, rc); + goto error; + } + if (class == CKO_SECRET_KEY && csum_len >= EP11_CSUMSIZE) { /* First 3 bytes of csum is the check value */ rc = build_attribute(CKA_CHECK_VALUE, csum, EP11_CSUMSIZE, &attr); @@ -3999,7 +3895,8 @@ attr = NULL; /* key should be fully constructed. - * Assign an object handle and store key + * Assign an object handle and store key. + * Enforce policy. */ rc = object_mgr_create_final(tokdata, session, key_obj, handle); if (rc != CKR_OK) { @@ -4007,6 +3904,8 @@ goto error; } + INC_COUNTER(tokdata, session, mech, key_obj, POLICY_STRENGTH_IDX_0); + goto done; error: if (key_obj) @@ -4022,7 +3921,8 @@ return rc; } -static CK_BBOOL ep11tok_libica_digest_available(ep11_private_data_t *ep11_data, +static CK_BBOOL ep11tok_libica_digest_available(STDLL_TokData_t * tokdata, + ep11_private_data_t *ep11_data, CK_MECHANISM_TYPE mech) { int use_libica; @@ -4069,7 +3969,7 @@ if (use_libica == 0) TRACE_DEVEL("%s mech=%s is not supported by libica\n", __func__, - ep11_get_ckm(mech)); + ep11_get_ckm(tokdata, mech)); return use_libica ? CK_TRUE : CK_FALSE; } @@ -4253,10 +4153,11 @@ break; } - return ep11tok_libica_digest_available(ep11_data, digest_mech); + return ep11tok_libica_digest_available(tokdata, ep11_data, digest_mech); } -static CK_RV ep11tok_libica_digest(ep11_private_data_t *ep11_data, +static CK_RV ep11tok_libica_digest(STDLL_TokData_t * tokdata, + ep11_private_data_t *ep11_data, CK_MECHANISM_TYPE mech, libica_sha_context_t *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, @@ -4273,7 +4174,7 @@ return CKR_BUFFER_TOO_SMALL; TRACE_DEVEL("%s mech=%s part=%u\n", __func__, - ep11_get_ckm(mech), message_part); + ep11_get_ckm(tokdata, mech), message_part); switch (mech) { case CKM_SHA_1: @@ -4324,13 +4225,13 @@ #endif default: TRACE_ERROR("%s Invalid mechanism: mech=%s\n", __func__, - ep11_get_ckm(mech)); + ep11_get_ckm(tokdata, mech)); return CKR_MECHANISM_INVALID; } if (rc != CKR_OK) { TRACE_ERROR("%s Libica SHA failed. mech=%s rc=0x%lx\n", __func__, - ep11_get_ckm(mech), rc); + ep11_get_ckm(tokdata, mech), rc); switch (rc) { case EINVAL: @@ -4354,6 +4255,7 @@ size_t state_len = MAX(MAX_DIGEST_STATE_BYTES, sizeof(libica_sha_context_t)); CK_BYTE *state; libica_sha_context_t *libica_ctx; + ep11_target_info_t* target_info; state = calloc(state_len, 1); /* freed by dig_mgr.c */ if (!state) { @@ -4361,15 +4263,21 @@ return CKR_HOST_MEMORY; } - if (ep11tok_libica_digest_available(ep11_data, mech->mechanism)) { + target_info = get_target_info(tokdata); + if (target_info == NULL) + return CKR_FUNCTION_FAILED; + + if (ep11tok_libica_digest_available(tokdata, ep11_data, mech->mechanism)) { libica_ctx = (libica_sha_context_t *)state; state_len = sizeof(libica_sha_context_t); libica_ctx->first = CK_TRUE; rc = get_sha_block_size(mech->mechanism, &libica_ctx->block_size); } else { - rc = dll_m_DigestInit(state, &state_len, mech, ep11_data->target); + rc = dll_m_DigestInit(state, &state_len, mech, target_info->target); } + put_target_info(tokdata, target_info); + if (rc != CKR_OK) { rc = ep11_error_to_pkcs11_error(rc, NULL); TRACE_ERROR("%s rc=0x%lx\n", __func__, rc); @@ -4399,16 +4307,21 @@ { ep11_private_data_t *ep11_data = tokdata->private_data; CK_RV rc; + ep11_target_info_t* target_info; - if (ep11tok_libica_digest_available(ep11_data, c->mech.mechanism)) { - rc = ep11tok_libica_digest(ep11_data, c->mech.mechanism, + target_info = get_target_info(tokdata); + if (target_info == NULL) + return CKR_FUNCTION_FAILED; + + if (ep11tok_libica_digest_available(tokdata, ep11_data, c->mech.mechanism)) { + rc = ep11tok_libica_digest(tokdata, ep11_data, c->mech.mechanism, (libica_sha_context_t *)c->context, in_data, in_data_len, out_data, out_data_len, SHA_MSG_PART_ONLY); } else { rc = dll_m_Digest(c->context, c->context_len, in_data, in_data_len, - out_data, out_data_len, ep11_data->target); + out_data, out_data_len, target_info->target); } if (rc != CKR_OK) { @@ -4417,6 +4330,8 @@ } else { TRACE_INFO("%s rc=0x%lx\n", __func__, rc); } + + put_target_info(tokdata, target_info); return rc; } @@ -4430,8 +4345,13 @@ CK_ULONG out_len = sizeof(temp_out); CK_ULONG len; CK_RV rc = CKR_OK; + ep11_target_info_t* target_info; - if (ep11tok_libica_digest_available(ep11_data, c->mech.mechanism)) { + target_info = get_target_info(tokdata); + if (target_info == NULL) + return CKR_FUNCTION_FAILED; + + if (ep11tok_libica_digest_available(tokdata, ep11_data, c->mech.mechanism)) { if (libica_ctx->offset > 0 || in_data_len < libica_ctx->block_size) { len = MIN(libica_ctx->block_size - libica_ctx->offset, in_data_len); @@ -4442,7 +4362,8 @@ in_data_len -= len; if (libica_ctx->offset == libica_ctx->block_size) { - rc = ep11tok_libica_digest(ep11_data, c->mech.mechanism, + rc = ep11tok_libica_digest(tokdata, + ep11_data, c->mech.mechanism, libica_ctx, libica_ctx->buffer, libica_ctx->offset, temp_out, &out_len, libica_ctx->first ? @@ -4459,7 +4380,7 @@ if (in_data_len > 0) { len = (in_data_len / libica_ctx->block_size) * libica_ctx->block_size; - rc = ep11tok_libica_digest(ep11_data, c->mech.mechanism, + rc = ep11tok_libica_digest(tokdata, ep11_data, c->mech.mechanism, libica_ctx, in_data, len, temp_out, &out_len, libica_ctx->first ? SHA_MSG_PART_FIRST : @@ -4479,7 +4400,7 @@ } } else { rc = dll_m_DigestUpdate(c->context, c->context_len, - in_data, in_data_len, ep11_data->target); + in_data, in_data_len, target_info->target); } out: @@ -4489,6 +4410,8 @@ } else { TRACE_INFO("%s rc=0x%lx\n", __func__, rc); } + + put_target_info(tokdata, target_info); return rc; } @@ -4499,9 +4422,14 @@ ep11_private_data_t *ep11_data = tokdata->private_data; libica_sha_context_t *libica_ctx = (libica_sha_context_t *)c->context; CK_RV rc; + ep11_target_info_t* target_info; - if (ep11tok_libica_digest_available(ep11_data, c->mech.mechanism)) { - rc = ep11tok_libica_digest(ep11_data, c->mech.mechanism, + target_info = get_target_info(tokdata); + if (target_info == NULL) + return CKR_FUNCTION_FAILED; + + if (ep11tok_libica_digest_available(tokdata, ep11_data, c->mech.mechanism)) { + rc = ep11tok_libica_digest(tokdata, ep11_data, c->mech.mechanism, libica_ctx, libica_ctx->buffer, libica_ctx->offset, out_data, out_data_len, @@ -4510,7 +4438,7 @@ SHA_MSG_PART_FINAL); } else { rc = dll_m_DigestFinal(c->context, c->context_len, - out_data, out_data_len, ep11_data->target); + out_data, out_data_len, target_info->target); } if (rc != CKR_OK) { @@ -4520,6 +4448,7 @@ TRACE_INFO("%s rc=0x%lx\n", __func__, rc); } + put_target_info(tokdata, target_info); return rc; } @@ -4528,7 +4457,6 @@ CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj) { - ep11_private_data_t *ep11_data = tokdata->private_data; CK_RV rc; size_t keyblobsize = 0; CK_BYTE *keyblob; @@ -4544,9 +4472,9 @@ mech.pParameter = NULL; mech.ulParameterLen = 0; - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_SignSingle(keyblob, keyblobsize, &mech, in_data, in_data_len, - out_data, out_data_len, ep11_data->target); + out_data, out_data_len, target_info->target); RETRY_END(rc, tokdata, session) if (rc != CKR_OK) { rc = ep11_error_to_pkcs11_error(rc, session); @@ -4563,7 +4491,6 @@ CK_BYTE *signature, CK_ULONG sig_len, OBJECT *key_obj) { - ep11_private_data_t *ep11_data = tokdata->private_data; CK_RV rc; CK_BYTE *spki; size_t spki_len = 0; @@ -4579,9 +4506,9 @@ mech.pParameter = NULL; mech.ulParameterLen = 0; - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_VerifySingle(spki, spki_len, &mech, in_data, in_data_len, - signature, sig_len, ep11_data->target); + signature, sig_len, target_info->target); RETRY_END(rc, tokdata, session) if (rc != CKR_OK) { rc = ep11_error_to_pkcs11_error(rc, session); @@ -4598,7 +4525,6 @@ CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *sig, CK_ULONG *sig_len) { - ep11_private_data_t *ep11_data = tokdata->private_data; CK_RV rc; size_t keyblobsize = 0; CK_BYTE *keyblob; @@ -4616,9 +4542,9 @@ mech.ulParameterLen = ctx->mech.ulParameterLen; mech.pParameter = ctx->mech.pParameter; - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_SignSingle(keyblob, keyblobsize, &mech, in_data, in_data_len, - sig, sig_len, ep11_data->target); + sig, sig_len, target_info->target); RETRY_END(rc, tokdata, session) if (rc != CKR_OK) { rc = ep11_error_to_pkcs11_error(rc, session); @@ -4638,7 +4564,6 @@ CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG sig_len) { - ep11_private_data_t *ep11_data = tokdata->private_data; CK_RV rc; CK_BYTE *spki; size_t spki_len = 0; @@ -4656,9 +4581,9 @@ mech.ulParameterLen = ctx->mech.ulParameterLen; mech.pParameter = ctx->mech.pParameter; - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_VerifySingle(spki, spki_len, &mech, in_data, in_data_len, - signature, sig_len, ep11_data->target); + signature, sig_len, target_info->target); RETRY_END(rc, tokdata, session) if (rc != CKR_OK) { rc = ep11_error_to_pkcs11_error(rc, session); @@ -4678,7 +4603,6 @@ CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj ) { - ep11_private_data_t *ep11_data = tokdata->private_data; SIGN_VERIFY_CONTEXT *ctx = &(session->sign_ctx); CK_RV rc; size_t keyblobsize = 0; @@ -4707,9 +4631,9 @@ mech.pParameter = NULL; mech.ulParameterLen = 0; - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_SignSingle(keyblob, keyblobsize, &mech, in_data, in_data_len, - out_data, out_data_len, ep11_data->target); + out_data, out_data_len, target_info->target); RETRY_END(rc, tokdata, session) if (rc != CKR_OK) { rc = ep11_error_to_pkcs11_error(rc, session); @@ -4728,7 +4652,6 @@ CK_BYTE *out_data, CK_ULONG out_data_len, OBJECT *key_obj ) { - ep11_private_data_t *ep11_data = tokdata->private_data; SIGN_VERIFY_CONTEXT *ctx = &(session->verify_ctx); CK_RV rc; CK_BYTE *spki; @@ -4757,9 +4680,9 @@ mech.pParameter = NULL; mech.ulParameterLen = 0; - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_VerifySingle(spki, spki_len, &mech, in_data, in_data_len, - out_data, out_data_len, ep11_data->target); + out_data, out_data_len, target_info->target); RETRY_END(rc, tokdata, session) if (rc != CKR_OK) { rc = ep11_error_to_pkcs11_error(rc, session); @@ -4784,7 +4707,6 @@ CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { - ep11_private_data_t *ep11_data = tokdata->private_data; CK_RV rc; CK_BYTE *decr_key, *encr_key; size_t decr_key_len = 0, encr_key_len = 0; @@ -4813,10 +4735,10 @@ return rc; } - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_ReencryptSingle(decr_key, decr_key_len, encr_key, encr_key_len, decr_mech, encr_mech, in_data, in_data_len, - out_data, out_data_len, ep11_data->target); + out_data, out_data_len, target_info->target); RETRY_END(rc, tokdata, session) if (rc != CKR_OK) { rc = ep11_error_to_pkcs11_error(rc, session); @@ -4892,7 +4814,6 @@ CK_OBJECT_HANDLE_PTR handle, CK_ATTRIBUTE_PTR attrs, CK_ULONG attrs_len) { - ep11_private_data_t *ep11_data = tokdata->private_data; CK_RV rc; CK_BYTE *keyblob; size_t keyblobsize; @@ -4920,6 +4841,9 @@ CK_ULONG privlen; int curve_type; CK_BBOOL allocated = FALSE; + ep11_target_info_t* target_info; + CK_ULONG used_firmware_API_version; + CK_MECHANISM_PTR mech_orig = mech; memset(newblob, 0, sizeof(newblob)); @@ -4929,7 +4853,7 @@ if (mech->ulParameterLen != sizeof(CK_ECDH1_DERIVE_PARAMS) || mech->pParameter == NULL) { TRACE_ERROR("%s Param NULL or len for %s wrong: %lu\n", - __func__, ep11_get_ckm(mech->mechanism ), + __func__, ep11_get_ckm(tokdata, mech->mechanism), mech->ulParameterLen); return CKR_MECHANISM_PARAM_INVALID; } @@ -4949,14 +4873,14 @@ ecdh1_parms2 = *ecdh1_parms; - rc = h_opaque_2_blob(tokdata, hBaseKey, &keyblob, &keyblobsize, - &base_key_obj, READ_LOCK); - if (rc != CKR_OK) { - TRACE_ERROR("%s failed hBaseKey=0x%lx\n", __func__, hBaseKey); - return rc; - } - if (mech->mechanism == CKM_ECDH1_DERIVE) { + rc = h_opaque_2_blob(tokdata, hBaseKey, &keyblob, &keyblobsize, + &base_key_obj, READ_LOCK); + if (rc != CKR_OK) { + TRACE_ERROR("%s failed hBaseKey=0x%lx\n", __func__, hBaseKey); + return rc; + } + rc = get_ecsiglen(base_key_obj, &privlen); privlen /= 2; @@ -5009,7 +4933,15 @@ * then we can pass the mechanism parameters as-is, otherwise we still * need to use the old way. */ - if (ep11_data->used_firmware_API_version <= 2) { + target_info = get_target_info(tokdata); + if (target_info == NULL) + return CKR_FUNCTION_FAILED; + + used_firmware_API_version = target_info->used_firmware_API_version; + + put_target_info(tokdata, target_info); + + if (used_firmware_API_version <= 2) { if (ecdh1_parms->kdf != CKD_NULL) { TRACE_ERROR("%s KDF for CKM_ECDH1_DERIVE not supported: %lu\n", __func__, ecdh1_parms->kdf); @@ -5036,6 +4968,14 @@ TRACE_ERROR("%s failedL hBaseKey=0x%lx\n", __func__, hBaseKey); return rc; } + rc = tokdata->policy->is_mech_allowed(tokdata->policy, mech_orig, + &base_key_obj->strength, + POLICY_CHECK_DERIVE, + session); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: derive key\n"); + goto error; + } if (!key_object_is_mechanism_allowed(base_key_obj->template, mech->mechanism)) { @@ -5130,14 +5070,16 @@ goto error; } + trace_attributes(__func__, "Derive:", new_attrs2, new_attrs2_len); + ep11_get_pin_blob(ep11_session, ep11_is_session_object(attrs, attrs_len), &ep11_pin_blob, &ep11_pin_blob_len); - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_DeriveKey(mech, new_attrs2, new_attrs2_len, keyblob, keyblobsize, NULL, 0, ep11_pin_blob, ep11_pin_blob_len, newblob, - &newblobsize, csum, &cslen, ep11_data->target); + &newblobsize, csum, &cslen, target_info->target); RETRY_END(rc, tokdata, session) if (rc != CKR_OK) { @@ -5163,6 +5105,13 @@ } opaque_attr = NULL; + rc = update_ep11_attrs_from_blob(tokdata, key_obj->template); + if (rc != CKR_OK) { + TRACE_ERROR("%s update_ep11_attrs_from_blob failed with rc=0x%lx\n", + __func__, rc); + goto error; + } + if (class == CKO_SECRET_KEY && cslen >= EP11_CSUMSIZE) { /* First 3 bytes of csum is the check value */ rc = build_attribute(CKA_CHECK_VALUE, csum, EP11_CSUMSIZE, &chk_attr); @@ -5182,7 +5131,8 @@ } /* key should be fully constructed. - * Assign an object handle and store key + * Assign an object handle and store key. + * Enforce policy. */ rc = object_mgr_create_final(tokdata, session, key_obj, handle); if (rc != CKR_OK) { @@ -5190,24 +5140,21 @@ goto error; } - if (allocated && ecpoint != NULL) - free(ecpoint); - - object_put(tokdata, base_key_obj, TRUE); - base_key_obj = NULL; - - return rc; + INC_COUNTER(tokdata, session, mech_orig, base_key_obj, + POLICY_STRENGTH_IDX_0); + goto out; error: if (key_obj) object_free(key_obj); *handle = 0; - if (new_attrs) - free_attribute_array(new_attrs, new_attrs_len); + out: if (opaque_attr != NULL) free(opaque_attr); if (chk_attr != NULL) free(chk_attr); + if (new_attrs) + free_attribute_array(new_attrs, new_attrs_len); if (new_attrs2) free_attribute_array(new_attrs2, new_attrs2_len); if (allocated && ecpoint != NULL) @@ -5231,7 +5178,6 @@ CK_ULONG ulPrivateKeyAttributeCount, CK_SESSION_HANDLE h) { - ep11_private_data_t *ep11_data = tokdata->private_data; CK_RV rc; CK_BYTE publblob[MAX_BLOBSIZE]; size_t publblobsize = sizeof(publblob); @@ -5411,6 +5357,11 @@ goto dh_generate_keypair_end; } + trace_attributes(__func__, "DH public key attributes:", + new_publ_attrs, new_publ_attrs_len); + trace_attributes(__func__, "DH private key attributes:", + new_priv_attrs, new_priv_attrs_len); + ep11_get_pin_blob(ep11_session, (ep11_is_session_object (pPublicKeyTemplate, ulPublicKeyAttributeCount) @@ -5418,13 +5369,13 @@ ulPrivateKeyAttributeCount)), &ep11_pin_blob, &ep11_pin_blob_len); - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_GenerateKeyPair(pMechanism, new_publ_attrs, new_publ_attrs_len, new_priv_attrs, new_priv_attrs_len, ep11_pin_blob, ep11_pin_blob_len, privblob, &privblobsize, - publblob, &publblobsize, ep11_data->target); + publblob, &publblobsize, target_info->target); RETRY_END(rc, tokdata, sess) if (rc != CKR_OK) { @@ -5543,7 +5494,6 @@ CK_ULONG ulPrivateKeyAttributeCount, CK_SESSION_HANDLE h) { - ep11_private_data_t *ep11_data = tokdata->private_data; CK_RV rc; CK_BYTE publblob[MAX_BLOBSIZE]; size_t publblobsize = sizeof(publblob); @@ -5657,7 +5607,7 @@ goto dsa_generate_keypair_end; } - rc = build_attribute(CKA_PRIME, sub_prime_attr->pValue, + rc = build_attribute(CKA_SUBPRIME, sub_prime_attr->pValue, sub_prime_attr->ulValueLen, &attr); if (rc != CKR_OK) { TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", __func__, rc); @@ -5745,6 +5695,11 @@ goto dsa_generate_keypair_end; } + trace_attributes(__func__, "DSA public key attributes:", + new_publ_attrs2, new_publ_attrs2_len); + trace_attributes(__func__, "DSA private key attributes:", + new_priv_attrs2, new_priv_attrs2_len); + ep11_get_pin_blob(ep11_session, (ep11_is_session_object (pPublicKeyTemplate, ulPublicKeyAttributeCount) @@ -5752,13 +5707,13 @@ ulPrivateKeyAttributeCount)), &ep11_pin_blob, &ep11_pin_blob_len); - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_GenerateKeyPair(pMechanism, new_publ_attrs2, new_publ_attrs2_len, new_priv_attrs2, new_priv_attrs2_len, ep11_pin_blob, ep11_pin_blob_len, privblob, &privblobsize, publblob, &publblobsize, - ep11_data->target); + target_info->target); RETRY_END(rc, tokdata, sess) if (rc != CKR_OK) { @@ -5866,7 +5821,6 @@ CK_ULONG ulPrivateKeyAttributeCount, CK_SESSION_HANDLE h) { - ep11_private_data_t *ep11_data = tokdata->private_data; CK_RV rc; CK_ATTRIBUTE *attr = NULL; CK_ATTRIBUTE *n_attr = NULL; @@ -5960,6 +5914,11 @@ new_ulPrivateKeyAttributeCount); } + trace_attributes(__func__, "RSA/EC public key attributes:", + new_publ_attrs2, new_publ_attrs2_len); + trace_attributes(__func__, "RSA/EC private key attributes:", + new_priv_attrs2, new_priv_attrs2_len); + ep11_get_pin_blob(ep11_session, (ep11_is_session_object (pPublicKeyTemplate, ulPublicKeyAttributeCount) @@ -5967,26 +5926,26 @@ ulPrivateKeyAttributeCount)), &ep11_pin_blob, &ep11_pin_blob_len); - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_GenerateKeyPair(pMechanism, new_publ_attrs2, new_publ_attrs2_len, new_priv_attrs2, new_priv_attrs2_len, ep11_pin_blob, ep11_pin_blob_len, privkey_blob, &privkey_blob_len, spki, - &spki_len, ep11_data->target); + &spki_len, target_info->target); RETRY_END(rc, tokdata, sess) if (rc != CKR_OK) { rc = ep11_error_to_pkcs11_error(rc, sess); TRACE_ERROR("%s m_GenerateKeyPair rc=0x%lx spki_len=0x%zx " "privkey_blob_len=0x%zx mech='%s'\n", __func__, rc, spki_len, privkey_blob_len, - ep11_get_ckm(pMechanism->mechanism)); + ep11_get_ckm(tokdata, pMechanism->mechanism)); goto error; } TRACE_INFO("%s m_GenerateKeyPair rc=0x%lx spki_len=0x%zx " "privkey_blob_len=0x%zx mech='%s'\n", __func__, rc, spki_len, privkey_blob_len, - ep11_get_ckm(pMechanism->mechanism)); + ep11_get_ckm(tokdata, pMechanism->mechanism)); if (spki_len > MAX_BLOBSIZE || privkey_blob_len > MAX_BLOBSIZE) { TRACE_ERROR("%s blobsize error\n", __func__); @@ -6225,7 +6184,6 @@ CK_ULONG ulPrivateKeyAttributeCount, CK_SESSION_HANDLE h) { - ep11_private_data_t *ep11_data = tokdata->private_data; CK_RV rc; CK_ATTRIBUTE *attr = NULL; CK_BYTE privkey_blob[MAX_BLOBSIZE]; @@ -6251,6 +6209,8 @@ CK_ULONG new_publ_attrs_len = 0, new_priv_attrs_len = 0; CK_ATTRIBUTE *new_publ_attrs2 = NULL, *new_priv_attrs2 = NULL; CK_ULONG new_publ_attrs2_len = 0, new_priv_attrs2_len = 0; + const CK_BYTE dilithium_oid[] = { 0x06, 0x0b, 0x2b, 0x06, 0x01, 0x04, 0x01, + 0x02, 0x82, 0x0b, 0x01, 0x06, 0x05 }; UNUSED(h); @@ -6275,6 +6235,24 @@ goto error; } + rc = add_to_attribute_array(&new_publ_attrs, &new_publ_attrs_len, + CKA_IBM_PQC_PARAMS, (CK_BYTE *)dilithium_oid, + sizeof(dilithium_oid)); + if (rc != CKR_OK) { + TRACE_ERROR("%s add_to_attribute_array failed with rc=0x%lx\n", + __func__, rc); + goto error; + } + + rc = add_to_attribute_array(&new_priv_attrs, &new_priv_attrs_len, + CKA_IBM_PQC_PARAMS,(CK_BYTE *)dilithium_oid, + sizeof(dilithium_oid)); + if (rc != CKR_OK) { + TRACE_ERROR("%s add_to_attribute_array failed with rc=0x%lx\n", + __func__, rc); + goto error; + } + rc = check_key_attributes(tokdata, ktype, CKO_PUBLIC_KEY, new_publ_attrs, new_publ_attrs_len, &new_publ_attrs2, &new_publ_attrs2_len, -1); @@ -6301,6 +6279,11 @@ new_ulPrivateKeyAttributeCount); } + trace_attributes(__func__, "Dilithium public key attributes:", + new_publ_attrs2, new_publ_attrs2_len); + trace_attributes(__func__, "Dilithium private key attributes:", + new_priv_attrs2, new_priv_attrs2_len); + ep11_get_pin_blob(ep11_session, (ep11_is_session_object (pPublicKeyTemplate, ulPublicKeyAttributeCount) @@ -6308,26 +6291,26 @@ ulPrivateKeyAttributeCount)), &ep11_pin_blob, &ep11_pin_blob_len); - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_GenerateKeyPair(pMechanism, new_publ_attrs2, new_publ_attrs2_len, new_priv_attrs2, new_priv_attrs2_len, ep11_pin_blob, ep11_pin_blob_len, privkey_blob, &privkey_blob_len, spki, - &spki_len, ep11_data->target); + &spki_len, target_info->target); RETRY_END(rc, tokdata, sess) if (rc != CKR_OK) { rc = ep11_error_to_pkcs11_error(rc, sess); TRACE_ERROR("%s m_GenerateKeyPair rc=0x%lx spki_len=0x%zx " "privkey_blob_len=0x%zx mech='%s'\n", __func__, rc, spki_len, privkey_blob_len, - ep11_get_ckm(pMechanism->mechanism)); + ep11_get_ckm(tokdata, pMechanism->mechanism)); goto error; } TRACE_INFO("%s m_GenerateKeyPair rc=0x%lx spki_len=0x%zx " "privkey_blob_len=0x%zx mech='%s'\n", __func__, rc, spki_len, privkey_blob_len, - ep11_get_ckm(pMechanism->mechanism)); + ep11_get_ckm(tokdata, pMechanism->mechanism)); if (spki_len > MAX_BLOBSIZE || privkey_blob_len > MAX_BLOBSIZE) { TRACE_ERROR("%s blobsize error\n", __func__); @@ -6553,7 +6536,7 @@ break; default: TRACE_ERROR("%s invalid mech %s\n", __func__, - ep11_get_ckm(pMechanism->mechanism)); + ep11_get_ckm(tokdata, pMechanism->mechanism)); rc = CKR_MECHANISM_INVALID; goto error; } @@ -6573,6 +6556,13 @@ (void *)public_key_obj, (void *)private_key_obj); } + rc = update_ep11_attrs_from_blob(tokdata, private_key_obj->template); + if (rc != CKR_OK) { + TRACE_ERROR("%s update_ep11_attrs_from_blob failed with rc=0x%lx\n", + __func__, rc); + goto error; + } + /* Copy CKA_MODULUS and CKA_PUBLIC_EXPONENT attributes from * public key object to private key object to fulfill PKCS#11 * private key template requirements @@ -6693,6 +6683,7 @@ goto error; } + /* Enforce policy */ rc = object_mgr_create_final(tokdata, sess, private_key_obj, phPrivateKey); if (rc != CKR_OK) { TRACE_DEVEL("%s Object mgr create final failed\n", __func__); @@ -6700,6 +6691,10 @@ public_key_obj = NULL; goto error; } + + INC_COUNTER(tokdata, sess, pMechanism, private_key_obj, + POLICY_STRENGTH_IDX_0); + return rc; error: @@ -6914,7 +6909,6 @@ CK_MECHANISM * mech, CK_BBOOL recover_mode, CK_OBJECT_HANDLE key) { - ep11_private_data_t *ep11_data = tokdata->private_data; CK_RV rc; size_t keyblobsize = 0; CK_BYTE *keyblob; @@ -6937,6 +6931,14 @@ free(ep11_sign_state); return rc; } + rc = tokdata->policy->is_mech_allowed(tokdata->policy, mech, + &key_obj->strength, + POLICY_CHECK_SIGNATURE, + session); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Sign init\n"); + goto done; + } if (!key_object_is_mechanism_allowed(key_obj->template, mech->mechanism)) { TRACE_ERROR("Mechanism not allwed per CKA_ALLOWED_MECHANISMS.\n"); @@ -6948,6 +6950,13 @@ rc = ep11tok_pkey_check(tokdata, session, key_obj, mech); switch (rc) { case CKR_OK: + /* + * Release obj lock, sign_mgr_init or ep11tok_sign_verify_init_ibm_ed + * may re-acquire the lock + */ + object_put(tokdata, key_obj, TRUE); + key_obj = NULL; + /* Note that Edwards curves in general are not yet supported in * opencryptoki. These two special IBM specific ED mechs are only * supported by the ep11token, so let's keep them local here. */ @@ -6956,7 +6965,9 @@ rc = ep11tok_sign_verify_init_ibm_ed(tokdata, session, ctx, mech, key, CK_TRUE); else - rc = sign_mgr_init(tokdata, session, ctx, mech, recover_mode, key); + /* Policy already checked. */ + rc = sign_mgr_init(tokdata, session, ctx, mech, recover_mode, key, + FALSE); if (rc == CKR_OK) ctx->pkey_active = TRUE; /* Regardless of the rc goto done here, because ep11tok_pkey_check @@ -6973,9 +6984,9 @@ goto done; } - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_SignInit(ep11_sign_state, &ep11_sign_state_l, - mech, keyblob, keyblobsize, ep11_data->target); + mech, keyblob, keyblobsize, target_info->target); RETRY_END(rc, tokdata, session) if (rc != CKR_OK) { @@ -6998,6 +7009,9 @@ } done: + if (rc == CKR_OK) + INC_COUNTER(tokdata, session, mech, key_obj, POLICY_STRENGTH_IDX_0); + object_put(tokdata, key_obj, TRUE); key_obj = NULL; @@ -7010,7 +7024,6 @@ CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG * sig_len) { - ep11_private_data_t *ep11_data = tokdata->private_data; CK_RV rc; SIGN_VERIFY_CONTEXT *ctx = &session->sign_ctx; size_t keyblobsize = 0; @@ -7029,17 +7042,22 @@ * opencryptoki. These two special IBM specific ED mechs are only * supported by the ep11token, so let's keep them local here. */ if (ctx->mech.mechanism == CKM_IBM_ED25519_SHA512 || - ctx->mech.mechanism == CKM_IBM_ED448_SHA3) + ctx->mech.mechanism == CKM_IBM_ED448_SHA3) { rc = pkey_ibm_ed_sign(key_obj, in_data, in_data_len, signature, sig_len); - else + } else { + /* Release obj lock, sign_mgr_sign may re-acquire the lock */ + object_put(tokdata, key_obj, TRUE); + key_obj = NULL; + rc = sign_mgr_sign(tokdata, session, length_only, ctx, in_data, in_data_len, signature, sig_len); + } goto done; /* no ep11 fallback possible */ } - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_Sign(ctx->context, ctx->context_len, in_data, in_data_len, - signature, sig_len, ep11_data->target); + signature, sig_len, target_info->target); RETRY_END(rc, tokdata, session) if (rc != CKR_OK) { @@ -7061,7 +7079,6 @@ CK_RV ep11tok_sign_update(STDLL_TokData_t * tokdata, SESSION * session, CK_BYTE * in_data, CK_ULONG in_data_len) { - ep11_private_data_t *ep11_data = tokdata->private_data; CK_RV rc; SIGN_VERIFY_CONTEXT *ctx = &session->sign_ctx; size_t keyblobsize = 0; @@ -7071,6 +7088,11 @@ if (!in_data || !in_data_len) return CKR_OK; + if (ctx->pkey_active) { + rc = sign_mgr_sign_update(tokdata, session, ctx, in_data, in_data_len); + goto done; /* no ep11 fallback possible */ + } + rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj, READ_LOCK); if (rc != CKR_OK) { @@ -7078,14 +7100,9 @@ return rc; } - if (ctx->pkey_active) { - rc = sign_mgr_sign_update(tokdata, session, ctx, in_data, in_data_len); - goto done; /* no ep11 fallback possible */ - } - - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_SignUpdate(ctx->context, ctx->context_len, in_data, - in_data_len, ep11_data->target); + in_data_len, target_info->target); RETRY_END(rc, tokdata, session) if (rc != CKR_OK) { @@ -7108,13 +7125,17 @@ CK_BBOOL length_only, CK_BYTE * signature, CK_ULONG * sig_len) { - ep11_private_data_t *ep11_data = tokdata->private_data; CK_RV rc; SIGN_VERIFY_CONTEXT *ctx = &session->sign_ctx; size_t keyblobsize = 0; CK_BYTE *keyblob; OBJECT *key_obj = NULL; + if (ctx->pkey_active) { + rc = sign_mgr_sign_final(tokdata, session, length_only, ctx, signature, sig_len); + goto done; /* no ep11 fallback possible */ + } + rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj, READ_LOCK); if (rc != CKR_OK) { @@ -7122,14 +7143,9 @@ return rc; } - if (ctx->pkey_active) { - rc = sign_mgr_sign_final(tokdata, session, length_only, ctx, signature, sig_len); - goto done; /* no ep11 fallback possible */ - } - - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_SignFinal(ctx->context, ctx->context_len, signature, sig_len, - ep11_data->target); + target_info->target); RETRY_END(rc, tokdata, session) if (rc != CKR_OK) { @@ -7157,9 +7173,6 @@ size_t keyblobsize = 0; CK_BYTE *keyblob; OBJECT *key_obj = NULL; - ep11_private_data_t *ep11_data = tokdata->private_data; - - UNUSED(length_only); rc = h_opaque_2_blob(tokdata, key, &keyblob, &keyblobsize, &key_obj, READ_LOCK); @@ -7167,6 +7180,14 @@ TRACE_ERROR("%s no blob rc=0x%lx\n", __func__, rc); return rc; } + rc = tokdata->policy->is_mech_allowed(tokdata->policy, mech, + &key_obj->strength, + POLICY_CHECK_SIGNATURE, + session); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Sign single\n"); + goto done; + } if (!key_object_is_mechanism_allowed(key_obj->template, mech->mechanism)) { TRACE_ERROR("Mechanism not allwed per CKA_ALLOWED_MECHANISMS.\n"); @@ -7174,9 +7195,9 @@ goto done; } - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_SignSingle(keyblob, keyblobsize, mech, in_data, in_data_len, - signature, sig_len, ep11_data->target); + signature, sig_len, target_info->target); RETRY_END(rc, tokdata, session) if (rc != CKR_OK) { rc = ep11_error_to_pkcs11_error(rc, session); @@ -7186,6 +7207,9 @@ } done: + if (rc == CKR_OK && length_only == FALSE) + INC_COUNTER(tokdata, session, mech, key_obj, POLICY_STRENGTH_IDX_0); + object_put(tokdata, key_obj, TRUE); key_obj = NULL; @@ -7197,7 +7221,6 @@ CK_MECHANISM * mech, CK_BBOOL recover_mode, CK_OBJECT_HANDLE key) { - ep11_private_data_t *ep11_data = tokdata->private_data; CK_RV rc; CK_BYTE *spki; size_t spki_len = 0; @@ -7217,6 +7240,14 @@ free(ep11_sign_state); return rc; } + rc = tokdata->policy->is_mech_allowed(tokdata->policy, mech, + &key_obj->strength, + POLICY_CHECK_VERIFY, + session); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Verify init\n"); + goto done; + } if (!key_object_is_mechanism_allowed(key_obj->template, mech->mechanism)) { TRACE_ERROR("Mechanism not allwed per CKA_ALLOWED_MECHANISMS.\n"); @@ -7241,6 +7272,13 @@ rc = ep11tok_pkey_check(tokdata, session, key_obj, mech); switch (rc) { case CKR_OK: + /* + * Release obj lock, verify_mgr_init or ep11tok_sign_verify_init_ibm_ed + * may re-acquire the lock + */ + object_put(tokdata, key_obj, TRUE); + key_obj = NULL; + /* Note that Edwards curves in general are not yet supported in * opencryptoki. These two special IBM specific ED mechs are only * supported by the ep11token, so let's keep them local here. */ @@ -7249,7 +7287,9 @@ rc = ep11tok_sign_verify_init_ibm_ed(tokdata, session, ctx, mech, key, CK_FALSE); else - rc = verify_mgr_init(tokdata, session, ctx, mech, CK_FALSE, key); + /* Policy already checked */ + rc = verify_mgr_init(tokdata, session, ctx, mech, CK_FALSE, key, + FALSE); if (rc == CKR_OK) ctx->pkey_active = TRUE; /* Regardless of the rc goto done here, because ep11tok_pkey_check @@ -7266,9 +7306,9 @@ goto done; } - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_VerifyInit(ep11_sign_state, &ep11_sign_state_l, mech, - spki, spki_len, ep11_data->target); + spki, spki_len, target_info->target); RETRY_END(rc, tokdata, session) if (rc != CKR_OK) { @@ -7290,6 +7330,9 @@ } done: + if (rc == CKR_OK) + INC_COUNTER(tokdata, session, mech, key_obj, POLICY_STRENGTH_IDX_0); + object_put(tokdata, key_obj, TRUE); key_obj = NULL; @@ -7301,7 +7344,6 @@ CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG sig_len) { - ep11_private_data_t *ep11_data = tokdata->private_data; CK_RV rc; SIGN_VERIFY_CONTEXT *ctx = &session->verify_ctx; size_t keyblobsize = 0; @@ -7320,18 +7362,23 @@ * opencryptoki. These two special IBM specific ED mechs are only * supported by the ep11token, so let's keep them local here. */ if (ctx->mech.mechanism == CKM_IBM_ED25519_SHA512 || - ctx->mech.mechanism == CKM_IBM_ED448_SHA3) + ctx->mech.mechanism == CKM_IBM_ED448_SHA3) { rc = pkey_ibm_ed_verify(key_obj, in_data, in_data_len, signature, sig_len); - else + } else { + /* Release obj lock, verify_mgr_verify may re-acquire the lock */ + object_put(tokdata, key_obj, TRUE); + key_obj = NULL; + rc = verify_mgr_verify(tokdata, session, ctx, in_data, in_data_len, signature, sig_len); + } goto done; /* no ep11 fallback possible */ } - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_Verify(ctx->context, ctx->context_len, in_data, in_data_len, - signature, sig_len, ep11_data->target); + signature, sig_len, target_info->target); RETRY_END(rc, tokdata, session) if (rc != CKR_OK) { @@ -7353,7 +7400,6 @@ CK_RV ep11tok_verify_update(STDLL_TokData_t * tokdata, SESSION * session, CK_BYTE * in_data, CK_ULONG in_data_len) { - ep11_private_data_t *ep11_data = tokdata->private_data; CK_RV rc; SIGN_VERIFY_CONTEXT *ctx = &session->verify_ctx; size_t keyblobsize = 0; @@ -7363,6 +7409,11 @@ if (!in_data || !in_data_len) return CKR_OK; + if (ctx->pkey_active) { + rc = verify_mgr_verify_update(tokdata, session, ctx, in_data, in_data_len); + goto done; /* no ep11 fallback possible */ + } + rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj, READ_LOCK); if (rc != CKR_OK) { @@ -7370,14 +7421,9 @@ return rc; } - if (ctx->pkey_active) { - rc = verify_mgr_verify_update(tokdata, session, ctx, in_data, in_data_len); - goto done; /* no ep11 fallback possible */ - } - - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_VerifyUpdate(ctx->context, ctx->context_len, in_data, - in_data_len, ep11_data->target); + in_data_len, target_info->target); RETRY_END(rc, tokdata, session) if (rc != CKR_OK) { @@ -7399,13 +7445,17 @@ CK_RV ep11tok_verify_final(STDLL_TokData_t * tokdata, SESSION * session, CK_BYTE * signature, CK_ULONG sig_len) { - ep11_private_data_t *ep11_data = tokdata->private_data; CK_RV rc; SIGN_VERIFY_CONTEXT *ctx = &session->verify_ctx; size_t keyblobsize = 0; CK_BYTE *keyblob; OBJECT *key_obj = NULL; + if (ctx->pkey_active) { + rc = verify_mgr_verify_final(tokdata, session, ctx, signature, sig_len); + goto done; /* no ep11 fallback possible */ + } + rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj, READ_LOCK); if (rc != CKR_OK) { @@ -7413,14 +7463,9 @@ return rc; } - if (ctx->pkey_active) { - rc = verify_mgr_verify_final(tokdata, session, ctx, signature, sig_len); - goto done; /* no ep11 fallback possible */ - } - - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_VerifyFinal(ctx->context, ctx->context_len, signature, - sig_len, ep11_data->target); + sig_len, target_info->target); RETRY_END(rc, tokdata, session) if (rc != CKR_OK) { @@ -7447,13 +7492,20 @@ CK_BYTE *spki; size_t spki_len = 0; OBJECT *key_obj = NULL; - ep11_private_data_t *ep11_data = tokdata->private_data; rc = h_opaque_2_blob(tokdata, key, &spki, &spki_len, &key_obj, READ_LOCK); if (rc != CKR_OK) { TRACE_ERROR("%s no blob rc=0x%lx\n", __func__, rc); return rc; } + rc = tokdata->policy->is_mech_allowed(tokdata->policy, mech, + &key_obj->strength, + POLICY_CHECK_VERIFY, + session); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Verify single\n"); + goto done; + } if (!key_object_is_mechanism_allowed(key_obj->template, mech->mechanism)) { TRACE_ERROR("Mechanism not allwed per CKA_ALLOWED_MECHANISMS.\n"); @@ -7471,9 +7523,9 @@ goto done; } - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_VerifySingle(spki, spki_len, mech, in_data, in_data_len, - signature, sig_len, ep11_data->target); + signature, sig_len, target_info->target); RETRY_END(rc, tokdata, session) if (rc != CKR_OK) { rc = ep11_error_to_pkcs11_error(rc, session); @@ -7483,6 +7535,9 @@ } done: + if (rc == CKR_OK || rc == CKR_SIGNATURE_INVALID) + INC_COUNTER(tokdata, session, mech, key_obj, POLICY_STRENGTH_IDX_0); + object_put(tokdata, key_obj, TRUE); key_obj = NULL; @@ -7493,7 +7548,6 @@ CK_BYTE_PTR output_part, CK_ULONG_PTR p_output_part_len) { - ep11_private_data_t *ep11_data = tokdata->private_data; CK_RV rc = CKR_OK; ENCR_DECR_CONTEXT *ctx = &session->decr_ctx; CK_BBOOL length_only = (output_part == NULL ? CK_TRUE : CK_FALSE); @@ -7501,6 +7555,12 @@ CK_BYTE *keyblob; OBJECT *key_obj = NULL; + if (ctx->pkey_active) { + rc = decr_mgr_decrypt_final(tokdata, session, length_only, + ctx, output_part, p_output_part_len); + goto done; /* no ep11 fallback possible */ + } + rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj, READ_LOCK); if (rc != CKR_OK) { @@ -7508,16 +7568,10 @@ return rc; } - if (ctx->pkey_active) { - rc = decr_mgr_decrypt_final(tokdata, session, length_only, - ctx, output_part, p_output_part_len); - goto done; /* no ep11 fallback possible */ - } - - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_DecryptFinal(ctx->context, ctx->context_len, output_part, p_output_part_len, - ep11_data->target); + target_info->target); RETRY_END(rc, tokdata, session) if (rc != CKR_OK) { @@ -7540,7 +7594,6 @@ CK_BYTE_PTR input_data, CK_ULONG input_data_len, CK_BYTE_PTR output_data, CK_ULONG_PTR p_output_data_len) { - ep11_private_data_t *ep11_data = tokdata->private_data; CK_RV rc = CKR_OK; ENCR_DECR_CONTEXT *ctx = &session->decr_ctx; CK_BBOOL length_only = (output_data == NULL ? CK_TRUE : CK_FALSE); @@ -7548,13 +7601,6 @@ CK_BYTE *keyblob; OBJECT *key_obj = NULL; - rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj, - READ_LOCK); - if (rc != CKR_OK) { - TRACE_ERROR("%s h_opaque_2_blob, rc=0x%lx\n", __func__, rc); - return rc; - } - if (ctx->pkey_active) { rc = decr_mgr_decrypt(tokdata, session, length_only, ctx, input_data, input_data_len, output_data, @@ -7562,10 +7608,17 @@ goto done; /* no ep11 fallback possible */ } - RETRY_START + rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj, + READ_LOCK); + if (rc != CKR_OK) { + TRACE_ERROR("%s h_opaque_2_blob, rc=0x%lx\n", __func__, rc); + return rc; + } + + RETRY_START(rc, tokdata) rc = dll_m_Decrypt(ctx->context, ctx->context_len, input_data, input_data_len, output_data, p_output_data_len, - ep11_data->target); + target_info->target); RETRY_END(rc, tokdata, session) if (rc != CKR_OK) { @@ -7589,7 +7642,6 @@ CK_BYTE_PTR output_part, CK_ULONG_PTR p_output_part_len) { - ep11_private_data_t *ep11_data = tokdata->private_data; CK_RV rc = CKR_OK; ENCR_DECR_CONTEXT *ctx = &session->decr_ctx; CK_BBOOL length_only = (output_part == NULL ? CK_TRUE : CK_FALSE); @@ -7602,13 +7654,6 @@ return CKR_OK; /* nothing to update, keep context */ } - rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj, - READ_LOCK); - if (rc != CKR_OK) { - TRACE_ERROR("%s h_opaque_2_blob, rc=0x%lx\n", __func__, rc); - return rc; - } - if (ctx->pkey_active) { rc = decr_mgr_decrypt_update(tokdata, session, length_only, ctx, input_part, input_part_len, @@ -7616,10 +7661,17 @@ goto done; /* no ep11 fallback possible */ } - RETRY_START + rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj, + READ_LOCK); + if (rc != CKR_OK) { + TRACE_ERROR("%s h_opaque_2_blob, rc=0x%lx\n", __func__, rc); + return rc; + } + + RETRY_START(rc, tokdata) rc = dll_m_DecryptUpdate(ctx->context, ctx->context_len, input_part, input_part_len, output_part, - p_output_part_len, ep11_data->target); + p_output_part_len, target_info->target); RETRY_END(rc, tokdata, session) if (rc != CKR_OK) { @@ -7647,9 +7699,6 @@ size_t keyblobsize = 0; CK_BYTE *keyblob; OBJECT *key_obj = NULL; - ep11_private_data_t *ep11_data = tokdata->private_data; - - UNUSED(length_only); rc = h_opaque_2_blob(tokdata, key, &keyblob, &keyblobsize, &key_obj, READ_LOCK); @@ -7663,11 +7712,19 @@ rc = CKR_MECHANISM_INVALID; goto done; } + rc = tokdata->policy->is_mech_allowed(tokdata->policy, mech, + &key_obj->strength, + POLICY_CHECK_DECRYPT, + session); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY_VIOLATION on decrypt single\n"); + goto done; + } - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_DecryptSingle(keyblob, keyblobsize, mech, input_data, input_data_len, output_data, p_output_data_len, - ep11_data->target); + target_info->target); RETRY_END(rc, tokdata, session) if (rc != CKR_OK) { rc = ep11_error_to_pkcs11_error(rc, session); @@ -7676,6 +7733,9 @@ TRACE_INFO("%s rc=0x%lx\n", __func__, rc); } + if (rc == CKR_OK && length_only == FALSE) + INC_COUNTER(tokdata, session, mech, key_obj, POLICY_STRENGTH_IDX_0); + done: object_put(tokdata, key_obj, TRUE); key_obj = NULL; @@ -7687,7 +7747,6 @@ CK_BYTE_PTR output_part, CK_ULONG_PTR p_output_part_len) { - ep11_private_data_t *ep11_data = tokdata->private_data; CK_RV rc = CKR_OK; ENCR_DECR_CONTEXT *ctx = &session->encr_ctx; CK_BBOOL length_only = (output_part == NULL ? CK_TRUE : CK_FALSE); @@ -7695,6 +7754,12 @@ CK_BYTE *keyblob; OBJECT *key_obj = NULL; + if (ctx->pkey_active) { + rc = encr_mgr_encrypt_final(tokdata, session, length_only, + ctx, output_part, p_output_part_len); + goto done; /* no ep11 fallback possible */ + } + rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj, READ_LOCK); if (rc != CKR_OK) { @@ -7702,16 +7767,10 @@ return rc; } - if (ctx->pkey_active) { - rc = encr_mgr_encrypt_final(tokdata, session, length_only, - ctx, output_part, p_output_part_len); - goto done; /* no ep11 fallback possible */ - } - - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_EncryptFinal(ctx->context, ctx->context_len, output_part, p_output_part_len, - ep11_data->target); + target_info->target); RETRY_END(rc, tokdata, session) if (rc != CKR_OK) { @@ -7734,7 +7793,6 @@ CK_BYTE_PTR input_data, CK_ULONG input_data_len, CK_BYTE_PTR output_data, CK_ULONG_PTR p_output_data_len) { - ep11_private_data_t *ep11_data = tokdata->private_data; CK_RV rc = CKR_OK; ENCR_DECR_CONTEXT *ctx = &session->encr_ctx; CK_BBOOL length_only = (output_data == NULL ? CK_TRUE : CK_FALSE); @@ -7742,13 +7800,6 @@ CK_BYTE *keyblob; OBJECT *key_obj = NULL; - rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj, - READ_LOCK); - if (rc != CKR_OK) { - TRACE_ERROR("%s h_opaque_2_blob, rc=0x%lx\n", __func__, rc); - return rc; - } - if (ctx->pkey_active) { rc = encr_mgr_encrypt(tokdata, session, length_only, ctx, input_data, input_data_len, output_data, @@ -7756,10 +7807,17 @@ goto done; /* no ep11 fallback possible */ } - RETRY_START + rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj, + READ_LOCK); + if (rc != CKR_OK) { + TRACE_ERROR("%s h_opaque_2_blob, rc=0x%lx\n", __func__, rc); + return rc; + } + + RETRY_START(rc, tokdata) rc = dll_m_Encrypt(ctx->context, ctx->context_len, input_data, input_data_len, output_data, p_output_data_len, - ep11_data->target); + target_info->target); RETRY_END(rc, tokdata, session) if (rc != CKR_OK) { @@ -7783,7 +7841,6 @@ CK_BYTE_PTR output_part, CK_ULONG_PTR p_output_part_len) { - ep11_private_data_t *ep11_data = tokdata->private_data; CK_RV rc = CKR_OK; ENCR_DECR_CONTEXT *ctx = &session->encr_ctx; CK_BBOOL length_only = (output_part == NULL ? CK_TRUE : CK_FALSE); @@ -7796,13 +7853,6 @@ return CKR_OK; /* nothing to update, keep context */ } - rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj, - READ_LOCK); - if (rc != CKR_OK) { - TRACE_ERROR("%s h_opaque_2_blob, rc=0x%lx\n", __func__, rc); - return rc; - } - if (ctx->pkey_active) { rc = encr_mgr_encrypt_update(tokdata, session, length_only, ctx, input_part, input_part_len, output_part, @@ -7810,10 +7860,17 @@ goto done; /* no ep11 fallback possible */ } - RETRY_START + rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj, + READ_LOCK); + if (rc != CKR_OK) { + TRACE_ERROR("%s h_opaque_2_blob, rc=0x%lx\n", __func__, rc); + return rc; + } + + RETRY_START(rc, tokdata) rc = dll_m_EncryptUpdate(ctx->context, ctx->context_len, input_part, input_part_len, output_part, - p_output_part_len, ep11_data->target); + p_output_part_len, target_info->target); RETRY_END(rc, tokdata, session) if (rc != CKR_OK) { @@ -7841,9 +7898,6 @@ size_t keyblobsize = 0; CK_BYTE *keyblob; OBJECT *key_obj = NULL; - ep11_private_data_t *ep11_data = tokdata->private_data; - - UNUSED(length_only); rc = h_opaque_2_blob(tokdata, key, &keyblob, &keyblobsize, &key_obj, READ_LOCK); @@ -7857,6 +7911,14 @@ rc = CKR_MECHANISM_INVALID; goto done; } + rc = tokdata->policy->is_mech_allowed(tokdata->policy, mech, + &key_obj->strength, + POLICY_CHECK_ENCRYPT, + session); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY_VIOLATION on encrypt single\n"); + goto done; + } /* * Enforce key usage restrictions. EP11 does not allow to restrict @@ -7869,10 +7931,10 @@ goto done; } - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_EncryptSingle(keyblob, keyblobsize, mech, input_data, input_data_len, output_data, p_output_data_len, - ep11_data->target); + target_info->target); RETRY_END(rc, tokdata, session) if (rc != CKR_OK) { rc = ep11_error_to_pkcs11_error(rc, session); @@ -7881,6 +7943,9 @@ TRACE_INFO("%s rc=0x%lx\n", __func__, rc); } + if (rc == CKR_OK && length_only == FALSE) + INC_COUNTER(tokdata, session, mech, key_obj, POLICY_STRENGTH_IDX_0); + done: object_put(tokdata, key_obj, TRUE); key_obj = NULL; @@ -7892,7 +7957,6 @@ CK_MECHANISM_PTR mech, CK_OBJECT_HANDLE key, int op) { - ep11_private_data_t *ep11_data = tokdata->private_data; CK_RV rc = CKR_OK; CK_BYTE *blob; size_t blob_len = 0; @@ -7917,16 +7981,31 @@ rc = CKR_MECHANISM_INVALID; goto error; } + rc = tokdata->policy->is_mech_allowed(tokdata->policy, mech, + &key_obj->strength, + op == DECRYPT ? POLICY_CHECK_DECRYPT : + POLICY_CHECK_ENCRYPT, + session); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY_VIOLATION on encrypt/decrypt initialization\n"); + goto error; + } rc = ep11tok_pkey_check(tokdata, session, key_obj, mech); switch (rc) { case CKR_OK: + /* Release obj lock, encr/decr_mgr_init may re-acquire the lock */ + object_put(tokdata, key_obj, TRUE); + key_obj = NULL; + if (op == DECRYPT) { + /* Policy already checked */ rc = decr_mgr_init(tokdata, session, &session->decr_ctx, - OP_DECRYPT_INIT, mech, key); + OP_DECRYPT_INIT, mech, key, FALSE); } else { + /* Policy already checked */ rc = encr_mgr_init(tokdata, session, &session->encr_ctx, - OP_ENCRYPT_INIT, mech, key); + OP_ENCRYPT_INIT, mech, key, FALSE); } if (rc == CKR_OK) { if (op == DECRYPT) @@ -7951,9 +8030,9 @@ if (op == DECRYPT) { ENCR_DECR_CONTEXT *ctx = &session->decr_ctx; - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_DecryptInit(ep11_state, &ep11_state_l, mech, blob, - blob_len, ep11_data->target); + blob_len, target_info->target); RETRY_END(rc, tokdata, session) ctx->key = key; ctx->active = TRUE; @@ -7961,7 +8040,7 @@ ctx->context_len = ep11_state_l; ctx->pkey_active = FALSE; if (rc != CKR_OK) { - decr_mgr_cleanup(ctx); + decr_mgr_cleanup(tokdata, session, ctx); rc = ep11_error_to_pkcs11_error(rc, session); TRACE_ERROR("%s m_DecryptInit rc=0x%lx blob_len=0x%zx " "mech=0x%lx\n", __func__, rc, blob_len, @@ -7984,9 +8063,9 @@ goto error; } - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_EncryptInit(ep11_state, &ep11_state_l, mech, blob, - blob_len, ep11_data->target); + blob_len, target_info->target); RETRY_END(rc, tokdata, session) ctx->key = key; ctx->active = TRUE; @@ -7994,7 +8073,7 @@ ctx->context_len = ep11_state_l; ctx->pkey_active = FALSE; if (rc != CKR_OK) { - encr_mgr_cleanup(ctx); + encr_mgr_cleanup(tokdata, session, ctx); rc = ep11_error_to_pkcs11_error(rc, session); TRACE_ERROR("%s m_EncryptInit rc=0x%lx blob_len=0x%zx " "mech=0x%lx\n", __func__, rc, blob_len, @@ -8006,6 +8085,9 @@ } done: + if (rc == CKR_OK) + INC_COUNTER(tokdata, session, mech, key_obj, POLICY_STRENGTH_IDX_0); + object_put(tokdata, key_obj, TRUE); key_obj = NULL; @@ -8064,7 +8146,6 @@ CK_OBJECT_HANDLE key, CK_BYTE_PTR wrapped_key, CK_ULONG_PTR p_wrapped_key_len) { - ep11_private_data_t *ep11_data = tokdata->private_data; CK_RV rc; CK_BYTE *wrapping_blob; size_t wrapping_blob_len; @@ -8120,7 +8201,19 @@ free(wrapped_key); goto done; } - + rc = tokdata->policy->is_mech_allowed(tokdata->policy, mech, + &wrap_key_obj->strength, + POLICY_CHECK_WRAP, session); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: key wrap\n"); + goto done; + } + rc = tokdata->policy->is_key_allowed(tokdata->policy, &key_obj->strength, + session); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: key wrap\n"); + goto done; + } if (!key_object_wrap_template_matches(wrap_key_obj->template, key_obj->template)) { TRACE_ERROR("Wrap template does not match.\n"); @@ -8131,7 +8224,7 @@ } rc = check_ab_wrap(tokdata, &sign_blob, &sign_blob_len, &sobj, - key_obj, wrap_key_obj, mech); + key_obj, wrap_key_obj, mech, session); if (rc != CKR_OK) { TRACE_ERROR("AB wrapping check failed (rc=0x%lx).\n", rc); goto done; @@ -8164,11 +8257,11 @@ * (wrapping blob). The wrapped key can be processed by any PKCS11 * implementation. */ - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_WrapKey(wrap_target_blob, wrap_target_blob_len, wrapping_blob, wrapping_blob_len, sign_blob, sign_blob_len, mech, - wrapped_key, p_wrapped_key_len, ep11_data->target); + wrapped_key, p_wrapped_key_len, target_info->target); RETRY_END(rc, tokdata, session) if (rc != CKR_OK) { @@ -8182,6 +8275,10 @@ free(wrapped_key); done: + if (rc == CKR_OK && !size_query) + INC_COUNTER(tokdata, session, mech, wrap_key_obj, + POLICY_STRENGTH_IDX_0); + object_put(tokdata, wrap_key_obj, TRUE); wrap_key_obj = NULL; object_put(tokdata, key_obj, TRUE); @@ -8200,7 +8297,6 @@ CK_OBJECT_HANDLE wrapping_key, CK_OBJECT_HANDLE_PTR p_key) { - ep11_private_data_t *ep11_data = tokdata->private_data; CK_RV rc; CK_BYTE *wrapping_blob, *temp; size_t wrapping_blob_len; @@ -8235,6 +8331,13 @@ __func__, rc); return rc; } + rc = tokdata->policy->is_mech_allowed(tokdata->policy, mech, + &kobj->strength, + POLICY_CHECK_UNWRAP, session); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: key unwrap\n"); + goto done; + } TRACE_DEVEL("%s start unwrapKey: mech=0x%lx attrs_len=0x%lx " "wr_key=0x%lx\n", __func__, mech->mechanism, attrs_len, @@ -8263,7 +8366,7 @@ goto error; } rc = check_ab_unwrap(tokdata, &verifyblob, &verifyblobsize, &vobj, kobj, - attrs, attrs_len, mech, &isab); + attrs, attrs_len, mech, &isab, session); if (rc != CKR_OK) { TRACE_ERROR("check_ab_unwrap failed with rc=0x%08lx\n", rc); goto error; @@ -8354,19 +8457,21 @@ goto error; } + trace_attributes(__func__, "Unwrap:", new_attrs2, new_attrs2_len); + ep11_get_pin_blob(ep11_session, ep11_is_session_object(attrs, attrs_len), &ep11_pin_blob, &ep11_pin_blob_len); /* we need a blob for the new key created by unwrapping, * the wrapped key comes in BER */ - RETRY_START + RETRY_START(rc, tokdata) rc = dll_m_UnwrapKey(wrapped_key, wrapped_key_len, wrapping_blob, wrapping_blob_len, verifyblob, verifyblobsize, ep11_pin_blob, ep11_pin_blob_len, mech, new_attrs2, new_attrs2_len, keyblob, &keyblobsize, csum, &cslen, - ep11_data->target); + target_info->target); RETRY_END(rc, tokdata, session) if (rc != CKR_OK) { @@ -8378,8 +8483,6 @@ TRACE_INFO("%s m_UnwrapKey rc=0x%lx blobsize=0x%zx mech=0x%lx\n", __func__, rc, keyblobsize, mech->mechanism); - - rc = build_attribute(CKA_IBM_OPAQUE, keyblob, keyblobsize, &attr); if (rc != CKR_OK) { TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", __func__, rc); @@ -8399,10 +8502,17 @@ *(CK_KEY_TYPE *) keytype_attr->pValue); if (rc != CKR_OK) { TRACE_ERROR("ab_unwrap_update_template failed with rc=0x%08lx\n", rc); - return rc; + goto error; } } + rc = update_ep11_attrs_from_blob(tokdata, key_obj->template); + if (rc != CKR_OK) { + TRACE_ERROR("%s update_ep11_attrs_from_blob failed with rc=0x%lx\n", + __func__, rc); + goto error; + } + switch (*(CK_OBJECT_CLASS *) cla_attr->pValue) { case CKO_SECRET_KEY: /* card provides bit length in csum last 4 bytes big endian */ @@ -8509,6 +8619,7 @@ /* key should be fully constructed. * Assign an object handle and store key. + * Enforce policy. */ rc = object_mgr_create_final(tokdata, session, key_obj, p_key); if (rc != CKR_OK) { @@ -8516,6 +8627,8 @@ goto error; } + INC_COUNTER(tokdata, session, mech, kobj, POLICY_STRENGTH_IDX_0); + goto done; error: @@ -8616,12 +8729,31 @@ CKM_SHA512_RSA_PKCS_PSS, CKM_SHA_1, CKM_SHA_1_HMAC, + CKM_GENERIC_SECRET_KEY_GEN, CKM_IBM_ATTRIBUTEBOUND_WRAP, }; static const CK_ULONG supported_mech_list_len = (sizeof(ep11_supported_mech_list) / sizeof(CK_MECHANISM_TYPE)); +/* Note: Do not move this function inside + ep11tok_is_mechanism_supported since that would introduce an + endless loop. Also do not use it in ep11tok_get_mechanism_info for + the same reason. */ +static CK_RV ep11tok_check_policy_for_mech(STDLL_TokData_t *tokdata, + CK_MECHANISM_TYPE mech, + CK_MECHANISM_INFO_PTR pinfo) +{ + CK_RV rc; + + if (tokdata->policy->active == CK_FALSE) + return CKR_OK; + rc = ep11tok_get_mechanism_info(tokdata, mech, pinfo); + if (rc != CKR_OK) + return rc; + return tokdata->policy->update_mech_info(tokdata->policy, mech, pinfo); +} + /* filtering out some mechanisms we do not want to provide * makes it complicated */ @@ -8629,21 +8761,27 @@ CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount) { - ep11_private_data_t *ep11_data = tokdata->private_data; CK_RV rc = 0; CK_ULONG counter = 0, size = 0; CK_MECHANISM_TYPE_PTR mlist = NULL; + CK_MECHANISM_TYPE_PTR tmp; CK_ULONG i; + ep11_target_info_t* target_info; + CK_MECHANISM_INFO info; - /* size querry */ + target_info = get_target_info(tokdata); + if (target_info == NULL) + return CKR_FUNCTION_FAILED; + + /* size query */ if (pMechanismList == NULL) { rc = dll_m_GetMechanismList(0, pMechanismList, pulCount, - ep11_data->target); + target_info->target); if (rc != CKR_OK) { rc = ep11_error_to_pkcs11_error(rc, NULL); TRACE_ERROR("%s bad rc=0x%lx from m_GetMechanismList() #1\n", __func__, rc); - return rc; + goto out; } /* adjust the size according to the ban list, @@ -8661,29 +8799,37 @@ * larger list. */ do { - mlist = (CK_MECHANISM_TYPE *) malloc( + tmp = (CK_MECHANISM_TYPE *) realloc(mlist, sizeof(CK_MECHANISM_TYPE) * counter); - if (!mlist) { + if (!tmp) { TRACE_ERROR("%s Memory allocation failed\n", __func__); - return CKR_HOST_MEMORY; + rc = CKR_HOST_MEMORY; + goto out; } - rc = dll_m_GetMechanismList(0, mlist, &counter, ep11_data->target); + mlist = tmp; + rc = dll_m_GetMechanismList(0, mlist, &counter, target_info->target); if (rc != CKR_OK) { rc = ep11_error_to_pkcs11_error(rc, NULL); TRACE_ERROR("%s bad rc=0x%lx from m_GetMechanismList() #2\n", __func__, rc); - free(mlist); if (rc != CKR_BUFFER_TOO_SMALL) - return rc; + goto out; } } while (rc == CKR_BUFFER_TOO_SMALL); for (i = 0; i < counter; i++) { - if (ep11tok_is_mechanism_supported(tokdata, mlist[i]) != CKR_OK) { + if (mlist[i] == CKM_IBM_CPACF_WRAP) { + /* Internal mechanisms should not be exposed. */ + *pulCount = *pulCount - 1; + } else if (ep11tok_is_mechanism_supported(tokdata, mlist[i]) != CKR_OK) { /* banned mech found, * decrement reported list size */ *pulCount = *pulCount - 1; + } else if (ep11tok_check_policy_for_mech(tokdata, mlist[i], &info) != + CKR_OK) { + TRACE_DEVEL("Policy blocks mechanism 0x%lx!\n", mlist[i]); + *pulCount -= 1; } } } else { @@ -8694,12 +8840,12 @@ * that comes as parameter, this is a 'reduced size', * ep11 would complain about insufficient list size */ - rc = dll_m_GetMechanismList(0, mlist, &counter, ep11_data->target); + rc = dll_m_GetMechanismList(0, mlist, &counter, target_info->target); if (rc != CKR_OK) { rc = ep11_error_to_pkcs11_error(rc, NULL); TRACE_ERROR("%s bad rc=0x%lx from m_GetMechanismList() #3\n", __func__, rc); - return rc; + goto out; } /* @@ -8712,31 +8858,40 @@ * larger list. */ do { - mlist = (CK_MECHANISM_TYPE *) malloc( + tmp = (CK_MECHANISM_TYPE *) realloc(mlist, sizeof(CK_MECHANISM_TYPE) * counter); - if (!mlist) { + if (!tmp) { TRACE_ERROR("%s Memory allocation failed\n", __func__); - return CKR_HOST_MEMORY; + rc = CKR_HOST_MEMORY; + goto out; } + mlist = tmp; /* all the card has */ - rc = dll_m_GetMechanismList(0, mlist, &counter, ep11_data->target); + rc = dll_m_GetMechanismList(0, mlist, &counter, target_info->target); if (rc != CKR_OK) { rc = ep11_error_to_pkcs11_error(rc, NULL); TRACE_ERROR("%s bad rc=0x%lx from m_GetMechanismList() #4\n", __func__, rc); - free(mlist); if (rc != CKR_BUFFER_TOO_SMALL) - return rc; + goto out; } } while (rc == CKR_BUFFER_TOO_SMALL); for (i = 0; i < counter; i++) TRACE_INFO("%s raw mech list entry '%s'\n", - __func__, ep11_get_ckm(mlist[i])); + __func__, ep11_get_ckm(tokdata, mlist[i])); /* copy only mechanisms not banned */ *pulCount = 0; for (i = 0; i < counter; i++) { + if (mlist[i] == CKM_IBM_CPACF_WRAP) + /* Internal mechanisms should not be exposed. */ + continue; + if (ep11tok_check_policy_for_mech(tokdata, mlist[i], &info) != + CKR_OK) { + TRACE_DEVEL("Policy blocks mechanism 0x%lx!\n", mlist[i]); + continue; + } if (ep11tok_is_mechanism_supported(tokdata, mlist[i]) == CKR_OK) { if (*pulCount < size) pMechanismList[*pulCount] = mlist[i]; @@ -8747,8 +8902,10 @@ rc = CKR_BUFFER_TOO_SMALL; } +out: if (mlist) free(mlist); + put_target_info(tokdata, target_info); return rc; } @@ -8762,6 +8919,8 @@ CK_BBOOL found = FALSE; CK_ULONG i; int status; + CK_RV rc = CKR_OK; + ep11_target_info_t* target_info; for (i = 0; i < supported_mech_list_len; i++) { if (type == ep11_supported_mech_list[i]) { @@ -8772,17 +8931,22 @@ if (!found) { TRACE_INFO("%s Mech '%s' not suppported\n", __func__, - ep11_get_ckm(type)); + ep11_get_ckm(tokdata, type)); return CKR_MECHANISM_INVALID; } - if (check_cps_for_mechanism(ep11_data->cp_config, - type, ep11_data->control_points, - ep11_data->control_points_len, - ep11_data->max_control_point_index) != CKR_OK) { + target_info = get_target_info(tokdata); + if (target_info == NULL) + return CKR_FUNCTION_FAILED; + + if (check_cps_for_mechanism(tokdata, ep11_data->cp_config, + type, target_info->control_points, + target_info->control_points_len, + target_info->max_control_point_index) != CKR_OK) { TRACE_INFO("%s Mech '%s' banned due to control point\n", - __func__, ep11_get_ckm(type)); - return CKR_MECHANISM_INVALID; + __func__, ep11_get_ckm(tokdata, type)); + rc = CKR_MECHANISM_INVALID; + goto out; } switch(type) { @@ -8811,15 +8975,27 @@ NUM_HMAC_REQ); if (status == -1) { TRACE_INFO("%s Mech '%s' banned due to mixed firmware versions\n", - __func__, ep11_get_ckm(type)); - return CKR_MECHANISM_INVALID; + __func__, ep11_get_ckm(tokdata, type)); + rc = CKR_MECHANISM_INVALID; + goto out; } break; case CKM_RSA_PKCS_OAEP: /* CKM_RSA_PKCS_OAEP is not supported with EP11 host library <= 1.3 */ - if (compare_ck_version(&ep11_data->ep11_lib_version, &ver1_3) <= 0) - return CKR_MECHANISM_INVALID; + if (compare_ck_version(&ep11_data->ep11_lib_version, &ver1_3) <= 0) { + rc = CKR_MECHANISM_INVALID; + goto out; + } + + status = check_required_versions(tokdata, oaep_req_versions, + NUM_OAEP_REQ); + if (status != 1) { + TRACE_INFO("%s Mech '%s' banned due to mixed firmware versions\n", + __func__, ep11_get_ckm(tokdata, type)); + rc = CKR_MECHANISM_INVALID; + goto out; + } break; case CKM_IBM_SHA3_224: @@ -8834,8 +9010,9 @@ NUM_IBM_SHA3_REQ); if (status != 1) { TRACE_INFO("%s Mech '%s' banned due to mixed firmware versions\n", - __func__, ep11_get_ckm(type)); - return CKR_MECHANISM_INVALID; + __func__, ep11_get_ckm(tokdata, type)); + rc = CKR_MECHANISM_INVALID; + goto out; } break; @@ -8847,8 +9024,9 @@ NUM_CMAC_REQ); if (status != 1) { TRACE_INFO("%s Mech '%s' banned due to mixed firmware versions\n", - __func__, ep11_get_ckm(type)); - return CKR_MECHANISM_INVALID; + __func__, ep11_get_ckm(tokdata, type)); + rc = CKR_MECHANISM_INVALID; + goto out; } break; @@ -8858,52 +9036,60 @@ case CKM_IBM_ED448_SHA3: if (compare_ck_version(&ep11_data->ep11_lib_version, &ver3) < 0) { TRACE_INFO("%s Mech '%s' banned due to host library version\n", - __func__, ep11_get_ckm(type)); - return CKR_MECHANISM_INVALID; + __func__, ep11_get_ckm(tokdata, type)); + rc = CKR_MECHANISM_INVALID; + goto out; } status = check_required_versions(tokdata, edwards_req_versions, NUM_EDWARDS_REQ); if (status != 1) { TRACE_INFO("%s Mech '%s' banned due to mixed firmware versions\n", - __func__, ep11_get_ckm(type)); - return CKR_MECHANISM_INVALID; + __func__, ep11_get_ckm(tokdata, type)); + rc = CKR_MECHANISM_INVALID; + goto out; } break; case CKM_IBM_DILITHIUM: if (compare_ck_version(&ep11_data->ep11_lib_version, &ver3) <= 0) { TRACE_INFO("%s Mech '%s' banned due to host library version\n", - __func__, ep11_get_ckm(type)); - return CKR_MECHANISM_INVALID; + __func__, ep11_get_ckm(tokdata, type)); + rc = CKR_MECHANISM_INVALID; + goto out; } status = check_required_versions(tokdata, ibm_dilithium_req_versions, NUM_DILITHIUM_REQ); if (status != 1) { TRACE_INFO("%s Mech '%s' banned due to mixed firmware versions\n", - __func__, ep11_get_ckm(type)); - return CKR_MECHANISM_INVALID; + __func__, ep11_get_ckm(tokdata, type)); + rc = CKR_MECHANISM_INVALID; + goto out; } break; case CKM_IBM_CPACF_WRAP: if (compare_ck_version(&ep11_data->ep11_lib_version, &ver3) <= 0) { TRACE_INFO("%s Mech '%s' banned due to host library version\n", - __func__, ep11_get_ckm(type)); + __func__, ep11_get_ckm(tokdata, type)); - return CKR_MECHANISM_INVALID; + rc = CKR_MECHANISM_INVALID; + goto out; } status = check_required_versions(tokdata, ibm_cpacf_wrap_req_versions, NUM_CPACF_WRAP_REQ); if (status != 1) { TRACE_INFO("%s Mech '%s' banned due to mixed firmware versions\n", - __func__, ep11_get_ckm(type)); - return CKR_MECHANISM_INVALID; + __func__, ep11_get_ckm(tokdata, type)); + rc = CKR_MECHANISM_INVALID; + goto out; } break; } - return CKR_OK; +out: + put_target_info(tokdata, target_info); + return rc; } CK_RV ep11tok_is_mechanism_supported_ex(STDLL_TokData_t *tokdata, @@ -8948,18 +9134,25 @@ CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo) { - ep11_private_data_t *ep11_data = tokdata->private_data; CK_RV rc; int status; + ep11_target_info_t* target_info; rc = ep11tok_is_mechanism_supported(tokdata, type); if (rc != CKR_OK) { TRACE_DEBUG("%s rc=0x%lx unsupported '%s'\n", __func__, rc, - ep11_get_ckm(type)); + ep11_get_ckm(tokdata, type)); return rc; } - rc = dll_m_GetMechanismInfo(0, type, pInfo, ep11_data->target); + target_info = get_target_info(tokdata); + if (target_info == NULL) + return CKR_FUNCTION_FAILED; + + rc = dll_m_GetMechanismInfo(0, type, pInfo, target_info->target); + + put_target_info(tokdata, target_info); + if (rc != CKR_OK) { rc = ep11_error_to_pkcs11_error(rc, NULL); TRACE_ERROR("%s m_GetMechanismInfo(0x%lx) failed with rc=0x%lx\n", @@ -9049,7 +9242,7 @@ } #endif /* DEFENSIVE_MECHLIST */ - return CKR_OK; + return tokdata->policy->update_mech_info(tokdata->policy, type, pInfo); } @@ -9217,10 +9410,12 @@ token = strtok(str, "\n\t "); if (i == 0) { - /* expecting APQN_WHITELIST or APQN_ANY or LOGLEVEL or eof */ + /* expecting APQN_ALLOWLIST or APQN_WHITELIST or APQN_ANY + or LOGLEVEL or eof */ if (token == NULL) break; - if (strncmp(token, "APQN_WHITELIST", 14) == 0) { + if (strncmp(token, "APQN_WHITELIST", 14) == 0 || + strncmp(token, "APQN_ALLOWLIST", 14) == 0) { whitemode = 1; i = 1; } else if (strncmp(token, "APQN_ANY", 8) == 0) { @@ -9252,14 +9447,14 @@ token_specific.t_rng = NULL; } else { /* syntax error */ - TRACE_ERROR("%s Expected APQN_WHITELIST," + TRACE_ERROR("%s Expected APQN_ALLOWLIST," " APQN_ANY, LOGLEVEL, FORCE_SENSITIVE, CPFILTER," " STRICT_MODE, VHSM_MODE, " " OPTIMIZE_SINGLE_PART_OPERATIONS, PKEY_MODE, DIGEST_LIBICA, " "or USE_PRANDOM keyword, found '%s' in config file " "'%s'\n", __func__, token, fname); - OCK_SYSLOG(LOG_ERR, "%s: Error: Expected APQN_WHITELIST," + OCK_SYSLOG(LOG_ERR, "%s: Error: Expected APQN_ALLOWLIST," " APQN_ANY, LOGLEVEL, FORCE_SENSITIVE, CPFILTER," " STRICT_MODE, VHSM_MODE," " OPTIMIZE_SINGLE_PART_OPERATIONS, PKEY_MODE, DIGEST_LIBICA, " @@ -9452,18 +9647,18 @@ if (rc == 0) { if (!(whitemode || anymode)) { TRACE_ERROR("%s At least one APQN mode needs to be present in " - "config file: APQN_WHITEMODE or APQN_ANY\n", __func__); + "config file: APQN_ALLOWLIST or APQN_ANY\n", __func__); OCK_SYSLOG(LOG_ERR, "%s: Error: At least one APQN mode needs to be present " - " in config file '%s': APQN_WHITEMODE or APQN_ANY\n", + " in config file '%s': APQN_ALLOWLIST or APQN_ANY\n", __func__, fname); rc = APQN_FILE_NO_APQN_MODE; } else if (whitemode && anymode) { TRACE_ERROR("%s Only one APQN mode can be present in config file:" - " APQN_WHITEMODE or APQN_ANY\n", __func__); + " APQN_ALLOWLIST or APQN_ANY\n", __func__); OCK_SYSLOG(LOG_ERR, "%s: Error: Only one APQN mode can be present in" - " config file '%s': APQN_WHITEMODE or APQN_ANY\n", + " config file '%s': APQN_ALLOWLIST or APQN_ANY\n", __func__, fname); rc = APQN_FILE_NO_APQN_MODE; } else if (whitemode) { @@ -9518,11 +9713,11 @@ sizeof(ep11_data->cp_filter_config_filename) - 1] = '\0'; } - rc = read_cp_filter_config_file(ep11_data->cp_filter_config_filename, + rc = read_cp_filter_config_file(tokdata, + ep11_data->cp_filter_config_filename, &ep11_data->cp_config); } - tokdata->initialized = TRUE; return rc; } @@ -9532,7 +9727,8 @@ #define CP_BIT_IN_BYTE(cp) ((cp) % 8) #define CP_BIT_MASK(cp) (0x80 >> CP_BIT_IN_BYTE(cp)) -static int read_cp_filter_config_file(const char *conf_name, +static int read_cp_filter_config_file(STDLL_TokData_t *tokdata, + const char *conf_name, cp_config_t ** cp_config) { int rc = 0; @@ -9601,7 +9797,7 @@ val = strtoul(tok, &endp, 0); if (*endp != '\0') { - val = ep11_get_mechanisms_by_name(tok); + val = ep11_get_mechanisms_by_name(tokdata, tok); if (val == UNKNOWN_MECHANISM) { TRACE_ERROR("%s Syntax error in EP 11 CP-filter config file" " found. \n", __func__); @@ -9657,7 +9853,7 @@ mech = cp->mech; while (mech != NULL) { TRACE_INFO(" Mechanism 0x%08lx (%s)\n", mech->mech, - ep11_get_ckm(mech->mech)); + ep11_get_ckm(tokdata, mech->mech)); mech = mech->next; } cp = cp->next; @@ -9775,16 +9971,18 @@ return UNKNOWN_CP; } -static CK_RV check_cps_for_mechanism(cp_config_t * cp_config, +static CK_RV check_cps_for_mechanism(STDLL_TokData_t *tokdata, + cp_config_t * cp_config, CK_MECHANISM_TYPE mech, unsigned char *cp, size_t cp_len, size_t max_cp_index) { + UNUSED(tokdata); cp_config_t *cp_cfg = cp_config; cp_mech_config_t *mech_cfg; TRACE_DEBUG("%s Check mechanism 0x%08lx ('%s')\n", __func__, mech, - ep11_get_ckm(mech)); + ep11_get_ckm(tokdata, mech)); while (cp_cfg != NULL) { if (CP_BYTE_NO(cp_cfg->cp) < cp_len && @@ -9796,7 +9994,7 @@ while (mech_cfg != NULL) { if (mech_cfg->mech == mech) { TRACE_DEBUG("%s mechanism 0x%08lx ('%s') not enabled\n", - __func__, mech, ep11_get_ckm(mech)); + __func__, mech, ep11_get_ckm(tokdata, mech)); return CKR_MECHANISM_INVALID; } mech_cfg = mech_cfg->next; @@ -9988,7 +10186,7 @@ CK_RV rc; if (ep11_targets->length > 0) { - /* APQN_WHITELIST is specified */ + /* APQN_WHITELIST or APQN_ALLOWLIST is specified */ for (i = 0; i < ep11_targets->length; i++) { rc = handler(ep11_targets->apqns[2 * i], ep11_targets->apqns[2 * i + 1], handler_data); @@ -10237,6 +10435,11 @@ CK_MECHANISM mech; CK_ULONG len; libica_sha_context_t ctx; + ep11_target_info_t* target_info; + + target_info = get_target_info(tokdata); + if (target_info == NULL) + return CKR_FUNCTION_FAILED; session_id_data.handle = session->handle; gettimeofday(&session_id_data.timeofday, NULL); @@ -10248,8 +10451,8 @@ mech.ulParameterLen = 0; len = sizeof(ep11_session->session_id); - if (ep11tok_libica_digest_available(ep11_data, mech.mechanism)) - rc = ep11tok_libica_digest(ep11_data, mech.mechanism, &ctx, + if (ep11tok_libica_digest_available(tokdata, ep11_data, mech.mechanism)) + rc = ep11tok_libica_digest(tokdata, ep11_data, mech.mechanism, &ctx, (CK_BYTE_PTR)&session_id_data, sizeof(session_id_data), ep11_session->session_id, &len, @@ -10258,7 +10461,9 @@ rc = dll_m_DigestSingle(&mech, (CK_BYTE_PTR)&session_id_data, sizeof(session_id_data), ep11_session->session_id, &len, - ep11_data->target); + target_info->target); + + put_target_info(tokdata, target_info); if (rc != CKR_OK) { rc = ep11_error_to_pkcs11_error(rc, session); @@ -10711,6 +10916,9 @@ TRACE_INFO("%s session=%lu\n", __func__, session->handle); + if (!ep11_data->strict_mode && !ep11_data->vhsm_mode) + return CKR_OK; + if (ep11_session == NULL) { TRACE_INFO("%s Session not yet logged in\n", __func__); return CKR_USER_NOT_LOGGED_IN; @@ -10936,7 +11144,7 @@ typedef struct query_version { - ep11_private_data_t *ep11_data; + ep11_target_info_t *target_info; CK_CHAR serialNumber[16]; CK_BBOOL first; CK_BBOOL error; @@ -10977,7 +11185,7 @@ } /* Try to find existing version info for this card type */ - card_version = qv->ep11_data->card_versions; + card_version = qv->target_info->card_versions; while (card_version != NULL) { if (card_version->card_type == card_type) break; @@ -11022,8 +11230,8 @@ card_version->firmware_version = xcp_info.firmwareVersion; #endif - card_version->next = qv->ep11_data->card_versions; - qv->ep11_data->card_versions = card_version; + card_version->next = qv->target_info->card_versions; + qv->target_info->card_versions = card_version; } else { /* * Version info for this card type is already available, so check this @@ -11106,23 +11314,16 @@ return CKR_OK; } -static CK_RV ep11tok_get_ep11_version(STDLL_TokData_t *tokdata) +static CK_RV ep11tok_get_ep11_version(STDLL_TokData_t *tokdata, + ep11_target_info_t *target_info) { ep11_private_data_t *ep11_data = tokdata->private_data; ep11_card_version_t *card_version; query_version_t qv; CK_RV rc; - rc = ep11tok_get_ep11_library_version(&ep11_data->ep11_lib_version); - if (rc != CKR_OK) - return rc; - - TRACE_INFO("%s Host library version: %d.%d\n", __func__, - ep11_data->ep11_lib_version.major, - ep11_data->ep11_lib_version.minor); - memset(&qv, 0, sizeof(qv)); - qv.ep11_data = ep11_data; + qv.target_info = target_info; qv.first = TRUE; rc = handle_all_ep11_cards(&ep11_data->target_list, version_query_handler, @@ -11141,18 +11342,18 @@ return CKR_DEVICE_ERROR; } - memcpy(ep11_data->serialNumber, qv.serialNumber, - sizeof(ep11_data->serialNumber)); + memcpy(target_info->serialNumber, qv.serialNumber, + sizeof(target_info->serialNumber)); - TRACE_INFO("%s Serial number: %.16s\n", __func__, ep11_data->serialNumber); + TRACE_INFO("%s Serial number: %.16s\n", __func__, target_info->serialNumber); /* EP11 host lib version <= 2 only support API version 2 */ if (ep11_data->ep11_lib_version.major <= 2) - ep11_data->used_firmware_API_version = 2; + target_info->used_firmware_API_version = 2; else - ep11_data->used_firmware_API_version = 0; + target_info->used_firmware_API_version = 0; - card_version = ep11_data->card_versions; + card_version = target_info->card_versions; while (card_version != NULL) { TRACE_INFO("%s Card type: CEX%luP\n", __func__, card_version->card_type); @@ -11162,19 +11363,19 @@ card_version->firmware_version.major, card_version->firmware_version.minor); - if (ep11_data->used_firmware_API_version == 0) - ep11_data->used_firmware_API_version = + if (target_info->used_firmware_API_version == 0) + target_info->used_firmware_API_version = card_version->firmware_API_version; else - ep11_data->used_firmware_API_version = - MIN(ep11_data->used_firmware_API_version, + target_info->used_firmware_API_version = + MIN(target_info->used_firmware_API_version, card_version->firmware_API_version); card_version = card_version->next; } TRACE_INFO("%s Used Firmware API: %lu\n", __func__, - ep11_data->used_firmware_API_version); + target_info->used_firmware_API_version); return CKR_OK; } @@ -11192,20 +11393,29 @@ } } -void ep11tok_copy_firmware_info(STDLL_TokData_t *tokdata, +CK_RV ep11tok_copy_firmware_info(STDLL_TokData_t *tokdata, CK_TOKEN_INFO_PTR pInfo) { ep11_private_data_t *ep11_data = tokdata->private_data; + ep11_target_info_t* target_info; + + target_info = get_target_info(tokdata); + if (target_info == NULL) + return CKR_FUNCTION_FAILED; /* * report the EP11 firmware version as hardware version, and * the EP11 host library version as firmware version */ - if (ep11_data->card_versions != NULL) - pInfo->hardwareVersion = ep11_data->card_versions->firmware_version; + if (target_info->card_versions != NULL) + pInfo->hardwareVersion = target_info->card_versions->firmware_version; pInfo->firmwareVersion = ep11_data->ep11_lib_version; - memcpy(pInfo->serialNumber, ep11_data->serialNumber, + memcpy(pInfo->serialNumber, target_info->serialNumber, sizeof(pInfo->serialNumber)); + + put_target_info(tokdata, target_info); + + return CKR_OK; } /** @@ -11219,13 +11429,17 @@ const version_req_t req[], CK_ULONG num_req) { - ep11_private_data_t *ep11_data = tokdata->private_data; CK_ULONG i, max_card_type = 0, min_card_type = 0xFFFFFFFF; CK_BBOOL req_not_fullfilled = CK_FALSE; CK_BBOOL req_fullfilled = CK_FALSE; ep11_card_version_t *card_version; + ep11_target_info_t* target_info; int status; + target_info = get_target_info(tokdata); + if (target_info == NULL) + return CKR_FUNCTION_FAILED; + for (i = 0; i < num_req; i++) { status = check_card_version(tokdata, req[i].card_type, req[i].min_lib_version, @@ -11240,7 +11454,7 @@ } /* Are card types < min_card_type present? */ - card_version = ep11_data->card_versions; + card_version = target_info->card_versions; while (card_version != NULL) { if (card_version->card_type < min_card_type) req_not_fullfilled = CK_TRUE; @@ -11248,7 +11462,7 @@ } /* Are card types > max_card_type present? */ - card_version = ep11_data->card_versions; + card_version = target_info->card_versions; while (card_version != NULL) { if (card_version->card_type > max_card_type) { /* @@ -11257,9 +11471,10 @@ * So all others must also meet the version requirements or be * not present. */ + status = 1; if (req_not_fullfilled == CK_TRUE) - return -1; - return 1; + status = -1; + goto out; } card_version = card_version->next; } @@ -11270,13 +11485,19 @@ * At least one don't meet the requirements, so all other must not * fulfill the requirements, too, or are not present. */ + status = 0; if (req_fullfilled == CK_TRUE) - return -1; - return 0; + status = -1; + goto out; } else { /* All of the cards that are present fulfill the requirements */ - return 1; + status = 1; + goto out; } + +out: + put_target_info(tokdata, target_info); + return status; } /** @@ -11292,6 +11513,8 @@ { ep11_private_data_t *ep11_data = tokdata->private_data; ep11_card_version_t *card_version; + ep11_target_info_t* target_info; + int status = 1; TRACE_DEBUG("%s checking versions for CEX%luP cards.\n", __func__, card_type); @@ -11303,21 +11526,28 @@ } } - card_version = ep11_data->card_versions; + target_info = get_target_info(tokdata); + if (target_info == NULL) + return -1; + + card_version = target_info->card_versions; while (card_version != NULL) { if (card_version->card_type == card_type) break; card_version = card_version->next; } - if (card_version == NULL) - return -1; + if (card_version == NULL) { + status = -1; + goto out; + } if (firmware_version != NULL) { if (compare_ck_version(&card_version->firmware_version, firmware_version) < 0) { TRACE_DEBUG("%s firmware_version is less than required\n", __func__); - return 0; + status = 0; + goto out; } } @@ -11325,53 +11555,57 @@ if (card_version->firmware_API_version < *firmware_API_version) { TRACE_DEBUG("%s firmware_API_version is less than required\n", __func__); - return 0; + status = 0; + goto out; } } - return 1; + out: + put_target_info(tokdata, target_info); + return status; } -static CK_RV ep11tok_setup_target(STDLL_TokData_t *tokdata) +static CK_RV ep11tok_setup_target(STDLL_TokData_t *tokdata, + ep11_target_info_t *target_info) { ep11_private_data_t *ep11_data = tokdata->private_data; struct XCP_Module module; - CK_RV rc; + CK_RV rc = CKR_OK; short i; if (dll_m_add_module == NULL) { TRACE_WARNING("%s Function dll_m_add_module is not available, falling " "back to old target handling\n", __func__); - if (ep11_data->used_firmware_API_version > 2) { + if (target_info->used_firmware_API_version > 2) { TRACE_ERROR("%s selecting an API version is not possible with old " "target handling\n", __func__); return CKR_FUNCTION_FAILED; } - ep11_data->target = (target_t)&ep11_data->target_list; + target_info->target = (target_t)&ep11_data->target_list; return CKR_OK; } - if (ep11_data->used_firmware_API_version > 2 && + if (target_info->used_firmware_API_version > 2 && ep11_data->ep11_lib_version.major < 3) { TRACE_ERROR("%s selecting an API version is not possible with an EP11" " host library version < 3.0\n", __func__); return CKR_FUNCTION_FAILED; } - ep11_data->target = XCP_TGT_INIT; + target_info->target = XCP_TGT_INIT; memset(&module, 0, sizeof(module)); module.version = ep11_data->ep11_lib_version.major >= 3 ? XCP_MOD_VERSION_2 : XCP_MOD_VERSION_1; module.flags = XCP_MFL_VIRTUAL | XCP_MFL_MODULE; - module.api = ep11_data->used_firmware_API_version; + module.api = target_info->used_firmware_API_version; TRACE_DEVEL("%s XCP_MOD_VERSION: %u\n", __func__, module.version); if (ep11_data->target_list.length == 0) { /* APQN_ANY: Create an empty module group */ - rc = dll_m_add_module(&module, &ep11_data->target); + rc = dll_m_add_module(&module, &target_info->target); if (rc != CKR_OK) { TRACE_ERROR("%s dll_m_add_module (ANY) failed: rc=%ld\n", __func__, rc); @@ -11386,11 +11620,12 @@ XCPTGTMASK_SET_DOM(module.domainmask, ep11_data->target_list.apqns[2 * i + 1]); - rc = dll_m_add_module(&module, &ep11_data->target); + rc = dll_m_add_module(&module, &target_info->target); if (rc != CKR_OK) { TRACE_ERROR("%s dll_m_add_module (%02x.%04x) failed: rc=%ld\n", __func__, ep11_data->target_list.apqns[2 * i], ep11_data->target_list.apqns[2 * i + 1], rc); + dll_m_rm_module(NULL, target_info->target); return CKR_FUNCTION_FAILED; } } @@ -11466,6 +11701,7 @@ CK_ULONG num_attributes = 0; CK_ATTRIBUTE *attr; CK_RV rc; + ep11_target_info_t* target_info; rc = template_attribute_get_ulong(obj->template, CKA_CLASS, &class); if (rc != CKR_OK) { @@ -11495,17 +11731,21 @@ /* EP11 can set certain boolean attributes only */ switch (attr->type) { + case CKA_VERIFY: + case CKA_VERIFY_RECOVER: + case CKA_ENCRYPT: + /* Can not restrict public key for verify and encrypt */ + if (class == CKO_PUBLIC_KEY) + break; + /* Fallthrough */ case CKA_EXTRACTABLE: case CKA_MODIFIABLE: case CKA_SIGN: case CKA_SIGN_RECOVER: case CKA_DECRYPT: - case CKA_ENCRYPT: case CKA_DERIVE: case CKA_UNWRAP: case CKA_WRAP: - case CKA_VERIFY: - case CKA_VERIFY_RECOVER: case CKA_WRAP_WITH_TRUSTED: case CKA_TRUSTED: case CKA_IBM_RESTRICTABLE: @@ -11547,9 +11787,18 @@ goto out; } + target_info = get_target_info(tokdata); + if (target_info == NULL) { + rc = CKR_FUNCTION_FAILED; + goto out; + } + rc = dll_m_SetAttributeValue(ibm_opaque_attr->pValue, ibm_opaque_attr->ulValueLen, attributes, - num_attributes, ep11_data->target); + num_attributes, target_info->target); + + put_target_info(tokdata, target_info); + if (rc != CKR_OK) { rc = ep11_error_to_pkcs11_error(rc, NULL); TRACE_ERROR("%s m_SetAttributeValue failed rc=0x%lx\n", @@ -11573,3 +11822,317 @@ return rc; } +/* + * ATTENTION: This function is called in a separate thread. All actions + * performed by this function must be thread save and use locks to lock + * against concurrent access by other threads. + */ +static CK_RV ep11tok_handle_apqn_event(STDLL_TokData_t *tokdata, + unsigned int event_type, + event_udev_apqn_data_t *apqn_data) +{ + ep11_private_data_t *ep11_data = tokdata->private_data; + CK_BBOOL found = FALSE; + CK_RV rc = CKR_OK; + char name[20]; + int i; + + /* Is it one of the configured APQNs ?*/ + if (ep11_data->target_list.length > 0) { + /* APQN_WHITELIST or APQN_ALLOWLIST is specified */ + for (i = 0; i < ep11_data->target_list.length; i++) { + if (ep11_data->target_list.apqns[2 * i] == apqn_data->card && + ep11_data->target_list.apqns[2 * i + 1] == apqn_data->domain) { + found = TRUE; + break; + } + } + } else { + /* APQN_ANY is specified */ + found = TRUE; + if (event_type == EVENT_TYPE_APQN_ADD) { + snprintf(name, sizeof(name), "card%02x", apqn_data->card); + if (is_card_ep11_and_online(name) != CKR_OK) + found = FALSE; /* Not an EP11 APQN */ + } + } + if (!found) + return CKR_OK; + + TRACE_DEVEL("%s Refreshing target infos due to event for APQN %02x.%04x\n", + __func__, apqn_data->card, apqn_data->domain); + + rc = refresh_target_info(tokdata); + if (rc != CKR_OK) { + TRACE_ERROR("%s Failed to get the target infos (refresh_target_info " + "rc=0x%lx)\n", __func__, rc); + OCK_SYSLOG(LOG_ERR, "%s: Failed to get the target info rc=0x%lx\n", + __func__, rc); + return rc; + } + + return CKR_OK; +} + +/* + * Called by the event thread, on receipt of an event. + * + * ATTENTION: This function is called in a separate thread. All actions + * performed by this function must be thread save and use locks to lock + * against concurrent access by other threads. + */ +CK_RV token_specific_handle_event(STDLL_TokData_t *tokdata, + unsigned int event_type, + unsigned int event_flags, + const char *payload, + unsigned int payload_len) +{ + UNUSED(event_flags); + + switch (event_type) { + case EVENT_TYPE_APQN_ADD: + case EVENT_TYPE_APQN_REMOVE: + if (payload_len != sizeof(event_udev_apqn_data_t)) + return CKR_FUNCTION_FAILED; + return ep11tok_handle_apqn_event(tokdata, event_type, + (event_udev_apqn_data_t *)payload); + + default: + return CKR_FUNCTION_NOT_SUPPORTED; + } + + return CKR_OK; +} + +/* + * Refreshes the target info using the currently configured and available + * APQNs. Registers the newly allocated target info as the current one in a + * thread save way and gives back the previous one so that it is release when + * no longer used (i.e. by a concurrently running thread). + */ +static CK_RV refresh_target_info(STDLL_TokData_t *tokdata) +{ + ep11_private_data_t *ep11_data = tokdata->private_data; + volatile ep11_target_info_t *prev_info; + ep11_target_info_t *target_info; + CK_RV rc; + + target_info = calloc(1, sizeof(ep11_target_info_t)); + if (target_info == NULL) { + TRACE_ERROR("%s Memory allocation failed\n", __func__); + return CKR_HOST_MEMORY; + } + + target_info->ref_count = 1; + + /* Get the version info freshly with the current set of APQNs */ + rc = ep11tok_get_ep11_version(tokdata, target_info); + if (rc != 0) + goto error; + + /* Get the control points freshly with the current set of APQNs */ + target_info->control_points_len = sizeof(target_info->control_points); + rc = get_control_points(tokdata, target_info->control_points, + &target_info->control_points_len, + &target_info->max_control_point_index); + if (rc != 0) + goto error; + + /* Setup the group target freshly with the current set of APQNs */ + rc = ep11tok_setup_target(tokdata, target_info); + if (rc != CKR_OK) + goto error; + + /* Set the new one as the current one (locked against concurrent get's) */ + if (pthread_rwlock_wrlock(&ep11_data->target_rwlock) != 0) { + TRACE_DEVEL("Target Write-Lock failed.\n"); + rc = CKR_CANT_LOCK; + goto error; + } + + prev_info = ep11_data->target_info; + ep11_data->target_info = target_info; + + if (pthread_rwlock_unlock(&ep11_data->target_rwlock) != 0) { + TRACE_DEVEL("Target Unlock failed.\n"); + return CKR_CANT_LOCK; + } + + /* Release the previous one */ + if (prev_info != NULL) + put_target_info(tokdata, (ep11_target_info_t *)prev_info); + + return CKR_OK; + +error: + free_card_versions(target_info->card_versions); + free((void *)target_info); + return rc; +} + +/* + * Get the current EP11 target info. + * Do NOT use the ep11_data->target_info directly, always get a copy using + * this function. This will increment the reference count of the target info, + * and return the current target info in a thread save way. + * When no longer needed, put it back using put_target_info(). + */ +static ep11_target_info_t *get_target_info(STDLL_TokData_t *tokdata) +{ + ep11_private_data_t *ep11_data = tokdata->private_data; + volatile ep11_target_info_t *target_info; +#ifdef DEBUG + unsigned long ref_count; +#endif + + /* + * Lock until we have obtained the current target info and have + * increased the reference counter + */ + if (pthread_rwlock_rdlock(&ep11_data->target_rwlock) != 0) { + TRACE_DEVEL("Target Read-Lock failed.\n"); + return NULL; + } + + target_info = *((void * volatile *)&ep11_data->target_info); + if (target_info == NULL) { + TRACE_ERROR("%s: target_info is NULL\n", __func__); + return NULL; + } + +#ifdef DEBUG + ref_count = __sync_add_and_fetch(&target_info->ref_count, 1); + + TRACE_DEBUG("%s: target_info: %p ref_count: %lu\n", __func__, + (void *)target_info, ref_count); +#else + __sync_add_and_fetch(&target_info->ref_count, 1); +#endif + + if (pthread_rwlock_unlock(&ep11_data->target_rwlock) != 0) { + TRACE_DEVEL("Target Unlock failed.\n"); + return NULL; + } + + return (ep11_target_info_t *)target_info; +} + +/* + * Give back an EP11 target info. This will decrement the reference count, + * and will free it if the reference count reaches zero. + */ +static void put_target_info(STDLL_TokData_t *tokdata, + ep11_target_info_t *target_info) +{ + ep11_private_data_t *ep11_data = tokdata->private_data; + unsigned long ref_count; + + if (target_info == NULL) + return; + + if (target_info->ref_count > 0) { + ref_count = __sync_sub_and_fetch(&target_info->ref_count, 1); + + TRACE_DEBUG("%s: target_info: %p ref_count: %lu\n", __func__, + (void *)target_info, ref_count); + } else { + TRACE_WARNING("%s: target_info: %p ref_count already 0.\n", __func__, + (void *)target_info); + ref_count = 0; + } + + if (ref_count == 0 && target_info != ep11_data->target_info) { + TRACE_DEBUG("%s: target_info: %p is freed\n", __func__, + (void *)target_info); + + if (dll_m_rm_module != NULL) + dll_m_rm_module(NULL, target_info->target); + free_card_versions(target_info->card_versions); + free(target_info); + } +} + +/* + * Must be called either with WRITE_LOCK on the object that owns the template + * specified as @tmpl, or before the object is made publicly available via + * object_mgr_create_final. + */ +static CK_RV update_ep11_attrs_from_blob(STDLL_TokData_t *tokdata, + TEMPLATE *tmpl) +{ + ep11_private_data_t *ep11_data = tokdata->private_data; + CK_BBOOL restr = CK_FALSE; /*, never_mod = CK_FALSE; */ + CK_BBOOL attrb = CK_FALSE, useasdata = CK_FALSE; + CK_BBOOL pkeyextr = CK_FALSE, pkeyneverextr = CK_FALSE; + CK_ULONG stdcomp1 = 0; + CK_ATTRIBUTE *attr, *blob_attr = NULL; + ep11_target_info_t* target_info; + CK_RV rc = CKR_OK; + CK_ULONG i; + + CK_ATTRIBUTE ibm_attrs[] = { + { CKA_IBM_RESTRICTABLE, &restr, sizeof(restr) }, + /* Skip CKA_IBM_NEVER_MODIFIABLE for now, it causes CKR_ARGUMENTS_BAD + { CKA_IBM_NEVER_MODIFIABLE, &never_mod, sizeof(never_mod) }, */ + { CKA_IBM_USE_AS_DATA, &useasdata, sizeof(useasdata) }, + { CKA_IBM_ATTRBOUND, &attrb, sizeof(attrb) }, + { CKA_IBM_STD_COMPLIANCE1, &stdcomp1, sizeof(stdcomp1) }, + /* PROTKEY attributes must be the last 2 */ + { CKA_IBM_PROTKEY_EXTRACTABLE, &pkeyextr, sizeof(pkeyextr) }, + { CKA_IBM_PROTKEY_NEVER_EXTRACTABLE, &pkeyneverextr, + sizeof(pkeyneverextr) }, + }; + CK_ULONG num_ibm_attrs = sizeof(ibm_attrs) / sizeof(CK_ATTRIBUTE); + + if (!ep11_data->pkey_wrap_supported) + num_ibm_attrs -= 2; + + if (template_attribute_get_non_empty(tmpl, CKA_IBM_OPAQUE, + &blob_attr) != CKR_OK) { + TRACE_ERROR("This key has no CKA_IBM_OPAQUE: should not occur!\n"); + return CKR_FUNCTION_FAILED; + } + + target_info = get_target_info(tokdata); + if (target_info == NULL) + return CKR_FUNCTION_FAILED; + + rc = dll_m_GetAttributeValue(blob_attr->pValue, + blob_attr->ulValueLen, ibm_attrs, + num_ibm_attrs, target_info->target); + + put_target_info(tokdata, target_info); + + if (rc != CKR_OK) { + rc = ep11_error_to_pkcs11_error(rc, NULL); + TRACE_ERROR("%s m_GetAttributeValue failed rc=0x%lx\n", + __func__, rc); + return rc; + } + + /* Set/Update all available attributes in the object's template */ + for (i = 0; i < num_ibm_attrs; i++) { + if (ibm_attrs[i].ulValueLen == CK_UNAVAILABLE_INFORMATION) { + TRACE_DEVEL("%s Attribute 0x%lx not available\n", __func__, + ibm_attrs[i].type); + continue; + } + + rc = build_attribute(ibm_attrs[i].type, ibm_attrs[i].pValue, + ibm_attrs[i].ulValueLen, &attr); + if (rc != CKR_OK) { + TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", __func__, rc); + return rc; + } + + rc = template_update_attribute(tmpl, attr); + if (rc != CKR_OK) { + free(attr); + TRACE_ERROR("%s template_update_attribute failed with rc=0x%lx\n", + __func__, rc); + return rc; + } + } + + return CKR_OK; +} diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/ep11_stdll/ep11_specific.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/ep11_stdll/ep11_specific.h --- opencryptoki-3.16.0+dfsg/usr/lib/ep11_stdll/ep11_specific.h 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/ep11_stdll/ep11_specific.h 2022-02-02 15:05:41.000000000 +0100 @@ -161,7 +161,7 @@ CK_MECHANISM_TYPE mech, CK_OBJECT_HANDLE hKey); -void ep11tok_copy_firmware_info(STDLL_TokData_t *tokdata, +CK_RV ep11tok_copy_firmware_info(STDLL_TokData_t *tokdata, CK_TOKEN_INFO_PTR pInfo); CK_BBOOL ep11tok_pkey_usage_ok(STDLL_TokData_t *tokdata, SESSION *session, diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/ep11_stdll/ep11_stdll.mk opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/ep11_stdll/ep11_stdll.mk --- opencryptoki-3.16.0+dfsg/usr/lib/ep11_stdll/ep11_stdll.mk 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/ep11_stdll/ep11_stdll.mk 2022-02-02 15:05:41.000000000 +0100 @@ -11,34 +11,37 @@ -DTOK_NEW_DATA_STORE=0x0003000c \ -DSTDLL_NAME=\"ep11tok\" \ -I${srcdir}/usr/lib/ep11_stdll -I${srcdir}/usr/lib/common \ - -I${srcdir}/usr/include + -I${srcdir}/usr/include -I${top_builddir}/usr/lib/api \ + -I${srcdir}/usr/lib/api opencryptoki_stdll_libpkcs11_ep11_la_LDFLAGS = \ -shared -Wl,-z,defs,-Bsymbolic -lc -lpthread -lcrypto -lrt \ -llber -ldl -Wl,--version-script=${srcdir}/opencryptoki_tok.map -opencryptoki_stdll_libpkcs11_ep11_la_SOURCES = \ - usr/lib/common/asn1.c usr/lib/common/cert.c \ - usr/lib/common/hwf_obj.c usr/lib/common/dp_obj.c \ - usr/lib/common/data_obj.c usr/lib/common/dig_mgr.c \ - usr/lib/common/encr_mgr.c usr/lib/common/decr_mgr.c \ - usr/lib/common/globals.c usr/lib/common/loadsave.c \ - usr/lib/common/mech_aes.c usr/lib/common/mech_des.c \ - usr/lib/common/mech_des3.c usr/lib/common/mech_ec.c \ - usr/lib/common/mech_md5.c usr/lib/common/mech_md2.c \ - usr/lib/common/mech_rng.c usr/lib/common/mech_rsa.c \ - usr/lib/common/mech_sha.c usr/lib/common/mech_dsa.c \ - usr/lib/common/mech_dh.c usr/lib/common/mech_ssl3.c \ - usr/lib/common/obj_mgr.c usr/lib/common/object.c \ - usr/lib/common/sign_mgr.c usr/lib/common/verify_mgr.c \ - usr/lib/common/key.c usr/lib/common/key_mgr.c \ - usr/lib/common/template.c usr/lib/common/p11util.c \ - usr/lib/common/utility.c usr/lib/common/trace.c \ - usr/lib/common/mech_list.c usr/lib/common/shared_memory.c \ - usr/lib/common/attributes.c usr/lib/common/sw_crypt.c \ - usr/lib/common/profile_obj.c \ - usr/lib/common/pkey_utils.c \ - usr/lib/ep11_stdll/new_host.c usr/lib/ep11_stdll/ep11_specific.c +opencryptoki_stdll_libpkcs11_ep11_la_SOURCES = usr/lib/common/asn1.c \ + usr/lib/common/cert.c usr/lib/common/hwf_obj.c \ + usr/lib/common/dp_obj.c usr/lib/common/data_obj.c \ + usr/lib/common/dig_mgr.c usr/lib/common/encr_mgr.c \ + usr/lib/common/decr_mgr.c usr/lib/common/globals.c \ + usr/lib/common/loadsave.c usr/lib/common/mech_aes.c \ + usr/lib/common/mech_des.c usr/lib/common/mech_des3.c \ + usr/lib/common/mech_ec.c usr/lib/common/mech_md5.c \ + usr/lib/common/mech_md2.c usr/lib/common/mech_rng.c \ + usr/lib/common/mech_rsa.c usr/lib/common/mech_sha.c \ + usr/lib/common/mech_dsa.c usr/lib/common/mech_dh.c \ + usr/lib/common/mech_ssl3.c usr/lib/common/obj_mgr.c \ + usr/lib/common/object.c usr/lib/common/sign_mgr.c \ + usr/lib/common/verify_mgr.c usr/lib/common/key.c \ + usr/lib/common/key_mgr.c usr/lib/common/template.c \ + usr/lib/common/p11util.c usr/lib/common/utility.c \ + usr/lib/common/trace.c usr/lib/common/mech_list.c \ + usr/lib/common/shared_memory.c usr/lib/common/attributes.c \ + usr/lib/common/sw_crypt.c usr/lib/common/profile_obj.c \ + usr/lib/common/dlist.c usr/lib/common/pkey_utils.c \ + usr/lib/ep11_stdll/new_host.c \ + usr/lib/ep11_stdll/ep11_specific.c \ + usr/lib/common/utility_common.c usr/lib/common/ec_supported.c \ + usr/lib/api/policyhelper.c if ENABLE_LOCKS opencryptoki_stdll_libpkcs11_ep11_la_SOURCES += \ diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/ep11_stdll/ep11tok.conf opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/ep11_stdll/ep11tok.conf --- opencryptoki-3.16.0+dfsg/usr/lib/ep11_stdll/ep11tok.conf 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/ep11_stdll/ep11tok.conf 2022-02-02 15:05:41.000000000 +0100 @@ -80,7 +80,7 @@ # There are 2 ways to specify the crypto adapters: # 1) explicitly list of adapter/domain pairs # -# APQN_WHITELIST +# APQN_ALLOWLIST # 8 13 # 10 13 # END @@ -88,7 +88,7 @@ # The adapter and domain may be given in decimal, # octal (with leading 0) or hexadecimal (with leading 0x): # -# APQN_WHITELIST +# APQN_ALLOWLIST # 8 0x0d # 0x0a 13 # END diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/ep11_stdll/new_host.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/ep11_stdll/new_host.c --- opencryptoki-3.16.0+dfsg/usr/lib/ep11_stdll/new_host.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/ep11_stdll/new_host.c 2022-02-02 15:05:41.000000000 +0100 @@ -39,6 +39,7 @@ #include "ep11_specific.h" #include "../api/apiproto.h" +#include "../api/policy.h" void SC_SetFunctionList(void); CK_RV SC_Finalize(STDLL_TokData_t *tokdata, CK_SLOT_ID sid, SLOT_INFO *sinfp, @@ -72,34 +73,12 @@ { CK_RV rc = CKR_OK; char abs_tokdir_name[PATH_MAX]; - - if ((rc = check_user_and_group()) != CKR_OK) - return rc; + CK_BBOOL newdatastore; + policy_t policy = sltp->TokData->policy; /* set trace info */ set_trace(t); - if (sltp->TokData != NULL) { - TRACE_ERROR("Already initialized.\n"); - return CKR_CRYPTOKI_ALREADY_INITIALIZED; - } - - /* - * Create separate memory area for each token specific data - */ - sltp->TokData = (STDLL_TokData_t *) calloc(1, sizeof(STDLL_TokData_t)); - if (!sltp->TokData) { - TRACE_ERROR("Allocating host memory failed.\n"); - return CKR_HOST_MEMORY; - } - - sltp->TokData->ro_session_count = 0; - sltp->TokData->global_login_state = CKS_RO_PUBLIC_SESSION; -#ifdef ENABLE_LOCKS - pthread_rwlock_init(&sltp->TokData->sess_list_rwlock, NULL); -#endif - pthread_mutex_init(&sltp->TokData->login_mutex, NULL); - bt_init(&sltp->TokData->sess_btree, free); bt_init(&sltp->TokData->object_map_btree, free); bt_init(&sltp->TokData->sess_obj_btree, call_object_free); @@ -132,6 +111,16 @@ (unsigned int)(sinfp->version >> 16), (unsigned int)(sinfp->version & 0xffff)); + /* Check token store encryption against policy */ + newdatastore = sinfp->version >= TOK_NEW_DATA_STORE ? CK_TRUE : CK_FALSE; + rc = policy->check_token_store(policy, newdatastore, + token_specific.data_store.encryption_algorithm, + SlotNumber, &sltp->TokData->store_strength); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Token cannot load since data store encryption is too weak for policy.\n"); + goto done; + } + /* Initialize Lock */ if (XProcLock_Init(sltp->TokData) != CKR_OK) { TRACE_ERROR("Thread lock failed.\n"); @@ -164,9 +153,7 @@ if (rc != 0) { sltp->FcnList = NULL; detach_shm(sltp->TokData, 0); - if (sltp->TokData) - free(sltp->TokData); - sltp->TokData = NULL; + final_data_store(sltp->TokData); TRACE_DEVEL("Token Specific Init failed.\n"); goto done; } @@ -176,9 +163,7 @@ rc = load_token_data(sltp->TokData, SlotNumber); if (rc != CKR_OK) { sltp->FcnList = NULL; - if (sltp->TokData) - free(sltp->TokData); - sltp->TokData = NULL; + final_data_store(sltp->TokData); TRACE_DEVEL("Failed to load token data. (rc=0x%02lx)\n", rc); goto done; } @@ -208,8 +193,7 @@ SC_Finalize(sltp->TokData, SlotNumber, sinfp, NULL, 0); } else { CloseXProcLock(sltp->TokData); - free(sltp->TokData); - sltp->TokData = NULL; + final_data_store(sltp->TokData); } } @@ -254,11 +238,6 @@ bt_destroy(&tokdata->priv_token_obj_btree); bt_destroy(&tokdata->publ_token_obj_btree); -#ifdef ENABLE_LOCKS - pthread_rwlock_destroy(&tokdata->sess_list_rwlock); -#endif - pthread_mutex_destroy(&tokdata->login_mutex); - detach_shm(tokdata, in_fork_initializer); /* close spin lock file */ CloseXProcLock(tokdata); @@ -270,9 +249,6 @@ final_data_store(tokdata); - if (tokdata) - free(tokdata); - return rc; } @@ -298,7 +274,7 @@ goto done; } copy_token_contents_sensibly(pInfo, tokdata->nv_token_data); - ep11tok_copy_firmware_info(tokdata, pInfo); + rc = ep11tok_copy_firmware_info(tokdata, pInfo); /* Set the time */ now = time((time_t *) NULL); @@ -437,6 +413,10 @@ dat = &tokdata->nv_token_data->dat; if (tokdata->version < TOK_NEW_DATA_STORE) { rc = compute_sha1(tokdata, pPin, ulPinLen, hash_sha); + if (rc != CKR_OK) { + TRACE_DEVEL("compute_sha1 failed.\n"); + goto done; + } if (memcmp(tokdata->nv_token_data->so_pin_sha, hash_sha, SHA1_HASH_SIZE) != 0) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT)); @@ -444,13 +424,12 @@ goto done; } } else { - rc = PKCS5_PBKDF2_HMAC((char *)pPin, ulPinLen, - dat->so_login_salt, 64, - dat->so_login_it, EVP_sha512(), - 256 / 8, login_key); - if (rc != 1) { + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pPin, ulPinLen, + dat->so_login_salt, 64, + dat->so_login_it, EVP_sha512(), + 256 / 8, login_key); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - rc = CKR_FUNCTION_FAILED; goto done; } if (CRYPTO_memcmp(dat->so_login_key, login_key, 32) != 0) { @@ -519,7 +498,7 @@ return CKR_FUNCTION_FAILED; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -558,13 +537,13 @@ memcpy(login_salt, USER_KDF_LOGIN_PURPOSE, 32); rng_generate(tokdata, login_salt + 32, 32); - rc = PKCS5_PBKDF2_HMAC((char *)pPin, ulPinLen, - login_salt, 64, - login_it, EVP_sha512(), - 256 / 8, login_key); - if (rc != 1) { + + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pPin, ulPinLen, + login_salt, 64, + login_it, EVP_sha512(), + 256 / 8, login_key); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - rc = CKR_FUNCTION_FAILED; goto done; } @@ -572,13 +551,12 @@ memcpy(wrap_salt, USER_KDF_WRAP_PURPOSE, 32); rng_generate(tokdata, wrap_salt + 32, 32); - rc = PKCS5_PBKDF2_HMAC((char *)pPin, ulPinLen, - wrap_salt, 64, - wrap_it, EVP_sha512(), - 256 / 8, wrap_key); - if (rc != 1) { + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pPin, ulPinLen, + wrap_salt, 64, + wrap_it, EVP_sha512(), + 256 / 8, wrap_key); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - rc = CKR_FUNCTION_FAILED; goto done; } } @@ -661,7 +639,7 @@ return CKR_FUNCTION_FAILED; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -728,13 +706,12 @@ memcpy(login_salt, USER_KDF_LOGIN_PURPOSE, 32); rng_generate(tokdata, login_salt + 32, 32); - rc = PKCS5_PBKDF2_HMAC((char *)pNewPin, ulNewLen, - login_salt, 64, - login_it, EVP_sha512(), - 256 / 8, new_login_key); - if (rc != 1) { + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pNewPin, ulNewLen, + login_salt, 64, + login_it, EVP_sha512(), + 256 / 8, new_login_key); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - rc = CKR_FUNCTION_FAILED; goto done; } @@ -742,32 +719,30 @@ memcpy(wrap_salt, USER_KDF_WRAP_PURPOSE, 32); rng_generate(tokdata, wrap_salt + 32, 32); - rc = PKCS5_PBKDF2_HMAC((char *)pNewPin, ulNewLen, - wrap_salt, 64, - wrap_it, EVP_sha512(), - 256 / 8, new_wrap_key); - if (rc != 1) { + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pNewPin, ulNewLen, + wrap_salt, 64, + wrap_it, EVP_sha512(), + 256 / 8, new_wrap_key); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - rc = CKR_FUNCTION_FAILED; goto done; } - rc = PKCS5_PBKDF2_HMAC((char *)pOldPin, ulOldLen, - dat->user_login_salt, 64, - dat->user_login_it, EVP_sha512(), - 256 / 8, old_login_key); - if (rc != 1) { + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pOldPin, ulOldLen, + dat->user_login_salt, 64, + dat->user_login_it, EVP_sha512(), + 256 / 8, old_login_key); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - rc = CKR_FUNCTION_FAILED; goto done; } - rc = PKCS5_PBKDF2_HMAC((char *)pNewPin, ulNewLen, - dat->user_login_salt, 64, - dat->user_login_it, EVP_sha512(), - 256 / 8, new_login_key_old_salt); - if (rc != 1) { + + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pNewPin, ulNewLen, + dat->user_login_salt, 64, + dat->user_login_it, EVP_sha512(), + 256 / 8, new_login_key_old_salt); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - rc = CKR_FUNCTION_FAILED; goto done; } @@ -852,13 +827,12 @@ memcpy(login_salt, SO_KDF_LOGIN_PURPOSE, 32); rng_generate(tokdata, login_salt + 32, 32); - rc = PKCS5_PBKDF2_HMAC((char *)pNewPin, ulNewLen, - login_salt, 64, - login_it, EVP_sha512(), - 256 / 8, new_login_key); - if (rc != 1) { + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pNewPin, ulNewLen, + login_salt, 64, + login_it, EVP_sha512(), + 256 / 8, new_login_key); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - rc = CKR_FUNCTION_FAILED; goto done; } @@ -866,32 +840,30 @@ memcpy(wrap_salt, SO_KDF_WRAP_PURPOSE, 32); rng_generate(tokdata, wrap_salt + 32, 32); - rc = PKCS5_PBKDF2_HMAC((char *)pNewPin, ulNewLen, - wrap_salt, 64, - wrap_it, EVP_sha512(), - 256 / 8, new_wrap_key); - if (rc != 1) { + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pNewPin, ulNewLen, + wrap_salt, 64, + wrap_it, EVP_sha512(), + 256 / 8, new_wrap_key); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - rc = CKR_FUNCTION_FAILED; goto done; } - rc = PKCS5_PBKDF2_HMAC((char *)pOldPin, ulOldLen, - dat->so_login_salt, 64, - dat->so_login_it, EVP_sha512(), - 256 / 8, old_login_key); - if (rc != 1) { + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pOldPin, ulOldLen, + dat->so_login_salt, 64, + dat->so_login_it, EVP_sha512(), + 256 / 8, old_login_key); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - rc = CKR_FUNCTION_FAILED; goto done; } - rc = PKCS5_PBKDF2_HMAC((char *)pNewPin, ulNewLen, - dat->so_login_salt, 64, - dat->so_login_it, EVP_sha512(), - 256 / 8, new_login_key_old_salt); - if (rc != 1) { + + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pNewPin, ulNewLen, + dat->so_login_salt, 64, + dat->so_login_it, EVP_sha512(), + 256 / 8, new_login_key_old_salt); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - rc = CKR_FUNCTION_FAILED; goto done; } @@ -997,7 +969,7 @@ return rc; } - sess = session_mgr_find(tokdata, *phSession); + sess = session_mgr_find_reset_error(tokdata, *phSession); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; @@ -1058,7 +1030,7 @@ if (session_mgr_so_session_exists(tokdata) || session_mgr_user_session_exists(tokdata)) { - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1171,7 +1143,7 @@ if (!pOperationState) length_only = TRUE; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1216,15 +1188,16 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } - rc = session_mgr_set_op_state(sess, hEncryptionKey, hAuthenticationKey, - pOperationState, ulOperationStateLen); + rc = session_mgr_set_op_state(tokdata, sess, hEncryptionKey, + hAuthenticationKey, pOperationState, + ulOperationStateLen); if (rc != CKR_OK) TRACE_DEVEL("session_mgr_set_op_state() failed.\n"); @@ -1264,7 +1237,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1335,6 +1308,10 @@ } rc = compute_sha1(tokdata, pPin, ulPinLen, hash_sha); + if (rc != CKR_OK) { + TRACE_DEVEL("compute_sha1 failed.\n"); + goto done; + } if (memcmp(tokdata->nv_token_data->user_pin_sha, hash_sha, SHA1_HASH_SIZE) != 0) { set_login_flags(userType, flags); @@ -1349,22 +1326,21 @@ compute_md5(tokdata, pPin, ulPinLen, tokdata->user_pin_md5); memset(tokdata->so_pin_md5, 0x0, MD5_HASH_SIZE); } else { - rc = PKCS5_PBKDF2_HMAC((char *)pPin, ulPinLen, - dat->user_login_salt, 64, - dat->user_login_it, EVP_sha512(), - 256 / 8, login_key); - if (rc != 1) { + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pPin, ulPinLen, + dat->user_login_salt, 64, + dat->user_login_it, EVP_sha512(), + 256 / 8, login_key); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - rc = CKR_FUNCTION_FAILED; goto done; } - rc = PKCS5_PBKDF2_HMAC((char *)pPin, ulPinLen, - dat->user_wrap_salt, 64, - dat->user_wrap_it, EVP_sha512(), - 256 / 8, wrap_key); - if (rc != 1) { + + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pPin, ulPinLen, + dat->user_wrap_salt, 64, + dat->user_wrap_it, EVP_sha512(), + 256 / 8, wrap_key); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - rc = CKR_FUNCTION_FAILED; goto done; } @@ -1417,6 +1393,10 @@ if (tokdata->version < TOK_NEW_DATA_STORE) { rc = compute_sha1(tokdata, pPin, ulPinLen, hash_sha); + if (rc != CKR_OK) { + TRACE_DEVEL("compute_sha1 failed.\n"); + goto done; + } if (memcmp(tokdata->nv_token_data->so_pin_sha, hash_sha, SHA1_HASH_SIZE) != 0) { set_login_flags(userType, flags); @@ -1431,22 +1411,21 @@ compute_md5(tokdata, pPin, ulPinLen, tokdata->so_pin_md5); memset(tokdata->user_pin_md5, 0x0, MD5_HASH_SIZE); } else { - rc = PKCS5_PBKDF2_HMAC((char *)pPin, ulPinLen, - dat->so_login_salt, 64, - dat->so_login_it, EVP_sha512(), - 256 / 8, login_key); - if (rc != 1) { + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pPin, ulPinLen, + dat->so_login_salt, 64, + dat->so_login_it, EVP_sha512(), + 256 / 8, login_key); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - rc = CKR_FUNCTION_FAILED; goto done; } - rc = PKCS5_PBKDF2_HMAC((char *)pPin, ulPinLen, - dat->so_wrap_salt, 64, - dat->so_wrap_it, EVP_sha512(), - 256 / 8, wrap_key); - if (rc != 1) { + + rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pPin, ulPinLen, + dat->so_wrap_salt, 64, + dat->so_wrap_it, EVP_sha512(), + 256 / 8, wrap_key); + if (rc != CKR_OK) { TRACE_DEVEL("PBKDF2 failed.\n"); - rc = CKR_FUNCTION_FAILED; goto done; } @@ -1513,7 +1492,7 @@ return CKR_FUNCTION_FAILED; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1564,7 +1543,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1578,6 +1557,7 @@ goto done; } + /* Enforces policy */ rc = object_mgr_add(tokdata, sess, pTemplate, ulCount, phObject); if (rc != CKR_OK) TRACE_DEVEL("object_mgr_add() failed.\n"); @@ -1620,7 +1600,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1634,6 +1614,7 @@ goto done; } + /* Enforces policy */ rc = object_mgr_copy(tokdata, sess, pTemplate, ulCount, hObject, phNewObject); if (rc != CKR_OK) @@ -1662,7 +1643,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1702,7 +1683,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1737,7 +1718,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1765,13 +1746,14 @@ for (i = 0; i < ulCount; i++, attr++) { TRACE_DEBUG("%lu: Attribute type: 0x%08lx, Value Length: %lu\n", i, attr->type, attr->ulValueLen); - - if (attr->ulValueLen >= sizeof(val) && attr->pValue != NULL) { - memset(val, 0, sizeof(val)); - memcpy(val, attr->pValue, attr->ulValueLen > sizeof(val) ? - sizeof(val) : attr->ulValueLen); - TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n", + if (rc == CKR_OK && attr->ulValueLen != CK_UNAVAILABLE_INFORMATION) { + if (attr->ulValueLen >= sizeof(val) && attr->pValue != NULL) { + memset(val, 0, sizeof(val)); + memcpy(val, attr->pValue, attr->ulValueLen > sizeof(val) ? + sizeof(val) : attr->ulValueLen); + TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n", val[0], val[1], val[2], val[3]); + } } } #endif @@ -1794,7 +1776,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1850,7 +1832,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1922,7 +1904,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1972,7 +1954,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2027,7 +2009,7 @@ if (rc != CKR_OK) goto done; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2109,7 +2091,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2160,7 +2142,7 @@ done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) { if (sess) - encr_mgr_cleanup(&sess->encr_ctx); + encr_mgr_cleanup(tokdata, sess, &sess->encr_ctx); } TRACE_INFO("C_Encrypt: rc = 0x%08lx, sess = %ld, amount = %lu\n", @@ -2187,7 +2169,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2236,7 +2218,7 @@ done: if (rc != CKR_OK && rc != CKR_BUFFER_TOO_SMALL) { if (sess) - encr_mgr_cleanup(&sess->encr_ctx); + encr_mgr_cleanup(tokdata, sess, &sess->encr_ctx); } TRACE_INFO("C_EncryptUpdate: rc = 0x%08lx, sess = %ld, amount = %lu\n", @@ -2263,7 +2245,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2310,7 +2292,7 @@ done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) { if (sess) - encr_mgr_cleanup(&sess->encr_ctx); + encr_mgr_cleanup(tokdata, sess, &sess->encr_ctx); } TRACE_INFO("C_EncryptFinal: rc = 0x%08lx, sess = %ld\n", @@ -2345,7 +2327,7 @@ if (rc != CKR_OK) goto done; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2427,7 +2409,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2478,7 +2460,7 @@ done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) { if (sess) - decr_mgr_cleanup(&sess->decr_ctx); + decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx); } TRACE_INFO("C_Decrypt: rc = 0x%08lx, sess = %ld, amount = %lu\n", @@ -2505,7 +2487,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2554,7 +2536,7 @@ done: if (rc != CKR_OK && rc != CKR_BUFFER_TOO_SMALL && sess != NULL) { if (sess) - decr_mgr_cleanup(&sess->decr_ctx); + decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx); } TRACE_INFO("C_DecryptUpdate: rc = 0x%08lx, sess = %ld, amount = %lu\n", @@ -2581,7 +2563,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2626,7 +2608,7 @@ done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) { if (sess) - decr_mgr_cleanup(&sess->decr_ctx); + decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx); } TRACE_INFO("C_DecryptFinal: rc = 0x%08lx, sess = %ld, amount = %lu\n", @@ -2661,12 +2643,18 @@ if (rc != CKR_OK) goto done; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } + rc = tokdata->policy->is_mech_allowed(tokdata->policy, pMechanism, NULL, + POLICY_CHECK_DIGEST, sess); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY_VIOLATION on digest initialization\n"); + goto done; + } if (pin_expired(&sess->session_info, tokdata->nv_token_data->token_info.flags) == TRUE) { @@ -2681,7 +2669,9 @@ goto done; } - rc = digest_mgr_init(tokdata, sess, &sess->digest_ctx, pMechanism); + sess->digest_ctx.count_statistics = TRUE; + /* Policy already checked. */ + rc = digest_mgr_init(tokdata, sess, &sess->digest_ctx, pMechanism, FALSE); if (rc != CKR_OK) TRACE_DEVEL("digest_mgr_init() failed.\n"); @@ -2711,7 +2701,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2755,7 +2745,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2817,7 +2807,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2867,7 +2857,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2892,8 +2882,9 @@ } if (ep11tok_libica_mech_available(tokdata, pMechanism->mechanism, hKey)) { + sess->sign_ctx.count_statistics = TRUE; rc = sign_mgr_init(tokdata, sess, &sess->sign_ctx, pMechanism, FALSE, - hKey); + hKey, TRUE); if (rc != CKR_OK) TRACE_DEVEL("sign_mgr_init() failed.\n"); @@ -2962,7 +2953,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -3022,7 +3013,7 @@ done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) { if (sess != NULL) - sign_mgr_cleanup(&sess->sign_ctx); + sign_mgr_cleanup(tokdata, sess, &sess->sign_ctx); } TRACE_INFO("C_Sign: rc = 0x%08lx, sess = %ld, datalen = %lu\n", @@ -3047,7 +3038,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -3104,7 +3095,7 @@ done: if (rc != CKR_OK && sess != NULL) - sign_mgr_cleanup(&sess->sign_ctx); + sign_mgr_cleanup(tokdata, sess, &sess->sign_ctx); TRACE_INFO("C_SignUpdate: rc = 0x%08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulPartLen); @@ -3129,7 +3120,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -3185,7 +3176,7 @@ done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) { if (sess != NULL) - sign_mgr_cleanup(&sess->sign_ctx); + sign_mgr_cleanup(tokdata, sess, &sess->sign_ctx); } TRACE_INFO("C_SignFinal: rc = 0x%08lx, sess = %ld\n", @@ -3259,7 +3250,7 @@ if (rc != CKR_OK) goto done; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -3280,8 +3271,9 @@ } if (ep11tok_libica_mech_available(tokdata, pMechanism->mechanism, hKey)) { + sess->verify_ctx.count_statistics = TRUE; rc = verify_mgr_init(tokdata, sess, &sess->verify_ctx, pMechanism, - FALSE, hKey); + FALSE, hKey, TRUE); if (rc != CKR_OK) TRACE_DEVEL("verify_mgr_init() failed.\n"); @@ -3350,7 +3342,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -3406,7 +3398,7 @@ done: if (sess != NULL) - verify_mgr_cleanup(&sess->verify_ctx); + verify_mgr_cleanup(tokdata, sess, &sess->verify_ctx); TRACE_INFO("C_Verify: rc = 0x%08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulDataLen); @@ -3430,7 +3422,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -3487,7 +3479,7 @@ done: if (rc != CKR_OK && sess != NULL) - verify_mgr_cleanup(&sess->verify_ctx); + verify_mgr_cleanup(tokdata, sess, &sess->verify_ctx); TRACE_INFO("C_VerifyUpdate: rc = 0x%08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulPartLen); @@ -3511,7 +3503,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -3562,7 +3554,7 @@ done: if (sess != NULL) - verify_mgr_cleanup(&sess->verify_ctx); + verify_mgr_cleanup(tokdata, sess, &sess->verify_ctx); TRACE_INFO("C_VerifyFinal: rc = 0x%08lx, sess = %ld\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle); @@ -3727,12 +3719,18 @@ if (rc != CKR_OK) goto done; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } + rc = tokdata->policy->is_mech_allowed(tokdata->policy, pMechanism, NULL, + POLICY_CHECK_KEYGEN, sess); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Key generation mechanism not allowed\n"); + goto done; + } if (pin_expired(&sess->session_info, tokdata->nv_token_data->token_info.flags) == TRUE) { @@ -3809,12 +3807,18 @@ if (rc != CKR_OK) goto done; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } + rc = tokdata->policy->is_mech_allowed(tokdata->policy, pMechanism, NULL, + POLICY_CHECK_KEYGEN, sess); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Keypair generation mechanism not allowed\n"); + goto done; + } if (pin_expired(&sess->session_info, tokdata->nv_token_data->token_info.flags) == TRUE) { @@ -3890,7 +3894,7 @@ if (rc != CKR_OK) goto done; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -3947,7 +3951,7 @@ if (rc != CKR_OK) goto done; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -4029,7 +4033,7 @@ if (rc != CKR_OK) goto done; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -4139,7 +4143,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -4215,7 +4219,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -4242,6 +4246,8 @@ goto done; } + sess->decr_ctx.count_statistics = TRUE; + sess->encr_ctx.count_statistics = TRUE; rc = encr_mgr_reencrypt_single(tokdata, sess, &sess->decr_ctx, pDecrMech, hDecrKey, &sess->encr_ctx, pEncrMech, hEncrKey, pEncryptedData, ulEncryptedDataLen, @@ -4262,6 +4268,24 @@ return rc; } +CK_RV SC_HandleEvent(STDLL_TokData_t *tokdata, unsigned int event_type, + unsigned int event_flags, const char *payload, + unsigned int payload_len) +{ + CK_RV rc; + + if (token_specific.t_handle_event == NULL) + return CKR_FUNCTION_NOT_SUPPORTED; + + rc = token_specific.t_handle_event(tokdata, event_type, event_flags, + payload, payload_len); + + TRACE_INFO("SC_HandleEvent: rc = 0x%08lx, event_type = 0x%08x, " + "event_flags = 0x%08x\n", rc, event_type, event_flags); + + return rc; +} + void SC_SetFunctionList(void) { function_list.ST_Initialize = ST_Initialize; @@ -4327,4 +4351,6 @@ function_list.ST_CancelFunction = NULL; // SC_CancelFunction; function_list.ST_IBM_ReencryptSingle = SC_IBM_ReencryptSingle; + + function_list.ST_HandleEvent = SC_HandleEvent; } diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/ep11_stdll/tok_struct.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/ep11_stdll/tok_struct.h --- opencryptoki-3.16.0+dfsg/usr/lib/ep11_stdll/tok_struct.h 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/ep11_stdll/tok_struct.h 2022-02-02 15:05:41.000000000 +0100 @@ -137,6 +137,7 @@ &token_specific_reencrypt_single, &token_specific_set_attribute_values, &token_specific_set_attrs_for_new_object, + &token_specific_handle_event, }; #endif diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/ica_s390_stdll/ica_s390_stdll.mk opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/ica_s390_stdll/ica_s390_stdll.mk --- opencryptoki-3.16.0+dfsg/usr/lib/ica_s390_stdll/ica_s390_stdll.mk 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/ica_s390_stdll/ica_s390_stdll.mk 2022-02-02 15:05:41.000000000 +0100 @@ -7,7 +7,8 @@ -DNODH -DNOCDMF -DNOMD2 -DNODSA -DSTDLL_NAME=\"icatok\" \ -DTOK_NEW_DATA_STORE=0x0003000c \ $(ICA_INC_DIRS) -I${srcdir}/usr/lib/ica_s390_stdll \ - -I${srcdir}/usr/lib/common -I${srcdir}/usr/include + -I${srcdir}/usr/lib/common -I${srcdir}/usr/include \ + -I${top_builddir}/usr/lib/api -I${srcdir}/usr/lib/api opencryptoki_stdll_libpkcs11_ica_la_LDFLAGS = \ $(LCRYPTO) $(ICA_LIB_DIRS) -nostartfiles -shared \ @@ -34,7 +35,10 @@ usr/lib/common/verify_mgr.c usr/lib/common/trace.c \ usr/lib/common/mech_list.c usr/lib/common/shared_memory.c \ usr/lib/common/profile_obj.c usr/lib/common/attributes.c \ - usr/lib/ica_s390_stdll/ica_specific.c + usr/lib/ica_s390_stdll/ica_specific.c usr/lib/common/dlist.c \ + usr/lib/common/mech_openssl.c \ + usr/lib/common/utility_common.c usr/lib/common/ec_supported.c \ + usr/lib/api/policyhelper.c if ENABLE_LOCKS opencryptoki_stdll_libpkcs11_ica_la_SOURCES += \ diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/ica_s390_stdll/ica_specific.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/ica_s390_stdll/ica_specific.c --- opencryptoki-3.16.0+dfsg/usr/lib/ica_s390_stdll/ica_specific.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/ica_s390_stdll/ica_specific.c 2022-02-02 15:05:41.000000000 +0100 @@ -27,6 +27,7 @@ #include "host_defs.h" #include "h_extern.h" #include "trace.h" +#include "pkcs_utils.h" #include @@ -45,11 +46,25 @@ #endif #include -#define ICA_MAX_MECH_LIST_ENTRIES 98 +#define ICA_MAX_MECH_LIST_ENTRIES 120 typedef struct { ica_adapter_handle_t adapter_handle; int ica_ec_support_available; + int ica_ec_keygen_available; + int ica_ec_signverify_available; + int ica_ec_derive_available; + int ica_rsa_keygen_available; + int ica_rsa_endecrypt_available; + int ica_p_rng_available; + int ica_sha1_available; + int ica_sha2_available; + int ica_sha512_224_available; + int ica_sha512_256_available; + int ica_sha3_available; + int ica_aes_available; + int ica_des_available; + int ica_des3_available; MECH_LIST_ELEMENT mech_list[ICA_MAX_MECH_LIST_ENTRIES]; CK_ULONG mech_list_len; } ica_private_data_t; @@ -68,7 +83,8 @@ static pthread_mutex_t rngmtx = PTHREAD_MUTEX_INITIALIZER; -#define LIBICA_SHARED_LIB "libica.so.3" +#define LIBICA_SHARED_LIB_V3 "libica.so.3" +#define LIBICA_SHARED_LIB_V4 "libica.so.4" #define BIND(dso, sym) do { \ if (p_##sym == NULL) \ *(void **)(&p_##sym) = dlsym(dso, #sym); \ @@ -206,9 +222,13 @@ void *ibmca_dso = NULL; /* Load libica */ - ibmca_dso = dlopen(LIBICA_SHARED_LIB, RTLD_NOW); + ibmca_dso = dlopen(LIBICA_SHARED_LIB_V4, RTLD_NOW); + if (ibmca_dso == NULL) + ibmca_dso = dlopen(LIBICA_SHARED_LIB_V3, RTLD_NOW); + if (ibmca_dso == NULL) { - TRACE_ERROR("%s: dlopen(%s) failed\n", __func__, LIBICA_SHARED_LIB); + TRACE_ERROR("%s: dlopen(%s or %s) failed: %s\n", __func__, + LIBICA_SHARED_LIB_V4, LIBICA_SHARED_LIB_V3, dlerror()); return CKR_FUNCTION_FAILED; } @@ -250,23 +270,26 @@ CK_RV token_specific_rng(STDLL_TokData_t *tokdata, CK_BYTE *output, CK_ULONG bytes) { - unsigned int rc; - - UNUSED(tokdata); + ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; + CK_RV rc = CKR_FUNCTION_FAILED; - pthread_mutex_lock(&rngmtx); + if (ica_data->ica_p_rng_available) { + if (pthread_mutex_lock(&rngmtx)) { + TRACE_ERROR("ICA Rng Lock failed.\n"); + return CKR_CANT_LOCK; + } - rc = ica_random_number_generate((unsigned int) bytes, output); + rc = ica_random_number_generate((unsigned int)bytes, output); + if (rc != 0) + ica_data->ica_p_rng_available = FALSE; - if (rc != 0) { pthread_mutex_unlock(&rngmtx); - return CKR_GENERAL_ERROR; - /* report error */ } - pthread_mutex_unlock(&rngmtx); + if (!ica_data->ica_p_rng_available) + rc = local_rng(output, bytes); - return CKR_OK; + return rc; } CK_RV token_specific_init(STDLL_TokData_t *tokdata, CK_SLOT_ID SlotNumber, @@ -294,8 +317,15 @@ goto out; } - tokdata->mech_list = ica_data->mech_list; - tokdata->mech_list_len = ica_data->mech_list_len; + rc = ock_generic_filter_mechanism_list(tokdata, + ica_data->mech_list, + ica_data->mech_list_len, + &(tokdata->mech_list), + &(tokdata->mech_list_len)); + if (rc != CKR_OK) { + TRACE_ERROR("Mechanism filtering failed! rc = 0x%lx\n", rc); + return rc; + } TRACE_INFO("ica %s slot=%lu running\n", __func__, SlotNumber); @@ -323,6 +353,7 @@ TRACE_INFO("ica %s running\n", __func__); ica_close_adapter(ica_data->adapter_handle); + free(tokdata->mech_list); free(ica_data); tokdata->private_data = NULL; @@ -397,10 +428,13 @@ CK_ULONG *out_data_len, OBJECT *key, CK_BYTE encrypt) { + ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; CK_RV rc; CK_ATTRIBUTE *attr = NULL; - UNUSED(tokdata); + if (!ica_data->ica_des_available) + return openssl_specific_des_ecb(tokdata, in_data, in_data_len, + out_data, out_data_len, key, encrypt); /* * checks for input and output data length and block sizes @@ -440,10 +474,14 @@ CK_ULONG *out_data_len, OBJECT *key, CK_BYTE *init_v, CK_BYTE encrypt) { + ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; CK_RV rc; CK_ATTRIBUTE *attr = NULL; - UNUSED(tokdata); + if (!ica_data->ica_des_available) + return openssl_specific_des_cbc(tokdata, in_data, in_data_len, + out_data, out_data_len, key, + init_v, encrypt); /* * checks for input and output data length and block sizes @@ -483,12 +521,15 @@ CK_ULONG *out_data_len, OBJECT *key, CK_BYTE encrypt) { + ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; CK_RV rc; CK_ATTRIBUTE *attr = NULL; CK_KEY_TYPE keytype; CK_BYTE key_value[3 * DES_KEY_SIZE]; - UNUSED(tokdata); + if (!ica_data->ica_des3_available) + return openssl_specific_tdes_ecb(tokdata, in_data, in_data_len, + out_data, out_data_len, key, encrypt); /* * checks for input and output data length and block sizes @@ -543,12 +584,16 @@ CK_ULONG *out_data_len, OBJECT *key, CK_BYTE *init_v, CK_BYTE encrypt) { + ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; CK_RV rc; CK_ATTRIBUTE *attr = NULL; CK_KEY_TYPE keytype; CK_BYTE key_value[3 * DES_KEY_SIZE]; - UNUSED(tokdata); + if (!ica_data->ica_des3_available) + return openssl_specific_tdes_cbc(tokdata, in_data, in_data_len, + out_data, out_data_len, key, + init_v, encrypt); /* * checks for input and output data length and block sizes @@ -604,10 +649,13 @@ CK_BYTE *out_data, CK_ULONG data_len, OBJECT *key, CK_BYTE *iv, uint_32 direction) { + ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; CK_RV rc; CK_ATTRIBUTE *attr = NULL; - UNUSED(tokdata); + if (!ica_data->ica_des3_available) + return openssl_specific_tdes_ofb(tokdata, in_data, data_len, out_data, + key, iv, direction); rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); if (rc != CKR_OK) { @@ -636,10 +684,13 @@ OBJECT *key, CK_BYTE *iv, uint_32 cfb_len, uint_32 direction) { + ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; CK_RV rc; CK_ATTRIBUTE *attr = NULL; - UNUSED(tokdata); + if (!ica_data->ica_des3_available) + return openssl_specific_tdes_cfb(tokdata, in_data, data_len, out_data, + key, iv, cfb_len, direction); rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); if (rc != CKR_OK) { @@ -662,12 +713,15 @@ CK_RV token_specific_tdes_mac(STDLL_TokData_t *tokdata, CK_BYTE *message, CK_ULONG message_len, OBJECT *key, CK_BYTE *mac) { + ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; CK_RV rc; CK_ATTRIBUTE *attr = NULL; CK_KEY_TYPE keytype; CK_BYTE key_value[3 * DES_KEY_SIZE]; - UNUSED(tokdata); + if (!ica_data->ica_des3_available) + return openssl_specific_tdes_mac(tokdata, message, message_len, + key, mac); // get the key type rc = template_attribute_get_ulong(key->template, CKA_KEY_TYPE, &keytype); @@ -705,13 +759,18 @@ CK_ULONG message_len, OBJECT *key, CK_BYTE *mac, CK_BBOOL first, CK_BBOOL last, CK_VOID_PTR *ctx) { + ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; CK_RV rc; CK_ATTRIBUTE *attr = NULL; CK_KEY_TYPE keytype; CK_BYTE key_value[3 * DES_KEY_SIZE]; - UNUSED(tokdata); - UNUSED(ctx); + if (!ica_data->ica_des3_available) + return openssl_specific_tdes_cmac(tokdata, message, message_len, + key, mac, first, last, ctx); + + if (key == NULL) + return CKR_ARGUMENTS_BAD; // get the key type rc = template_attribute_get_ulong(key->template, CKA_KEY_TYPE, &keytype); @@ -755,6 +814,32 @@ return rc; } +int ica_sha_supported(STDLL_TokData_t *tokdata, CK_MECHANISM_TYPE mech) +{ + ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; + + switch (mech) { + case CKM_SHA_1: + return ica_data->ica_sha1_available; + case CKM_SHA224: + case CKM_SHA256: + case CKM_SHA384: + case CKM_SHA512: + return ica_data->ica_sha2_available; + case CKM_SHA512_224: + return ica_data->ica_sha512_224_available; + case CKM_SHA512_256: + return ica_data->ica_sha512_256_available; + case CKM_IBM_SHA3_224: + case CKM_IBM_SHA3_256: + case CKM_IBM_SHA3_384: + case CKM_IBM_SHA3_512: + return ica_data->ica_sha3_available; + default: + return FALSE; + } +} + /* * Init SHA data structures */ @@ -764,7 +849,8 @@ unsigned int ctxsize, devctxsize; struct oc_sha_ctx *sc; - UNUSED(tokdata); + if (!ica_sha_supported(tokdata, mech->mechanism)) + return openssl_specific_sha_init(tokdata, ctx, mech); ctxsize = (sizeof(struct oc_sha_ctx) + 0x000F) & ~0x000F; switch (mech->mechanism) { @@ -810,8 +896,10 @@ } /* (re)alloc ctx in one memory area */ - if (ctx->context) + if (ctx->context) { free(ctx->context); + ctx->context_free_func = NULL; + } ctx->context_len = 0; ctx->context = malloc(ctxsize + devctxsize); if (ctx->context == NULL) { @@ -895,9 +983,14 @@ struct oc_sha_ctx *sc; void *dev_ctx; - UNUSED(tokdata); + if (!ctx) + return CKR_OPERATION_NOT_INITIALIZED; + + if (!ica_sha_supported(tokdata, ctx->mech.mechanism)) + return openssl_specific_sha(tokdata, ctx, in_data, in_data_len, + out_data, out_data_len); - if (!ctx || !ctx->context) + if (!ctx->context) return CKR_OPERATION_NOT_INITIALIZED; if (!in_data || !out_data) @@ -1223,9 +1316,13 @@ struct oc_sha_ctx *sc; int fill, len, rest, ret; - UNUSED(tokdata); + if (!ctx) + return CKR_OPERATION_NOT_INITIALIZED; - if (!ctx || !ctx->context) + if (!ica_sha_supported(tokdata, ctx->mech.mechanism)) + return openssl_specific_sha_update(tokdata, ctx, in_data, in_data_len); + + if (!ctx->context) return CKR_OPERATION_NOT_INITIALIZED; if (!in_data_len) @@ -1304,9 +1401,13 @@ struct oc_sha_ctx *sc; void *dev_ctx; - UNUSED(tokdata); + if (!ctx) + return CKR_OPERATION_NOT_INITIALIZED; - if (!ctx || !ctx->context) + if (!ica_sha_supported(tokdata, ctx->mech.mechanism)) + return openssl_specific_sha_final(tokdata, ctx, out_data, out_data_len); + + if (!ctx->context) return CKR_OPERATION_NOT_INITIALIZED; if (!out_data || !out_data_len) @@ -1689,8 +1790,8 @@ // -static CK_RV os_specific_rsa_keygen(STDLL_TokData_t *tokdata, - TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl) +static CK_RV ica_specific_rsa_keygen(STDLL_TokData_t *tokdata, + TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl) { ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; CK_ATTRIBUTE *publ_exp = NULL; @@ -1829,15 +1930,32 @@ rc = ica_rsa_key_generate_crt(ica_data->adapter_handle, (unsigned int) mod_bits, publKey, privKey); - - - if (rc) { + switch (rc) { + case 0: + rc = CKR_OK; + break; + case EINVAL: + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + rc = CKR_ARGUMENTS_BAD; + goto privkey_cleanup; + break; + case ENODEV: + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + rc = CKR_FUNCTION_NOT_SUPPORTED; + goto privkey_cleanup; + break; + case EPERM: + TRACE_ERROR("%s\n", ock_err(ERR_KEY_SIZE_RANGE)); + rc = CKR_KEY_SIZE_RANGE; + goto privkey_cleanup; + break; + default: TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); rc = CKR_FUNCTION_FAILED; goto privkey_cleanup; + break; } - /* Build the PKCS#11 public key */ // modulus: n // @@ -2038,13 +2156,20 @@ TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl) { - CK_RV rc; + ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; + CK_RV rc = CKR_FUNCTION_FAILED; - UNUSED(tokdata); + if (ica_data->ica_rsa_keygen_available) { + rc = ica_specific_rsa_keygen(tokdata, publ_tmpl, priv_tmpl); + if (rc == CKR_FUNCTION_NOT_SUPPORTED) + ica_data->ica_rsa_keygen_available = FALSE; + } + + if (!ica_data->ica_rsa_keygen_available) + rc = openssl_specific_rsa_keygen(publ_tmpl, priv_tmpl); - rc = os_specific_rsa_keygen(tokdata, publ_tmpl, priv_tmpl); if (rc != CKR_OK) - TRACE_DEVEL("os_specific_rsa_keygen failed\n"); + TRACE_DEVEL("ica/openssl_specific_rsa_keygen failed\n"); return rc; } @@ -2052,10 +2177,10 @@ // // -static CK_RV os_specific_rsa_encrypt(STDLL_TokData_t *tokdata, - CK_BYTE *in_data, - CK_ULONG in_data_len, - CK_BYTE *out_data, OBJECT *key_obj) +static CK_RV ica_specific_rsa_encrypt(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, OBJECT *key_obj) { ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; CK_ATTRIBUTE *modulus = NULL; @@ -2088,19 +2213,28 @@ goto cleanup_pubkey; } rc = ica_rsa_mod_expo(ica_data->adapter_handle, in_data, publKey, out_data); - if (rc != 0) { - if (rc == EINVAL) { - TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); - rc = CKR_ARGUMENTS_BAD; - } else { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - rc = CKR_FUNCTION_FAILED; - } - goto cleanup_pubkey; + switch (rc) { + case 0: + rc = CKR_OK; + break; + case EINVAL: + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + rc = CKR_ARGUMENTS_BAD; + break; + case ENODEV: + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + rc = CKR_FUNCTION_NOT_SUPPORTED; + break; + case EPERM: + TRACE_ERROR("%s\n", ock_err(ERR_KEY_SIZE_RANGE)); + rc = CKR_KEY_SIZE_RANGE; + break; + default: + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rc = CKR_FUNCTION_FAILED; + break; } - rc = CKR_OK; - cleanup_pubkey: free(publKey->modulus); free(publKey->exponent); @@ -2112,10 +2246,10 @@ // // -static CK_RV os_specific_rsa_decrypt(STDLL_TokData_t *tokdata, - CK_BYTE *in_data, - CK_ULONG in_data_len, - CK_BYTE *out_data, OBJECT *key_obj) +static CK_RV ica_specific_rsa_decrypt(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, OBJECT *key_obj) { ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; CK_ATTRIBUTE *modulus = NULL; @@ -2168,12 +2302,26 @@ } rc = ica_rsa_crt(ica_data->adapter_handle, in_data, crtKey, out_data); - - if (rc != 0) { + switch (rc) { + case 0: + rc = CKR_OK; + break; + case EINVAL: + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + rc = CKR_ARGUMENTS_BAD; + break; + case ENODEV: + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + rc = CKR_FUNCTION_NOT_SUPPORTED; + break; + case EPERM: + TRACE_ERROR("%s\n", ock_err(ERR_KEY_SIZE_RANGE)); + rc = CKR_KEY_SIZE_RANGE; + break; + default: TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); rc = CKR_FUNCTION_FAILED; - } else { - rc = CKR_OK; + break; } goto crt_cleanup; } else if (modulus && priv_exp) { @@ -2197,12 +2345,26 @@ rc = ica_rsa_mod_expo(ica_data->adapter_handle, in_data, modexpoKey, out_data); - - if (rc != 0) { + switch (rc) { + case 0: + rc = CKR_OK; + break; + case EINVAL: + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + rc = CKR_ARGUMENTS_BAD; + break; + case ENODEV: + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + rc = CKR_FUNCTION_NOT_SUPPORTED; + break; + case EPERM: + TRACE_ERROR("%s\n", ock_err(ERR_KEY_SIZE_RANGE)); + rc = CKR_KEY_SIZE_RANGE; + break; + default: TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); rc = CKR_FUNCTION_FAILED; - } else { - rc = CKR_OK; + break; } goto modexpo_cleanup; } else { @@ -2230,76 +2392,67 @@ return rc; } - -CK_RV token_specific_rsa_encrypt(STDLL_TokData_t *tokdata, CK_BYTE *in_data, - CK_ULONG in_data_len, CK_BYTE *out_data, - CK_ULONG *out_data_len, OBJECT *key_obj) +static CK_RV os_specific_rsa_encrypt(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, OBJECT *key_obj) { - CK_RV rc; - CK_BYTE clear[MAX_RSA_KEYLEN], cipher[MAX_RSA_KEYLEN]; - CK_ULONG modulus_bytes; - CK_ATTRIBUTE *attr = NULL; + ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; + CK_RV rc = CKR_FUNCTION_FAILED; - rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, - &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); - return rc; + if (ica_data->ica_rsa_endecrypt_available) { + rc = ica_specific_rsa_encrypt(tokdata, in_data, in_data_len, + out_data, key_obj); + if (rc == CKR_FUNCTION_NOT_SUPPORTED) + ica_data->ica_rsa_endecrypt_available = FALSE; } - modulus_bytes = attr->ulValueLen; - /* format the data */ - rc = rsa_format_block(tokdata, in_data, in_data_len, clear, - modulus_bytes, PKCS_BT_2); - if (rc != CKR_OK) { - TRACE_DEVEL("rsa_format_block failed\n"); - return rc; - } - - rc = os_specific_rsa_encrypt(tokdata, clear, modulus_bytes, cipher, key_obj); - if (rc == CKR_OK) { - memcpy(out_data, cipher, modulus_bytes); - *out_data_len = modulus_bytes; - } else { - TRACE_DEVEL("os_specific_rsa_encrypt failed\n"); - } + if (!ica_data->ica_rsa_endecrypt_available) + rc = openssl_specific_rsa_encrypt(tokdata, in_data, in_data_len, + out_data, key_obj); return rc; } - -CK_RV token_specific_rsa_decrypt(STDLL_TokData_t *tokdata, CK_BYTE *in_data, - CK_ULONG in_data_len, CK_BYTE *out_data, - CK_ULONG *out_data_len, OBJECT *key_obj) +static CK_RV os_specific_rsa_decrypt(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, OBJECT *key_obj) { - CK_BYTE out[MAX_RSA_KEYLEN]; - CK_RV rc; + ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; + CK_RV rc = CKR_FUNCTION_FAILED; - UNUSED(tokdata); + if (ica_data->ica_rsa_endecrypt_available) { + rc = ica_specific_rsa_decrypt(tokdata, in_data, in_data_len, + out_data, key_obj); + if (rc == CKR_FUNCTION_NOT_SUPPORTED) + ica_data->ica_rsa_endecrypt_available = FALSE; + } - rc = os_specific_rsa_decrypt(tokdata, in_data, in_data_len, out, key_obj); + if (!ica_data->ica_rsa_endecrypt_available) + rc = openssl_specific_rsa_decrypt(tokdata, in_data, in_data_len, + out_data, key_obj); - if (rc != CKR_OK) { - TRACE_DEVEL("os_specific_rsa_decrypt failed\n"); - return rc; - } + return rc; - rc = rsa_parse_block(out, in_data_len, out_data, out_data_len, PKCS_BT_2); - if (rc != CKR_OK) { - TRACE_DEVEL("rsa_parse_block failed\n"); - return rc; - } +} - /* - * For PKCS #1 v1.5 padding, out_data_len must be less - * than in_data_len (which is modulus_bytes) - 11. - */ - if (*out_data_len > (in_data_len - 11)) { - TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE)); - rc = CKR_ENCRYPTED_DATA_LEN_RANGE; - } +CK_RV token_specific_rsa_encrypt(STDLL_TokData_t *tokdata, CK_BYTE *in_data, + CK_ULONG in_data_len, CK_BYTE *out_data, + CK_ULONG *out_data_len, OBJECT *key_obj) +{ + return openssl_specific_rsa_pkcs_encrypt(tokdata, in_data, in_data_len, + out_data, out_data_len, key_obj, + os_specific_rsa_encrypt); +} - return rc; +CK_RV token_specific_rsa_decrypt(STDLL_TokData_t *tokdata, CK_BYTE *in_data, + CK_ULONG in_data_len, CK_BYTE *out_data, + CK_ULONG *out_data_len, OBJECT *key_obj) +{ + return openssl_specific_rsa_pkcs_decrypt(tokdata, in_data, in_data_len, + out_data, out_data_len, key_obj, + os_specific_rsa_decrypt); } CK_RV token_specific_rsa_sign(STDLL_TokData_t *tokdata, SESSION *sess, @@ -2307,40 +2460,9 @@ CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj) { - CK_ATTRIBUTE *attr = NULL; - CK_RV rc; - CK_BYTE data[MAX_RSA_KEYLEN], sig[MAX_RSA_KEYLEN]; - CK_ULONG modulus_bytes; - - UNUSED(tokdata); - UNUSED(sess); - - rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, - &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); - return rc; - } else { - modulus_bytes = attr->ulValueLen; - } - - rc = rsa_format_block(tokdata, in_data, in_data_len, data, - modulus_bytes, PKCS_BT_1); - if (rc != CKR_OK) { - TRACE_DEVEL("rsa_format_block failed\n"); - return rc; - } - - /* signing is a private key operation --> decrypt */ - rc = os_specific_rsa_decrypt(tokdata, data, modulus_bytes, sig, key_obj); - if (rc == CKR_OK) { - memcpy(out_data, sig, modulus_bytes); - *out_data_len = modulus_bytes; - } else { - TRACE_DEVEL("os_specific_rsa_decrypt failed\n"); - } - - return rc; + return openssl_specific_rsa_pkcs_sign(tokdata, sess, in_data, in_data_len, + out_data, out_data_len, key_obj, + os_specific_rsa_decrypt); } CK_RV token_specific_rsa_verify(STDLL_TokData_t *tokdata, SESSION *sess, @@ -2348,59 +2470,9 @@ CK_BYTE *signature, CK_ULONG sig_len, OBJECT *key_obj) { - CK_RV rc; - CK_BYTE out[MAX_RSA_KEYLEN], out_data[MAX_RSA_KEYLEN]; - CK_ATTRIBUTE *attr = NULL; - CK_ULONG modulus_bytes, out_data_len; - - UNUSED(tokdata); - UNUSED(sess); - UNUSED(sig_len); - - out_data_len = MAX_RSA_KEYLEN; - rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, - &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); - return rc; - } else { - modulus_bytes = attr->ulValueLen; - } - - rc = os_specific_rsa_encrypt(tokdata, signature, modulus_bytes, out, - key_obj); - if (rc != CKR_OK) { - /* - * Return CKR_SIGNATURE_INVALID in case of CKR_ARGUMENTS_BAD - * because we dont know why the RSA op failed and it may have - * failed due to a tampered signature being greater or equal - * to the modulus. - */ - TRACE_DEVEL("os_specific_rsa_encrypt failed\n"); - return rc == CKR_ARGUMENTS_BAD ? CKR_SIGNATURE_INVALID : rc; - } - - rc = rsa_parse_block(out, modulus_bytes, out_data, &out_data_len, - PKCS_BT_1); - if (rc == CKR_ENCRYPTED_DATA_INVALID) { - TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); - return CKR_SIGNATURE_INVALID; - } else if (rc != CKR_OK) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - return CKR_FUNCTION_FAILED; - } - - if (in_data_len != out_data_len) { - TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); - return CKR_SIGNATURE_INVALID; - } - - if (CRYPTO_memcmp(in_data, out_data, out_data_len) != 0) { - TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); - return CKR_SIGNATURE_INVALID; - } - - return CKR_OK; + return openssl_specific_rsa_pkcs_verify(tokdata, sess, in_data, in_data_len, + signature, sig_len, key_obj, + os_specific_rsa_encrypt); } CK_RV token_specific_rsa_verify_recover(STDLL_TokData_t *tokdata, @@ -2409,39 +2481,30 @@ CK_ULONG *out_data_len, OBJECT *key_obj) { - CK_RV rc; - CK_BYTE out[MAX_RSA_KEYLEN]; - CK_ATTRIBUTE *attr = NULL; - CK_ULONG modulus_bytes; - - UNUSED(tokdata); - UNUSED(sig_len); - - rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, - &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); - return rc; - } else { - modulus_bytes = attr->ulValueLen; - } - - rc = os_specific_rsa_encrypt(tokdata, signature, modulus_bytes, out, - key_obj); - if (rc != CKR_OK) { - TRACE_DEVEL("os_specific_rsa_encrypt failed\n"); - return rc; - } + return openssl_specific_rsa_pkcs_verify_recover(tokdata, signature, + sig_len, out_data, + out_data_len, key_obj, + os_specific_rsa_encrypt); +} - rc = rsa_parse_block(out, modulus_bytes, out_data, out_data_len, PKCS_BT_1); - if (rc == CKR_ENCRYPTED_DATA_INVALID) { - TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); - return CKR_SIGNATURE_INVALID; - } else if (rc != CKR_OK) { - TRACE_DEVEL("rsa_parse_block failed\n"); - } +CK_RV token_specific_rsa_pss_sign(STDLL_TokData_t *tokdata, SESSION *sess, + SIGN_VERIFY_CONTEXT *ctx, + CK_BYTE *in_data, CK_ULONG in_data_len, + CK_BYTE *sig, CK_ULONG *sig_len) +{ + return openssl_specific_rsa_pss_sign(tokdata, sess, ctx, in_data, + in_data_len, sig, sig_len, + os_specific_rsa_decrypt); +} - return rc; +CK_RV token_specific_rsa_pss_verify(STDLL_TokData_t *tokdata, SESSION *sess, + SIGN_VERIFY_CONTEXT *ctx, + CK_BYTE *in_data, CK_ULONG in_data_len, + CK_BYTE *signature, CK_ULONG sig_len) +{ + return openssl_specific_rsa_pss_verify(tokdata, sess, ctx, in_data, + in_data_len, signature, sig_len, + os_specific_rsa_encrypt); } CK_RV token_specific_rsa_x509_encrypt(STDLL_TokData_t *tokdata, @@ -2449,36 +2512,9 @@ CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj) { - CK_RV rc; - CK_BYTE clear[MAX_RSA_KEYLEN], cipher[MAX_RSA_KEYLEN]; - CK_ATTRIBUTE *attr = NULL; - CK_ULONG modulus_bytes; - - UNUSED(tokdata); - - rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, - &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); - return rc; - } else { - modulus_bytes = attr->ulValueLen; - } - - // prepad with zeros - // - memset(clear, 0x0, modulus_bytes - in_data_len); - memcpy(&clear[modulus_bytes - in_data_len], in_data, in_data_len); - - rc = os_specific_rsa_encrypt(tokdata, clear, modulus_bytes, cipher, key_obj); - if (rc == CKR_OK) { - memcpy(out_data, cipher, modulus_bytes); - *out_data_len = modulus_bytes; - } else { - TRACE_DEVEL("os_specific_rsa_encrypt failed\n"); - } - - return rc; + return openssl_specific_rsa_x509_encrypt(tokdata, in_data, in_data_len, + out_data, out_data_len, key_obj, + os_specific_rsa_encrypt); } CK_RV token_specific_rsa_x509_decrypt(STDLL_TokData_t *tokdata, @@ -2486,132 +2522,30 @@ CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj) { - CK_RV rc; - CK_BYTE out[MAX_RSA_KEYLEN]; - CK_ATTRIBUTE *attr = NULL; - CK_ULONG modulus_bytes; - - UNUSED(tokdata); - UNUSED(in_data_len); - - rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, - &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); - return rc; - } else { - modulus_bytes = attr->ulValueLen; - } - - rc = os_specific_rsa_decrypt(tokdata, in_data, modulus_bytes, out, key_obj); - if (rc == CKR_OK) { - memcpy(out_data, out, modulus_bytes); - *out_data_len = modulus_bytes; - } else { - TRACE_DEVEL("os_specific_rsa_decrypt failed\n"); - } - - return rc; + return openssl_specific_rsa_x509_decrypt(tokdata, in_data, in_data_len, + out_data, out_data_len, key_obj, + os_specific_rsa_decrypt); } CK_RV token_specific_rsa_x509_sign(STDLL_TokData_t *tokdata, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj) { - CK_RV rc; - CK_BYTE data[MAX_RSA_KEYLEN], sig[MAX_RSA_KEYLEN]; - CK_ATTRIBUTE *attr = NULL; - CK_ULONG modulus_bytes; - - UNUSED(tokdata); - - rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, - &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); - return rc; - } else { - modulus_bytes = attr->ulValueLen; - } - - // prepad with zeros - // - memset(data, 0x0, modulus_bytes - in_data_len); - memcpy(&data[modulus_bytes - in_data_len], in_data, in_data_len); - - rc = os_specific_rsa_decrypt(tokdata, data, modulus_bytes, sig, key_obj); - if (rc == CKR_OK) { - memcpy(out_data, sig, modulus_bytes); - *out_data_len = modulus_bytes; - } else { - TRACE_DEVEL("os_specific_rsa_decrypt failed\n"); - } - - return rc; + return openssl_specific_rsa_x509_sign(tokdata, in_data, in_data_len, + out_data, out_data_len, key_obj, + os_specific_rsa_decrypt); } - CK_RV token_specific_rsa_x509_verify(STDLL_TokData_t *tokdata, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG sig_len, OBJECT *key_obj) { - CK_RV rc; - CK_BYTE out[MAX_RSA_KEYLEN]; - CK_ATTRIBUTE *attr = NULL; - CK_ULONG modulus_bytes; - - UNUSED(tokdata); - UNUSED(sig_len); - - rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, - &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); - return rc; - } else { - modulus_bytes = attr->ulValueLen; - } - - rc = os_specific_rsa_encrypt(tokdata, signature, modulus_bytes, out, - key_obj); - if (rc == CKR_OK) { - CK_ULONG pos1, pos2, len; - - // it should be noted that in_data_len is not necessarily - // the same as the modulus length - // - for (pos1 = 0; pos1 < in_data_len; pos1++) - if (in_data[pos1] != 0) - break; - - for (pos2 = 0; pos2 < modulus_bytes; pos2++) - if (out[pos2] != 0) - break; - - // at this point, pos1 and pos2 point to the first non-zero - // bytes in the input data and the decrypted signature - // (the recovered data), respectively. - // - if ((in_data_len - pos1) != (modulus_bytes - pos2)) { - TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); - return CKR_SIGNATURE_INVALID; - } - len = in_data_len - pos1; - - if (CRYPTO_memcmp(&in_data[pos1], &out[pos2], len) != 0) { - TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); - return CKR_SIGNATURE_INVALID; - } - return CKR_OK; - } else { - TRACE_DEVEL("os_specific_rsa_encrypt failed\n"); - } - - return rc; + return openssl_specific_rsa_x509_verify(tokdata, in_data, in_data_len, + signature, sig_len, key_obj, + os_specific_rsa_encrypt); } - CK_RV token_specific_rsa_x509_verify_recover(STDLL_TokData_t *tokdata, CK_BYTE *signature, CK_ULONG sig_len, @@ -2619,33 +2553,10 @@ CK_ULONG *out_data_len, OBJECT *key_obj) { - CK_RV rc; - CK_BYTE out[MAX_RSA_KEYLEN]; - CK_ATTRIBUTE *attr = NULL; - CK_ULONG modulus_bytes; - - UNUSED(tokdata); - UNUSED(sig_len); - - rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, - &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); - return rc; - } else { - modulus_bytes = attr->ulValueLen; - } - - rc = os_specific_rsa_encrypt(tokdata, signature, modulus_bytes, out, - key_obj); - if (rc == CKR_OK) { - memcpy(out_data, out, modulus_bytes); - *out_data_len = modulus_bytes; - } else { - TRACE_DEVEL("os_specific_rsa_encrypt failed\n"); - } - - return rc; + return openssl_specific_rsa_x509_verify_recover(tokdata, signature, sig_len, + out_data, out_data_len, + key_obj, + os_specific_rsa_encrypt); } CK_RV token_specific_rsa_oaep_encrypt(STDLL_TokData_t *tokdata, @@ -2655,68 +2566,10 @@ CK_ULONG *out_data_len, CK_BYTE *hash, CK_ULONG hlen) { - CK_RV rc; - CK_BYTE cipher[MAX_RSA_KEYLEN]; - CK_ULONG modulus_bytes; - CK_ATTRIBUTE *attr = NULL; - CK_BYTE *em_data = NULL; - OBJECT *key_obj = NULL; - CK_RSA_PKCS_OAEP_PARAMS_PTR oaepParms = NULL; - - if (!in_data || !out_data || !hash) { - TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); - return CKR_ARGUMENTS_BAD; - } - - oaepParms = (CK_RSA_PKCS_OAEP_PARAMS_PTR) ctx->mech.pParameter; - - rc = object_mgr_find_in_map1(tokdata, ctx->key, &key_obj, READ_LOCK); - if (rc != CKR_OK) { - TRACE_DEVEL("object_mgr_find_in_map1 failed\n"); - return rc; - } - - rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, - &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); - goto done; - } else { - modulus_bytes = attr->ulValueLen; - } - - /* pkcs1v2.2, section 7.1.1 Step 2: - * EME-OAEP encoding. - */ - em_data = (CK_BYTE *) malloc(modulus_bytes); - if (em_data == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - - rc = encode_eme_oaep(tokdata, in_data, in_data_len, em_data, - modulus_bytes, oaepParms->mgf, hash, hlen); - if (rc != CKR_OK) - goto done; - - rc = os_specific_rsa_encrypt(tokdata, em_data, modulus_bytes, cipher, - key_obj); - if (rc == CKR_OK) { - memcpy(out_data, cipher, modulus_bytes); - *out_data_len = modulus_bytes; - } else { - TRACE_DEVEL("os_specific_rsa_encrypt failed\n"); - } - -done: - if (em_data) - free(em_data); - - object_put(tokdata, key_obj, TRUE); - key_obj = NULL; - - return rc; + return openssl_specific_rsa_oaep_encrypt(tokdata, ctx, in_data, + in_data_len, out_data, + out_data_len, hash, hlen, + os_specific_rsa_encrypt); } CK_RV token_specific_rsa_oaep_decrypt(STDLL_TokData_t *tokdata, @@ -2726,194 +2579,10 @@ CK_ULONG *out_data_len, CK_BYTE *hash, CK_ULONG hlen) { - CK_RV rc; - CK_BYTE *decr_data = NULL; - OBJECT *key_obj = NULL; - CK_ATTRIBUTE *attr = NULL; - CK_RSA_PKCS_OAEP_PARAMS_PTR oaepParms = NULL; - - if (!in_data || !out_data || !hash) { - TRACE_ERROR("Invalid function arguments.\n"); - return CKR_FUNCTION_FAILED; - } - - oaepParms = (CK_RSA_PKCS_OAEP_PARAMS_PTR) ctx->mech.pParameter; - - rc = object_mgr_find_in_map1(tokdata, ctx->key, &key_obj, READ_LOCK); - if (rc != CKR_OK) { - TRACE_DEVEL("object_mgr_find_in_map1 failed\n"); - return rc; - } - - rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, - &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); - goto done; - } else { - *out_data_len = attr->ulValueLen; - } - - decr_data = (CK_BYTE *) malloc(in_data_len); - if (decr_data == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - - rc = os_specific_rsa_decrypt(tokdata, in_data, in_data_len, decr_data, - key_obj); - if (rc != CKR_OK) - goto done; - - /* pkcs1v2.2, section 7.1.2 Step 2: - * EME-OAEP decoding. - */ - rc = decode_eme_oaep(tokdata, decr_data, in_data_len, out_data, - out_data_len, oaepParms->mgf, hash, hlen); - - if (decr_data) - free(decr_data); - -done: - object_put(tokdata, key_obj, TRUE); - key_obj = NULL; - - return rc; -} - -CK_RV token_specific_rsa_pss_sign(STDLL_TokData_t *tokdata, SESSION *sess, - SIGN_VERIFY_CONTEXT *ctx, - CK_BYTE *in_data, CK_ULONG in_data_len, - CK_BYTE *sig, CK_ULONG *sig_len) -{ - CK_RV rc; - CK_ULONG modbytes; - CK_ATTRIBUTE *attr = NULL; - OBJECT *key_obj = NULL; - CK_BYTE *emdata = NULL; - CK_RSA_PKCS_PSS_PARAMS *pssParms = NULL; - - UNUSED(sess); - - /* check the arguments */ - if (!in_data || !sig) { - TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); - return CKR_ARGUMENTS_BAD; - } - - if (!ctx) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - return CKR_FUNCTION_FAILED; - } - - pssParms = (CK_RSA_PKCS_PSS_PARAMS *) ctx->mech.pParameter; - - /* get the key */ - rc = object_mgr_find_in_map1(tokdata, ctx->key, &key_obj, READ_LOCK); - if (rc != CKR_OK) { - TRACE_DEVEL("object_mgr_find_in_map1 failed\n"); - return rc; - } - - rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, - &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); - goto done; - } else { - modbytes = attr->ulValueLen; - } - - emdata = (CK_BYTE *) malloc(modbytes); - if (emdata == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - - rc = emsa_pss_encode(tokdata, pssParms, in_data, in_data_len, emdata, - &modbytes); - if (rc != CKR_OK) - goto done; - - /* signing is a private key operation --> decrypt */ - rc = os_specific_rsa_decrypt(tokdata, emdata, modbytes, sig, key_obj); - if (rc == CKR_OK) - *sig_len = modbytes; - else - TRACE_DEVEL("os_specific_rsa_decrypt failed\n"); - -done: - if (emdata) - free(emdata); - - object_put(tokdata, key_obj, TRUE); - key_obj = NULL; - - return rc; -} - - -CK_RV token_specific_rsa_pss_verify(STDLL_TokData_t *tokdata, SESSION *sess, - SIGN_VERIFY_CONTEXT *ctx, - CK_BYTE *in_data, CK_ULONG in_data_len, - CK_BYTE *signature, CK_ULONG sig_len) -{ - CK_RV rc; - CK_ULONG modbytes; - OBJECT *key_obj = NULL; - CK_ATTRIBUTE *attr = NULL; - CK_BYTE out[MAX_RSA_KEYLEN]; - CK_RSA_PKCS_PSS_PARAMS *pssParms = NULL; - - UNUSED(sess); - - /* check the arguments */ - if (!in_data || !signature) { - TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); - return CKR_ARGUMENTS_BAD; - } - - if (!ctx) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - return CKR_FUNCTION_FAILED; - } - - pssParms = (CK_RSA_PKCS_PSS_PARAMS *) ctx->mech.pParameter; - - /* get the key */ - rc = object_mgr_find_in_map1(tokdata, ctx->key, &key_obj, READ_LOCK); - if (rc != CKR_OK) { - TRACE_DEVEL("object_mgr_find_in_map1 failed\n"); - return rc; - } - - /* verify is a public key operation ... encrypt */ - rc = os_specific_rsa_encrypt(tokdata, signature, sig_len, out, key_obj); - if (rc != CKR_OK) { - TRACE_DEVEL("os_specific_rsa_encrypt failed\n"); - goto done; - } - - rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, - &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); - goto done; - } else { - modbytes = attr->ulValueLen; - } - - /* call the pss verify scheme */ - rc = emsa_pss_verify(tokdata, pssParms, in_data, in_data_len, out, - modbytes); - -done: - object_put(tokdata, key_obj, TRUE); - key_obj = NULL; - - return rc; + return openssl_specific_rsa_oaep_decrypt(tokdata, ctx, in_data, + in_data_len, out_data, + out_data_len, hash, hlen, + os_specific_rsa_decrypt); } #ifndef NOAES @@ -2936,10 +2605,13 @@ CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key, CK_BYTE encrypt) { + ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; int rc = CKR_OK; CK_ATTRIBUTE *attr = NULL; - UNUSED(tokdata); + if (!ica_data->ica_aes_available) + return openssl_specific_aes_ecb(tokdata, in_data, in_data_len, + out_data, out_data_len, key, encrypt); /* * checks for input and output data length and block sizes @@ -2978,10 +2650,14 @@ CK_ULONG *out_data_len, OBJECT *key, CK_BYTE *init_v, CK_BYTE encrypt) { + ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; CK_RV rc; CK_ATTRIBUTE *attr = NULL; - UNUSED(tokdata); + if (!ica_data->ica_aes_available) + return openssl_specific_aes_cbc(tokdata, in_data, in_data_len, + out_data, out_data_len, key, + init_v, encrypt); /* * checks for input and output data length and block sizes @@ -3023,10 +2699,14 @@ CK_BYTE *counterblock, CK_ULONG counter_width, CK_BYTE encrypt) { + ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; CK_RV rc; CK_ATTRIBUTE *attr = NULL; - UNUSED(tokdata); + if (!ica_data->ica_aes_available) + return openssl_specific_aes_ctr(tokdata, in_data, in_data_len, + out_data, out_data_len, key, + counterblock, counter_width, encrypt); /* * checks for input and output data length and block sizes @@ -3071,6 +2751,7 @@ ENCR_DECR_CONTEXT *ctx, CK_MECHANISM *mech, CK_OBJECT_HANDLE key, CK_BYTE encrypt) { + ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; CK_RV rc = CKR_OK; OBJECT *key_obj = NULL; CK_ATTRIBUTE *attr = NULL; @@ -3079,7 +2760,9 @@ CK_BYTE *icv, *icb, *ucb, *subkey; CK_ULONG icv_length; - UNUSED(sess); + if (!ica_data->ica_aes_available) + return openssl_specific_aes_gcm_init(tokdata, sess, ctx, mech, + key, encrypt); /* find key object */ rc = object_mgr_find_in_map1(tokdata, key, &key_obj, READ_LOCK); @@ -3133,6 +2816,7 @@ CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_BYTE encrypt) { + ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; CK_RV rc; OBJECT *key = NULL; CK_ATTRIBUTE *attr = NULL; @@ -3143,7 +2827,10 @@ CK_ULONG auth_data_len; CK_ULONG tag_data_len; - UNUSED(sess); + if (!ica_data->ica_aes_available) + return openssl_specific_aes_gcm(tokdata, sess, ctx, in_data, + in_data_len, out_data, out_data_len, + encrypt); /* * Checks for input and output data length and block sizes are already @@ -3223,6 +2910,7 @@ CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_BYTE encrypt) { + ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; CK_RV rc; CK_ATTRIBUTE *attr = NULL; OBJECT *key = NULL; @@ -3234,8 +2922,10 @@ CK_BYTE *ucb, *subkey; CK_BYTE *buffer = NULL; - UNUSED(tokdata); - UNUSED(sess); + if (!ica_data->ica_aes_available) + return openssl_specific_aes_gcm_update(tokdata, sess, ctx, in_data, + in_data_len, out_data, + out_data_len, encrypt); context = (AES_GCM_CONTEXT *) ctx->context; total = (context->len + in_data_len); @@ -3373,6 +3063,7 @@ ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_BYTE encrypt) { + ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; CK_RV rc = CKR_OK; CK_ATTRIBUTE *attr = NULL; OBJECT *key = NULL; @@ -3383,8 +3074,9 @@ CK_ULONG auth_data_len, tag_data_len; CK_BYTE *buffer = NULL; - UNUSED(tokdata); - UNUSED(sess); + if (!ica_data->ica_aes_available) + return openssl_specific_aes_gcm_final(tokdata, sess, ctx, out_data, + out_data_len, encrypt); /* find key object */ rc = object_mgr_find_in_map_nocache(tokdata, ctx->key, &key, READ_LOCK); @@ -3526,10 +3218,24 @@ CK_ULONG in_data_len, CK_BYTE *out_data, OBJECT *key, CK_BYTE *init_v, uint_32 direction) { +#if OPENSSL_VERSION_PREREQ(3, 0) || OPENSSL_VERSION_NUMBER >= 0x101010cfL + ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; +#endif CK_RV rc; CK_ATTRIBUTE *attr = NULL; +#if OPENSSL_VERSION_PREREQ(3, 0) || OPENSSL_VERSION_NUMBER >= 0x101010cfL + /* + * AES-OFB/CFB currently only works with >= OpenSSl 3.0 or >= OpenSSL 1.1.1l, + * due to a bug in OpenSSL <= 1.1.1k in s390x_aes_ofb_cipher() not updating + * the IV in the context. + */ + if (!ica_data->ica_aes_available) + return openssl_specific_aes_ofb(tokdata, in_data, in_data_len, + out_data, key, init_v, direction); +#else UNUSED(tokdata); +#endif rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); if (rc != CKR_OK) { @@ -3560,10 +3266,25 @@ OBJECT *key, CK_BYTE *init_v, uint_32 lcfb, uint_32 direction) { +#if OPENSSL_VERSION_PREREQ(3, 0) || OPENSSL_VERSION_NUMBER >= 0x101010cfL + ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; +#endif CK_RV rc; CK_ATTRIBUTE *attr = NULL; +#if OPENSSL_VERSION_PREREQ(3, 0) || OPENSSL_VERSION_NUMBER >= 0x101010cfL + /* + * AES-OFB/CFB currently only works with >= OpenSSl 3.0 or >= OpenSSL 1.1.1l, + * due to a bug in OpenSSL <= 1.1.1k in s390x_aes_ofb_cipher() not updating + * the IV in the context. + */ + if (!ica_data->ica_aes_available) + return openssl_specific_aes_cfb(tokdata, in_data, in_data_len, + out_data, key, init_v, lcfb, + direction); +#else UNUSED(tokdata); +#endif rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); if (rc != CKR_OK) { @@ -3586,10 +3307,13 @@ CK_RV token_specific_aes_mac(STDLL_TokData_t *tokdata, CK_BYTE *message, CK_ULONG message_len, OBJECT *key, CK_BYTE *mac) { + ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; CK_RV rc; CK_ATTRIBUTE *attr = NULL; - UNUSED(tokdata); + if (!ica_data->ica_aes_available) + return openssl_specific_aes_mac(tokdata, message, message_len, + key, mac); rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); if (rc != CKR_OK) { @@ -3613,11 +3337,16 @@ CK_ULONG message_len, OBJECT *key, CK_BYTE *mac, CK_BBOOL first, CK_BBOOL last, CK_VOID_PTR *ctx) { + ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; CK_RV rc; CK_ATTRIBUTE *attr = NULL; - UNUSED(tokdata); - UNUSED(ctx); + if (!ica_data->ica_aes_available) + return openssl_specific_aes_cmac(tokdata, message, message_len, + key, mac, first, last, ctx); + + if (key == NULL) + return CKR_ARGUMENTS_BAD; rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); if (rc != CKR_OK) { @@ -3653,175 +3382,169 @@ #endif typedef struct _REF_MECH_LIST_ELEMENT { - CK_ULONG lica_idx; + CK_ULONG lica_idx; /* 0 means its a combined mechanism */ CK_MECHANISM_TYPE mech_type; CK_MECHANISM_INFO mech_info; } REF_MECH_LIST_ELEMENT; static const REF_MECH_LIST_ELEMENT ref_mech_list[] = { - {92, CKM_RSA_PKCS_KEY_PAIR_GEN, - {512, 4096, CKF_HW | CKF_GENERATE_KEY_PAIR} + {RSA_KEY_GEN_ME, CKM_RSA_PKCS_KEY_PAIR_GEN, + {512, 4096, CKF_GENERATE_KEY_PAIR} }, -#if !(NODSA) -// {1, CKM_DSA_KEY_PAIR_GEN, {512, 1024, CKF_HW|CKF_GENERATE_KEY_PAIR}}, -#endif -#if !(NOCDMF) -// {4, CKM_CDMF_KEY_GEN, {0, 0, CKF_HW|CKF_GENERATE}}, -#endif - {80, CKM_DES_KEY_GEN, {8, 8, CKF_HW | CKF_GENERATE}}, - {80, CKM_DES3_KEY_GEN, {24, 24, CKF_HW | CKF_GENERATE}}, - {90, CKM_RSA_PKCS, - {512, 4096, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP | + {P_RNG, CKM_DES_KEY_GEN, {8, 8, CKF_GENERATE}}, + {P_RNG, CKM_DES3_KEY_GEN, {24, 24, CKF_GENERATE}}, + {RSA_ME, CKM_RSA_PKCS, + {512, 4096, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP | CKF_SIGN | CKF_VERIFY | CKF_SIGN_RECOVER | CKF_VERIFY_RECOVER} }, + {0, CKM_SHA1_RSA_PKCS, {512, 4096, CKF_SIGN | CKF_VERIFY}}, + {0, CKM_SHA224_RSA_PKCS, {512, 4096, CKF_SIGN | CKF_VERIFY}}, + {0, CKM_SHA256_RSA_PKCS, {512, 4096, CKF_SIGN | CKF_VERIFY}}, + {0, CKM_SHA384_RSA_PKCS, {512, 4096, CKF_SIGN | CKF_VERIFY}}, + {0, CKM_SHA512_RSA_PKCS, {512, 4096, CKF_SIGN | CKF_VERIFY}}, #if !(NOX509) - {90, CKM_RSA_X_509, - {512, 4096, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP | + {RSA_ME, CKM_RSA_X_509, + {512, 4096, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP | CKF_SIGN | CKF_VERIFY | CKF_SIGN_RECOVER | CKF_VERIFY_RECOVER} }, #endif - {90, CKM_RSA_PKCS_OAEP, - {512, 4096, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP} + {0, CKM_RSA_PKCS_OAEP, + {512, 4096, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP} }, - {90, CKM_RSA_PKCS_PSS, {512, 4096, CKF_HW | CKF_SIGN | CKF_VERIFY}}, - {90, CKM_SHA1_RSA_PKCS_PSS, {512, 4096, CKF_SIGN | CKF_VERIFY}}, - {90, CKM_SHA224_RSA_PKCS_PSS, {512, 4096, CKF_SIGN | CKF_VERIFY}}, - {90, CKM_SHA256_RSA_PKCS_PSS, {512, 4096, CKF_SIGN | CKF_VERIFY}}, - {90, CKM_SHA384_RSA_PKCS_PSS, {512, 4096, CKF_SIGN | CKF_VERIFY}}, - {90, CKM_SHA512_RSA_PKCS_PSS, {512, 4096, CKF_SIGN | CKF_VERIFY}}, - {190, CKM_SHA1_RSA_PKCS, {512, 4096, CKF_HW | CKF_SIGN | CKF_VERIFY}}, - {190, CKM_SHA224_RSA_PKCS, {512, 4096, CKF_HW | CKF_SIGN | CKF_VERIFY}}, - {190, CKM_SHA256_RSA_PKCS, {512, 4096, CKF_HW | CKF_SIGN | CKF_VERIFY}}, - {190, CKM_SHA384_RSA_PKCS, {512, 4096, CKF_HW | CKF_SIGN | CKF_VERIFY}}, - {190, CKM_SHA512_RSA_PKCS, {512, 4096, CKF_HW | CKF_SIGN | CKF_VERIFY}}, - {20, CKM_DES_ECB, - {8, 8, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP} + {0, CKM_RSA_PKCS_PSS, {512, 4096, CKF_SIGN | CKF_VERIFY}}, + {0, CKM_SHA1_RSA_PKCS_PSS, {512, 4096, CKF_SIGN | CKF_VERIFY}}, + {0, CKM_SHA224_RSA_PKCS_PSS, {512, 4096, CKF_SIGN | CKF_VERIFY}}, + {0, CKM_SHA256_RSA_PKCS_PSS, {512, 4096, CKF_SIGN | CKF_VERIFY}}, + {0, CKM_SHA384_RSA_PKCS_PSS, {512, 4096, CKF_SIGN | CKF_VERIFY}}, + {0, CKM_SHA512_RSA_PKCS_PSS, {512, 4096, CKF_SIGN | CKF_VERIFY}}, + {DES_ECB, CKM_DES_ECB, + {8, 8, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP} }, - {21, CKM_DES_CBC, - {8, 8, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP} + {DES_CBC, CKM_DES_CBC, + {8, 8, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP} }, - {21, CKM_DES_CBC_PAD, - {8, 8, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP} + {DES_CBC, CKM_DES_CBC_PAD, + {8, 8, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP} }, - {41, CKM_DES3_ECB, - {24, 24, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP} + {DES3_ECB, CKM_DES3_ECB, + {24, 24, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP} }, - {42, CKM_DES3_CBC, - {24, 24, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP} + {DES3_ECB, CKM_DES3_CBC, + {24, 24, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP} }, - {42, CKM_DES3_CBC_PAD, - {24, 24, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP} + {DES3_CBC, CKM_DES3_CBC_PAD, + {24, 24, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP} }, - {49, CKM_DES3_MAC, {24, 24, CKF_HW | CKF_SIGN | CKF_VERIFY}}, - {49, CKM_DES3_MAC_GENERAL, {24, 24, CKF_HW | CKF_SIGN | CKF_VERIFY}}, - {49, CKM_DES3_CMAC, {16, 24, CKF_HW | CKF_SIGN | CKF_VERIFY}}, - {49, CKM_DES3_CMAC_GENERAL, {16, 24, CKF_HW | CKF_SIGN | CKF_VERIFY}}, - {24, CKM_DES_CFB8, {8, 8, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT}}, - {44, CKM_DES_OFB64, {8, 8, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT}}, - {45, CKM_DES_CFB64, {8, 8, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT}}, - {01, CKM_SHA_1, {0, 0, CKF_HW | CKF_DIGEST}}, - {01, CKM_SHA_1_HMAC, {0, 0, CKF_HW | CKF_SIGN | CKF_VERIFY}}, - {01, CKM_SHA_1_HMAC_GENERAL, {0, 0, CKF_HW | CKF_SIGN | CKF_VERIFY}}, - {03, CKM_SHA224, {0, 0, CKF_HW | CKF_DIGEST}}, - {03, CKM_SHA224_HMAC, {0, 0, CKF_HW | CKF_SIGN | CKF_VERIFY}}, - {03, CKM_SHA224_HMAC_GENERAL, {0, 0, CKF_HW | CKF_SIGN | CKF_VERIFY}}, - {03, CKM_SHA256, {0, 0, CKF_HW | CKF_DIGEST}}, - {03, CKM_SHA256_HMAC, {0, 0, CKF_HW | CKF_SIGN | CKF_VERIFY}}, - {03, CKM_SHA256_HMAC_GENERAL, {0, 0, CKF_HW | CKF_SIGN | CKF_VERIFY}}, - {04, CKM_SHA384, {0, 0, CKF_HW | CKF_DIGEST}}, - {04, CKM_SHA384_HMAC, {0, 0, CKF_HW | CKF_SIGN | CKF_VERIFY}}, - {04, CKM_SHA384_HMAC_GENERAL, {0, 0, CKF_HW | CKF_SIGN | CKF_VERIFY}}, - {05, CKM_SHA512, {0, 0, CKF_HW | CKF_DIGEST}}, - {05, CKM_SHA512_HMAC, {0, 0, CKF_HW | CKF_SIGN | CKF_VERIFY}}, - {05, CKM_SHA512_HMAC_GENERAL, {0, 0, CKF_HW | CKF_SIGN | CKF_VERIFY}}, + {DES3_CMAC, CKM_DES3_MAC, {24, 24, CKF_SIGN | CKF_VERIFY}}, + {DES3_CMAC, CKM_DES3_MAC_GENERAL, {24, 24, CKF_SIGN | CKF_VERIFY}}, + {DES3_CMAC, CKM_DES3_CMAC, {16, 24, CKF_SIGN | CKF_VERIFY}}, + {DES3_CMAC, CKM_DES3_CMAC_GENERAL, {16, 24, CKF_SIGN | CKF_VERIFY}}, + {DES_CFB, CKM_DES_CFB8, {8, 8, CKF_ENCRYPT | CKF_DECRYPT}}, + {DES3_OFB, CKM_DES_OFB64, {8, 8, CKF_ENCRYPT | CKF_DECRYPT}}, + {DES3_CFB, CKM_DES_CFB64, {8, 8, CKF_ENCRYPT | CKF_DECRYPT}}, + {SHA1, CKM_SHA_1, {0, 0, CKF_DIGEST}}, + {SHA1, CKM_SHA_1_HMAC, {0, 0, CKF_SIGN | CKF_VERIFY}}, + {SHA1, CKM_SHA_1_HMAC_GENERAL, {0, 0, CKF_SIGN | CKF_VERIFY}}, + {SHA256, CKM_SHA224, {0, 0, CKF_DIGEST}}, + {SHA256, CKM_SHA224_HMAC, {0, 0, CKF_SIGN | CKF_VERIFY}}, + {SHA256, CKM_SHA224_HMAC_GENERAL, {0, 0, CKF_SIGN | CKF_VERIFY}}, + {SHA256, CKM_SHA256, {0, 0, CKF_DIGEST}}, + {SHA256, CKM_SHA256_HMAC, {0, 0, CKF_SIGN | CKF_VERIFY}}, + {SHA256, CKM_SHA256_HMAC_GENERAL, {0, 0, CKF_SIGN | CKF_VERIFY}}, + {SHA384, CKM_SHA384, {0, 0, CKF_DIGEST}}, + {SHA384, CKM_SHA384_HMAC, {0, 0, CKF_SIGN | CKF_VERIFY}}, + {SHA384, CKM_SHA384_HMAC_GENERAL, {0, 0, CKF_SIGN | CKF_VERIFY}}, + {SHA512, CKM_SHA512, {0, 0, CKF_DIGEST}}, + {SHA512, CKM_SHA512_HMAC, {0, 0, CKF_SIGN | CKF_VERIFY}}, + {SHA512, CKM_SHA512_HMAC_GENERAL, {0, 0, CKF_SIGN | CKF_VERIFY}}, #ifdef SHA512_224 - {95, CKM_SHA512_224, {0, 0, CKF_HW|CKF_DIGEST}}, - {95, CKM_SHA512_224_HMAC, {0, 0, CKF_HW | CKF_SIGN | CKF_VERIFY}}, - {95, CKM_SHA512_224_HMAC_GENERAL, {0, 0, CKF_HW | CKF_SIGN | CKF_VERIFY}}, + {SHA512_224, CKM_SHA512_224, {0, 0, CKF_HW|CKF_DIGEST}}, + {SHA512_224, CKM_SHA512_224_HMAC, {0, 0, CKF_SIGN | CKF_VERIFY}}, + {SHA512_224, CKM_SHA512_224_HMAC_GENERAL, {0, 0, CKF_SIGN | CKF_VERIFY}}, #endif #ifdef SHA512_256 - {96, CKM_SHA512_256, {0, 0, CKF_HW|CKF_DIGEST}}, - {96, CKM_SHA512_256_HMAC, {0, 0, CKF_HW | CKF_SIGN | CKF_VERIFY}}, - {96, CKM_SHA512_256_HMAC_GENERAL, {0, 0, CKF_HW | CKF_SIGN | CKF_VERIFY}}, + {SHA512_256, CKM_SHA512_256, {0, 0, CKF_HW|CKF_DIGEST}}, + {SHA512_256, CKM_SHA512_256_HMAC, {0, 0, CKF_SIGN | CKF_VERIFY}}, + {SHA512_256, CKM_SHA512_256_HMAC_GENERAL, {0, 0, CKF_SIGN | CKF_VERIFY}}, #endif #ifdef SHA3_224 - {6, CKM_IBM_SHA3_224, {0, 0, CKF_HW|CKF_DIGEST}}, - {6, CKM_IBM_SHA3_224_HMAC, {0, 0, CKF_HW | CKF_SIGN | CKF_VERIFY}}, + {SHA3_224, CKM_IBM_SHA3_224, {0, 0, CKF_HW|CKF_DIGEST}}, + {SHA3_224, CKM_IBM_SHA3_224_HMAC, {0, 0, CKF_SIGN | CKF_VERIFY}}, #endif #ifdef SHA3_256 - {7, CKM_IBM_SHA3_256, {0, 0, CKF_HW|CKF_DIGEST}}, - {7, CKM_IBM_SHA3_256_HMAC, {0, 0, CKF_HW | CKF_SIGN | CKF_VERIFY}}, + {SHA3_256, CKM_IBM_SHA3_256, {0, 0, CKF_HW|CKF_DIGEST}}, + {SHA3_256, CKM_IBM_SHA3_256_HMAC, {0, 0, CKF_SIGN | CKF_VERIFY}}, #endif #ifdef SHA3_384 - {8, CKM_IBM_SHA3_384, {0, 0, CKF_HW|CKF_DIGEST}}, - {8, CKM_IBM_SHA3_384_HMAC, {0, 0, CKF_HW | CKF_SIGN | CKF_VERIFY}}, + {SHA3_384, CKM_IBM_SHA3_384, {0, 0, CKF_HW|CKF_DIGEST}}, + {SHA3_384, CKM_IBM_SHA3_384_HMAC, {0, 0, CKF_SIGN | CKF_VERIFY}}, #endif #ifdef SHA3_512 - {9, CKM_IBM_SHA3_512, {0, 0, CKF_HW|CKF_DIGEST}}, - {9, CKM_IBM_SHA3_512_HMAC, {0, 0, CKF_HW | CKF_SIGN | CKF_VERIFY}}, + {SHA3_512, CKM_IBM_SHA3_512, {0, 0, CKF_HW|CKF_DIGEST}}, + {SHA3_512, CKM_IBM_SHA3_512_HMAC, {0, 0, CKF_SIGN | CKF_VERIFY}}, #endif #if !(NOMD5) - {53, CKM_MD5, {0, 0, CKF_HW | CKF_DIGEST}}, - {54, CKM_MD5_HMAC, {0, 0, CKF_HW | CKF_SIGN | CKF_VERIFY}}, - {55, CKM_MD5_HMAC_GENERAL, {0, 0, CKF_HW | CKF_SIGN | CKF_VERIFY}}, + {53, CKM_MD5, {0, 0, CKF_DIGEST}}, + {54, CKM_MD5_HMAC, {0, 0, CKF_SIGN | CKF_VERIFY}}, + {55, CKM_MD5_HMAC_GENERAL, {0, 0, CKF_SIGN | CKF_VERIFY}}, #endif #if !(NOAES) - {80, CKM_AES_KEY_GEN, {16, 32, CKF_HW | CKF_GENERATE}}, - {60, CKM_AES_ECB, - {16, 32, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP} + {P_RNG, CKM_AES_KEY_GEN, {16, 32, CKF_GENERATE}}, + {AES_ECB, CKM_AES_ECB, + {16, 32, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP} }, - {61, CKM_AES_CBC, - {16, 32, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP} + {AES_CBC, CKM_AES_CBC, + {16, 32, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP} }, - {61, CKM_AES_CBC_PAD, - {16, 32, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP} + {AES_CBC, CKM_AES_CBC_PAD, + {16, 32, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP} }, - {63, CKM_AES_OFB, - {16, 32, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP} + {AES_OFB, CKM_AES_OFB, + {16, 32, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP} }, - {64, CKM_AES_CFB8, - {16, 32, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP} + {AES_CFB, CKM_AES_CFB8, + {16, 32, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP} }, - {64, CKM_AES_CFB64, - {16, 32, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP} + {AES_CFB, CKM_AES_CFB64, + {16, 32, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP} }, - {64, CKM_AES_CFB128, - {16, 32, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP} + {AES_CFB, CKM_AES_CFB128, + {16, 32, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP} }, - {65, CKM_AES_CTR, - {16, 32, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP} + {AES_CTR, CKM_AES_CTR, + {16, 32, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP} }, - {70, CKM_AES_GCM, {16, 32, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT}}, - {68, CKM_AES_MAC, {16, 32, CKF_HW | CKF_SIGN | CKF_VERIFY}}, - {68, CKM_AES_MAC_GENERAL, {16, 32, CKF_HW | CKF_SIGN | CKF_VERIFY}}, - {68, CKM_AES_CMAC, {16, 32, CKF_HW | CKF_SIGN | CKF_VERIFY}}, - {68, CKM_AES_CMAC_GENERAL, {16, 32, CKF_HW | CKF_SIGN | CKF_VERIFY}}, + {AES_GCM, CKM_AES_GCM, {16, 32, CKF_ENCRYPT | CKF_DECRYPT}}, + {AES_CMAC, CKM_AES_MAC, {16, 32, CKF_SIGN | CKF_VERIFY}}, + {AES_CMAC, CKM_AES_MAC_GENERAL, {16, 32, CKF_SIGN | CKF_VERIFY}}, + {AES_CMAC, CKM_AES_CMAC, {16, 32, CKF_SIGN | CKF_VERIFY}}, + {AES_CMAC, CKM_AES_CMAC_GENERAL, {16, 32, CKF_SIGN | CKF_VERIFY}}, #endif - {80, CKM_GENERIC_SECRET_KEY_GEN, {80, 2048, CKF_HW | CKF_GENERATE}}, + {P_RNG, CKM_GENERIC_SECRET_KEY_GEN, {80, 2048, CKF_GENERATE}}, #ifndef NO_EC - {85, CKM_ECDH1_DERIVE, - {160, 521, CKF_HW | CKF_DERIVE | CKF_EC_NAMEDCURVE | CKF_EC_F_P} + {EC_DH, CKM_ECDH1_DERIVE, + {160, 521, CKF_DERIVE | CKF_EC_NAMEDCURVE | CKF_EC_F_P} }, - {86, CKM_ECDSA, - {160, 521, CKF_HW | CKF_SIGN | CKF_VERIFY | CKF_EC_NAMEDCURVE | CKF_EC_F_P} + {EC_DSA_SIGN, CKM_ECDSA, + {160, 521, CKF_SIGN | CKF_VERIFY | CKF_EC_NAMEDCURVE | CKF_EC_F_P} }, - {86, CKM_ECDSA_SHA1, - {160, 521, CKF_HW | CKF_SIGN | CKF_VERIFY | CKF_EC_NAMEDCURVE | CKF_EC_F_P} + {0, CKM_ECDSA_SHA1, + {160, 521, CKF_SIGN | CKF_VERIFY | CKF_EC_NAMEDCURVE | CKF_EC_F_P} }, - {86, CKM_ECDSA_SHA224, - {160, 521, CKF_HW | CKF_SIGN | CKF_VERIFY | CKF_EC_NAMEDCURVE | CKF_EC_F_P} + {0, CKM_ECDSA_SHA224, + {160, 521, CKF_SIGN | CKF_VERIFY | CKF_EC_NAMEDCURVE | CKF_EC_F_P} }, - {86, CKM_ECDSA_SHA256, - {160, 521, CKF_HW | CKF_SIGN | CKF_VERIFY | CKF_EC_NAMEDCURVE | CKF_EC_F_P} + {0, CKM_ECDSA_SHA256, + {160, 521, CKF_SIGN | CKF_VERIFY | CKF_EC_NAMEDCURVE | CKF_EC_F_P} }, - {86, CKM_ECDSA_SHA384, - {160, 521, CKF_HW | CKF_SIGN | CKF_VERIFY | CKF_EC_NAMEDCURVE | CKF_EC_F_P} + {0, CKM_ECDSA_SHA384, + {160, 521, CKF_SIGN | CKF_VERIFY | CKF_EC_NAMEDCURVE | CKF_EC_F_P} }, - {86, CKM_ECDSA_SHA512, - {160, 521, CKF_HW | CKF_SIGN | CKF_VERIFY | CKF_EC_NAMEDCURVE | CKF_EC_F_P} + {0, CKM_ECDSA_SHA512, + {160, 521, CKF_SIGN | CKF_VERIFY | CKF_EC_NAMEDCURVE | CKF_EC_F_P} }, - {88, CKM_EC_KEY_PAIR_GEN, - {160, 521, CKF_HW | CKF_GENERATE_KEY_PAIR | CKF_EC_NAMEDCURVE | CKF_EC_F_P} + {EC_KGEN, CKM_EC_KEY_PAIR_GEN, + {160, 521, CKF_GENERATE_KEY_PAIR | CKF_EC_NAMEDCURVE | CKF_EC_F_P} }, #endif @@ -3886,7 +3609,59 @@ return FALSE; } -static CK_RV addMechanismToList(STDLL_TokData_t *tokdata, CK_ULONG mechanism) +static CK_BBOOL isMechanismHW(STDLL_TokData_t *tokdata, CK_ULONG mechanism) +{ + ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; + unsigned int i; + + for (i = 0; i < ica_data->mech_list_len; i++) { + if (ica_data->mech_list[i].mech_type == mechanism) + return ica_data->mech_list[i].mech_info.flags & CKF_HW; + } + + return FALSE; +} + +#define KEY_SIZE_512 0x01 +#define KEY_SIZE_1024 0x02 +#define KEY_SIZE_2048 0x04 +#define KEY_SIZE_4096 0x08 + +static void adjust_rsa_key_sizes(unsigned int mask, + CK_MECHANISM_INFO *mech_info) +{ + CK_ULONG min = 0, max = 0; + + if (mask == 0) + return; + + if (mask & KEY_SIZE_512) + min = 512; + else if (mask & KEY_SIZE_1024) + min = 1024; + else if (mask & KEY_SIZE_2048) + min = 2048; + else if (mask & KEY_SIZE_4096) + min = 4096; + + max = min; + if (mask & KEY_SIZE_4096) + max = 4096; + else if (mask & KEY_SIZE_2048) + max = 2048; + else if (mask & KEY_SIZE_1024) + max = 1024; + else if (mask & KEY_SIZE_512) + max = 512; + + if (min > mech_info->ulMinKeySize) + mech_info->ulMinKeySize = min; + if (max < mech_info->ulMaxKeySize) + mech_info->ulMaxKeySize = max; +} + +static CK_RV addMechanismToList(STDLL_TokData_t *tokdata, CK_ULONG mechanism, + CK_BBOOL hw, unsigned int rsa_keysize_mask) { ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; CK_ULONG ret; @@ -3903,11 +3678,15 @@ } ica_data->mech_list[ica_data->mech_list_len].mech_type = ref_mech_list[refIdx].mech_type; ica_data->mech_list[ica_data->mech_list_len].mech_info.flags = - (ref_mech_list[refIdx].mech_info.flags & 0xfffffffe); + (ref_mech_list[refIdx].mech_info.flags & (~CKF_HW)) | (hw ? CKF_HW : 0); ica_data->mech_list[ica_data->mech_list_len].mech_info.ulMinKeySize = ref_mech_list[refIdx].mech_info.ulMinKeySize; ica_data->mech_list[ica_data->mech_list_len].mech_info.ulMaxKeySize = ref_mech_list[refIdx].mech_info.ulMaxKeySize; + + adjust_rsa_key_sizes(rsa_keysize_mask, + &ica_data->mech_list[ica_data->mech_list_len].mech_info); + ica_data->mech_list_len++; return CKR_OK; @@ -3921,17 +3700,95 @@ { ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; CK_ULONG ret, rc = CKR_OK; - unsigned int i, n; + unsigned int i, n, rsa_props = 0; unsigned int ica_specific_mech_list_len; CK_ULONG tmp, ulActMechCtr, ulPreDefMechCtr, refIdx; + CK_BBOOL rsa_hw, ec_hw, sha_hw; + +#if !(NOMD5) + addMechanismToList(tokdata, CKM_MD5, 0, 0); + addMechanismToList(tokdata, CKM_MD5_HMAC, 0, 0); + addMechanismToList(tokdata, CKM_MD5_HMAC_GENERAL, 0, 0); +#endif - ica_data->mech_list[0].mech_type = CKF_DIGEST; - ica_data->mech_list[0].mech_info.flags = CKF_DIGEST; - ica_data->mech_list[1].mech_type = CKM_MD5_HMAC; - ica_data->mech_list[1].mech_info.flags = CKF_SIGN | CKF_VERIFY; - ica_data->mech_list[2].mech_type = CKM_MD5_HMAC_GENERAL; - ica_data->mech_list[2].mech_info.flags = CKF_SIGN | CKF_VERIFY; - ica_data->mech_list_len = 3; + /* We have RSA support (SW) in any case, regardless if libica supports it */ + addMechanismToList(tokdata, CKM_RSA_PKCS_KEY_PAIR_GEN, 0, 0); + addMechanismToList(tokdata, CKM_RSA_PKCS, 0, 0); +#if !(NOX509) + addMechanismToList(tokdata, CKM_RSA_X_509, 0, 0); +#endif + + /* We have RNG support (SW) in any case, regardless if libica supports it */ + addMechanismToList(tokdata, CKM_GENERIC_SECRET_KEY_GEN, 0, 0); + addMechanismToList(tokdata, CKM_DES_KEY_GEN, 0, 0); + addMechanismToList(tokdata, CKM_DES3_KEY_GEN, 0, 0); + addMechanismToList(tokdata, CKM_AES_KEY_GEN, 0, 0); + + /* We have EC support (SW) in any case, regardless if libica supports it */ + addMechanismToList(tokdata, CKM_EC_KEY_PAIR_GEN, 0, 0); + addMechanismToList(tokdata, CKM_ECDSA, 0, 0); + + /* We have SHA support (SW) in any case, regardless if libica supports it */ + addMechanismToList(tokdata, CKM_SHA_1, 0, 0); + addMechanismToList(tokdata, CKM_SHA224, 0, 0); + addMechanismToList(tokdata, CKM_SHA256, 0, 0); + addMechanismToList(tokdata, CKM_SHA384, 0, 0); + addMechanismToList(tokdata, CKM_SHA512, 0, 0); +#ifdef NID_sha512_224WithRSAEncryption + addMechanismToList(tokdata, CKM_SHA512_224, 0, 0); +#endif +#ifdef NID_sha512_256WithRSAEncryption + addMechanismToList(tokdata, CKM_SHA512_256, 0, 0); +#endif +#ifdef NID_sha3_224 + addMechanismToList(tokdata, CKM_IBM_SHA3_224, 0, 0); +#endif +#ifdef NID_sha3_256 + addMechanismToList(tokdata, CKM_IBM_SHA3_256, 0, 0); +#endif +#ifdef NID_sha3_384 + addMechanismToList(tokdata, CKM_IBM_SHA3_384, 0, 0); +#endif +#ifdef NID_sha3_512 + addMechanismToList(tokdata, CKM_IBM_SHA3_512, 0, 0); +#endif + + /* We have AES support (SW) in any case, regardless if libica supports it */ + addMechanismToList(tokdata, CKM_AES_ECB, 0, 0); + addMechanismToList(tokdata, CKM_AES_CBC, 0, 0); + addMechanismToList(tokdata, CKM_AES_CBC_PAD, 0, 0); + addMechanismToList(tokdata, CKM_AES_CTR, 0, 0); +#if OPENSSL_VERSION_PREREQ(3, 0) || OPENSSL_VERSION_NUMBER >= 0x101010cfL + /* + * AES-OFB/CFB currently only works with >= OpenSSl 3.0 or >= OpenSSL 1.1.1l, + * due to a bug in OpenSSL <= 1.1.1k in s390x_aes_ofb_cipher() not updating + * the IV in the context. + */ + addMechanismToList(tokdata, CKM_AES_OFB, 0, 0); + addMechanismToList(tokdata, CKM_AES_CFB8, 0, 0); + /* CFB64 is not supported as SW fallback */ + addMechanismToList(tokdata, CKM_AES_CFB128, 0, 0); +#endif + addMechanismToList(tokdata, CKM_AES_GCM, 0, 0); + addMechanismToList(tokdata, CKM_AES_MAC, 0, 0); + addMechanismToList(tokdata, CKM_AES_MAC_GENERAL, 0, 0); + addMechanismToList(tokdata, CKM_AES_CMAC, 0, 0); + addMechanismToList(tokdata, CKM_AES_CMAC_GENERAL, 0, 0); + + /* We have DES/3DES support (SW) in any case, regardless if libica supports it */ + addMechanismToList(tokdata, CKM_DES_ECB, 0, 0); + addMechanismToList(tokdata, CKM_DES_CBC, 0, 0); + addMechanismToList(tokdata, CKM_DES_CBC_PAD, 0, 0); + addMechanismToList(tokdata, CKM_DES3_ECB, 0, 0); + addMechanismToList(tokdata, CKM_DES3_CBC, 0, 0); + addMechanismToList(tokdata, CKM_DES3_CBC_PAD, 0, 0); + addMechanismToList(tokdata, CKM_DES_OFB64, 0, 0); + addMechanismToList(tokdata, CKM_DES_CFB8, 0, 0); + addMechanismToList(tokdata, CKM_DES_CFB64, 0, 0); + addMechanismToList(tokdata, CKM_DES3_MAC, 0, 0); + addMechanismToList(tokdata, CKM_DES3_MAC_GENERAL, 0, 0); + addMechanismToList(tokdata, CKM_DES3_CMAC, 0, 0); + addMechanismToList(tokdata, CKM_DES3_CMAC_GENERAL, 0, 0); rc = ica_get_functionlist(NULL, &ica_specific_mech_list_len); if (rc != CKR_OK) { @@ -3957,8 +3814,59 @@ if (libica_func_list[i].flags == 0) continue; - // loop over libica supported list - ulActMechCtr = (CK_ULONG)(-1); + /* Remember if libica supports RSA mechanisms (HW or SW) */ + if (libica_func_list[i].mech_mode_id == RSA_KEY_GEN_ME) { + ica_data->ica_rsa_keygen_available = TRUE; + if (libica_func_list[i].property != 0) + rsa_props = libica_func_list[i].property; + } + if (libica_func_list[i].mech_mode_id == RSA_ME) { + ica_data->ica_rsa_endecrypt_available = TRUE; + if (libica_func_list[i].property != 0) + rsa_props = libica_func_list[i].property; + } + + /* Remember if libica supports RNG mechanisms (HW or SW) */ + if (libica_func_list[i].mech_mode_id == P_RNG) + ica_data->ica_p_rng_available = TRUE; + + /* Remember if libica supports EC mechanisms (HW or SW) */ + if (ica_data->ica_ec_support_available) { + if (libica_func_list[i].mech_mode_id == EC_KGEN) + ica_data->ica_ec_keygen_available = TRUE; + if (libica_func_list[i].mech_mode_id == EC_DSA_SIGN) + ica_data->ica_ec_signverify_available = TRUE; + if (libica_func_list[i].mech_mode_id == EC_DH) + ica_data->ica_ec_derive_available = TRUE; + } + + /* Remember if libica supports SHA mechanisms (HW or SW) */ + if (libica_func_list[i].mech_mode_id == SHA1) + ica_data->ica_sha1_available = TRUE; + if (libica_func_list[i].mech_mode_id == SHA512) + ica_data->ica_sha2_available = TRUE; +#ifdef SHA512_224 + if (libica_func_list[i].mech_mode_id == SHA512_224) + ica_data->ica_sha512_224_available = TRUE; +#endif +#ifdef SHA512_256 + if (libica_func_list[i].mech_mode_id == SHA512_256) + ica_data->ica_sha512_256_available = TRUE; +#endif +#ifdef SHA3_512 + if (libica_func_list[i].mech_mode_id == SHA3_512) + ica_data->ica_sha3_available = TRUE; +#endif + + /* Remember if libica supports AES mechanisms (HW or SW) */ + if (libica_func_list[i].mech_mode_id == AES_CBC) + ica_data->ica_aes_available = TRUE; + + /* Remember if libica supports DES/3DES mechanisms (HW or SW) */ + if (libica_func_list[i].mech_mode_id == DES_CBC) + ica_data->ica_des_available = TRUE; + if (libica_func_list[i].mech_mode_id == DES3_CBC) + ica_data->ica_des3_available = TRUE; /* --- walk through the whole reflist and fetch all * matching mechanism's (if present) --- @@ -3967,12 +3875,12 @@ while ((ret = getRefListIdxfromId(libica_func_list[i].mech_mode_id, &refIdx)) == CKR_OK) { /* - * Loop over the predefined mechanism list and check + * Loop over the predefined mechanism list and check * if we have to overrule a software implemented * mechanism from token by libica HW supported * mechanism. */ - for (n = 0; n < ulPreDefMechCtr; n++) { + for (n = 0, ulActMechCtr = (CK_ULONG)-1; n < ulPreDefMechCtr; n++) { if (ica_data->mech_list[n].mech_type == ref_mech_list[refIdx].mech_type) { ulActMechCtr = n; @@ -3988,18 +3896,29 @@ ica_data->mech_list[ica_data->mech_list_len].mech_type = ref_mech_list[refIdx].mech_type; ica_data->mech_list[ica_data->mech_list_len].mech_info.flags = - (libica_func_list[i].flags & 0x01) | - (ref_mech_list[refIdx].mech_info.flags & 0xfffffffe); + (libica_func_list[i].flags & (ICA_FLAG_DHW | ICA_FLAG_SHW) ? CKF_HW : 0) | + (ref_mech_list[refIdx].mech_info.flags & (~CKF_HW)); ica_data->mech_list[ica_data->mech_list_len].mech_info.ulMinKeySize = ref_mech_list[refIdx].mech_info.ulMinKeySize; ica_data->mech_list[ica_data->mech_list_len].mech_info.ulMaxKeySize = ref_mech_list[refIdx].mech_info.ulMaxKeySize; + + if (libica_func_list[i].mech_mode_id == RSA_KEY_GEN_ME || + libica_func_list[i].mech_mode_id == RSA_ME) + adjust_rsa_key_sizes(rsa_props, + &ica_data->mech_list[ica_data->mech_list_len].mech_info); + ica_data->mech_list_len++; } else { /* replace existing entry */ ica_data->mech_list[ulActMechCtr].mech_info.flags = - (libica_func_list[i].flags & 0x01) | - ica_data->mech_list[ulActMechCtr].mech_info.flags; + (libica_func_list[i].flags & (ICA_FLAG_DHW | ICA_FLAG_SHW) ? CKF_HW : 0) | + (ref_mech_list[refIdx].mech_info.flags & (~CKF_HW)); + + if (libica_func_list[i].mech_mode_id == RSA_KEY_GEN_ME || + libica_func_list[i].mech_mode_id == RSA_ME) + adjust_rsa_key_sizes(rsa_props, + &ica_data->mech_list[ulActMechCtr].mech_info); } refIdx++; } @@ -4007,32 +3926,132 @@ /* * check if special combined mechanisms are supported - * if SHA1 and RSA is available -> insert CKM_SHA1_RSA_PKCS - * if SHA256 and RSA is available -> insert CKM_SHA256_RSA_PKCS + * if SHAnnn and RSA is available -> insert CKM_SHAnnn_RSA_PKCS[_PSS] * if MD2 and RSA is available -> insert CKM_MD2_RSA_PKCS * if MD5 and RSA is available -> insert CKM_MD5_RSA_PKCS + * if SHAnnn and EC is available -> insert CKM_ECDSA_SHAnnn + * if SHAnnn and EC is available -> insert CKM_ECDH1_DERIVE + * if SHAnnn is available -> insert CKM_SHAxxx_HMAC[_GENERAL] */ + rsa_hw = isMechanismHW(tokdata, CKM_RSA_PKCS); + sha_hw = isMechanismHW(tokdata, CKM_SHA_1); + if (isMechanismAvailable(tokdata, CKM_SHA_1) && + isMechanismAvailable(tokdata, CKM_SHA224) && + isMechanismAvailable(tokdata, CKM_SHA256) && + isMechanismAvailable(tokdata, CKM_SHA384) && + isMechanismAvailable(tokdata, CKM_SHA512)) { + addMechanismToList(tokdata, CKM_RSA_PKCS_OAEP, 0, rsa_props); + addMechanismToList(tokdata, CKM_RSA_PKCS_PSS, 0, rsa_props); + } if (isMechanismAvailable(tokdata, CKM_SHA_1) && isMechanismAvailable(tokdata, CKM_RSA_PKCS)) - addMechanismToList(tokdata, CKM_SHA1_RSA_PKCS); + addMechanismToList(tokdata, CKM_SHA1_RSA_PKCS, rsa_hw && sha_hw, rsa_props); if (isMechanismAvailable(tokdata, CKM_SHA224) && isMechanismAvailable(tokdata, CKM_RSA_PKCS)) - addMechanismToList(tokdata, CKM_SHA224_RSA_PKCS); + addMechanismToList(tokdata, CKM_SHA224_RSA_PKCS, rsa_hw && sha_hw, rsa_props); if (isMechanismAvailable(tokdata, CKM_SHA256) && isMechanismAvailable(tokdata, CKM_RSA_PKCS)) - addMechanismToList(tokdata, CKM_SHA256_RSA_PKCS); + addMechanismToList(tokdata, CKM_SHA256_RSA_PKCS, rsa_hw && sha_hw, rsa_props); if (isMechanismAvailable(tokdata, CKM_SHA384) && isMechanismAvailable(tokdata, CKM_RSA_PKCS)) - addMechanismToList(tokdata, CKM_SHA384_RSA_PKCS); + addMechanismToList(tokdata, CKM_SHA384_RSA_PKCS, rsa_hw && sha_hw, rsa_props); if (isMechanismAvailable(tokdata, CKM_SHA512) && isMechanismAvailable(tokdata, CKM_RSA_PKCS)) - addMechanismToList(tokdata, CKM_SHA512_RSA_PKCS); + addMechanismToList(tokdata, CKM_SHA512_RSA_PKCS, rsa_hw && sha_hw, rsa_props); if (isMechanismAvailable(tokdata, CKM_MD2) && isMechanismAvailable(tokdata, CKM_RSA_PKCS)) - addMechanismToList(tokdata, CKM_MD2_RSA_PKCS); + addMechanismToList(tokdata, CKM_MD2_RSA_PKCS, rsa_hw && sha_hw, rsa_props); if (isMechanismAvailable(tokdata, CKM_MD5) && isMechanismAvailable(tokdata, CKM_RSA_PKCS)) - addMechanismToList(tokdata, CKM_MD5_RSA_PKCS); + addMechanismToList(tokdata, CKM_MD5_RSA_PKCS, rsa_hw && sha_hw, rsa_props); + if (isMechanismAvailable(tokdata, CKM_SHA_1) && + isMechanismAvailable(tokdata, CKM_RSA_PKCS_PSS)) + addMechanismToList(tokdata, CKM_SHA1_RSA_PKCS_PSS, rsa_hw && sha_hw, rsa_props); + if (isMechanismAvailable(tokdata, CKM_SHA224) && + isMechanismAvailable(tokdata, CKM_RSA_PKCS_PSS)) + addMechanismToList(tokdata, CKM_SHA224_RSA_PKCS_PSS, rsa_hw && sha_hw, rsa_props); + if (isMechanismAvailable(tokdata, CKM_SHA256) && + isMechanismAvailable(tokdata, CKM_RSA_PKCS_PSS)) + addMechanismToList(tokdata, CKM_SHA256_RSA_PKCS_PSS, rsa_hw && sha_hw, rsa_props); + if (isMechanismAvailable(tokdata, CKM_SHA384) && + isMechanismAvailable(tokdata, CKM_RSA_PKCS_PSS)) + addMechanismToList(tokdata, CKM_SHA384_RSA_PKCS_PSS, rsa_hw && sha_hw, rsa_props); + if (isMechanismAvailable(tokdata, CKM_SHA512) && + isMechanismAvailable(tokdata, CKM_RSA_PKCS_PSS)) + addMechanismToList(tokdata, CKM_SHA512_RSA_PKCS_PSS, rsa_hw && sha_hw, rsa_props); + + ec_hw = isMechanismHW(tokdata, CKM_ECDSA); + if (isMechanismAvailable(tokdata, CKM_SHA_1) && + isMechanismAvailable(tokdata, CKM_ECDSA)) + addMechanismToList(tokdata, CKM_ECDSA_SHA1, ec_hw && sha_hw, 0); + if (isMechanismAvailable(tokdata, CKM_SHA224) && + isMechanismAvailable(tokdata, CKM_ECDSA)) + addMechanismToList(tokdata, CKM_ECDSA_SHA224, ec_hw && sha_hw, 0); + if (isMechanismAvailable(tokdata, CKM_SHA256) && + isMechanismAvailable(tokdata, CKM_ECDSA)) + addMechanismToList(tokdata, CKM_ECDSA_SHA256, ec_hw && sha_hw, 0); + if (isMechanismAvailable(tokdata, CKM_SHA384) && + isMechanismAvailable(tokdata, CKM_ECDSA)) + addMechanismToList(tokdata, CKM_ECDSA_SHA384, ec_hw && sha_hw, 0); + if (isMechanismAvailable(tokdata, CKM_SHA512) && + isMechanismAvailable(tokdata, CKM_ECDSA)) + addMechanismToList(tokdata, CKM_ECDSA_SHA512, ec_hw && sha_hw, 0); + if (isMechanismAvailable(tokdata, CKM_EC_KEY_PAIR_GEN) && + isMechanismAvailable(tokdata, CKM_SHA_1) && + isMechanismAvailable(tokdata, CKM_SHA224) && + isMechanismAvailable(tokdata, CKM_SHA256) && + isMechanismAvailable(tokdata, CKM_SHA384) && + isMechanismAvailable(tokdata, CKM_SHA512)) + addMechanismToList(tokdata, CKM_ECDH1_DERIVE, ec_hw && sha_hw, 0); + + if (isMechanismAvailable(tokdata, CKM_SHA_1)) { + addMechanismToList(tokdata, CKM_SHA_1_HMAC, sha_hw, 0); + addMechanismToList(tokdata, CKM_SHA_1_HMAC_GENERAL, sha_hw, 0); + } + if (isMechanismAvailable(tokdata, CKM_SHA224)) { + addMechanismToList(tokdata, CKM_SHA224_HMAC, sha_hw, 0); + addMechanismToList(tokdata, CKM_SHA224_HMAC_GENERAL, sha_hw, 0); + } + if (isMechanismAvailable(tokdata, CKM_SHA256)) { + addMechanismToList(tokdata, CKM_SHA256_HMAC, sha_hw, 0); + addMechanismToList(tokdata, CKM_SHA256_HMAC_GENERAL, sha_hw, 0); + } + if (isMechanismAvailable(tokdata, CKM_SHA384)) { + addMechanismToList(tokdata, CKM_SHA384_HMAC, sha_hw, 0); + addMechanismToList(tokdata, CKM_SHA384_HMAC_GENERAL, sha_hw, 0); + } + if (isMechanismAvailable(tokdata, CKM_SHA512)) { + addMechanismToList(tokdata, CKM_SHA512_HMAC, sha_hw, 0); + addMechanismToList(tokdata, CKM_SHA512_HMAC_GENERAL, sha_hw, 0); + } +#ifdef NID_sha512_224WithRSAEncryption + if (isMechanismAvailable(tokdata, CKM_SHA512_224)) { + addMechanismToList(tokdata, CKM_SHA512_224_HMAC, 0, 0); + addMechanismToList(tokdata, CKM_SHA512_224_HMAC_GENERAL, 0, 0); + } +#endif +#ifdef NID_sha512_256WithRSAEncryption + if (isMechanismAvailable(tokdata, CKM_SHA512_256)) { + addMechanismToList(tokdata, CKM_SHA512_256_HMAC, 0, 0); + addMechanismToList(tokdata, CKM_SHA512_256_HMAC_GENERAL, 0, 0); + } +#endif +#ifdef NID_sha3_224 + if (isMechanismAvailable(tokdata, CKM_IBM_SHA3_224)) + addMechanismToList(tokdata, CKM_IBM_SHA3_224_HMAC, 0, 0); +#endif +#ifdef NID_sha3_256 + if (isMechanismAvailable(tokdata, CKM_IBM_SHA3_256)) + addMechanismToList(tokdata, CKM_IBM_SHA3_256_HMAC, 0, 0); +#endif +#ifdef NID_sha3_384 + if (isMechanismAvailable(tokdata, CKM_IBM_SHA3_384)) + addMechanismToList(tokdata, CKM_IBM_SHA3_384_HMAC, 0, 0); +#endif +#ifdef NID_sha3_512 + if (isMechanismAvailable(tokdata, CKM_IBM_SHA3_512)) + addMechanismToList(tokdata, CKM_IBM_SHA3_512_HMAC, 0, 0); +#endif /* sort the mech_list_ica by mechanism ID's (bubble sort) */ for (i = 0; i < ica_data->mech_list_len; i++) { @@ -4218,9 +4237,9 @@ return -1; } -CK_RV token_specific_ec_generate_keypair(STDLL_TokData_t *tokdata, - TEMPLATE *publ_tmpl, - TEMPLATE *priv_tmpl) +static CK_RV ica_specific_ec_generate_keypair(STDLL_TokData_t *tokdata, + TEMPLATE *publ_tmpl, + TEMPLATE *priv_tmpl) { ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; CK_RV ret = CKR_OK; @@ -4261,8 +4280,20 @@ /* Generate key data for this key object */ rc = p_ica_ec_key_generate(ica_data->adapter_handle, eckey); if (rc != 0) { - TRACE_ERROR("ica_ec_key_generate() failed with rc=%d.\n", rc); - ret = CKR_FUNCTION_FAILED; + switch (rc) { + case EPERM: + TRACE_ERROR("ica_ec_key_generate() failed with rc=EPERM, probably curve not supported by openssl.\n"); + ret = CKR_CURVE_NOT_SUPPORTED; + break; + case ENODEV: + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + ret = CKR_FUNCTION_NOT_SUPPORTED; + break; + default: + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + ret = CKR_FUNCTION_FAILED; + break; + } goto end; } @@ -4324,100 +4355,23 @@ return ret; } -CK_RV token_specific_ec_sign(STDLL_TokData_t *tokdata, SESSION *sess, - CK_BYTE *in_data, CK_ULONG in_data_len, - CK_BYTE *out_data, CK_ULONG *out_data_len, - OBJECT *key_obj) +CK_RV token_specific_ec_generate_keypair(STDLL_TokData_t *tokdata, + TEMPLATE *publ_tmpl, + TEMPLATE *priv_tmpl) { ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; - CK_RV ret = CKR_OK; - CK_ATTRIBUTE *attr, *attr2; - ICA_EC_KEY *eckey; - unsigned int privlen; - unsigned char *d = NULL; - int rc, nid; - - UNUSED(sess); - - *out_data_len = 0; + CK_RV rc = CKR_FUNCTION_FAILED; - if (!ica_data->ica_ec_support_available) { - TRACE_ERROR("ECC support is not available in Libica\n"); - return CKR_FUNCTION_NOT_SUPPORTED; + if (ica_data->ica_ec_keygen_available) { + rc = ica_specific_ec_generate_keypair(tokdata, publ_tmpl, priv_tmpl); + if (rc == CKR_FUNCTION_NOT_SUPPORTED) + ica_data->ica_ec_keygen_available = FALSE; } - /* Get CKA_ECDSA_PARAMS from template */ - ret = template_attribute_get_non_empty(key_obj->template, CKA_ECDSA_PARAMS, - &attr); - if (ret != CKR_OK) { - TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); - return CKR_TEMPLATE_INCOMPLETE; - } + if (!ica_data->ica_ec_keygen_available) + rc = openssl_specific_ec_generate_keypair(tokdata, publ_tmpl, priv_tmpl); - /* Determine curve nid */ - nid = nid_from_oid(attr->pValue, attr->ulValueLen); - if (nid < 0) { - TRACE_ERROR("Cannot determine curve nid. \n"); - return CKR_CURVE_NOT_SUPPORTED; - } - - /* Create ICA_EC_KEY object */ - eckey = p_ica_ec_key_new(nid, &privlen); - if (!eckey) { - TRACE_ERROR("ica_ec_key_new() failed for curve %i.\n", nid); - return CKR_FUNCTION_FAILED; - } - - /* Get private key from template via CKA_VALUE */ - ret = template_attribute_get_non_empty(key_obj->template, CKA_VALUE, - &attr2); - if (ret != CKR_OK) { - TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); - ret = CKR_TEMPLATE_INCOMPLETE; - goto end; - } - - /* Add zero padding if needed */ - if (privlen > attr2->ulValueLen) { - d = calloc(privlen, 1); - if (d == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - ret = CKR_HOST_MEMORY; - goto end; - } - - memcpy(d + privlen - attr2->ulValueLen, attr2->pValue, - attr2->ulValueLen); - } - - /* Initialize ICA_EC_KEY with private key (D) */ - rc = p_ica_ec_key_init(NULL, NULL, d != NULL ? d : attr2->pValue, eckey); - if (rc != 0) { - TRACE_ERROR("ica_ec_key_init() failed with rc = %d \n", rc); - ret = CKR_FUNCTION_FAILED; - goto end; - } - - /* Create signature */ - rc = p_ica_ecdsa_sign(ica_data->adapter_handle, eckey, - (unsigned char *) in_data, - (unsigned int) in_data_len, - (unsigned char *) out_data, 2 * privlen); - if (rc != 0) { - TRACE_ERROR("ica_ecdsa_sign() failed with rc = %d. \n", rc); - ret = CKR_FUNCTION_FAILED; - goto end; - } - - *out_data_len = 2 * privlen; - ret = CKR_OK; - -end: - p_ica_ec_key_free(eckey); - if (d != NULL) - free(d); - - return ret; + return rc; } /** @@ -4555,31 +4509,11 @@ return CKR_FUNCTION_FAILED; } - -CK_RV token_specific_ec_verify(STDLL_TokData_t *tokdata, - SESSION *sess, - CK_BYTE *in_data, - CK_ULONG in_data_len, - CK_BYTE *signature, - CK_ULONG signature_len, OBJECT *key_obj) +static CK_RV ica_prepare_ec_key(OBJECT *key_obj, ICA_EC_KEY **eckey, + unsigned int *privlen, int *nid) { - ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; CK_RV ret = CKR_OK; - CK_ATTRIBUTE *attr, *attr2; - ICA_EC_KEY *eckey; - unsigned int privlen; - unsigned char x_array[ICATOK_EC_MAX_D_LEN]; - unsigned char y_array[ICATOK_EC_MAX_D_LEN]; - int rc, nid; - CK_BYTE *ecpoint; - CK_ULONG ecpoint_len, field_len; - - UNUSED(sess); - - if (!ica_data->ica_ec_support_available) { - TRACE_ERROR("ECC support is not available in Libica\n"); - return CKR_FUNCTION_NOT_SUPPORTED; - } + CK_ATTRIBUTE *attr; /* Get CKA_ECDSA_PARAMS from template */ ret = template_attribute_get_non_empty(key_obj->template, CKA_ECDSA_PARAMS, @@ -4589,22 +4523,112 @@ return CKR_TEMPLATE_INCOMPLETE; } - /* Create ICA_EC_KEY object */ - nid = nid_from_oid(attr->pValue, attr->ulValueLen); - if (nid < 0) { + /* Determine curve nid */ + *nid = nid_from_oid(attr->pValue, attr->ulValueLen); + if (*nid < 0) { TRACE_ERROR("Cannot determine curve nid. \n"); return CKR_CURVE_NOT_SUPPORTED; } - eckey = p_ica_ec_key_new(nid, &privlen); - if (!eckey) { - TRACE_ERROR("ica_ec_key_new() failed for curve %i. \n", nid); + /* Create ICA_EC_KEY object */ + *eckey = p_ica_ec_key_new(*nid, privlen); + if (!*eckey) { + TRACE_ERROR("ica_ec_key_new() failed for curve %i.\n", *nid); return CKR_FUNCTION_FAILED; } + return CKR_OK; +} + +static CK_RV ica_build_ec_priv_key(OBJECT *key_obj, ICA_EC_KEY **eckey, + unsigned int *privlen) +{ + CK_RV ret = CKR_OK; + CK_ATTRIBUTE *attr; + unsigned char *d = NULL; + int rc, nid; + + /* Prepare the ICA key */ + ret = ica_prepare_ec_key(key_obj, eckey, privlen, &nid); + if (ret != CKR_OK) { + TRACE_ERROR("ica_prepare_ec_key() failed with rc = 0x%lx. \n", ret); + return ret; + } + + /* Get private key from template via CKA_VALUE */ + ret = template_attribute_get_non_empty(key_obj->template, CKA_VALUE, + &attr); + if (ret != CKR_OK) { + TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); + ret = CKR_TEMPLATE_INCOMPLETE; + goto end; + } + + /* Add zero padding if needed */ + if (*privlen > attr->ulValueLen) { + d = calloc(*privlen, 1); + if (d == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + ret = CKR_HOST_MEMORY; + goto end; + } + + memcpy(d + *privlen - attr->ulValueLen, attr->pValue, + attr->ulValueLen); + } + + /* Initialize ICA_EC_KEY with private key (D) */ + rc = p_ica_ec_key_init(NULL, NULL, d != NULL ? d : attr->pValue, *eckey); + if (rc != 0) { + switch (rc) { + case ENODEV: + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + ret = CKR_FUNCTION_NOT_SUPPORTED; + break; + case EPERM: + TRACE_ERROR("ica_ec_key_init() failed with rc=EPERM, probably curve not supported by openssl.\n"); + ret = CKR_CURVE_NOT_SUPPORTED; + break; + default: + TRACE_ERROR("ica_ec_key_init() failed with rc = %d \n", rc); + ret = CKR_FUNCTION_FAILED; + break; + } + goto end; + } + +end: + if (ret != CKR_OK) { + p_ica_ec_key_free(*eckey); + *eckey = NULL; + } + if (d != NULL) + free(d); + + return ret; +} + +static CK_RV ica_build_ec_pub_key(OBJECT *key_obj, ICA_EC_KEY **eckey, + unsigned int *privlen) +{ + CK_RV ret = CKR_OK; + CK_ATTRIBUTE *attr; + unsigned char x_array[ICATOK_EC_MAX_D_LEN]; + unsigned char y_array[ICATOK_EC_MAX_D_LEN]; + int rc, nid; + CK_BYTE *ecpoint; + CK_ULONG ecpoint_len, field_len; + + /* Prepare the ICA key */ + ret = ica_prepare_ec_key(key_obj, eckey, privlen, &nid); + if (ret != CKR_OK) { + TRACE_ERROR("ica_prepare_ec_key() failed with rc = 0x%lx. \n", ret); + return ret; + } + /* Get public key (X,Y) from template via CKA_EC_POINT */ ret = template_attribute_get_non_empty(key_obj->template, CKA_EC_POINT, - &attr2); + &attr); if (ret != CKR_OK) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); ret = CKR_TEMPLATE_INCOMPLETE; @@ -4612,26 +4636,17 @@ } /* CKA_EC_POINT contains the EC point as OCTET STRING */ - ret = ber_decode_OCTET_STRING(attr2->pValue, &ecpoint, &ecpoint_len, + ret = ber_decode_OCTET_STRING(attr->pValue, &ecpoint, &ecpoint_len, &field_len); - if (ret != CKR_OK || field_len != attr2->ulValueLen) { + if (ret != CKR_OK || field_len != attr->ulValueLen) { TRACE_DEVEL("ber_decode_OCTET_STRING failed\n"); ret = CKR_ATTRIBUTE_VALUE_INVALID; goto end; } - /* Signature length ok? */ - if (signature_len != 2 * privlen) { - TRACE_ERROR("Supplied signature length mismatch: " - "supplied length = %ld, length from libica = %i\n", - signature_len, 2 * privlen); - ret = CKR_SIGNATURE_LEN_RANGE; - goto end; - } - /* Provide (X,Y), decompress key if necessary */ ret = set_pubkey_coordinates(nid, ecpoint, ecpoint_len, - privlen, x_array, y_array); + *privlen, x_array, y_array); if (ret != 0) { TRACE_ERROR("Cannot determine public key coordinates from " "given public key\n"); @@ -4639,11 +4654,144 @@ } /* Initialize ICA_EC_KEY with public key (Q) */ - rc = p_ica_ec_key_init(x_array, y_array, NULL, eckey); + rc = p_ica_ec_key_init(x_array, y_array, NULL, *eckey); if (rc != 0) { - TRACE_ERROR("ica_ec_key_init() for public key failed " - "with rc = %d \n", rc); - ret = CKR_FUNCTION_FAILED; + switch (rc) { + case ENODEV: + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + ret = CKR_FUNCTION_NOT_SUPPORTED; + break; + case EPERM: + TRACE_ERROR("ica_ec_key_init() failed with rc=EPERM, probably curve not supported by openssl.\n"); + ret = CKR_CURVE_NOT_SUPPORTED; + break; + default: + TRACE_ERROR("ica_ec_key_init() failed with rc = %d \n", rc); + ret = CKR_FUNCTION_FAILED; + break; + } + goto end; + } + +end: + if (ret != CKR_OK) { + p_ica_ec_key_free(*eckey); + *eckey = NULL; + } + + return ret; +} + +static CK_RV ica_specific_ec_sign(STDLL_TokData_t *tokdata, SESSION *sess, + CK_BYTE *in_data, CK_ULONG in_data_len, + CK_BYTE *out_data, CK_ULONG *out_data_len, + OBJECT *key_obj) +{ + ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; + CK_RV ret = CKR_OK; + ICA_EC_KEY *eckey; + unsigned int privlen; + int rc; + + UNUSED(sess); + + *out_data_len = 0; + + if (!ica_data->ica_ec_support_available) { + TRACE_ERROR("ECC support is not available in Libica\n"); + return CKR_FUNCTION_NOT_SUPPORTED; + } + + /* Get the private key */ + ret = ica_build_ec_priv_key(key_obj, &eckey, &privlen); + if (ret != CKR_OK) { + TRACE_ERROR("ica_build_ec_priv_key() failed with rc = 0x%lx. \n", ret); + return ret; + } + + /* Create signature */ + rc = p_ica_ecdsa_sign(ica_data->adapter_handle, eckey, + (unsigned char *) in_data, + (unsigned int) in_data_len, + (unsigned char *) out_data, 2 * privlen); + if (rc != 0) { + switch (rc) { + case ENODEV: + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + ret = CKR_FUNCTION_NOT_SUPPORTED; + break; + default: + TRACE_ERROR("ica_ecdsa_sign() failed with rc = %d. \n", rc); + ret = CKR_FUNCTION_FAILED; + break; + } + goto end; + } + + *out_data_len = 2 * privlen; + ret = CKR_OK; + +end: + p_ica_ec_key_free(eckey); + + return ret; +} + +CK_RV token_specific_ec_sign(STDLL_TokData_t *tokdata, SESSION *sess, + CK_BYTE *in_data, CK_ULONG in_data_len, + CK_BYTE *out_data, CK_ULONG *out_data_len, + OBJECT *key_obj) +{ + ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; + CK_RV rc = CKR_FUNCTION_FAILED; + + if (ica_data->ica_ec_signverify_available) { + rc = ica_specific_ec_sign(tokdata, sess, in_data, in_data_len, + out_data, out_data_len, key_obj); + if (rc == CKR_FUNCTION_NOT_SUPPORTED) + ica_data->ica_ec_signverify_available = FALSE; + } + + if (!ica_data->ica_ec_signverify_available) + rc = openssl_specific_ec_sign(tokdata, sess, in_data, in_data_len, + out_data, out_data_len, key_obj); + + return rc; +} + +static CK_RV ica_specific_ec_verify(STDLL_TokData_t *tokdata, + SESSION *sess, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *signature, + CK_ULONG signature_len, OBJECT *key_obj) +{ + ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; + CK_RV ret = CKR_OK; + ICA_EC_KEY *eckey; + unsigned int privlen; + int rc; + + UNUSED(sess); + + if (!ica_data->ica_ec_support_available) { + TRACE_ERROR("ECC support is not available in Libica\n"); + return CKR_FUNCTION_NOT_SUPPORTED; + } + + /* Get the public key */ + ret = ica_build_ec_pub_key(key_obj, &eckey, &privlen); + if (ret != CKR_OK) { + TRACE_ERROR("ica_build_ec_pub_key() failed with rc = 0x%lx. \n", ret); + return ret; + } + + /* Signature length ok? */ + if (signature_len != 2 * privlen) { + TRACE_ERROR("Supplied signature length mismatch: " + "supplied length = %ld, length from libica = %i\n", + signature_len, 2 * privlen); + ret = CKR_SIGNATURE_LEN_RANGE; goto end; } @@ -4657,6 +4805,10 @@ case 0: ret = CKR_OK; break; + case ENODEV: + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + ret = CKR_FUNCTION_NOT_SUPPORTED; + break; case EFAULT: TRACE_ERROR("ica_ecdsa_verify() returned invalid signature, " "rc = %d. \n", rc); @@ -4675,14 +4827,38 @@ return ret; } -CK_RV token_specific_ecdh_pkcs_derive(STDLL_TokData_t *tokdata, - CK_BYTE *priv_bytes, - CK_ULONG priv_length, - CK_BYTE *pub_bytes, - CK_ULONG pub_length, - CK_BYTE *secret_value, - CK_ULONG *secret_value_len, - CK_BYTE *oid, CK_ULONG oid_length) +CK_RV token_specific_ec_verify(STDLL_TokData_t *tokdata, + SESSION *sess, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *signature, + CK_ULONG signature_len, OBJECT *key_obj) +{ + ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; + CK_RV rc = CKR_FUNCTION_FAILED; + + if (ica_data->ica_ec_signverify_available) { + rc = ica_specific_ec_verify(tokdata, sess, in_data, in_data_len, + signature, signature_len, key_obj); + if (rc == CKR_FUNCTION_NOT_SUPPORTED) + ica_data->ica_ec_signverify_available = FALSE; + } + + if (!ica_data->ica_ec_signverify_available) + rc = openssl_specific_ec_verify(tokdata, sess, in_data, in_data_len, + signature, signature_len, key_obj); + + return rc; +} + +static CK_RV ica_specific_ecdh_pkcs_derive(STDLL_TokData_t *tokdata, + CK_BYTE *priv_bytes, + CK_ULONG priv_length, + CK_BYTE *pub_bytes, + CK_ULONG pub_length, + CK_BYTE *secret_value, + CK_ULONG *secret_value_len, + CK_BYTE *oid, CK_ULONG oid_length) { ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; CK_RV ret = CKR_OK; @@ -4770,8 +4946,20 @@ rc = p_ica_ecdh_derive_secret(ica_data->adapter_handle, privkey, pubkey, secret_value, privlen); if (rc != 0) { - TRACE_ERROR("ica_ecdh_derive_secret() failed with rc = %d. \n", rc); - ret = CKR_FUNCTION_FAILED; + switch (rc) { + case ENODEV: + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + ret = CKR_FUNCTION_NOT_SUPPORTED; + break; + case EPERM: + TRACE_ERROR("ica_ecdh_derive_secret() failed with rc=EPERM, probably curve not supported by openssl.\n"); + ret = CKR_CURVE_NOT_SUPPORTED; + break; + default: + TRACE_ERROR("ica_ecdh_derive_secret() failed with rc = %d. \n", rc); + ret = CKR_FUNCTION_FAILED; + break; + } goto end; } @@ -4786,4 +4974,92 @@ return ret; } + +CK_RV token_specific_ecdh_pkcs_derive(STDLL_TokData_t *tokdata, + CK_BYTE *priv_bytes, + CK_ULONG priv_length, + CK_BYTE *pub_bytes, + CK_ULONG pub_length, + CK_BYTE *secret_value, + CK_ULONG *secret_value_len, + CK_BYTE *oid, CK_ULONG oid_length) +{ + ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; + CK_RV rc = CKR_FUNCTION_FAILED; + + if (ica_data->ica_ec_derive_available) { + rc = ica_specific_ecdh_pkcs_derive(tokdata, priv_bytes, priv_length, + pub_bytes, pub_length, + secret_value, secret_value_len, + oid, oid_length); + if (rc == CKR_FUNCTION_NOT_SUPPORTED) + ica_data->ica_ec_derive_available = FALSE; + } + + if (!ica_data->ica_ec_derive_available) + rc = openssl_specific_ecdh_pkcs_derive(tokdata, priv_bytes, priv_length, + pub_bytes, pub_length, + secret_value, secret_value_len, + oid, oid_length); + + return rc; +} + +#endif + +CK_RV token_specific_object_add(STDLL_TokData_t *tokdata, SESSION *sess, + OBJECT *obj) +{ + ica_private_data_t *ica_data = (ica_private_data_t *)tokdata->private_data; + CK_OBJECT_CLASS class; + CK_KEY_TYPE keytype; +#ifndef NO_EC + ICA_EC_KEY *ica_eckey = NULL; + unsigned int privlen; + EVP_PKEY *ossl_eckey = NULL; #endif + CK_RV rc; + + UNUSED(sess); + + rc = template_attribute_get_ulong(obj->template, CKA_CLASS, &class); + if (rc != CKR_OK) + return CKR_OK; + + rc = template_attribute_get_ulong(obj->template, CKA_KEY_TYPE, &keytype); + if (rc != CKR_OK) + return CKR_OK; + + switch (keytype) { +#ifndef NO_EC + case CKK_EC: + if (ica_data->ica_ec_keygen_available) { + /* Check if libica supports the curve */ + switch (class) { + case CKO_PRIVATE_KEY: + rc = ica_build_ec_priv_key(obj, &ica_eckey, &privlen); + if (ica_eckey != NULL) + p_ica_ec_key_free(ica_eckey); + return rc; + case CKO_PUBLIC_KEY: + rc = ica_build_ec_pub_key(obj, &ica_eckey, &privlen); + if (ica_eckey != NULL) + p_ica_ec_key_free(ica_eckey); + return rc; + default: + return CKR_KEY_TYPE_INCONSISTENT; + } + } else { + /* Check if OpenSSL supports the curve */ + rc = openssl_make_ec_key_from_template(obj->template, &ossl_eckey); + if (ossl_eckey != NULL) + EVP_PKEY_free(ossl_eckey); + return rc; + } + return CKR_OK; +#endif + + default: + return CKR_OK; + } +} diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/ica_s390_stdll/tok_struct.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/ica_s390_stdll/tok_struct.h --- opencryptoki-3.16.0+dfsg/usr/lib/ica_s390_stdll/tok_struct.h 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/ica_s390_stdll/tok_struct.h 2022-02-02 15:05:41.000000000 +0100 @@ -141,12 +141,13 @@ NULL, // dsa_verify &token_specific_get_mechanism_list, &token_specific_get_mechanism_info, - NULL, // object_add + &token_specific_object_add, NULL, // key_wrap NULL, // key_unwrap NULL, // reencrypt_single NULL, // set_attribute_values NULL, // set_attrs_for_new_object + NULL, // handle_event }; #endif diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/icsf_stdll/icsf.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/icsf_stdll/icsf.c --- opencryptoki-3.16.0+dfsg/usr/lib/icsf_stdll/icsf.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/icsf_stdll/icsf.c 2022-02-02 15:05:41.000000000 +0100 @@ -3016,7 +3016,7 @@ *sig_len = length; /* leave if just returning the length. */ - if (!verify && *reason == 3003) + if (!verify && reason != NULL && *reason == 3003) goto done; /* copy the chained data when required */ @@ -3024,7 +3024,7 @@ memcpy(chain_data, bvChain.bv_val, bvChain.bv_len); /* copy signature when signing */ - if (!verify) + if (!verify && sig != NULL) memcpy(sig, bvSig.bv_val, bvSig.bv_len); done: diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/icsf_stdll/icsf_config.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/icsf_stdll/icsf_config.h --- opencryptoki-3.16.0+dfsg/usr/lib/icsf_stdll/icsf_config.h 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/icsf_stdll/icsf_config.h 2022-02-02 15:05:41.000000000 +0100 @@ -32,7 +32,7 @@ int mech; }; -CK_RV parse_config_file(const char *conf_name, CK_SLOT_ID slot_id, - struct icsf_config *data); +static CK_RV parse_config_file(const char *conf_name, CK_SLOT_ID slot_id, + struct icsf_config *data); #endif diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/icsf_stdll/icsf_config_lexer.l opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/icsf_stdll/icsf_config_lexer.l --- opencryptoki-3.16.0+dfsg/usr/lib/icsf_stdll/icsf_config_lexer.l 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/icsf_stdll/icsf_config_lexer.l 1970-01-01 01:00:00.000000000 +0100 @@ -1,81 +0,0 @@ -/* - * COPYRIGHT (c) International Business Machines Corp. 2013-2017 - * - * This program is provided under the terms of the Common Public License, - * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this - * software constitutes recipient's acceptance of CPL-1.0 terms which can be - * found in the file LICENSE file or at - * https://opensource.org/licenses/cpl1.0.php - */ - -%{ -#include -#include "icsf_config_parse.h" - -/* Ignore -Wsign-compare for autogenerated code. */ -#pragma GCC diagnostic ignored "-Wsign-compare" - -extern void yyerror(const char *s); - -%} - -%option noyywrap -%option nounput -%option noinput - -%% - -[\t\n ]+ { - /* Ignore spaces */ -} - -#.*\n { - /* Comment */ -} - -slot { - /* Identify a definition */ - return SLOT; -} - -[0-9]+ { - /* Number */ - yylval.num = strtoul(yytext, NULL, 10); - return INTEGER; -} - -\{ { - /* Open definition */ - return BEGIN_DEF; -} - -\} { - /* Close definition */ - return END_DEF; -} - -= { - /* Assignment */ - return EQUAL; -} - -[^\"= \t\n]+ { - /* String */ - yylval.str = strdup(yytext); - return STRING; -} - -\"[^\"\n]*\" { - /* Quoted string */ - yylval.str = strdup(yytext + 1); - if (yylval.str && yylval.str[0]) - yylval.str[strlen(yylval.str) - 1] = '\0'; - return STRING; -} - -. { - /* Default */ - yyerror(yytext); -} - -%% diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/icsf_stdll/icsf_config_parse.y opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/icsf_stdll/icsf_config_parse.y --- opencryptoki-3.16.0+dfsg/usr/lib/icsf_stdll/icsf_config_parse.y 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/icsf_stdll/icsf_config_parse.y 1970-01-01 01:00:00.000000000 +0100 @@ -1,229 +0,0 @@ -/* - * COPYRIGHT (c) International Business Machines Corp. 2013-2017 - * - * This program is provided under the terms of the Common Public License, - * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this - * software constitutes recipient's acceptance of CPL-1.0 terms which can be - * found in the file LICENSE file or at - * https://opensource.org/licenses/cpl1.0.php - */ - -%{ -#include -#include -#include -#include -#include -#include -#include -#include -#include "pkcs11types.h" -#include "icsf_config.h" -#include "defs.h" -#include "host_defs.h" -#include "h_extern.h" -#include "trace.h" - -/* Global vars used as parameter to bison/flex parser. */ -extern FILE *yyin; -CK_SLOT_ID in_slot_id; -int expected_slot; -struct icsf_config out_config; -char out_str_mech[64] = ""; -int out_rc; - -/* Function used to report error. */ -void yyerror(const char *str); - -extern int yylex(); - -/* */ -struct ref { - char *key; - char *addr; - size_t len; - int required; -}; -struct ref refs[] = { - { "token_name", out_config.name, sizeof(out_config.name), 1 }, - { "token_manufacture", out_config.manuf, sizeof(out_config.manuf), 1 }, - { "token_model", out_config.model, sizeof(out_config.model), 1 }, - { "token_serial", out_config.serial, sizeof(out_config.serial), 1 }, - { "mech", out_str_mech, sizeof(out_str_mech), 1 }, - { "uri", out_config.uri, sizeof(out_config.uri), 0 }, - { "binddn", out_config.dn, sizeof(out_config.dn), 0 }, - { "cacert", out_config.ca_file, sizeof(out_config.ca_file), 0 }, - { "cert", out_config.cert_file, sizeof(out_config.cert_file), 0 }, - { "key", out_config.key_file, sizeof(out_config.key_file), 0 }, -}; -size_t refs_len = sizeof(refs)/sizeof(*refs); -%} - -%union { - unsigned int num; - char *str; -}; - -%token STRING -%token INTEGER -%token SLOT -%token BEGIN_DEF -%token END_DEF -%token EQUAL - -%% - -slots: - slots slot - | - ; - -slot: - SLOT INTEGER - { - expected_slot = ($2 == in_slot_id); - } - BEGIN_DEF key_values END_DEF - ; - -key_values: - key_values key_value - | - ; - -key_value: - STRING EQUAL STRING - { - char *key = $1; - char *value = $3; - size_t i; - - /* Check if this keyword belongs to the expected slot. */ - if (!expected_slot || out_rc) - goto done; - - /* Check key and value */ - if (!key || !value) { - out_rc = 1; - TRACE_ERROR("Null %s found.\n", (!key) ? "key" : "value"); - goto done; - } - - /* Check if this keyword is expected. */ - for (i = 0; i < strlen(key); i++) - key[i] = tolower(key[i]); - - for(i = 0; i < refs_len; i++) { - if (!strcmp(refs[i].key, key)) { - strncpy(refs[i].addr, value, refs[i].len); - refs[i].addr[refs[i].len - 1] = '\0'; - goto done; - } - } - - out_rc = 1; - TRACE_ERROR("Invalid keyword: %s\n", key); - - done: - if (key) - free(key); - if (value) - free(value); - } - ; - -%% - -void -yyerror(const char *str) -{ - out_rc = 1; - fprintf(stderr,"Error: %s\n", str); - TRACE_DEBUG("Failed to parse config file. %s\n", str); -} - -static int -check_keys(const char *conf_name) -{ - size_t i; - - for (i = 0; i < refs_len; i++) { - if (refs[i].required && *refs[i].addr == '\0') { - TRACE_ERROR("Missing required key \"%s\" in \"%s\".\n", - refs[i].key, conf_name); - return -1; - } - } - - return 0; -} - -/* - * Parse config file using yacc. - */ -CK_RV -parse_config_file(const char *conf_name, CK_SLOT_ID slot_id, - struct icsf_config *data) -{ - CK_RV rc; - struct stat stat_info; - - /* Check is file exists. */ - if (stat(conf_name, &stat_info) || !S_ISREG(stat_info.st_mode)) { - TRACE_ERROR("File \"%s\" does not exist or is invalid.\n", - conf_name); - return CKR_FUNCTION_FAILED; - } - - /* Set parameters used by the parser */ - in_slot_id = slot_id; - out_rc = 0; - memset(&out_config, 0, sizeof(*data)); - expected_slot = FALSE; - - /* Open config file */ - yyin = fopen(conf_name, "r"); - if (yyin == NULL) { - TRACE_ERROR("Failed to open \"%s\".\n", conf_name); - return CKR_FUNCTION_FAILED; - } - - /* Parse config file */ - rc = yyparse(); - fclose(yyin); - if (rc || out_rc) { - TRACE_ERROR("Failed to parser file \"%s\" (%lu:%d).\n", - conf_name, rc, out_rc); - return CKR_FUNCTION_FAILED; - } - - /* Check required keys*/ - if (check_keys(conf_name)) - return CKR_FUNCTION_FAILED; - - /* Parse mechanism type */ - if (!strcmp(out_str_mech, "SIMPLE")) { - out_config.mech = ICSF_CFG_MECH_SIMPLE; - } else if (!strcmp(out_str_mech, "SASL")) { - out_config.mech = ICSF_CFG_MECH_SASL; - } else { - TRACE_ERROR("Unknown mechanism type found: %s\n", out_str_mech); - return CKR_FUNCTION_FAILED; - } - - /* Copy output data. */ - memcpy(data, &out_config, sizeof(*data)); - - #if DEBUG - { - size_t i; - TRACE_DEVEL("ICSF configs for slot %lu.\n", slot_id); - for (i = 0; i < refs_len; i++) { - TRACE_DEVEL(" %s = \"%s\"\n", refs[i].key, - refs[i].addr); - } - } - #endif - - return CKR_OK; -} diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/icsf_stdll/icsf.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/icsf_stdll/icsf.h --- opencryptoki-3.16.0+dfsg/usr/lib/icsf_stdll/icsf.h 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/icsf_stdll/icsf.h 2022-02-02 15:05:41.000000000 +0100 @@ -76,7 +76,7 @@ #define ICSF_FLAGS_LEN 4 #define ICSF_RULE_ITEM_LEN 8 -#define MAX_RECORDS 10 +#define MAX_RECORDS 100 /* Object types */ #define ICSF_SESSION_OBJECT 'S' diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/icsf_stdll/icsf_specific.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/icsf_stdll/icsf_specific.c --- opencryptoki-3.16.0+dfsg/usr/lib/icsf_stdll/icsf_specific.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/icsf_stdll/icsf_specific.c 2022-02-02 15:05:41.000000000 +0100 @@ -44,6 +44,9 @@ #include "trace.h" #include "shared_memory.h" #include "slotmgr.h" +#include "../api/policy.h" +#include "cfgparser.h" +#include "configuration.h" /* Default token attributes */ const char manuf[] = "IBM"; @@ -128,6 +131,7 @@ struct bt_ref_hdr hdr; CK_SESSION_HANDLE session_id; struct icsf_object_record icsf_object; + struct objstrength strength; }; /* @@ -141,6 +145,55 @@ size_t used_data_len; }; +struct icsf_policy_attr { + LDAP *ld; + struct icsf_object_record *icsf_object; +}; + +int icsf_to_ock_err(int icsf_return_code, int icsf_reason_code); + +static CK_RV icsf_policy_get_attr(void *data, + CK_ATTRIBUTE_TYPE type, + CK_ATTRIBUTE **attr) +{ + CK_RV rc; + int reason; + struct icsf_policy_attr *d = data; + CK_ATTRIBUTE *a; + CK_ATTRIBUTE s = { .type = type, .ulValueLen = 0, .pValue = NULL }; + + rc = icsf_get_attribute(d->ld, &reason, d->icsf_object, &s, 1); + if (rc != CKR_OK) { + TRACE_DEVEL("icsf_get_attribute failed\n"); + return icsf_to_ock_err(rc, reason); + } + if (s.ulValueLen == CK_UNAVAILABLE_INFORMATION) { + TRACE_DEVEL("Size information for attribute 0x%lx not available\n", + type); + return CKR_FUNCTION_FAILED; + } + a = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + s.ulValueLen); + if (!a) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + return CKR_HOST_MEMORY; + } + a->type = type; + a->ulValueLen = s.ulValueLen; + a->pValue = (CK_BYTE *) a + sizeof(CK_ATTRIBUTE); + rc = icsf_get_attribute(d->ld, &reason, d->icsf_object, a, 1); + if (rc != CKR_OK) { + TRACE_DEVEL("icsf_get_attribute failed\n"); + return icsf_to_ock_err(rc, reason); + } + *attr = a; + return rc; +} + +static void icsf_policy_free_attr(CK_ATTRIBUTE *attr) +{ + free(attr); +} + /* * Get the session specific structure. */ @@ -289,8 +342,15 @@ return CKR_FUNCTION_FAILED; } - tokdata->mech_list = (MECH_LIST_ELEMENT *)icsf_mech_list; - tokdata->mech_list_len = icsf_mech_list_len; + rc = ock_generic_filter_mechanism_list(tokdata, + icsf_mech_list, + icsf_mech_list_len, + &(tokdata->mech_list), + &(tokdata->mech_list_len)); + if (rc != CKR_OK) { + TRACE_ERROR("Mechanism filtering failed! rc = 0x%lx\n", rc); + return rc; + } icsf_data = calloc(1, sizeof(icsf_private_data_t)); if (icsf_data == NULL) @@ -324,6 +384,179 @@ return rc; } +static void config_parse_error(int line, int col, const char *msg) +{ + TRACE_ERROR("Error parsing config file: line %d column %d: %s\n", line, col, + msg); +} + +static struct icsf_config out_config; +static char out_str_mech[64] = ""; + +struct ref { + char *key; + char *addr; + size_t len; + int required; +}; + +static struct ref refs[] = { + { "token_name", out_config.name, sizeof(out_config.name), 1 }, + { "token_manufacture", out_config.manuf, sizeof(out_config.manuf), 1 }, + { "token_model", out_config.model, sizeof(out_config.model), 1 }, + { "token_serial", out_config.serial, sizeof(out_config.serial), 1 }, + { "mech", out_str_mech, sizeof(out_str_mech), 1 }, + { "uri", out_config.uri, sizeof(out_config.uri), 0 }, + { "binddn", out_config.dn, sizeof(out_config.dn), 0 }, + { "cacert", out_config.ca_file, sizeof(out_config.ca_file), 0 }, + { "cert", out_config.cert_file, sizeof(out_config.cert_file), 0 }, + { "key", out_config.key_file, sizeof(out_config.key_file), 0 }, +}; +static const size_t refs_len = sizeof(refs)/sizeof(*refs); + +static int check_keys(const char *conf_name) +{ + size_t i; + + for (i = 0; i < refs_len; i++) { + if (refs[i].required && *refs[i].addr == '\0') { + TRACE_ERROR("Missing required key \"%s\" in \"%s\".\n", + refs[i].key, conf_name); + return -1; + } + } + + return 0; +} + +static CK_RV config_parse_slot(const char *config_file, + struct ConfigIdxStructNode *slot) +{ + struct ConfigBaseNode *c; + int i; + size_t k; + char *str; + + TRACE_DEVEL("Slot: %lu\n", slot->idx); + + confignode_foreach(c, slot->value, i) { + TRACE_DEVEL("Config node: '%s' type: %u line: %u\n", + c->key, c->type, c->line); + + str = confignode_getstr(c); + if (str != NULL) { + for (k = 0; k < refs_len; k++) { + if (!strcasecmp(refs[k].key, c->key)) { + strncpy(refs[k].addr, str, refs[i].len); + refs[k].addr[refs[k].len - 1] = '\0'; + goto found; + } + } + + TRACE_ERROR("Error parsing config file '%s': unexpected token '%s' " + "at line %d: \n", config_file, c->key, c->line); + return CKR_FUNCTION_FAILED; + +found: + continue; + } + + TRACE_ERROR("Error parsing config file '%s': unexpected token '%s' " + "at line %d: \n", config_file, c->key, c->line); + return CKR_FUNCTION_FAILED; + } + + return CKR_OK; +} + +static CK_RV parse_config_file(const char *conf_name, CK_SLOT_ID slot_id, + struct icsf_config *data) +{ + FILE *file; + struct ConfigBaseNode *c, *config = NULL; + struct ConfigIdxStructNode *slot; + CK_RV ret = CKR_OK; + int i; + + file = fopen(conf_name, "r"); + if (file == NULL) { + TRACE_ERROR("Error opening config file '%s': %s\n", conf_name, + strerror(errno)); + return CKR_FUNCTION_FAILED; + } + + ret = parse_configlib_file(file, &config, config_parse_error, 0); + fclose(file); + if (ret != 0) { + TRACE_ERROR("Error parsing config file '%s'\n", conf_name); + ret = CKR_FUNCTION_FAILED; + goto done; + } + + confignode_foreach(c, config, i) { + TRACE_DEVEL("Config node: '%s' type: %u line: %u\n", + c->key, c->type, c->line); + + if (confignode_hastype(c, CT_IDX_STRUCT)) { + slot = confignode_to_idxstruct(c); + if (strcmp(slot->base.key, "slot") == 0 && + slot->idx == slot_id) { + ret = config_parse_slot(conf_name, slot); + if (ret != 0) + break; + continue; + } + + TRACE_ERROR("Error parsing config file '%s': unexpected token '%s' " + "at line %d: \n", conf_name, c->key, c->line); + ret = -1; + break; + } + + TRACE_ERROR("Error parsing config file '%s': unexpected token '%s' " + "at line %d: \n", conf_name, c->key, c->line); + ret = CKR_FUNCTION_FAILED; + break; + } + + if (ret != CKR_OK) + goto done; + + if (check_keys(conf_name)) { + ret = CKR_FUNCTION_FAILED; + goto done; + } + + /* Parse mechanism type */ + if (!strcmp(out_str_mech, "SIMPLE")) { + out_config.mech = ICSF_CFG_MECH_SIMPLE; + } else if (!strcmp(out_str_mech, "SASL")) { + out_config.mech = ICSF_CFG_MECH_SASL; + } else { + TRACE_ERROR("Unknown mechanism type found: %s\n", out_str_mech); + ret = CKR_FUNCTION_FAILED; + goto done; + } + + /* Copy output data. */ + memcpy(data, &out_config, sizeof(*data)); + + #if DEBUG + { + size_t i; + TRACE_DEVEL("ICSF configs for slot %lu.\n", slot_id); + for (i = 0; i < refs_len; i++) { + TRACE_DEVEL(" %s = \"%s\"\n", refs[i].key, + refs[i].addr); + } + } + #endif + +done: + confignode_deepfree(config); + return ret; +} + CK_RV token_specific_init_token_data(STDLL_TokData_t * tokdata, CK_SLOT_ID slot_id) { @@ -410,7 +643,7 @@ return CKR_FUNCTION_FAILED; } - if (!fread(&data, sizeof(data), 1, fh)) { + if (fread(&data, sizeof(data), 1, fh) != 1) { TRACE_ERROR("Failed to read ICSF slot data.\n"); return CKR_FUNCTION_FAILED; } @@ -491,7 +724,7 @@ return CKR_FUNCTION_FAILED; } - if (asprintf(&shm_id, "/icsf-%lu", slot_id) < 0) { + if (asprintf(&shm_id, "/icsf-%lu", slot_id) < 0 || shm_id == NULL) { TRACE_ERROR("Failed to allocate shared memory id " "for slot %lu.\n", slot_id); return CKR_HOST_MEMORY; @@ -499,15 +732,17 @@ TRACE_DEVEL("Attaching to shared memory \"%s\".\n", shm_id); rc = XProcLock(tokdata); - if (rc != CKR_OK) + if (rc != CKR_OK) { + free(shm_id); return CKR_FUNCTION_FAILED; + } /* * Attach to an existing shared memory region or create it if it doesn't * exists. When the it's created (ret=0) the region is initialized with * zeroes. */ - ret = sm_open(shm_id, 0666, (void **) &ptr, len, 1); + ret = sm_open(shm_id, 0660, (void **) &ptr, len, 1); if (ret < 0) { TRACE_ERROR("Failed to open shared memory \"%s\".\n", shm_id); rc = CKR_FUNCTION_FAILED; @@ -585,13 +820,13 @@ TRACE_ERROR("MK_SO buffer overflow\n"); return CKR_FUNCTION_FAILED; } - if (get_masterkey(pin, pin_len, fname, mk, &mk_len)) { + if (get_masterkey(tokdata, pin, pin_len, fname, mk, &mk_len)) { TRACE_DEVEL("Failed to get masterkey \"%s\".\n", fname); return CKR_FUNCTION_FAILED; } /* Load RACF password */ - if (get_racf(mk, mk_len, racf_pass, &racf_pass_len)) { + if (get_racf(tokdata, mk, mk_len, racf_pass, &racf_pass_len)) { TRACE_DEVEL("Failed to get RACF password.\n"); return CKR_FUNCTION_FAILED; } @@ -651,13 +886,13 @@ TRACE_ERROR("MK_SO filename buffer overflow\n"); return CKR_FUNCTION_FAILED; } - if (get_masterkey(pin, pin_len, fname, mk, &mk_len)) { + if (get_masterkey(tokdata, pin, pin_len, fname, mk, &mk_len)) { TRACE_DEVEL("Failed to load masterkey \"%s\".\n", fname); return CKR_FUNCTION_FAILED; } /* Load RACF password */ - if (get_racf(mk, mk_len, racf_pass, &racf_pass_len)) { + if (get_racf(tokdata, mk, mk_len, racf_pass, &racf_pass_len)) { TRACE_DEVEL("Failed to get RACF password.\n"); return CKR_FUNCTION_FAILED; } @@ -668,8 +903,14 @@ return CKR_FUNCTION_FAILED; } + if ((tokdata->statistics->flags & STATISTICS_FLAG_COUNT_INTERNAL) != 0) + tokdata->statistics->increment_func(tokdata->statistics, + tokdata->slot_id, + &tokdata->store_strength.mk_keygen, + tokdata->store_strength.mk_strength); + /* Save racf password using the new master key */ - if (secure_racf(racf_pass, racf_pass_len, mk, mk_len)) { + if (secure_racf(tokdata, racf_pass, racf_pass_len, mk, mk_len)) { TRACE_DEVEL("Failed to save racf password.\n"); return CKR_FUNCTION_FAILED; } @@ -686,7 +927,7 @@ if (slot_data[slot_id]->mech == ICSF_CFG_MECH_SIMPLE) { /* Save master key */ - if (secure_masterkey(mk, mk_len, pin, pin_len, fname)) { + if (secure_masterkey(tokdata, mk, mk_len, pin, pin_len, fname)) { TRACE_DEVEL("Failed to save the new master key.\n"); return CKR_FUNCTION_FAILED; } @@ -822,7 +1063,7 @@ return CKR_FUNCTION_FAILED; } - rc = secure_masterkey(tokdata->master_key, + rc = secure_masterkey(tokdata, tokdata->master_key, AES_KEY_SIZE_256, pPin, ulPinLen, fname); if (rc != CKR_OK) { TRACE_DEVEL("Could not create MK_USER.\n"); @@ -903,7 +1144,7 @@ TRACE_ERROR("MK_USER buffer overflow\n"); return CKR_FUNCTION_FAILED; } - rc = secure_masterkey(tokdata->master_key, + rc = secure_masterkey(tokdata, tokdata->master_key, AES_KEY_SIZE_256, pNewPin, ulNewLen, fname); if (rc != CKR_OK) { TRACE_ERROR("Save Master Key Failed.\n"); @@ -960,7 +1201,7 @@ return CKR_FUNCTION_FAILED; } - rc = secure_masterkey(tokdata->master_key, + rc = secure_masterkey(tokdata, tokdata->master_key, AES_KEY_SIZE_256, pNewPin, ulNewLen, fname); if (rc != CKR_OK) { TRACE_ERROR("Save Master Key Failed.\n"); @@ -1014,7 +1255,8 @@ if (slot_data[slot_id]->mech == ICSF_CFG_MECH_SIMPLE) { TRACE_INFO("Using SIMPLE auth with slot ID: %lu\n", slot_id); /* get racf passwd */ - rc = get_racf(tokdata->master_key, AES_KEY_SIZE_256, racfpwd, &racflen); + rc = get_racf(tokdata, tokdata->master_key, AES_KEY_SIZE_256, + racfpwd, &racflen); if (rc != CKR_OK) { TRACE_DEVEL("Failed to get racf passwd.\n"); return NULL; @@ -1261,6 +1503,7 @@ pthread_mutex_destroy(&icsf_data->sess_list_mutex); free(icsf_data); tokdata->private_data = NULL; + free(tokdata->mech_list); } return rc; @@ -1323,7 +1566,7 @@ TRACE_ERROR("MK_USER buffer overflow\n"); return CKR_FUNCTION_FAILED; } - rc = get_masterkey(pPin, ulPinLen, fname, + rc = get_masterkey(tokdata, pPin, ulPinLen, fname, tokdata->master_key, &mklen); if (rc != CKR_OK) { TRACE_DEVEL("Failed to load master key.\n"); @@ -1353,7 +1596,7 @@ TRACE_ERROR("MK_SO buffer overflow\n"); return CKR_FUNCTION_FAILED; } - rc = get_masterkey(pPin, ulPinLen, fname, + rc = get_masterkey(tokdata, pPin, ulPinLen, fname, tokdata->master_key, &mklen); if (rc != CKR_OK) { TRACE_DEVEL("Failed to load master key.\n"); @@ -1542,6 +1785,8 @@ rc = CKR_FUNCTION_FAILED; goto done; } + memcpy(&mapping_dst->strength, &mapping_src->strength, + sizeof(struct objstrength)); /* Use node number as handle */ *dst = node_number; @@ -1573,6 +1818,7 @@ CK_ULONG node_number; char token_name[sizeof(tokdata->nv_token_data->token_info.label) + 1]; int reason = 0; + struct icsf_policy_attr pattr; /* Check permissions based on attributes and session */ rc = check_session_permissions(session, attrs, attrs_len); @@ -1624,6 +1870,17 @@ rc = icsf_to_ock_err(rc, reason); goto done; } + /* Policy check */ + pattr.ld = session_state->ld; + pattr.icsf_object = &mapping->icsf_object; + rc = tokdata->policy->store_object_strength(tokdata->policy, + &mapping->strength, + icsf_policy_get_attr, &pattr, + icsf_policy_free_attr, session); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Object too weak\n"); + goto done; + } /* Add info about object into session */ if (!(node_number = bt_node_add(&icsf_data->objects, mapping))) { @@ -1763,6 +2020,7 @@ CK_ATTRIBUTE_PTR new_priv_attrs = NULL; CK_ULONG new_priv_attrs_len = 0; CK_ULONG key_type; + struct icsf_policy_attr pattr; /* Check and set default attributes based on mech */ if ((key_type = get_generate_key_type(mech)) == (CK_ULONG)-1) { @@ -1838,6 +2096,25 @@ rc = icsf_to_ock_err(rc, reason); goto done; } + pattr.ld = session_state->ld; + pattr.icsf_object = &pub_key_mapping->icsf_object; + rc = tokdata->policy->store_object_strength(tokdata->policy, + &pub_key_mapping->strength, + icsf_policy_get_attr, &pattr, + icsf_policy_free_attr, session); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Public key too weak\n"); + goto done; + } + pattr.icsf_object = &priv_key_mapping->icsf_object; + rc = tokdata->policy->store_object_strength(tokdata->policy, + &priv_key_mapping->strength, + icsf_policy_get_attr, &pattr, + icsf_policy_free_attr, session); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Private key too weak\n"); + goto done; + } /* Add info about objects into session */ if (!(pub_node_number = bt_node_add(&icsf_data->objects, pub_key_mapping)) || @@ -1852,6 +2129,12 @@ *p_priv_key = priv_node_number; done: + if (rc == CKR_OK && tokdata->statistics->increment_func != NULL) + tokdata->statistics->increment_func(tokdata->statistics, + session->session_info.slotID, + mech, + priv_key_mapping->strength.strength); + free_attribute_array(new_pub_attrs, new_pub_attrs_len); free_attribute_array(new_priv_attrs, new_priv_attrs_len); @@ -1882,6 +2165,7 @@ CK_ULONG class = CKO_SECRET_KEY; CK_ULONG key_type = 0; int reason = 0; + struct icsf_policy_attr pattr; /* Check attributes */ if ((key_type = get_generate_key_type(mech)) == (CK_ULONG)-1) { @@ -1946,6 +2230,16 @@ rc = icsf_to_ock_err(rc, reason); goto done; } + pattr.ld = session_state->ld; + pattr.icsf_object = &mapping->icsf_object; + rc = tokdata->policy->store_object_strength(tokdata->policy, + &mapping->strength, + icsf_policy_get_attr, &pattr, + icsf_policy_free_attr, session); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Public key too weak\n"); + goto done; + } /* Add info about object into session */ if (!(node_number = bt_node_add(&icsf_data->objects, mapping))) { @@ -1958,6 +2252,11 @@ *handle = node_number; done: + if (rc == CKR_OK && tokdata->statistics->increment_func != NULL) + tokdata->statistics->increment_func(tokdata->statistics, + session->session_info.slotID, + mech, mapping->strength.strength); + if (new_attrs) free_attribute_array(new_attrs, new_attrs_len); @@ -2102,8 +2401,14 @@ TRACE_ERROR("%s\n", ock_err(ERR_KEY_HANDLE_INVALID)); goto done; } - bt_put_node_value(&icsf_data->objects, mapping); - mapping = NULL; + rc = tokdata->policy->is_mech_allowed(tokdata->policy, mech, + &mapping->strength, + POLICY_CHECK_ENCRYPT, + session); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: encrypt init\n"); + goto done; + } /** validate the mechanism parameter length here */ if ((rc = validate_mech_parameters(mech))) @@ -2167,8 +2472,15 @@ } done: + if (rc == CKR_OK && tokdata->statistics->increment_func != NULL) + tokdata->statistics->increment_func(tokdata->statistics, + session->session_info.slotID, + mech, mapping->strength.strength); + if (rc != CKR_OK) free_encr_ctx(encr_ctx); + bt_put_node_value(&icsf_data->objects, mapping); + mapping = NULL; return rc; } @@ -2606,10 +2918,16 @@ TRACE_ERROR("%s\n", ock_err(ERR_KEY_HANDLE_INVALID)); goto done; } - bt_put_node_value(&icsf_data->objects, mapping); - mapping = NULL; + rc = tokdata->policy->is_mech_allowed(tokdata->policy, mech, + &mapping->strength, + POLICY_CHECK_DECRYPT, + session); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: decrypt init\n"); + goto done; + } - /** validate the mechanism parameter length here */ + /** validate the mechanism parameter length here */ if ((rc = validate_mech_parameters(mech))) goto done; @@ -2671,8 +2989,15 @@ } done: + if (rc == CKR_OK && tokdata->statistics->increment_func != NULL) + tokdata->statistics->increment_func(tokdata->statistics, + session->session_info.slotID, + mech, mapping->strength.strength); + if (rc != CKR_OK) free_encr_ctx(decr_ctx); + bt_put_node_value(&icsf_data->objects, mapping); + mapping = NULL; return rc; } @@ -3278,6 +3603,7 @@ int node_number, rc; int reason = 0; CK_RV rv = CKR_OK; + struct icsf_policy_attr pattr; /* Whether we retrieve public or private objects is determined by * the caller's SAF authority on the token, something ock doesn't @@ -3399,6 +3725,16 @@ } new_mapping->session_id = sess->handle; new_mapping->icsf_object = records[i]; + /* Policy check */ + pattr.ld = session_state->ld; + pattr.icsf_object = &new_mapping->icsf_object; + rc = tokdata->policy->store_object_strength( + tokdata->policy, &new_mapping->strength, + icsf_policy_get_attr, &pattr, icsf_policy_free_attr, sess); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Object too weak\n"); + goto done; + } if (!(node_number = bt_node_add(&icsf_data->objects, new_mapping))) { @@ -3567,6 +3903,14 @@ rc = CKR_KEY_HANDLE_INVALID; return rc; } + rc = tokdata->policy->is_mech_allowed(tokdata->policy, mech, + &mapping->strength, + POLICY_CHECK_SIGNATURE, + session); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Sign init\n"); + goto done; + } /* Check the mechanism info */ switch (mech->mechanism) { @@ -3698,6 +4042,11 @@ ctx->active = TRUE; done: + if (rc == CKR_OK && tokdata->statistics->increment_func != NULL) + tokdata->statistics->increment_func(tokdata->statistics, + session->session_info.slotID, + mech, mapping->strength.strength); + if (mapping) { bt_put_node_value(&icsf_data->objects, mapping); mapping = NULL; @@ -4146,6 +4495,14 @@ rc = CKR_KEY_HANDLE_INVALID; return rc; } + rc = tokdata->policy->is_mech_allowed(tokdata->policy, mech, + &mapping->strength, + POLICY_CHECK_VERIFY, + session); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Sign init\n"); + goto done; + } /* Check the mechanism info */ switch (mech->mechanism) { @@ -4282,6 +4639,11 @@ ctx->active = TRUE; done: + if (rc == CKR_OK && tokdata->statistics->increment_func != NULL) + tokdata->statistics->increment_func(tokdata->statistics, + session->session_info.slotID, + mech, mapping->strength.strength); + if (mapping) { bt_put_node_value(&icsf_data->objects, mapping); mapping = NULL; @@ -4704,6 +5066,20 @@ rc = CKR_KEY_HANDLE_INVALID; goto done; } + rc = tokdata->policy->is_mech_allowed(tokdata->policy, mech, + &wrapping_key_mapping->strength, + POLICY_CHECK_WRAP, session); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Wrap init\n"); + goto done; + } + rc = tokdata->policy->is_key_allowed(tokdata->policy, + &key_mapping->strength, + session); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Wrap init\n"); + goto done; + } /* validate mechanism parameters. Only 4 mechanisms support * key wrapping in icsf token */ @@ -4750,6 +5126,12 @@ } done: + if (rc == CKR_OK && tokdata->statistics->increment_func != NULL) + tokdata->statistics->increment_func(tokdata->statistics, + session->session_info.slotID, + mech, + wrapping_key_mapping->strength.strength); + if (wrapping_key_mapping) { bt_put_node_value(&icsf_data->objects, wrapping_key_mapping); wrapping_key_mapping = NULL; @@ -4780,6 +5162,7 @@ struct icsf_object_mapping *key_mapping = NULL; CK_ULONG node_number; size_t expected_block_size = 0; + struct icsf_policy_attr pattr; /* Check session */ if (!(session_state = get_session_state(tokdata, session->handle))) { @@ -4799,6 +5182,14 @@ TRACE_ERROR("%s\n", ock_err(ERR_KEY_HANDLE_INVALID)); return CKR_KEY_HANDLE_INVALID; } + rc = tokdata->policy->is_mech_allowed(tokdata->policy, mech, + &wrapping_key_mapping->strength, + POLICY_CHECK_UNWRAP, session); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Unwrap init\n"); + goto done; + } + /* Allocate structure to keep ICSF object information */ if (!(key_mapping = malloc(sizeof(*key_mapping)))) { @@ -4852,6 +5243,16 @@ rc = icsf_to_ock_err(rc, reason); goto done; } + pattr.ld = session_state->ld; + pattr.icsf_object = &key_mapping->icsf_object; + rc = tokdata->policy->store_object_strength(tokdata->policy, + &key_mapping->strength, + icsf_policy_get_attr, &pattr, + icsf_policy_free_attr, session); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Unwrapped key too weak\n"); + goto done; + } /* Add info about object into session */ if (!(node_number = bt_node_add(&icsf_data->objects, key_mapping))) { @@ -4864,6 +5265,12 @@ *p_key = node_number; done: + if (rc == CKR_OK && tokdata->statistics->increment_func != NULL) + tokdata->statistics->increment_func(tokdata->statistics, + session->session_info.slotID, + mech, + wrapping_key_mapping->strength.strength); + if (wrapping_key_mapping) { bt_put_node_value(&icsf_data->objects, wrapping_key_mapping); wrapping_key_mapping = NULL; @@ -4893,6 +5300,7 @@ CK_SSL3_KEY_MAT_PARAMS *params = { 0 }; unsigned int i; int reason = 0; + struct icsf_policy_attr pattr; /* Variable for multiple keys derivation */ int multiple = 0; @@ -4969,13 +5377,36 @@ rc = CKR_KEY_HANDLE_INVALID; goto done; } + rc = tokdata->policy->is_mech_allowed(tokdata->policy, mech, + &base_key_mapping->strength, + POLICY_CHECK_DERIVE, session); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Derive key\n"); + goto done; + } /* Call ICSF service */ - if (!multiple) + if (!multiple) { rc = icsf_derive_key(session_state->ld, &reason, mech, &base_key_mapping->icsf_object, &mappings[0]->icsf_object, attrs, attrs_len); - else + if (rc) { + rc = icsf_to_ock_err(rc, reason); + goto done; + } + pattr.ld = session_state->ld; + pattr.icsf_object = &mappings[0]->icsf_object; + rc = tokdata->policy->store_object_strength(tokdata->policy, + &mappings[0]->strength, + icsf_policy_get_attr, + &pattr, + icsf_policy_free_attr, + session); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Derived key too weak\n"); + goto done; + } + } else { rc = icsf_derive_multiple_keys(session_state->ld, &reason, mech, &base_key_mapping->icsf_object, attrs, attrs_len, @@ -4985,10 +5416,26 @@ &mappings[3]->icsf_object, params->pReturnedKeyMaterial->pIVClient, params->pReturnedKeyMaterial->pIVServer); - if (rc) { - rc = icsf_to_ock_err(rc, reason); - goto done; + if (rc) { + rc = icsf_to_ock_err(rc, reason); + goto done; + } + pattr.ld = session_state->ld; + for (i = 0; i < 4; ++i) { + pattr.icsf_object = &mappings[i]->icsf_object; + rc = tokdata->policy->store_object_strength(tokdata->policy, + &mappings[i]->strength, + icsf_policy_get_attr, + &pattr, + icsf_policy_free_attr, + session); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Derived key too weak\n"); + goto done; + } + } } + for (i = 0; i < sizeof(mappings) / sizeof(*mappings); i++) { /* Add info about object into session */ @@ -5007,6 +5454,12 @@ } done: + if (rc == CKR_OK && tokdata->statistics->increment_func != NULL) + tokdata->statistics->increment_func(tokdata->statistics, + session->session_info.slotID, + mech, + base_key_mapping->strength.strength); + if (base_key_mapping) { bt_put_node_value(&icsf_data->objects, base_key_mapping); base_key_mapping = NULL; diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/icsf_stdll/icsf_stdll.mk opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/icsf_stdll/icsf_stdll.mk --- opencryptoki-3.16.0+dfsg/usr/lib/icsf_stdll/icsf_stdll.mk 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/icsf_stdll/icsf_stdll.mk 2022-02-02 15:05:41.000000000 +0100 @@ -6,48 +6,45 @@ usr/lib/icsf_stdll/icsf_specific.h \ usr/lib/icsf_stdll/tok_struct.h -BUILT_SOURCES += usr/lib/icsf_stdll/icsf_config_parse.h -CLEANFILES += \ - usr/lib/icsf_stdll/icsf_config_lexer.c \ - usr/lib/icsf_stdll/icsf_config_parse.c \ - usr/lib/icsf_stdll/icsf_config_parse.h \ - usr/lib/icsf_stdll/icsf_config_parse.output - opencryptoki_stdll_libpkcs11_icsf_la_CFLAGS = \ -DNOCDMF -DNODSA -DNODH -DMMAP -I${srcdir}/usr/lib/icsf_stdll \ -I${srcdir}/usr/lib/common -I${srcdir}/usr/include \ -DSTDLL_NAME=\"icsftok\" \ - -DTOK_NEW_DATA_STORE=0xffffffff + -DTOK_NEW_DATA_STORE=0xffffffff \ + -I${top_builddir}/usr/lib/icsf_stdll \ + -I${top_builddir}/usr/lib/api -I${srcdir}/usr/lib/api \ + -I${top_builddir}/usr/lib/config -I${srcdir}/usr/lib/config opencryptoki_stdll_libpkcs11_icsf_la_LDFLAGS = \ -shared -Wl,-z,defs,-Bsymbolic -lcrypto -lldap -lpthread \ -lrt -llber \ -Wl,--version-script=${srcdir}/opencryptoki_tok.map -opencryptoki_stdll_libpkcs11_icsf_la_SOURCES = \ - usr/lib/common/asn1.c usr/lib/common/dig_mgr.c \ - usr/lib/common/hwf_obj.c usr/lib/common/trace.c \ - usr/lib/common/key.c usr/lib/common/mech_dh.c \ - usr/lib/common/mech_rng.c usr/lib/common/sign_mgr.c \ - usr/lib/common/cert.c usr/lib/common/dp_obj.c \ - usr/lib/common/mech_aes.c usr/lib/common/mech_rsa.c \ - usr/lib/common/mech_ec.c usr/lib/common/obj_mgr.c \ - usr/lib/common/template.c usr/lib/common/p11util.c \ - usr/lib/common/data_obj.c usr/lib/common/encr_mgr.c \ - usr/lib/common/key_mgr.c usr/lib/common/mech_md2.c \ - usr/lib/common/mech_sha.c usr/lib/common/object.c \ - usr/lib/common/decr_mgr.c usr/lib/common/globals.c \ - usr/lib/common/sw_crypt.c usr/lib/common/loadsave.c \ - usr/lib/common/utility.c usr/lib/common/mech_des.c \ - usr/lib/common/mech_des3.c usr/lib/common/mech_md5.c \ - usr/lib/common/mech_ssl3.c usr/lib/common/verify_mgr.c \ - usr/lib/common/mech_list.c usr/lib/common/shared_memory.c \ - usr/lib/common/attributes.c usr/lib/icsf_stdll/new_host.c \ - usr/lib/common/profile_obj.c \ - usr/lib/icsf_stdll/pbkdf.c usr/lib/icsf_stdll/icsf_specific.c \ - usr/lib/icsf_stdll/icsf_config_parse.y \ - usr/lib/icsf_stdll/icsf_config_lexer.l \ - usr/lib/icsf_stdll/icsf.c +opencryptoki_stdll_libpkcs11_icsf_la_SOURCES = usr/lib/common/asn1.c \ + usr/lib/common/dig_mgr.c usr/lib/common/hwf_obj.c \ + usr/lib/common/trace.c usr/lib/common/key.c \ + usr/lib/common/mech_dh.c usr/lib/common/mech_rng.c \ + usr/lib/common/sign_mgr.c usr/lib/common/cert.c \ + usr/lib/common/dp_obj.c usr/lib/common/mech_aes.c \ + usr/lib/common/mech_rsa.c usr/lib/common/mech_ec.c \ + usr/lib/common/obj_mgr.c usr/lib/common/template.c \ + usr/lib/common/p11util.c usr/lib/common/data_obj.c \ + usr/lib/common/encr_mgr.c usr/lib/common/key_mgr.c \ + usr/lib/common/mech_md2.c usr/lib/common/mech_sha.c \ + usr/lib/common/object.c usr/lib/common/decr_mgr.c \ + usr/lib/common/globals.c usr/lib/common/sw_crypt.c \ + usr/lib/common/loadsave.c usr/lib/common/utility.c \ + usr/lib/common/mech_des.c usr/lib/common/mech_des3.c \ + usr/lib/common/mech_md5.c usr/lib/common/mech_ssl3.c \ + usr/lib/common/verify_mgr.c usr/lib/common/mech_list.c \ + usr/lib/common/shared_memory.c usr/lib/common/attributes.c \ + usr/lib/icsf_stdll/new_host.c usr/lib/common/profile_obj.c \ + usr/lib/common/dlist.c usr/lib/icsf_stdll/pbkdf.c \ + usr/lib/icsf_stdll/icsf_specific.c \ + usr/lib/icsf_stdll/icsf.c usr/lib/common/utility_common.c \ + usr/lib/common/ec_supported.c usr/lib/api/policyhelper.c \ + usr/lib/config/configuration.c \ + usr/lib/config/cfgparse.y usr/lib/config/cfglex.l if ENABLE_LOCKS opencryptoki_stdll_libpkcs11_icsf_la_SOURCES += \ @@ -57,3 +54,5 @@ opencryptoki_stdll_libpkcs11_icsf_la_SOURCES += \ usr/lib/common/btree.c usr/lib/common/sess_mgr.c endif + +usr/lib/icsf_stdll/icsf_specific.$(OBJEXT): usr/lib/config/cfgparse.h diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/icsf_stdll/new_host.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/icsf_stdll/new_host.c --- opencryptoki-3.16.0+dfsg/usr/lib/icsf_stdll/new_host.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/icsf_stdll/new_host.c 2022-02-02 15:05:41.000000000 +0100 @@ -36,6 +36,7 @@ #include "attributes.h" #include "icsf_specific.h" #include "../api/apiproto.h" +#include "../api/policy.h" void SC_SetFunctionList(void); CK_RV SC_Finalize(STDLL_TokData_t *tokdata, CK_SLOT_ID sid, SLOT_INFO *sinfp, @@ -70,34 +71,12 @@ { CK_RV rc = CKR_OK; char abs_tokdir_name[PATH_MAX]; - - if ((rc = check_user_and_group()) != CKR_OK) - return rc; + CK_BBOOL newdatastore; + policy_t policy = sltp->TokData->policy; /* set trace info */ set_trace(t); - if (sltp->TokData != NULL) { - TRACE_ERROR("Already initialized.\n"); - return CKR_CRYPTOKI_ALREADY_INITIALIZED; - } - - /* - * Create separate memory area for each token specific data - */ - sltp->TokData = (STDLL_TokData_t *) calloc(1, sizeof(STDLL_TokData_t)); - if (!sltp->TokData) { - TRACE_ERROR("Allocating host memory failed.\n"); - return CKR_HOST_MEMORY; - } - - sltp->TokData->ro_session_count = 0; - sltp->TokData->global_login_state = CKS_RO_PUBLIC_SESSION; -#ifdef ENABLE_LOCKS - pthread_rwlock_init(&sltp->TokData->sess_list_rwlock, NULL); -#endif - pthread_mutex_init(&sltp->TokData->login_mutex, NULL); - bt_init(&sltp->TokData->sess_btree, free); bt_init(&sltp->TokData->object_map_btree, free); bt_init(&sltp->TokData->sess_obj_btree, call_object_free); @@ -130,6 +109,16 @@ (unsigned int)(sinfp->version >> 16), (unsigned int)(sinfp->version & 0xffff)); + /* Check token store encryption against policy */ + newdatastore = sinfp->version >= TOK_NEW_DATA_STORE ? CK_TRUE : CK_FALSE; + rc = policy->check_token_store(policy, newdatastore, + token_specific.data_store.encryption_algorithm, + SlotNumber, &sltp->TokData->store_strength); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Token cannot load since data store encryption is too weak for policy.\n"); + goto done; + } + /* Initialize Lock */ if (XProcLock_Init(sltp->TokData) != CKR_OK) { TRACE_ERROR("Thread lock failed.\n"); @@ -162,9 +151,7 @@ if (rc != 0) { sltp->FcnList = NULL; detach_shm(sltp->TokData, 0); - if (sltp->TokData) - free(sltp->TokData); - sltp->TokData = NULL; + final_data_store(sltp->TokData); TRACE_DEVEL("Token Specific Init failed.\n"); goto done; } @@ -174,9 +161,7 @@ rc = load_token_data(sltp->TokData, SlotNumber); if (rc != CKR_OK) { sltp->FcnList = NULL; - if (sltp->TokData) - free(sltp->TokData); - sltp->TokData = NULL; + final_data_store(sltp->TokData); TRACE_DEVEL("Failed to load token data. (rc=0x%02lx)\n", rc); goto done; } @@ -206,8 +191,7 @@ SC_Finalize(sltp->TokData, SlotNumber, sinfp, NULL, 0); } else { CloseXProcLock(sltp->TokData); - free(sltp->TokData); - sltp->TokData = NULL; + final_data_store(sltp->TokData); } } @@ -246,11 +230,6 @@ bt_destroy(&tokdata->priv_token_obj_btree); bt_destroy(&tokdata->publ_token_obj_btree); -#ifdef ENABLE_LOCKS - pthread_rwlock_destroy(&tokdata->sess_list_rwlock); -#endif - pthread_mutex_destroy(&tokdata->login_mutex); - detach_shm(tokdata, in_fork_initializer); /* close spin lock file */ CloseXProcLock(tokdata); @@ -263,9 +242,6 @@ final_data_store(tokdata); - if (tokdata) - free(tokdata); - return rc; } @@ -456,7 +432,7 @@ return CKR_FUNCTION_FAILED; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -515,7 +491,7 @@ return CKR_FUNCTION_FAILED; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -577,7 +553,7 @@ return rc; } - sess = session_mgr_find(tokdata, *phSession); + sess = session_mgr_find_reset_error(tokdata, *phSession); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; @@ -606,7 +582,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -717,7 +693,7 @@ if (!pOperationState) length_only = TRUE; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -764,7 +740,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -773,8 +749,9 @@ //set the handle into the session. sess->handle = sSession->sessionh; - rc = session_mgr_set_op_state(sess, hEncryptionKey, hAuthenticationKey, - pOperationState, ulOperationStateLen); + rc = session_mgr_set_op_state(tokdata, sess, hEncryptionKey, + hAuthenticationKey, pOperationState, + ulOperationStateLen); if (rc != CKR_OK) TRACE_DEVEL("session_mgr_set_op_state() failed.\n"); @@ -808,7 +785,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -932,7 +909,7 @@ return CKR_FUNCTION_FAILED; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -983,7 +960,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1040,7 +1017,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1084,7 +1061,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1136,7 +1113,7 @@ return CKR_CRYPTOKI_NOT_INITIALIZED; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1175,7 +1152,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1205,13 +1182,14 @@ for (i = 0; i < ulCount; i++, attr++) { TRACE_DEBUG("%lu: Attribute type: 0x%08lx, Value Length: %lu\n", i, attr->type, attr->ulValueLen); - - if (attr->ulValueLen >= sizeof(val) && attr->pValue != NULL) { - memset(val, 0, sizeof(val)); - memcpy(val, attr->pValue, attr->ulValueLen > sizeof(val) ? - sizeof(val) : attr->ulValueLen); - TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n", - val[0], val[1], val[2], val[3]); + if (rc == CKR_OK && attr->ulValueLen != CK_UNAVAILABLE_INFORMATION) { + if (attr->ulValueLen >= sizeof(val) && attr->pValue != NULL) { + memset(val, 0, sizeof(val)); + memcpy(val, attr->pValue, attr->ulValueLen > sizeof(val) ? + sizeof(val) : attr->ulValueLen); + TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n", + val[0], val[1], val[2], val[3]); + } } } #endif @@ -1234,7 +1212,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1291,7 +1269,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1365,7 +1343,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1417,7 +1395,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1474,7 +1452,7 @@ if (rc != CKR_OK) goto done; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1524,7 +1502,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1556,7 +1534,7 @@ done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) { if (sess) - encr_mgr_cleanup(&sess->encr_ctx); + encr_mgr_cleanup(tokdata, sess, &sess->encr_ctx); } TRACE_INFO("C_Encrypt: rc = 0x%08lx, sess = %ld, amount = %lu\n", @@ -1583,7 +1561,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1612,7 +1590,7 @@ done: if (rc != CKR_OK && rc != CKR_BUFFER_TOO_SMALL) { if (sess) - encr_mgr_cleanup(&sess->encr_ctx); + encr_mgr_cleanup(tokdata, sess, &sess->encr_ctx); } TRACE_INFO("C_EncryptUpdate: rc = 0x%08lx, sess = %ld, amount = %lu\n", @@ -1639,7 +1617,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1671,7 +1649,7 @@ done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) { if (sess) - encr_mgr_cleanup(&sess->encr_ctx); + encr_mgr_cleanup(tokdata, sess, &sess->encr_ctx); } TRACE_INFO("C_EncryptFinal: rc = 0x%08lx, sess = %ld\n", @@ -1706,7 +1684,7 @@ if (rc != CKR_OK) goto done; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1758,7 +1736,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1790,7 +1768,7 @@ done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) { if (sess) - decr_mgr_cleanup(&sess->decr_ctx); + decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx); } TRACE_INFO("C_Decrypt: rc = 0x%08lx, sess = %ld, amount = %lu\n", @@ -1817,7 +1795,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1846,7 +1824,7 @@ done: if (rc != CKR_OK && rc != CKR_BUFFER_TOO_SMALL && sess != NULL) { if (sess) - decr_mgr_cleanup(&sess->decr_ctx); + decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx); } TRACE_INFO("C_DecryptUpdate: rc = 0x%08lx, sess = %ld, amount = %lu\n", @@ -1873,7 +1851,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1903,7 +1881,7 @@ done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) { if (sess) - decr_mgr_cleanup(&sess->decr_ctx); + decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx); } TRACE_INFO("C_DecryptFinal: rc = 0x%08lx, sess = %ld, amount = %lu\n", @@ -1938,7 +1916,7 @@ if (rc != CKR_OK) goto done; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -1960,7 +1938,8 @@ goto done; } - rc = digest_mgr_init(tokdata, sess, &sess->digest_ctx, pMechanism); + sess->digest_ctx.count_statistics = TRUE; + rc = digest_mgr_init(tokdata, sess, &sess->digest_ctx, pMechanism, TRUE); if (rc != CKR_OK) TRACE_DEVEL("digest_mgr_init() failed.\n"); @@ -1990,7 +1969,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2036,7 +2015,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2082,7 +2061,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2125,7 +2104,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2177,7 +2156,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2232,7 +2211,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2261,7 +2240,7 @@ done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || pSignature)) { if (sess != NULL) - sign_mgr_cleanup(&sess->sign_ctx); + sign_mgr_cleanup(tokdata, sess, &sess->sign_ctx); } TRACE_INFO("C_Sign: rc = 0x%08lx, sess = %ld, datalen = %lu\n", @@ -2286,7 +2265,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2312,7 +2291,7 @@ TRACE_DEVEL("icsftok_sign_update() failed.\n"); done: if (rc != CKR_OK && sess != NULL) - sign_mgr_cleanup(&sess->sign_ctx); + sign_mgr_cleanup(tokdata, sess, &sess->sign_ctx); TRACE_INFO("C_SignUpdate: rc = 0x%08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulPartLen); @@ -2336,7 +2315,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2364,7 +2343,7 @@ done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || pSignature)) { if (sess != NULL) - sign_mgr_cleanup(&sess->sign_ctx); + sign_mgr_cleanup(tokdata, sess, &sess->sign_ctx); } TRACE_INFO("C_SignFinal: rc = 0x%08lx, sess = %ld\n", @@ -2438,7 +2417,7 @@ if (rc != CKR_OK) goto done; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2489,7 +2468,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2517,7 +2496,7 @@ done: if (sess != NULL) - verify_mgr_cleanup(&sess->verify_ctx); + verify_mgr_cleanup(tokdata, sess, &sess->verify_ctx); TRACE_INFO("C_Verify: rc = 0x%08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulDataLen); @@ -2541,7 +2520,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2568,7 +2547,7 @@ done: if (rc != CKR_OK && sess != NULL) - verify_mgr_cleanup(&sess->verify_ctx); + verify_mgr_cleanup(tokdata, sess, &sess->verify_ctx); TRACE_INFO("C_VerifyUpdate: rc = 0x%08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulPartLen); @@ -2592,7 +2571,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2619,7 +2598,7 @@ done: if (sess != NULL) - verify_mgr_cleanup(&sess->verify_ctx); + verify_mgr_cleanup(tokdata, sess, &sess->verify_ctx); TRACE_INFO("C_VerifyFinal: rc = 0x%08lx, sess = %ld\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle); @@ -2784,7 +2763,7 @@ if (rc != CKR_OK) goto done; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2792,6 +2771,12 @@ } //set the handle into the session. sess->handle = sSession->sessionh; + rc = tokdata->policy->is_mech_allowed(tokdata->policy, pMechanism, NULL, + POLICY_CHECK_KEYGEN, sess); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Key generation mechanism not allowed\n"); + goto done; + } if (pin_expired(&sess->session_info, tokdata->nv_token_data->token_info.flags) == TRUE) { @@ -2868,7 +2853,7 @@ if (rc != CKR_OK) goto done; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -2876,6 +2861,12 @@ } //set the handle into the session. sess->handle = sSession->sessionh; + rc = tokdata->policy->is_mech_allowed(tokdata->policy, pMechanism, NULL, + POLICY_CHECK_KEYGEN, sess); + if (rc != CKR_OK) { + TRACE_ERROR("POLICY VIOLATION: Keypair generation mechanism not allowed\n"); + goto done; + } if (pin_expired(&sess->session_info, tokdata->nv_token_data->token_info.flags) == TRUE) { @@ -2950,7 +2941,7 @@ if (rc != CKR_OK) goto done; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -3009,7 +3000,7 @@ if (rc != CKR_OK) goto done; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -3093,7 +3084,7 @@ if (rc != CKR_OK) goto done; - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -3205,7 +3196,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -3290,7 +3281,7 @@ goto done; } - sess = session_mgr_find(tokdata, sSession->sessionh); + sess = session_mgr_find_reset_error(tokdata, sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; @@ -3332,6 +3323,24 @@ return rc; } +CK_RV SC_HandleEvent(STDLL_TokData_t *tokdata, unsigned int event_type, + unsigned int event_flags, const char *payload, + unsigned int payload_len) +{ + CK_RV rc; + + if (token_specific.t_handle_event == NULL) + return CKR_FUNCTION_NOT_SUPPORTED; + + rc = token_specific.t_handle_event(tokdata, event_type, event_flags, + payload, payload_len); + + TRACE_INFO("SC_HandleEvent: rc = 0x%08lx, event_type = 0x%08x, " + "event_flags = 0x%08x\n", rc, event_type, event_flags); + + return rc; +} + void SC_SetFunctionList(void) { function_list.ST_Initialize = ST_Initialize; @@ -3397,4 +3406,6 @@ function_list.ST_CancelFunction = NULL; // SC_CancelFunction; function_list.ST_IBM_ReencryptSingle = SC_IBM_ReencryptSingle; + + function_list.ST_HandleEvent = SC_HandleEvent; } diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/icsf_stdll/pbkdf.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/icsf_stdll/pbkdf.c --- opencryptoki-3.16.0+dfsg/usr/lib/icsf_stdll/pbkdf.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/icsf_stdll/pbkdf.c 2022-02-02 15:05:41.000000000 +0100 @@ -76,16 +76,20 @@ return CKR_OK; } -CK_RV encrypt_aes(CK_BYTE * inbuf, int inbuflen, CK_BYTE * dkey, - CK_BYTE * iv, CK_BYTE * outbuf, int *outbuflen) +CK_RV encrypt_aes(STDLL_TokData_t *tokdata, + CK_BYTE * inbuf, int inbuflen, CK_BYTE * dkey, + CK_BYTE * iv, CK_BYTE * outbuf, int *outbuflen, + CK_BBOOL wrap) { const EVP_CIPHER *cipher = EVP_aes_256_cbc(); int tmplen; -#if OPENSSL_VERSION_NUMBER >= 0x10100000L EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); - EVP_EncryptInit_ex(ctx, cipher, NULL, dkey, iv); + if (!EVP_EncryptInit_ex(ctx, cipher, NULL, dkey, iv)) { + TRACE_ERROR("EVP_EncryptInit_ex failed.\n"); + return CKR_FUNCTION_FAILED; + } if (!EVP_EncryptUpdate(ctx, outbuf, outbuflen, inbuf, inbuflen)) { TRACE_ERROR("EVP_EncryptUpdate failed.\n"); return CKR_FUNCTION_FAILED; @@ -98,37 +102,37 @@ *outbuflen = (*outbuflen) + tmplen; EVP_CIPHER_CTX_free(ctx); -#else - EVP_CIPHER_CTX ctx; - EVP_CIPHER_CTX_init(&ctx); - - EVP_EncryptInit_ex(&ctx, cipher, NULL, dkey, iv); - if (!EVP_EncryptUpdate(&ctx, outbuf, outbuflen, inbuf, inbuflen)) { - TRACE_ERROR("EVP_EncryptUpdate failed.\n"); - return CKR_FUNCTION_FAILED; - } - if (!EVP_EncryptFinal_ex(&ctx, outbuf + (*outbuflen), &tmplen)) { - TRACE_ERROR("EVP_EncryptFinal failed.\n"); - return CKR_FUNCTION_FAILED; + if (tokdata != NULL && + (tokdata->statistics->flags & STATISTICS_FLAG_COUNT_INTERNAL) != 0) { + if (wrap) + tokdata->statistics->increment_func(tokdata->statistics, + tokdata->slot_id, + &tokdata->store_strength.wrap_crypt, + tokdata->store_strength.wrap_strength); + else + tokdata->statistics->increment_func(tokdata->statistics, + tokdata->slot_id, + &tokdata->store_strength.mk_crypt, + tokdata->store_strength.mk_strength); } - *outbuflen = (*outbuflen) + tmplen; - EVP_CIPHER_CTX_cleanup(&ctx); -#endif - return CKR_OK; } -CK_RV decrypt_aes(CK_BYTE * inbuf, int inbuflen, CK_BYTE * dkey, - CK_BYTE * iv, CK_BYTE * outbuf, int *outbuflen) +CK_RV decrypt_aes(STDLL_TokData_t *tokdata, + CK_BYTE * inbuf, int inbuflen, CK_BYTE * dkey, + CK_BYTE * iv, CK_BYTE * outbuf, int *outbuflen, + CK_BBOOL unwrap) { int size; const EVP_CIPHER *cipher = EVP_aes_256_cbc(); -#if OPENSSL_VERSION_NUMBER >= 0x10100000L EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); - EVP_DecryptInit_ex(ctx, cipher, NULL, dkey, iv); + if (!EVP_DecryptInit_ex(ctx, cipher, NULL, dkey, iv)) { + TRACE_ERROR("EVP_DecryptInit_ex failed.\n"); + return CKR_FUNCTION_FAILED; + } if (!EVP_DecryptUpdate(ctx, outbuf, outbuflen, inbuf, inbuflen)) { TRACE_ERROR("EVP_DecryptUpdate failed.\n"); return CKR_FUNCTION_FAILED; @@ -147,39 +151,30 @@ EVP_CIPHER_CTX_free(ctx); -#else - EVP_CIPHER_CTX ctx; - EVP_CIPHER_CTX_init(&ctx); - - EVP_DecryptInit_ex(&ctx, cipher, NULL, dkey, iv); - if (!EVP_DecryptUpdate(&ctx, outbuf, outbuflen, inbuf, inbuflen)) { - TRACE_ERROR("EVP_DecryptUpdate failed.\n"); - return CKR_FUNCTION_FAILED; - } - if (!EVP_DecryptFinal_ex(&ctx, outbuf + (*outbuflen), &size)) { - TRACE_ERROR("EVP_DecryptFinal failed.\n"); - return CKR_FUNCTION_FAILED; + if (tokdata != NULL && + (tokdata->statistics->flags & STATISTICS_FLAG_COUNT_INTERNAL) != 0) { + if (unwrap) + tokdata->statistics->increment_func(tokdata->statistics, + tokdata->slot_id, + &tokdata->store_strength.wrap_crypt, + tokdata->store_strength.wrap_strength); + else + tokdata->statistics->increment_func(tokdata->statistics, + tokdata->slot_id, + &tokdata->store_strength.mk_crypt, + tokdata->store_strength.mk_strength); } - /* total length of the decrypted data */ - *outbuflen = (*outbuflen) + size; - - /* EVP_DecryptFinal removes any padding. The final length - * is the length of the decrypted data without padding. - */ - - EVP_CIPHER_CTX_cleanup(&ctx); -#endif - return CKR_OK; } -CK_RV get_masterkey(CK_BYTE *pin, CK_ULONG pinlen, const char *fname, +CK_RV get_masterkey(STDLL_TokData_t *tokdata, + CK_BYTE *pin, CK_ULONG pinlen, const char *fname, CK_BYTE *masterkey, int *len) { struct stat statbuf; FILE *fp; - CK_ULONG_32 totallen, datasize, readsize; + CK_ULONG_32 totallen, datasize, readsize, version; int dkeysize; CK_BYTE salt[SALTSIZE]; CK_BYTE dkey[AES_KEY_SIZE_256]; @@ -200,13 +195,32 @@ return CKR_FUNCTION_FAILED; } - ret = fread(&totallen, sizeof(CK_ULONG_32), 1, fp); + ret = fread(&version, sizeof(CK_ULONG_32), 1, fp); if (ret != 1) { fclose(fp); TRACE_ERROR("fread failed.\n"); return CKR_FUNCTION_FAILED; } + /* + * Version 1 files did not have the version field, thus the first field read + * is the total length. If the first field is not a known version number, + * we assume it is an old version file. For an old version file, the total + * length is 64 bytes, this is it is much higher than the version number. + */ + if (version == ICSF_MK_FILE_VERSION) { + /* New version file detected */ + ret = fread(&totallen, sizeof(CK_ULONG_32), 1, fp); + if (ret != 1) { + fclose(fp); + TRACE_ERROR("fread failed.\n"); + return CKR_FUNCTION_FAILED; + } + } else { + TRACE_DEVEL("Old version master key file detected\n"); + totallen = version; + } + ret = fread(salt, SALTSIZE, 1, fp); if (ret != 1) { fclose(fp); @@ -227,7 +241,10 @@ /* now derive the key using the salt and PIN */ dkeysize = AES_KEY_SIZE_256; - rc = pbkdf(pin, pinlen, salt, dkey, dkeysize); + if (version == ICSF_MK_FILE_VERSION) + rc = pbkdf_openssl(tokdata, pin, pinlen, salt, dkey, dkeysize); + else + rc = pbkdf_old(tokdata, pin, pinlen, salt, dkey, dkeysize); if (rc != CKR_OK) { TRACE_DEBUG("pbkdf(): Failed to derive a key.\n"); return CKR_FUNCTION_FAILED; @@ -235,7 +252,8 @@ /* decrypt the masterkey */ /* re-use salt for iv */ - rc = decrypt_aes(outbuf, datasize, dkey, salt, masterkey, len); + rc = decrypt_aes(tokdata, outbuf, datasize, dkey, salt, masterkey, len, + CK_TRUE); if (rc != CKR_OK) { TRACE_DEBUG("Failed to decrypt the racf pwd.\n"); return CKR_FUNCTION_FAILED; @@ -250,7 +268,8 @@ return rc; } -CK_RV get_racf(CK_BYTE * masterkey, CK_ULONG mklen, CK_BYTE * racfpwd, +CK_RV get_racf(STDLL_TokData_t *tokdata, + CK_BYTE * masterkey, CK_ULONG mklen, CK_BYTE * racfpwd, int *racflen) { struct stat statbuf; @@ -300,7 +319,8 @@ fclose(fp); /* decrypt the data using the masterkey */ - rc = decrypt_aes(outbuf, datasize, masterkey, iv, racfpwd, racflen); + rc = decrypt_aes(tokdata, outbuf, datasize, masterkey, iv, racfpwd, racflen, + CK_FALSE); /* terminate the decrypted string. */ memset(racfpwd + (*racflen), 0, 1); @@ -313,10 +333,50 @@ return CKR_OK; } -CK_RV pbkdf(CK_BYTE * password, CK_ULONG len, CK_BYTE * salt, CK_BYTE * dkey, - CK_ULONG klen) +CK_RV pbkdf_openssl(STDLL_TokData_t *tokdata, + CK_BYTE *password, CK_ULONG len, CK_BYTE *salt, + CK_BYTE *dkey, CK_ULONG klen) { + const CK_MECHANISM mech = { CKM_PKCS5_PBKD2, NULL, 0 }; + const CK_MECHANISM mech2 = { CKM_SHA256_HMAC, NULL, 0 }; + int rc; + + if (!password || !salt || len > INT_MAX || klen > INT_MAX) { + TRACE_ERROR("Invalid function argument(s).\n"); + return CKR_FUNCTION_FAILED; + } + + rc = PKCS5_PBKDF2_HMAC((char *)password, len, salt, SALTSIZE, + ITERATIONS, EVP_sha256(), klen, dkey); + if (rc != 1) { + TRACE_ERROR("PBKDF2 failed.\n"); + return CKR_FUNCTION_FAILED; + } + + if (tokdata != NULL && + (tokdata->statistics->flags & STATISTICS_FLAG_COUNT_INTERNAL) != 0) { + tokdata->statistics->increment_func(tokdata->statistics, + tokdata->slot_id, &mech, + POLICY_STRENGTH_IDX_0); + if ((tokdata->statistics->flags & STATISTICS_FLAG_COUNT_IMPLICIT) != 0) { + /* + * We use CKM_PKCS5_PBKD2 with CKP_PKCS5_PBKD2_HMAC_SHA256. + * Use strength 0 because the HMAC key is the pin, and it is max + * 8 char (i.e. 64 bit) long, which is way below 112 bit anyway. + */ + tokdata->statistics->increment_func(tokdata->statistics, + tokdata->slot_id, &mech2, + POLICY_STRENGTH_IDX_0); + } + } + + return CKR_OK; +} +CK_RV pbkdf_old(STDLL_TokData_t *tokdata, + CK_BYTE * password, CK_ULONG len, CK_BYTE * salt, CK_BYTE * dkey, + CK_ULONG klen) +{ unsigned char hash[SHA256_HASH_SIZE]; unsigned char hash_block[SHA256_HASH_SIZE]; unsigned char *result; @@ -325,6 +385,8 @@ CK_ULONG rc = CKR_OK; unsigned int i, j; int k; + const CK_MECHANISM mech = { CKM_PKCS5_PBKD2, NULL, 0 }; + const CK_MECHANISM mech2 = { CKM_SHA256_HMAC, NULL, 0 }; /* check inputs */ if (!password || !salt) { @@ -409,10 +471,28 @@ } out: + if (rc == CKR_OK && tokdata != NULL && + (tokdata->statistics->flags & STATISTICS_FLAG_COUNT_INTERNAL) != 0) { + tokdata->statistics->increment_func(tokdata->statistics, + tokdata->slot_id, &mech, + POLICY_STRENGTH_IDX_0); + if ((tokdata->statistics->flags & STATISTICS_FLAG_COUNT_IMPLICIT) != 0) { + /* + * We use CKM_PKCS5_PBKD2 with CKP_PKCS5_PBKD2_HMAC_SHA256. + * Use strength 0 because the HMAC key is the pin, and it is max + * 8 char (i.e. 64 bit) long, which is way below 112 bit anyway. + */ + tokdata->statistics->increment_func(tokdata->statistics, + tokdata->slot_id, &mech2, + POLICY_STRENGTH_IDX_0); + } + } + return rc; } -CK_RV secure_racf(CK_BYTE * racf, CK_ULONG racflen, CK_BYTE * key, +CK_RV secure_racf(STDLL_TokData_t *tokdata, + CK_BYTE * racf, CK_ULONG racflen, CK_BYTE * key, CK_ULONG keylen) { CK_RV rc = CKR_OK; @@ -431,7 +511,8 @@ } /* encrypt the racf passwd using the masterkey */ - rc = encrypt_aes(racf, racflen, key, iv, output, &outputlen); + rc = encrypt_aes(tokdata, racf, racflen, key, iv, output, &outputlen, + CK_FALSE); if (rc != 0) { TRACE_DEBUG("Failed to encrypt racf pwd.\n"); return CKR_FUNCTION_FAILED; @@ -470,13 +551,14 @@ return rc; } -CK_RV secure_masterkey(CK_BYTE * masterkey, CK_ULONG len, CK_BYTE * pin, +CK_RV secure_masterkey(STDLL_TokData_t *tokdata, + CK_BYTE * masterkey, CK_ULONG len, CK_BYTE * pin, CK_ULONG pinlen, const char *fname) { CK_RV rc = CKR_OK; CK_BYTE salt[SALTSIZE]; CK_BYTE dkey[AES_KEY_SIZE_256]; - CK_ULONG_32 totallen, dkey_size; + CK_ULONG_32 totallen, dkey_size, version; int outputlen; CK_BYTE output[ENCRYPT_SIZE]; FILE *fp; @@ -492,7 +574,7 @@ } /* get a 32 byte key */ - rc = pbkdf(pin, pinlen, salt, dkey, dkey_size); + rc = pbkdf_openssl(tokdata, pin, pinlen, salt, dkey, dkey_size); if (rc != 0) { TRACE_DEBUG("Failed to derive a key for encryption.\n"); return CKR_FUNCTION_FAILED; @@ -500,7 +582,8 @@ /* encrypt the masterkey using the derived key */ /* re-use the salt for the iv... */ - rc = encrypt_aes(masterkey, len, dkey, salt, output, &outputlen); + rc = encrypt_aes(tokdata, masterkey, len, dkey, salt, output, &outputlen, + CK_TRUE); if (rc != 0) { TRACE_DEBUG("Failed to encrypt masterkey.\n"); return CKR_FUNCTION_FAILED; @@ -508,9 +591,10 @@ /* write the encrypted masterkey to named file */ /* store the following: - * 1. total length = salt + encrypted data - * 2. salt (always SALTSIZE) - * 3. encrypted data + * 1. version field + * 2. total length = salt + encrypted data + * 3. salt (always SALTSIZE) + * 4. encrypted data */ /* get the total length */ @@ -530,7 +614,9 @@ return CKR_FUNCTION_FAILED; } - /* write the info to the file */ + /* write the info to the file (always new version format) */ + version = ICSF_MK_FILE_VERSION; + (void) fwrite(&version, sizeof(CK_ULONG_32), 1, fp); (void) fwrite(&totallen, sizeof(CK_ULONG_32), 1, fp); (void) fwrite(salt, SALTSIZE, 1, fp); (void) fwrite(output, outputlen, 1, fp); diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/icsf_stdll/pbkdf.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/icsf_stdll/pbkdf.h --- opencryptoki-3.16.0+dfsg/usr/lib/icsf_stdll/pbkdf.h 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/icsf_stdll/pbkdf.h 2022-02-02 15:05:41.000000000 +0100 @@ -20,32 +20,53 @@ #define SALTSIZE 16 // salt is 16 bytes #define DKEYLEN 32 // 256 bytes is max key size to be derived -#define PIN_SIZE 80 // samedefine in pkcsconf +#define PIN_SIZE 80 // same define in pkcsconf #define ENCRYPT_SIZE 96 // PIN_SIZE + AES_BLOCK_SIZE (for padding) +/* + * SP 800-132 recommends a minimum iteration count of 1000. + * so lets try that for now... + */ +#define ITERATIONS 1000 + #define ICSF_CONFIG_PATH CONFIG_PATH "/icsf" #define RACFFILE ICSF_CONFIG_PATH "/RACF" -CK_RV get_randombytes(unsigned char *output, int bytes); +#define ICSF_MK_FILE_VERSION 2 -CK_RV encrypt_aes(CK_BYTE * racfpwd, int racflen, CK_BYTE * dkey, - CK_BYTE * iv, CK_BYTE * outbuf, int *outbuflen); +CK_RV get_randombytes(unsigned char *output, int bytes); -CK_RV decrypt_aes(CK_BYTE * edata, int edatalen, CK_BYTE * dkey, - CK_BYTE * iv, CK_BYTE * ddata, int *ddatalen); +CK_RV encrypt_aes(STDLL_TokData_t *tokdata, + CK_BYTE * racfpwd, int racflen, CK_BYTE * dkey, + CK_BYTE * iv, CK_BYTE * outbuf, int *outbuflen, + CK_BBOOL wrap); + +CK_RV decrypt_aes(STDLL_TokData_t *tokdata, + CK_BYTE * edata, int edatalen, CK_BYTE * dkey, + CK_BYTE * iv, CK_BYTE * ddata, int *ddatalen, + CK_BBOOL unwrap); -CK_RV get_racf(CK_BYTE * mk, CK_ULONG mklen, CK_BYTE * racfpwd, int *racflen); +CK_RV get_racf(STDLL_TokData_t *tokdata, + CK_BYTE * mk, CK_ULONG mklen, CK_BYTE * racfpwd, int *racflen); -CK_RV get_masterkey(CK_BYTE *pin, CK_ULONG pinlen, const char *fname, +CK_RV get_masterkey(STDLL_TokData_t *tokdata, + CK_BYTE *pin, CK_ULONG pinlen, const char *fname, CK_BYTE *masterkey, int *len); -CK_RV pbkdf(CK_BYTE * passwd, CK_ULONG passwdlen, CK_BYTE * salt, - CK_BYTE * dkey, CK_ULONG klen); +CK_RV pbkdf_old(STDLL_TokData_t *tokdata, + CK_BYTE * passwd, CK_ULONG passwdlen, CK_BYTE * salt, + CK_BYTE * dkey, CK_ULONG klen); + +CK_RV pbkdf_openssl(STDLL_TokData_t *tokdata, + CK_BYTE *password, CK_ULONG len, CK_BYTE *salt, + CK_BYTE *dkey, CK_ULONG klen); -CK_RV secure_racf(CK_BYTE * racfpwd, CK_ULONG racflen, CK_BYTE * mk, +CK_RV secure_racf(STDLL_TokData_t *tokdata, + CK_BYTE * racfpwd, CK_ULONG racflen, CK_BYTE * mk, CK_ULONG mklen); -CK_RV secure_masterkey(CK_BYTE * masterkey, CK_ULONG len, CK_BYTE * pin, +CK_RV secure_masterkey(STDLL_TokData_t *tokdata, + CK_BYTE * masterkey, CK_ULONG len, CK_BYTE * pin, CK_ULONG pinlen, const char *fname); #endif diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/icsf_stdll/tok_struct.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/icsf_stdll/tok_struct.h --- opencryptoki-3.16.0+dfsg/usr/lib/icsf_stdll/tok_struct.h 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/icsf_stdll/tok_struct.h 2022-02-02 15:05:41.000000000 +0100 @@ -129,6 +129,7 @@ NULL, // reencrypt_single NULL, // set_attribute_values NULL, // set_attrs_for_new_object + NULL, // handle_event }; #endif diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/lib.mk opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/lib.mk --- opencryptoki-3.16.0+dfsg/usr/lib/lib.mk 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/lib.mk 2022-02-02 15:05:41.000000000 +0100 @@ -21,3 +21,4 @@ endif include usr/lib/common/common.mk +include usr/lib/config/config.mk diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/soft_stdll/soft_specific.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/soft_stdll/soft_specific.c --- opencryptoki-3.16.0+dfsg/usr/lib/soft_stdll/soft_specific.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/soft_stdll/soft_specific.c 2022-02-02 15:05:41.000000000 +0100 @@ -26,10 +26,6 @@ #include -#if OPENSSL_VERSION_NUMBER < 0x10101000L -#define NO_EC 1 -#endif - #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" @@ -44,24 +40,15 @@ #include #include -#include #include -#include #include -#include #include -#include #include -#include -#include - -/* - * In order to make opencryptoki compatible with - * OpenSSL 1.1 API Changes and backward compatible - * we need to check for its version - */ -#if OPENSSL_VERSION_NUMBER < 0x10100000L -#define OLDER_OPENSSL +#include +#include +#if OPENSSL_VERSION_PREREQ(3, 0) +#include +#include #endif #define MAX_GENERIC_KEY_SIZE 256 @@ -84,33 +71,30 @@ {CKM_RSA_PKCS, {512, 4096, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP | CKF_SIGN | CKF_VERIFY | CKF_SIGN_RECOVER | CKF_VERIFY_RECOVER}}, - {CKM_SHA1_RSA_PKCS, {1024, 4096, CKF_SIGN | CKF_VERIFY}}, - {CKM_SHA224_RSA_PKCS, {1024, 4096, CKF_SIGN|CKF_VERIFY}}, - {CKM_SHA256_RSA_PKCS, {1024, 4096, CKF_SIGN | CKF_VERIFY}}, - {CKM_SHA384_RSA_PKCS, {1024, 4096, CKF_SIGN | CKF_VERIFY}}, - {CKM_SHA512_RSA_PKCS, {1024, 4096, CKF_SIGN | CKF_VERIFY}}, - {CKM_RSA_PKCS_PSS, {1024, 4096, CKF_SIGN | CKF_VERIFY}}, - {CKM_SHA1_RSA_PKCS_PSS, {1024, 4096, CKF_SIGN | CKF_VERIFY}}, - {CKM_SHA224_RSA_PKCS_PSS, {1024, 4096, CKF_SIGN|CKF_VERIFY}}, - {CKM_SHA256_RSA_PKCS_PSS, {1024, 4096, CKF_SIGN | CKF_VERIFY}}, - {CKM_SHA384_RSA_PKCS_PSS, {1024, 4096, CKF_SIGN | CKF_VERIFY}}, - {CKM_SHA512_RSA_PKCS_PSS, {1024, 4096, CKF_SIGN | CKF_VERIFY}}, + {CKM_SHA1_RSA_PKCS, {512, 4096, CKF_SIGN | CKF_VERIFY}}, + {CKM_SHA224_RSA_PKCS, {512, 4096, CKF_SIGN|CKF_VERIFY}}, + {CKM_SHA256_RSA_PKCS, {512, 4096, CKF_SIGN | CKF_VERIFY}}, + {CKM_SHA384_RSA_PKCS, {512, 4096, CKF_SIGN | CKF_VERIFY}}, + {CKM_SHA512_RSA_PKCS, {512, 4096, CKF_SIGN | CKF_VERIFY}}, + {CKM_RSA_PKCS_PSS, {512, 4096, CKF_SIGN | CKF_VERIFY}}, + {CKM_SHA1_RSA_PKCS_PSS, {512, 4096, CKF_SIGN | CKF_VERIFY}}, + {CKM_SHA224_RSA_PKCS_PSS, {512, 4096, CKF_SIGN|CKF_VERIFY}}, + {CKM_SHA256_RSA_PKCS_PSS, {512, 4096, CKF_SIGN | CKF_VERIFY}}, + {CKM_SHA384_RSA_PKCS_PSS, {512, 4096, CKF_SIGN | CKF_VERIFY}}, + {CKM_SHA512_RSA_PKCS_PSS, {512, 4096, CKF_SIGN | CKF_VERIFY}}, #if !(NOX509) {CKM_RSA_X_509, {512, 4096, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP | CKF_SIGN | CKF_VERIFY | CKF_SIGN_RECOVER | CKF_VERIFY_RECOVER}}, #endif {CKM_RSA_PKCS_OAEP, - {1024, 4096, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP}}, + {512, 4096, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP}}, #if !(NOMD2) {CKM_MD2_RSA_PKCS, {512, 4096, CKF_SIGN | CKF_VERIFY}}, #endif #if !(NOMD5) {CKM_MD5_RSA_PKCS, {512, 4096, CKF_SIGN | CKF_VERIFY}}, #endif -#if !(NOSHA1) - {CKM_SHA1_RSA_PKCS, {512, 4096, CKF_SIGN | CKF_VERIFY}}, -#endif #if !(NODSA) {CKM_DSA, {512, 1024, CKF_SIGN | CKF_VERIFY}}, #endif @@ -132,6 +116,9 @@ {CKM_DES3_CBC, {24, 24, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP}}, {CKM_DES3_CBC_PAD, {24, 24, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP}}, + {CKM_DES_OFB64, {24, 24, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP}}, + {CKM_DES_CFB8, {24, 24, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP}}, + {CKM_DES_CFB64, {24, 24, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP}}, {CKM_DES3_MAC, {16, 24, CKF_HW | CKF_SIGN | CKF_VERIFY}}, {CKM_DES3_MAC_GENERAL, {16, 24, CKF_HW | CKF_SIGN | CKF_VERIFY}}, {CKM_DES3_CMAC, {16, 24, CKF_SIGN | CKF_VERIFY}}, @@ -200,6 +187,18 @@ {CKM_AES_CBC, {16, 32, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP}}, {CKM_AES_CBC_PAD, {16, 32, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP}}, + {CKM_AES_CTR, {16, 32, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP}}, +#if OPENSSL_VERSION_PREREQ(3, 0) || OPENSSL_VERSION_NUMBER >= 0x101010cfL + /* + * AES-OFB currently only works with >= OpenSSl 3.0, or >= OpenSSL 1.1.1l, + * due to a bug in OpenSSL <= 1.1.1k in s390x_aes_ofb_cipher() not updating + * the IV in the context. + */ + {CKM_AES_OFB, {16, 32, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP}}, + {CKM_AES_CFB8, {16, 32, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP}}, + {CKM_AES_CFB128, {16, 32, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP}}, +#endif + {CKM_AES_GCM, {16, 32, CKF_ENCRYPT | CKF_DECRYPT}}, {CKM_AES_MAC, {16, 32, CKF_HW | CKF_SIGN | CKF_VERIFY}}, {CKM_AES_MAC_GENERAL, {16, 32, CKF_HW | CKF_SIGN | CKF_VERIFY}}, {CKM_AES_CMAC, {16, 32, CKF_SIGN | CKF_VERIFY}}, @@ -232,9 +231,16 @@ char *conf_name) { UNUSED(conf_name); + CK_RV rc; - tokdata->mech_list = (MECH_LIST_ELEMENT *)soft_mech_list; - tokdata->mech_list_len = soft_mech_list_len; + rc = ock_generic_filter_mechanism_list(tokdata, + soft_mech_list, soft_mech_list_len, + &(tokdata->mech_list), + &(tokdata->mech_list_len)); + if (rc != CKR_OK) { + TRACE_ERROR("Mechanism filtering failed! rc = 0x%lx\n", rc); + return rc; + } TRACE_INFO("soft %s slot=%lu running\n", __func__, SlotNumber); @@ -244,11 +250,12 @@ CK_RV token_specific_final(STDLL_TokData_t *tokdata, CK_BBOOL token_specific_final) { - UNUSED(tokdata); UNUSED(token_specific_final); TRACE_INFO("soft %s running\n", __func__); + free(tokdata->mech_list); + return CKR_OK; } @@ -286,105 +293,8 @@ CK_ULONG *out_data_len, OBJECT *key, CK_BYTE encrypt) { -#if OPENSSL_VERSION_NUMBER < 0x10100000L - CK_RV rc; - DES_key_schedule des_key2; - const_DES_cblock key_val_SSL, in_key_data; - DES_cblock out_key_data; - unsigned int i, j; - CK_ATTRIBUTE *attr = NULL; - - UNUSED(tokdata); - - // get the key value - rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_VALUE for the key\n"); - return rc; - } - // Create the key schedule - memcpy(&key_val_SSL, attr->pValue, 8); - DES_set_key_unchecked(&key_val_SSL, &des_key2); - - // the des decrypt will only fail if the data length is not evenly divisible - // by 8 - if (in_data_len % DES_BLOCK_SIZE) { - TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); - return CKR_DATA_LEN_RANGE; - } - // Both the encrypt and the decrypt are done 8 bytes at a time - if (encrypt) { - for (i = 0; i < in_data_len; i = i + 8) { - memcpy(in_key_data, in_data + i, 8); - DES_ecb_encrypt(&in_key_data, &out_key_data, &des_key2, - DES_ENCRYPT); - memcpy(out_data + i, out_key_data, 8); - } - - *out_data_len = in_data_len; - rc = CKR_OK; - } else { - - for (j = 0; j < in_data_len; j = j + 8) { - memcpy(in_key_data, in_data + j, 8); - DES_ecb_encrypt(&in_key_data, &out_key_data, &des_key2, - DES_DECRYPT); - memcpy(out_data + j, out_key_data, 8); - } - - *out_data_len = in_data_len; - rc = CKR_OK; - } - - return rc; -#else - const EVP_CIPHER *cipher = EVP_des_ecb(); - EVP_CIPHER_CTX *ctx = NULL; - CK_ATTRIBUTE *attr = NULL; - unsigned char dkey[DES_KEY_SIZE]; - CK_ULONG rc; - int outlen; - - UNUSED(tokdata); - - // get the key value - rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); - return rc; - } - - if (in_data_len % DES_BLOCK_SIZE || in_data_len > INT_MAX) { - TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); - return CKR_DATA_LEN_RANGE; - } - - memcpy(dkey, attr->pValue, sizeof(dkey)); - - ctx = EVP_CIPHER_CTX_new(); - if (ctx == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - - if (EVP_CipherInit_ex(ctx, cipher, - NULL, dkey, NULL, encrypt ? 1 : 0) != 1 - || EVP_CIPHER_CTX_set_padding(ctx, 0) != 1 - || EVP_CipherUpdate(ctx, out_data, &outlen, in_data, in_data_len) != 1 - || EVP_CipherFinal_ex(ctx, out_data, &outlen) != 1) { - TRACE_ERROR("%s\n", ock_err(ERR_GENERAL_ERROR)); - rc = CKR_GENERAL_ERROR; - goto done; - } - - *out_data_len = in_data_len; - rc = CKR_OK; -done: - OPENSSL_cleanse(dkey, sizeof(dkey)); - EVP_CIPHER_CTX_free(ctx); - return rc; -#endif + return openssl_specific_des_ecb(tokdata, in_data, in_data_len, + out_data, out_data_len, key, encrypt); } CK_RV token_specific_des_cbc(STDLL_TokData_t *tokdata, @@ -394,94 +304,9 @@ CK_ULONG *out_data_len, OBJECT *key, CK_BYTE *init_v, CK_BYTE encrypt) { -#if OPENSSL_VERSION_NUMBER < 0x10100000L - CK_RV rc; - CK_ATTRIBUTE *attr = NULL; - DES_cblock ivec; - DES_key_schedule des_key2; - const_DES_cblock key_val_SSL; - - UNUSED(tokdata); - - // get the key value - rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_VALUE for the key\n"); - return rc; - } - // Create the key schedule - memcpy(&key_val_SSL, attr->pValue, 8); - DES_set_key_unchecked(&key_val_SSL, &des_key2); - - memcpy(&ivec, init_v, 8); - // the des decrypt will only fail if the data length is not evenly divisible - // by 8 - if (in_data_len % DES_BLOCK_SIZE) { - TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); - return CKR_DATA_LEN_RANGE; - } - - if (encrypt) { - DES_ncbc_encrypt(in_data, out_data, in_data_len, &des_key2, &ivec, - DES_ENCRYPT); - *out_data_len = in_data_len; - rc = CKR_OK; - } else { - DES_ncbc_encrypt(in_data, out_data, in_data_len, &des_key2, &ivec, - DES_DECRYPT); - *out_data_len = in_data_len; - rc = CKR_OK; - } - - return rc; -#else - const EVP_CIPHER *cipher = EVP_des_cbc(); - EVP_CIPHER_CTX *ctx = NULL; - CK_ATTRIBUTE *attr = NULL; - unsigned char dkey[DES_KEY_SIZE]; - CK_ULONG rc; - int outlen; - - UNUSED(tokdata); - - // get the key value - rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); - return rc; - } - - if (in_data_len % DES_BLOCK_SIZE || in_data_len > INT_MAX) { - TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); - return CKR_DATA_LEN_RANGE; - } - - memcpy(dkey, attr->pValue, sizeof(dkey)); - - ctx = EVP_CIPHER_CTX_new(); - if (ctx == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - - if (EVP_CipherInit_ex(ctx, cipher, - NULL, dkey, init_v, encrypt ? 1 : 0) != 1 - || EVP_CIPHER_CTX_set_padding(ctx, 0) != 1 - || EVP_CipherUpdate(ctx, out_data, &outlen, in_data, in_data_len) != 1 - || EVP_CipherFinal_ex(ctx, out_data, &outlen) != 1) { - TRACE_ERROR("%s\n", ock_err(ERR_GENERAL_ERROR)); - rc = CKR_GENERAL_ERROR; - goto done; - } - - *out_data_len = in_data_len; - rc = CKR_OK; -done: - OPENSSL_cleanse(dkey, sizeof(dkey)); - EVP_CIPHER_CTX_free(ctx); - return rc; -#endif + return openssl_specific_des_cbc(tokdata, in_data, in_data_len, + out_data, out_data_len, key, + init_v, encrypt); } CK_RV token_specific_tdes_ecb(STDLL_TokData_t *tokdata, @@ -491,140 +316,8 @@ CK_ULONG *out_data_len, OBJECT *key, CK_BYTE encrypt) { -#if OPENSSL_VERSION_NUMBER < 0x10100000L - CK_RV rc; - CK_ATTRIBUTE *attr = NULL; - CK_BYTE key_value[3 * DES_KEY_SIZE]; - CK_KEY_TYPE keytype; - unsigned int k, j; - DES_key_schedule des_key1; - DES_key_schedule des_key2; - DES_key_schedule des_key3; - const_DES_cblock key_SSL1, key_SSL2, key_SSL3, in_key_data; - DES_cblock out_key_data; - - UNUSED(tokdata); - - // get the key type - rc = template_attribute_get_ulong(key->template, CKA_KEY_TYPE, &keytype); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_KEY_TYPE for the key\n"); - return rc; - } - - // get the key value - rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_VALUE for the key\n"); - return rc; - } - if (keytype == CKK_DES2) { - memcpy(key_value, attr->pValue, 2 * DES_KEY_SIZE); - memcpy(key_value + (2 * DES_KEY_SIZE), attr->pValue, DES_KEY_SIZE); - } else { - memcpy(key_value, attr->pValue, 3 * DES_KEY_SIZE); - } - - // The key as passed is a 24 byte long string containing three des keys - // pick them apart and create the 3 corresponding key schedules - memcpy(&key_SSL1, key_value, 8); - memcpy(&key_SSL2, key_value + 8, 8); - memcpy(&key_SSL3, key_value + 16, 8); - DES_set_key_unchecked(&key_SSL1, &des_key1); - DES_set_key_unchecked(&key_SSL2, &des_key2); - DES_set_key_unchecked(&key_SSL3, &des_key3); - - // the des decrypt will only fail if the data length is not evenly divisible - // by 8 - if (in_data_len % DES_BLOCK_SIZE) { - TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); - return CKR_DATA_LEN_RANGE; - } - // the encrypt and decrypt are done 8 bytes at a time - if (encrypt) { - for (k = 0; k < in_data_len; k = k + 8) { - memcpy(in_key_data, in_data + k, 8); - DES_ecb3_encrypt((const_DES_cblock *) & in_key_data, - (DES_cblock *) & out_key_data, - &des_key1, &des_key2, &des_key3, DES_ENCRYPT); - memcpy(out_data + k, out_key_data, 8); - } - *out_data_len = in_data_len; - rc = CKR_OK; - } else { - for (j = 0; j < in_data_len; j = j + 8) { - memcpy(in_key_data, in_data + j, 8); - DES_ecb3_encrypt((const_DES_cblock *) & in_key_data, - (DES_cblock *) & out_key_data, - &des_key1, &des_key2, &des_key3, DES_DECRYPT); - memcpy(out_data + j, out_key_data, 8); - } - *out_data_len = in_data_len; - rc = CKR_OK; - } - - return rc; -#else - const EVP_CIPHER *cipher = EVP_des_ede3_ecb(); - EVP_CIPHER_CTX *ctx = NULL; - CK_ATTRIBUTE *attr = NULL; - unsigned char dkey[3 * DES_KEY_SIZE]; - CK_KEY_TYPE keytype; - CK_ULONG rc; - int outlen; - - UNUSED(tokdata); - - // get the key type - rc = template_attribute_get_ulong(key->template, CKA_KEY_TYPE, &keytype); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_KEY_TYPE for the key\n"); - return rc; - } - - // get the key value - rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_VALUE for the key\n"); - return rc; - } - - if (in_data_len % DES_BLOCK_SIZE || in_data_len > INT_MAX) { - TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); - return CKR_DATA_LEN_RANGE; - } - - if (keytype == CKK_DES2) { - memcpy(dkey, attr->pValue, 2 * DES_KEY_SIZE); - memcpy(dkey + (2 * DES_KEY_SIZE), attr->pValue, DES_KEY_SIZE); - } else { - memcpy(dkey, attr->pValue, 3 * DES_KEY_SIZE); - } - - ctx = EVP_CIPHER_CTX_new(); - if (ctx == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - - if (EVP_CipherInit_ex(ctx, cipher, - NULL, dkey, NULL, encrypt ? 1 : 0) != 1 - || EVP_CIPHER_CTX_set_padding(ctx, 0) != 1 - || EVP_CipherUpdate(ctx, out_data, &outlen, in_data, in_data_len) != 1 - || EVP_CipherFinal_ex(ctx, out_data, &outlen) != 1) { - TRACE_ERROR("%s\n", ock_err(ERR_GENERAL_ERROR)); - rc = CKR_GENERAL_ERROR; - goto done; - } - - *out_data_len = in_data_len; - rc = CKR_OK; -done: - OPENSSL_cleanse(dkey, sizeof(dkey)); - EVP_CIPHER_CTX_free(ctx); - return rc; -#endif + return openssl_specific_tdes_ecb(tokdata, in_data, in_data_len, + out_data, out_data_len, key, encrypt); } CK_RV token_specific_tdes_cbc(STDLL_TokData_t *tokdata, @@ -634,1133 +327,83 @@ CK_ULONG *out_data_len, OBJECT *key, CK_BYTE *init_v, CK_BYTE encrypt) { -#if OPENSSL_VERSION_NUMBER < 0x10100000L - CK_ATTRIBUTE *attr = NULL; - CK_RV rc = CKR_OK; - CK_BYTE key_value[3 * DES_KEY_SIZE]; - CK_KEY_TYPE keytype; - DES_key_schedule des_key1; - DES_key_schedule des_key2; - DES_key_schedule des_key3; - const_DES_cblock key_SSL1, key_SSL2, key_SSL3; - DES_cblock ivec; - - UNUSED(tokdata); - - // get the key type - rc = template_attribute_get_ulong(key->template, CKA_KEY_TYPE, &keytype); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_KEY_TYPE for the key\n"); - return rc; - } - - // get the key value - rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_VALUE for the key\n"); - return rc; - } - if (keytype == CKK_DES2) { - memcpy(key_value, attr->pValue, 2 * DES_KEY_SIZE); - memcpy(key_value + (2 * DES_KEY_SIZE), attr->pValue, DES_KEY_SIZE); - } else { - memcpy(key_value, attr->pValue, 3 * DES_KEY_SIZE); - } - - // The key as passed in is a 24 byte string containing 3 keys - // pick it apart and create the key schedules - memcpy(&key_SSL1, key_value, 8); - memcpy(&key_SSL2, key_value + 8, 8); - memcpy(&key_SSL3, key_value + 16, 8); - DES_set_key_unchecked(&key_SSL1, &des_key1); - DES_set_key_unchecked(&key_SSL2, &des_key2); - DES_set_key_unchecked(&key_SSL3, &des_key3); - - memcpy(ivec, init_v, sizeof(ivec)); - - // the des decrypt will only fail if the data length is not evenly divisible - // by 8 - if (in_data_len % DES_BLOCK_SIZE) { - TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); - return CKR_DATA_LEN_RANGE; - } - // Encrypt or decrypt the data - if (encrypt) { - DES_ede3_cbc_encrypt(in_data, - out_data, - in_data_len, - &des_key1, - &des_key2, &des_key3, &ivec, DES_ENCRYPT); - *out_data_len = in_data_len; - rc = CKR_OK; - } else { - DES_ede3_cbc_encrypt(in_data, - out_data, - in_data_len, - &des_key1, - &des_key2, &des_key3, &ivec, DES_DECRYPT); - - *out_data_len = in_data_len; - rc = CKR_OK; - } - - return rc; -#else - const EVP_CIPHER *cipher = EVP_des_ede3_cbc(); - EVP_CIPHER_CTX *ctx = NULL; - CK_ATTRIBUTE *attr = NULL; - unsigned char dkey[3 * DES_KEY_SIZE]; - CK_KEY_TYPE keytype; - CK_RV rc; - int outlen; - - UNUSED(tokdata); - - // get the key type - rc = template_attribute_get_ulong(key->template, CKA_KEY_TYPE, &keytype); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_KEY_TYPE for the key\n"); - return rc; - } - - // get the key value - rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_VALUE for the key\n"); - return rc; - } - - if (keytype == CKK_DES2) { - memcpy(dkey, attr->pValue, 2 * DES_KEY_SIZE); - memcpy(dkey + (2 * DES_KEY_SIZE), attr->pValue, DES_KEY_SIZE); - } else { - memcpy(dkey, attr->pValue, 3 * DES_KEY_SIZE); - } - - if (in_data_len % DES_BLOCK_SIZE || in_data_len > INT_MAX) { - TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); - return CKR_DATA_LEN_RANGE; - } - - ctx = EVP_CIPHER_CTX_new(); - if (ctx == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - - if (EVP_CipherInit_ex(ctx, cipher, - NULL, dkey, init_v, encrypt ? 1 : 0) != 1 - || EVP_CIPHER_CTX_set_padding(ctx, 0) != 1 - || EVP_CipherUpdate(ctx, out_data, &outlen, in_data, in_data_len) != 1 - || EVP_CipherFinal_ex(ctx, out_data, &outlen) != 1) { - TRACE_ERROR("%s\n", ock_err(ERR_GENERAL_ERROR)); - rc = CKR_GENERAL_ERROR; - goto done; - } - - *out_data_len = in_data_len; - rc = CKR_OK; -done: - OPENSSL_cleanse(dkey, sizeof(dkey)); - EVP_CIPHER_CTX_free(ctx); - return rc; -#endif + return openssl_specific_tdes_cbc(tokdata, in_data, in_data_len, + out_data, out_data_len, key, + init_v, encrypt); } -CK_RV token_specific_tdes_mac(STDLL_TokData_t *tokdata, CK_BYTE *message, - CK_ULONG message_len, OBJECT *key, CK_BYTE *mac) +CK_RV token_specific_tdes_ofb(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, + CK_BYTE *out_data, + CK_ULONG data_len, + OBJECT *key, CK_BYTE *init_v, uint_32 direction) { - CK_BYTE *out_buf; - CK_ULONG out_len; - CK_RV rc; - - out_buf = malloc(message_len); - if (out_buf == NULL) { - TRACE_ERROR("Malloc failed.\n"); - return CKR_HOST_MEMORY; - } - - rc = token_specific_tdes_cbc(tokdata, message, message_len, out_buf, - &out_len, key, mac, 1); - - if (rc == CKR_OK && out_len >= DES_BLOCK_SIZE) - memcpy(mac, out_buf + out_len - DES_BLOCK_SIZE, DES_BLOCK_SIZE); - - free(out_buf); - - return rc; + return openssl_specific_tdes_ofb(tokdata, in_data, data_len, + out_data, key, init_v, direction); } -// convert from the local PKCS11 template representation to -// the underlying requirement -// returns the pointer to the local key representation -static void *rsa_convert_public_key(OBJECT *key_obj) -{ - CK_BBOOL rc; - CK_ATTRIBUTE *modulus = NULL; - CK_ATTRIBUTE *pub_exp = NULL; - - RSA *rsa; - BIGNUM *bn_mod, *bn_exp; - - rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, - &modulus); - if (rc != CKR_OK) - return NULL; - rc = template_attribute_get_non_empty(key_obj->template, - CKA_PUBLIC_EXPONENT, &pub_exp); - if (rc != CKR_OK) - return NULL; - - // Create an RSA key struct to return - rsa = RSA_new(); - if (rsa == NULL) - return NULL; - - // Create and init BIGNUM structs to stick in the RSA struct - bn_mod = BN_new(); - bn_exp = BN_new(); - - if (bn_exp == NULL || bn_mod == NULL) { - if (bn_mod) - free(bn_mod); - if (bn_exp) - free(bn_exp); - RSA_free(rsa); - return NULL; - } - // Convert from strings to BIGNUMs and stick them in the RSA struct - BN_bin2bn((unsigned char *) modulus->pValue, modulus->ulValueLen, bn_mod); - BN_bin2bn((unsigned char *) pub_exp->pValue, pub_exp->ulValueLen, bn_exp); - -#ifdef OLDER_OPENSSL - rsa->n = bn_mod; - rsa->e = bn_exp; -#else - RSA_set0_key(rsa, bn_mod, bn_exp, NULL); -#endif - - return (void *) rsa; +CK_RV token_specific_tdes_cfb(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, + CK_BYTE *out_data, + CK_ULONG data_len, + OBJECT *key, + CK_BYTE *init_v, uint_32 cfb_len, + uint_32 direction) +{ + return openssl_specific_tdes_cfb(tokdata, in_data, data_len, + out_data, key, init_v, cfb_len, + direction); } -static void *rsa_convert_private_key(OBJECT *key_obj) +CK_RV token_specific_tdes_mac(STDLL_TokData_t *tokdata, CK_BYTE *message, + CK_ULONG message_len, OBJECT *key, CK_BYTE *mac) { - CK_ATTRIBUTE *modulus = NULL; - CK_ATTRIBUTE *pub_exp = NULL; - CK_ATTRIBUTE *priv_exp = NULL; - CK_ATTRIBUTE *prime1 = NULL; - CK_ATTRIBUTE *prime2 = NULL; - CK_ATTRIBUTE *exp1 = NULL; - CK_ATTRIBUTE *exp2 = NULL; - CK_ATTRIBUTE *coeff = NULL; - - RSA *rsa; - RSA_METHOD *meth; - BIGNUM *bn_mod, *bn_pub_exp, *bn_priv_exp, *bn_p1, *bn_p2, *bn_e1, *bn_e2, - *bn_cf; - - template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, &modulus); - template_attribute_get_non_empty(key_obj->template, CKA_PUBLIC_EXPONENT, - &pub_exp); - template_attribute_find(key_obj->template, CKA_PRIVATE_EXPONENT, &priv_exp); - template_attribute_find(key_obj->template, CKA_PRIME_1, &prime1); - template_attribute_find(key_obj->template, CKA_PRIME_2, &prime2); - template_attribute_find(key_obj->template, CKA_EXPONENT_1, &exp1); - template_attribute_find(key_obj->template, CKA_EXPONENT_2,&exp2); - template_attribute_find(key_obj->template, CKA_COEFFICIENT, &coeff); - - if (!prime2 && !modulus) { - return NULL; - } - // Create and init all the RSA and BIGNUM structs we need. - rsa = RSA_new(); - if (rsa == NULL) - return NULL; - - /* - * Depending if an engine is loaded on OpenSSL and define its own - * RSA_METHOD, we can end up having an infinite loop as the SOFT - * Token doesn't implement RSA and, instead, calls OpenSSL for it. - * So to avoid it we set RSA methods to the default rsa methods. - */ -#ifdef OLDER_OPENSSL - if (rsa->engine) { - meth = (RSA_METHOD *) rsa->meth; - const RSA_METHOD *meth2 = RSA_PKCS1_SSLeay(); - meth->rsa_pub_enc = meth2->rsa_pub_enc; - meth->rsa_pub_dec = meth2->rsa_pub_dec; - meth->rsa_priv_enc = meth2->rsa_priv_enc; - meth->rsa_priv_dec = meth2->rsa_priv_dec; - meth->rsa_mod_exp = meth2->rsa_mod_exp; - meth->bn_mod_exp = meth2->bn_mod_exp; -#else -/* - * XXX I dont see a better way than to ignore this warning for now. - * Note that the GCC pragma also works for clang. - */ -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wdeprecated-declarations" - ENGINE *e = RSA_get0_engine(rsa); - if (e) { - meth = (RSA_METHOD *) RSA_get_method(rsa); - const RSA_METHOD *meth2 = RSA_PKCS1_OpenSSL(); - RSA_meth_set_pub_enc(meth, RSA_meth_get_pub_enc(meth2)); - RSA_meth_set_pub_dec(meth, RSA_meth_get_pub_dec(meth2)); - RSA_meth_set_priv_enc(meth, RSA_meth_get_priv_enc(meth2)); - RSA_meth_set_priv_dec(meth, RSA_meth_get_priv_dec(meth2)); - RSA_meth_set_mod_exp(meth, RSA_meth_get_mod_exp(meth2)); - RSA_meth_set_bn_mod_exp(meth, RSA_meth_get_bn_mod_exp(meth2)); -# pragma GCC diagnostic pop -#endif - } - - bn_mod = BN_new(); - bn_pub_exp = BN_new(); - bn_priv_exp = BN_new(); - bn_p1 = BN_new(); - bn_p2 = BN_new(); - bn_e1 = BN_new(); - bn_e2 = BN_new(); - bn_cf = BN_new(); - - if ((bn_cf == NULL) || (bn_e2 == NULL) || (bn_e1 == NULL) || - (bn_p2 == NULL) || (bn_p1 == NULL) || (bn_priv_exp == NULL) || - (bn_pub_exp == NULL) || (bn_mod == NULL)) { - if (rsa) - RSA_free(rsa); - if (bn_mod) - BN_free(bn_mod); - if (bn_pub_exp) - BN_free(bn_pub_exp); - if (bn_priv_exp) - BN_free(bn_priv_exp); - if (bn_p1) - BN_free(bn_p1); - if (bn_p2) - BN_free(bn_p2); - if (bn_e1) - BN_free(bn_e1); - if (bn_e2) - BN_free(bn_e2); - if (bn_cf) - BN_free(bn_cf); - return NULL; - } - - // CRT key? - if (prime1) { - if (!prime2 || !exp1 || !exp2 || !coeff) { - return NULL; - } - // Even though this is CRT key, OpenSSL requires the - // modulus and exponents filled in or encrypt and decrypt will - // not work - BN_bin2bn((unsigned char *) modulus->pValue, modulus->ulValueLen, - bn_mod); - BN_bin2bn((unsigned char *) pub_exp->pValue, pub_exp->ulValueLen, - bn_pub_exp); - BN_bin2bn((unsigned char *) priv_exp->pValue, priv_exp->ulValueLen, - bn_priv_exp); - - BN_bin2bn((unsigned char *) prime1->pValue, prime1->ulValueLen, bn_p1); - BN_bin2bn((unsigned char *) prime2->pValue, prime2->ulValueLen, bn_p2); - - BN_bin2bn((unsigned char *) exp1->pValue, exp1->ulValueLen, bn_e1); - BN_bin2bn((unsigned char *) exp2->pValue, exp2->ulValueLen, bn_e2); - BN_bin2bn((unsigned char *) coeff->pValue, coeff->ulValueLen, bn_cf); -#ifdef OLDER_OPENSSL - rsa->n = bn_mod; - rsa->d = bn_priv_exp; - rsa->p = bn_p1; - rsa->q = bn_p2; - rsa->dmp1 = bn_e1; - rsa->dmq1 = bn_e2; - rsa->iqmp = bn_cf; -#else - RSA_set0_key(rsa, bn_mod, bn_pub_exp, bn_priv_exp); - RSA_set0_factors(rsa, bn_p1, bn_p2); - RSA_set0_crt_params(rsa, bn_e1, bn_e2, bn_cf); -#endif - return rsa; - } else { // must be a non-CRT key - if (!priv_exp) { - return NULL; - } - BN_bin2bn((unsigned char *) modulus->pValue, modulus->ulValueLen, - bn_mod); - BN_bin2bn((unsigned char *) pub_exp->pValue, pub_exp->ulValueLen, - bn_pub_exp); - BN_bin2bn((unsigned char *) priv_exp->pValue, priv_exp->ulValueLen, - bn_priv_exp); -#ifdef OLDER_OPENSSL - rsa->n = bn_mod; - rsa->d = bn_priv_exp; -#else - RSA_set0_key(rsa, bn_mod, bn_pub_exp, bn_priv_exp); -#endif - } - - return (void *) rsa; + return openssl_specific_tdes_mac(tokdata, message, message_len, key, mac); } -static CK_RV os_specific_rsa_keygen(TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl) +CK_RV token_specific_tdes_cmac(STDLL_TokData_t *tokdata, CK_BYTE *message, + CK_ULONG message_len, OBJECT *key, CK_BYTE *mac, + CK_BBOOL first, CK_BBOOL last, CK_VOID_PTR *ctx) { - CK_ATTRIBUTE *publ_exp = NULL; - CK_ATTRIBUTE *attr = NULL; - CK_ULONG mod_bits; - CK_BBOOL flag; - CK_RV rc; - CK_ULONG BNLength; - RSA *rsa = NULL; - const BIGNUM *bignum = NULL; - CK_BYTE *ssl_ptr = NULL; - BIGNUM *e = NULL; -#ifndef OLDER_OPENSSL - EVP_PKEY *pkey = NULL; - EVP_PKEY_CTX *ctx = NULL; -#endif - - rc = template_attribute_get_ulong(publ_tmpl, CKA_MODULUS_BITS, &mod_bits); - if (rc != CKR_OK) { - TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); - return CKR_TEMPLATE_INCOMPLETE; // should never happen - } - - // we don't support less than 1024 bit keys in the sw - if (mod_bits < 512 || mod_bits > 4096) { - TRACE_ERROR("%s\n", ock_err(ERR_KEY_SIZE_RANGE)); - return CKR_KEY_SIZE_RANGE; - } - - rc = template_attribute_get_non_empty(publ_tmpl, CKA_PUBLIC_EXPONENT, - &publ_exp); - if (rc != CKR_OK) { - TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); - return CKR_TEMPLATE_INCOMPLETE; - } - - if (publ_exp->ulValueLen > sizeof(CK_ULONG)) { - TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); - return CKR_ATTRIBUTE_VALUE_INVALID; - } - - e = BN_new(); - if (e == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - return CKR_HOST_MEMORY; - } - BN_bin2bn(publ_exp->pValue, publ_exp->ulValueLen, e); - -#ifdef OLDER_OPENSSL - rsa = RSA_new(); - if (rsa == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - return CKR_HOST_MEMORY; - } - - if (!RSA_generate_key_ex(rsa, mod_bits, e, NULL)) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - rc = CKR_FUNCTION_FAILED; - goto done; - } - bignum = rsa->n; -#else - ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); - if (ctx == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - - if (EVP_PKEY_keygen_init(ctx) != 1) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - rc = CKR_FUNCTION_FAILED; - goto done; - } - if (mod_bits > INT_MAX - || EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, mod_bits) != 1) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - rc = CKR_FUNCTION_FAILED; - goto done; - } - if (EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, e) != 1) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - rc = CKR_FUNCTION_FAILED; - goto done; - } - if (EVP_PKEY_keygen(ctx, &pkey) != 1) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - rc = CKR_FUNCTION_FAILED; - goto done; - } - if ((rsa = EVP_PKEY_get0_RSA(pkey)) == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - rc = CKR_FUNCTION_FAILED; - goto done; - } - RSA_get0_key(rsa, &bignum, NULL, NULL); -#endif - BNLength = BN_num_bytes(bignum); - ssl_ptr = malloc(BNLength); - if (ssl_ptr == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - BNLength = BN_bn2bin(bignum, ssl_ptr); - rc = build_attribute(CKA_MODULUS, ssl_ptr, BNLength, &attr); // in bytes - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute failed\n"); - goto done; - } - rc = template_update_attribute(publ_tmpl, attr); - if (rc != CKR_OK) { - TRACE_ERROR("template_update_attribute failed\n"); - free(attr); - goto done; - } - free(ssl_ptr); - ssl_ptr = NULL; - - // Public Exponent -#ifdef OLDER_OPENSSL - bignum = rsa->e; -#else - RSA_get0_key(rsa, NULL, &bignum, NULL); -#endif - BNLength = BN_num_bytes(bignum); - ssl_ptr = malloc(BNLength); - if (ssl_ptr == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - BNLength = BN_bn2bin(bignum, ssl_ptr); - // in bytes - rc = build_attribute(CKA_PUBLIC_EXPONENT, ssl_ptr, BNLength, &attr); - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute failed\n"); - goto done; - } - rc = template_update_attribute(publ_tmpl, attr); - if (rc != CKR_OK) { - TRACE_ERROR("template_update_attribute failed\n"); - free(attr); - goto done; - } - - /* add public exponent to the private template. Its already an attribute in - * the private template at this point, we're just making its value correct - */ - rc = build_attribute(CKA_PUBLIC_EXPONENT, ssl_ptr, BNLength, &attr); - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute failed\n"); - goto done; - } - rc = template_update_attribute(priv_tmpl, attr); - if (rc != CKR_OK) { - TRACE_ERROR("template_update_attribute failed\n"); - free(attr); - goto done; - } - free(ssl_ptr); - ssl_ptr = NULL; - - // local = TRUE - // - flag = TRUE; - rc = build_attribute(CKA_LOCAL, &flag, sizeof(CK_BBOOL), &attr); - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute failed\n"); - goto done; - } - rc = template_update_attribute(publ_tmpl, attr); - if (rc != CKR_OK) { - TRACE_ERROR("template_update_attribute failed\n"); - free(attr); - goto done; - } - - // - // now, do the private key - // - // Cheat here and put the whole original key into the CKA_VALUE... remember - // to force the system to not return this for RSA keys.. - - // Add the modulus to the private key information -#ifdef OLDER_OPENSSL - bignum = rsa->n; -#else - RSA_get0_key(rsa, &bignum, NULL, NULL); -#endif - BNLength = BN_num_bytes(bignum); - ssl_ptr = malloc(BNLength); - if (ssl_ptr == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - BNLength = BN_bn2bin(bignum, ssl_ptr); - rc = build_attribute(CKA_MODULUS, ssl_ptr, BNLength, &attr); // in bytes - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute failed\n"); - goto done; - } - rc = template_update_attribute(priv_tmpl, attr); - if (rc != CKR_OK) { - TRACE_ERROR("template_update_attribute failed\n"); - free(attr); - goto done; - } - free(ssl_ptr); - ssl_ptr = NULL; - - // Private Exponent -#ifdef OLDER_OPENSSL - bignum = rsa->d; -#else - RSA_get0_key(rsa, NULL, NULL, &bignum); -#endif - BNLength = BN_num_bytes(bignum); - ssl_ptr = malloc(BNLength); - if (ssl_ptr == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - BNLength = BN_bn2bin(bignum, ssl_ptr); - rc = build_attribute(CKA_PRIVATE_EXPONENT, ssl_ptr, BNLength, &attr); - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute failed\n"); - goto done; - } - rc = template_update_attribute(priv_tmpl, attr); - if (rc != CKR_OK) { - TRACE_ERROR("template_update_attribute failed\n"); - OPENSSL_cleanse(attr, sizeof(CK_ATTRIBUTE) + attr->ulValueLen); - free(attr); - goto done; - } - OPENSSL_cleanse(ssl_ptr, BNLength); - free(ssl_ptr); - ssl_ptr = NULL; - - // prime #1: p - // -#ifdef OLDER_OPENSSL - bignum = rsa->p; -#else - RSA_get0_factors(rsa, &bignum, NULL); -#endif - BNLength = BN_num_bytes(bignum); - ssl_ptr = malloc(BNLength); - if (ssl_ptr == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - BNLength = BN_bn2bin(bignum, ssl_ptr); - rc = build_attribute(CKA_PRIME_1, ssl_ptr, BNLength, &attr); - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute failed\n"); - goto done; - } - rc = template_update_attribute(priv_tmpl, attr); - if (rc != CKR_OK) { - TRACE_ERROR("template_update_attribute failed\n"); - OPENSSL_cleanse(attr, sizeof(CK_ATTRIBUTE) + attr->ulValueLen); - free(attr); - goto done; - } - OPENSSL_cleanse(ssl_ptr, BNLength); - free(ssl_ptr); - ssl_ptr = NULL; - - // prime #2: q - // -#ifdef OLDER_OPENSSL - bignum = rsa->q; -#else - RSA_get0_factors(rsa, NULL, &bignum); -#endif - BNLength = BN_num_bytes(bignum); - ssl_ptr = malloc(BNLength); - if (ssl_ptr == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - BNLength = BN_bn2bin(bignum, ssl_ptr); - rc = build_attribute(CKA_PRIME_2, ssl_ptr, BNLength, &attr); - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute failed\n"); - goto done; - } - rc = template_update_attribute(priv_tmpl, attr); - if (rc != CKR_OK) { - TRACE_ERROR("template_update_attribute failed\n"); - OPENSSL_cleanse(attr, sizeof(CK_ATTRIBUTE) + attr->ulValueLen); - free(attr); - goto done; - } - OPENSSL_cleanse(ssl_ptr, BNLength); - free(ssl_ptr); - ssl_ptr = NULL; - - // exponent 1: d mod(p-1) - // -#ifdef OLDER_OPENSSL - bignum = rsa->dmp1; -#else - RSA_get0_crt_params(rsa, &bignum, NULL, NULL); -#endif - BNLength = BN_num_bytes(bignum); - ssl_ptr = malloc(BNLength); - if (ssl_ptr == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - BNLength = BN_bn2bin(bignum, ssl_ptr); - rc = build_attribute(CKA_EXPONENT_1, ssl_ptr, BNLength, &attr); - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute failed\n"); - goto done; - } - rc = template_update_attribute(priv_tmpl, attr); - if (rc != CKR_OK) { - TRACE_ERROR("template_update_attribute failed\n"); - OPENSSL_cleanse(attr, sizeof(CK_ATTRIBUTE) + attr->ulValueLen); - free(attr); - goto done; - } - OPENSSL_cleanse(ssl_ptr, BNLength); - free(ssl_ptr); - ssl_ptr = NULL; - - // exponent 2: d mod(q-1) - // -#ifdef OLDER_OPENSSL - bignum = rsa->dmq1; -#else - RSA_get0_crt_params(rsa, NULL, &bignum, NULL); -#endif - BNLength = BN_num_bytes(bignum); - ssl_ptr = malloc(BNLength); - if (ssl_ptr == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - BNLength = BN_bn2bin(bignum, ssl_ptr); - rc = build_attribute(CKA_EXPONENT_2, ssl_ptr, BNLength, &attr); - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute failed\n"); - goto done; - } - rc = template_update_attribute(priv_tmpl, attr); - if (rc != CKR_OK) { - TRACE_ERROR("template_update_attribute failed\n"); - OPENSSL_cleanse(attr, sizeof(CK_ATTRIBUTE) + attr->ulValueLen); - free(attr); - goto done; - } - OPENSSL_cleanse(ssl_ptr, BNLength); - free(ssl_ptr); - ssl_ptr = NULL; - - // CRT coefficient: q_inverse mod(p) - // -#ifdef OLDER_OPENSSL - bignum = rsa->iqmp; -#else - RSA_get0_crt_params(rsa, NULL, NULL, &bignum); -#endif - BNLength = BN_num_bytes(bignum); - ssl_ptr = malloc(BNLength); - if (ssl_ptr == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - BNLength = BN_bn2bin(bignum, ssl_ptr); - rc = build_attribute(CKA_COEFFICIENT, ssl_ptr, BNLength, &attr); - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute failed\n"); - goto done; - } - rc = template_update_attribute(priv_tmpl, attr); - if (rc != CKR_OK) { - TRACE_ERROR("template_update_attribute failed\n"); - OPENSSL_cleanse(attr, sizeof(CK_ATTRIBUTE) + attr->ulValueLen); - free(attr); - goto done; - } - OPENSSL_cleanse(ssl_ptr, BNLength); - free(ssl_ptr); - ssl_ptr = NULL; - - flag = TRUE; - rc = build_attribute(CKA_LOCAL, &flag, sizeof(CK_BBOOL), &attr); - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute failed\n"); - goto done; - } - rc = template_update_attribute(priv_tmpl, attr); - if (rc != CKR_OK) { - TRACE_ERROR("template_update_attribute failed\n"); - free(attr); - goto done; - } - -done: -#ifdef OLDER_OPENSSL - if (e != NULL) - BN_free(e); - if (rsa != NULL) - RSA_free(rsa); - if (ssl_ptr != NULL) { - OPENSSL_cleanse(ssl_ptr, BNLength); - free(ssl_ptr); - } -#else - if (ssl_ptr != NULL) { - OPENSSL_cleanse(ssl_ptr, BNLength); - free(ssl_ptr); - } - if (pkey != NULL) - EVP_PKEY_free(pkey); - if (ctx != NULL) - EVP_PKEY_CTX_free(ctx); -#endif - return rc; + return openssl_specific_tdes_cmac(tokdata, message, message_len, key, mac, + first, last, ctx); } CK_RV token_specific_rsa_generate_keypair(STDLL_TokData_t *tokdata, TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl) { - CK_RV rc; - UNUSED(tokdata); - rc = os_specific_rsa_keygen(publ_tmpl, priv_tmpl); - if (rc != CKR_OK) - TRACE_DEVEL("os_specific_rsa_keygen failed\n"); - - return rc; -} - - -static CK_RV os_specific_rsa_encrypt(CK_BYTE *in_data, - CK_ULONG in_data_len, - CK_BYTE *out_data, OBJECT *key_obj) -{ -#ifdef OLDER_OPENSSL - CK_RV rc; - RSA *rsa; - int size; - - // Convert the local representation to an RSA representation - rsa = (RSA *) rsa_convert_public_key(key_obj); - if (rsa == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - rc = CKR_FUNCTION_FAILED; - return rc; - } - // Do an RSA public encryption - size = - RSA_public_encrypt(in_data_len, in_data, out_data, rsa, RSA_NO_PADDING); - if (size == -1) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - rc = CKR_ARGUMENTS_BAD; - goto done; - } - - rc = CKR_OK; - -done: - RSA_free(rsa); - - return rc; -#else - EVP_PKEY_CTX *ctx = NULL; - EVP_PKEY *pkey = NULL; - RSA *rsa = NULL; - CK_RV rc; - size_t outlen = in_data_len; - - rsa = (RSA *)rsa_convert_public_key(key_obj); - if (rsa == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - rc = CKR_FUNCTION_FAILED; - return rc; - } - - pkey = EVP_PKEY_new(); - if (pkey == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - - if (EVP_PKEY_assign_RSA(pkey, rsa) != 1) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - rc = CKR_FUNCTION_FAILED; - goto done; - } - rsa = NULL; /* freed together with pkey */ - - ctx = EVP_PKEY_CTX_new(pkey, NULL); - if (ctx == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - - if (EVP_PKEY_encrypt_init(ctx) != 1) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - rc = CKR_FUNCTION_FAILED; - goto done; - } - if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_NO_PADDING) != 1) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - rc = CKR_FUNCTION_FAILED; - goto done; - } - if (EVP_PKEY_encrypt(ctx, out_data, &outlen, - in_data, in_data_len) != 1) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - rc = CKR_FUNCTION_FAILED; - goto done; - } - - rc = CKR_OK; -done: - if (rsa != NULL) - RSA_free(rsa); - if (pkey != NULL) - EVP_PKEY_free(pkey); - if (ctx != NULL) - EVP_PKEY_CTX_free(ctx); - return rc; -#endif -} - -static CK_RV os_specific_rsa_decrypt(CK_BYTE *in_data, - CK_ULONG in_data_len, - CK_BYTE *out_data, OBJECT *key_obj) -{ -#ifdef OLDER_OPENSSL - CK_RV rc; - RSA *rsa; - int size; - - // Convert the local key representation to an RSA key representaion - rsa = (RSA *) rsa_convert_private_key(key_obj); - if (rsa == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - rc = CKR_FUNCTION_FAILED; - return rc; - } - // Do the private decryption - size = - RSA_private_decrypt(in_data_len, in_data, out_data, rsa, - RSA_NO_PADDING); - - if (size == -1) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - rc = CKR_FUNCTION_FAILED; - goto done; - } - - rc = CKR_OK; - -done: - RSA_free(rsa); - - return rc; -#else - EVP_PKEY_CTX *ctx = NULL; - EVP_PKEY *pkey = NULL; - RSA *rsa = NULL; - size_t outlen = in_data_len; - CK_RV rc; - - rsa = (RSA *)rsa_convert_private_key(key_obj); - if (rsa == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - rc = CKR_FUNCTION_FAILED; - return rc; - } - - pkey = EVP_PKEY_new(); - if (pkey == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - - if (EVP_PKEY_assign_RSA(pkey, rsa) != 1) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - rc = CKR_FUNCTION_FAILED; - goto done; - } - rsa = NULL; /* freed together with pkey */ - - ctx = EVP_PKEY_CTX_new(pkey, NULL); - if (ctx == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - - if (EVP_PKEY_decrypt_init(ctx) != 1) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - rc = CKR_FUNCTION_FAILED; - goto done; - } - if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_NO_PADDING) != 1) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - rc = CKR_FUNCTION_FAILED; - goto done; - } - if (EVP_PKEY_decrypt(ctx, out_data, &outlen, - in_data, in_data_len) != 1) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - rc = CKR_FUNCTION_FAILED; - goto done; - } - - rc = CKR_OK; -done: - if (rsa != NULL) - RSA_free(rsa); - if (pkey != NULL) - EVP_PKEY_free(pkey); - if (ctx != NULL) - EVP_PKEY_CTX_free(ctx); - return rc; -#endif + return openssl_specific_rsa_keygen(publ_tmpl, priv_tmpl); } CK_RV token_specific_rsa_encrypt(STDLL_TokData_t *tokdata, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj) { - CK_RV rc; - CK_ULONG modulus_bytes; - CK_BYTE clear[MAX_RSA_KEYLEN], cipher[MAX_RSA_KEYLEN]; - CK_ATTRIBUTE *attr = NULL; - - /* format the data */ - rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, - &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); - return rc; - } - modulus_bytes = attr->ulValueLen; - - rc = rsa_format_block(tokdata, in_data, in_data_len, clear, - modulus_bytes, PKCS_BT_2); - if (rc != CKR_OK) { - TRACE_DEVEL("rsa_format_block failed\n"); - goto done; - } - // Do an RSA public encryption - rc = os_specific_rsa_encrypt(clear, modulus_bytes, cipher, key_obj); - - if (rc == CKR_OK) { - memcpy(out_data, cipher, modulus_bytes); - *out_data_len = modulus_bytes; - } else { - TRACE_DEVEL("os_specific_rsa_encrypt failed\n"); - } - -done: - OPENSSL_cleanse(clear, sizeof(clear)); - return rc; + return openssl_specific_rsa_pkcs_encrypt(tokdata, in_data, in_data_len, + out_data, out_data_len, key_obj, + openssl_specific_rsa_encrypt); } CK_RV token_specific_rsa_decrypt(STDLL_TokData_t *tokdata, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj) { - CK_RV rc; - CK_BYTE out[MAX_RSA_KEYLEN]; - CK_ULONG modulus_bytes; - - UNUSED(tokdata); - - modulus_bytes = in_data_len; - - rc = os_specific_rsa_decrypt(in_data, modulus_bytes, out, key_obj); - if (rc != CKR_OK) { - TRACE_DEVEL("os_specific_rsa_decrypt failed\n"); - goto done; - } - - rc = rsa_parse_block(out, modulus_bytes, out_data, out_data_len, PKCS_BT_2); - if (rc != CKR_OK) { - TRACE_DEVEL("rsa_parse_block failed\n"); - goto done; - } - - /* - * For PKCS #1 v1.5 padding, out_data_len must be less than - * modulus_bytes - 11. - */ - if (*out_data_len > (modulus_bytes - 11)) { - TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE)); - rc = CKR_ENCRYPTED_DATA_LEN_RANGE; - } - -done: - OPENSSL_cleanse(out, sizeof(out)); - return rc; + return openssl_specific_rsa_pkcs_decrypt(tokdata, in_data, in_data_len, + out_data, out_data_len, key_obj, + openssl_specific_rsa_decrypt); } - CK_RV token_specific_rsa_sign(STDLL_TokData_t *tokdata, SESSION *sess, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj) { - CK_BYTE data[MAX_RSA_KEYLEN], sig[MAX_RSA_KEYLEN]; - CK_ULONG modulus_bytes; - CK_RV rc; - CK_ATTRIBUTE *attr = NULL; - - UNUSED(tokdata); - UNUSED(sess); - - /* format the data */ - rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, - &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); - return rc; - } - modulus_bytes = attr->ulValueLen; - rc = rsa_format_block(tokdata, in_data, in_data_len, data, - modulus_bytes, PKCS_BT_1); - if (rc != CKR_OK) { - TRACE_DEVEL("rsa_format_block failed\n"); - return rc; - } - - /* signing is a private key operation --> decrypt */ - rc = os_specific_rsa_decrypt(data, modulus_bytes, sig, key_obj); - if (rc == CKR_OK) { - memcpy(out_data, sig, modulus_bytes); - *out_data_len = modulus_bytes; - } else { - TRACE_DEVEL("os_specific_rsa_decrypt failed\n"); - } - - return rc; + return openssl_specific_rsa_pkcs_sign(tokdata, sess, in_data, in_data_len, + out_data, out_data_len, key_obj, + openssl_specific_rsa_decrypt); } CK_RV token_specific_rsa_verify(STDLL_TokData_t *tokdata, SESSION *sess, @@ -1768,64 +411,9 @@ CK_BYTE *signature, CK_ULONG sig_len, OBJECT *key_obj) { - CK_ATTRIBUTE *attr = NULL; - CK_BYTE out[MAX_RSA_KEYLEN], out_data[MAX_RSA_KEYLEN]; - CK_ULONG modulus_bytes, out_data_len; - CK_RV rc; - - UNUSED(tokdata); - UNUSED(sess); - UNUSED(sig_len); - - out_data_len = MAX_RSA_KEYLEN; - rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, - &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); - return rc; - } else { - modulus_bytes = attr->ulValueLen; - } - - // verifying is a public key operation --> encrypt - // - rc = os_specific_rsa_encrypt(signature, modulus_bytes, out, key_obj); - if (rc != CKR_OK) { - TRACE_DEVEL("os_specific_rsa_encrypt failed: %lx\n", rc); - /* - * Return CKR_SIGNATURE_INVALID in case of CKR_ARGUMENTS_BAD or - * CKR_FUNCTION_FAILED because we dont know why the RSA op failed and - * it may have failed due to a tampered signature being greater or equal - * to the modulus. - */ - if (rc == CKR_ARGUMENTS_BAD || rc == CKR_FUNCTION_FAILED) { - TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); - rc = CKR_SIGNATURE_INVALID; - } - return rc; - } - - rc = rsa_parse_block(out, modulus_bytes, out_data, &out_data_len, - PKCS_BT_1); - if (rc == CKR_ENCRYPTED_DATA_INVALID) { - TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); - return CKR_SIGNATURE_INVALID; - } else if (rc != CKR_OK) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - return CKR_FUNCTION_FAILED; - } - - if (in_data_len != out_data_len) { - TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); - return CKR_SIGNATURE_INVALID; - } - - if (CRYPTO_memcmp(in_data, out_data, out_data_len) != 0) { - TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); - return CKR_SIGNATURE_INVALID; - } - - return rc; + return openssl_specific_rsa_pkcs_verify(tokdata, sess, in_data, in_data_len, + signature, sig_len, key_obj, + openssl_specific_rsa_encrypt); } CK_RV token_specific_rsa_verify_recover(STDLL_TokData_t *tokdata, @@ -1834,50 +422,10 @@ CK_ULONG *out_data_len, OBJECT *key_obj) { - CK_ATTRIBUTE *attr = NULL; - CK_BYTE out[MAX_RSA_KEYLEN]; - CK_ULONG modulus_bytes; - CK_RV rc; - - UNUSED(tokdata); - UNUSED(sig_len); - - rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, - &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); - return rc; - } else { - modulus_bytes = attr->ulValueLen; - } - - // verifying is a public key operation --> encrypt - // - rc = os_specific_rsa_encrypt(signature, modulus_bytes, out, key_obj); - if (rc != CKR_OK) { - TRACE_DEVEL("os_specific_rsa_encrypt failed: %lx\n", rc); - /* - * Return CKR_SIGNATURE_INVALID in case of CKR_ARGUMENTS_BAD or - * CKR_FUNCTION_FAILED because we dont know why the RSA op failed and - * it may have failed due to a tampered signature being greater or equal - * to the modulus. - */ - if (rc == CKR_ARGUMENTS_BAD || rc == CKR_FUNCTION_FAILED) { - TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); - rc = CKR_SIGNATURE_INVALID; - } - return rc; - } - - rc = rsa_parse_block(out, modulus_bytes, out_data, out_data_len, PKCS_BT_1); - if (rc == CKR_ENCRYPTED_DATA_INVALID) { - TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); - return CKR_SIGNATURE_INVALID; - } else if (rc != CKR_OK) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - } - - return rc; + return openssl_specific_rsa_pkcs_verify_recover(tokdata, signature, + sig_len, out_data, + out_data_len, key_obj, + openssl_specific_rsa_encrypt); } CK_RV token_specific_rsa_pss_sign(STDLL_TokData_t *tokdata, SESSION *sess, @@ -1885,183 +433,29 @@ CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *sig, CK_ULONG *sig_len) { - CK_RV rc; - CK_ULONG modbytes; - CK_ATTRIBUTE *attr = NULL; - OBJECT *key_obj = NULL; - CK_BYTE *emdata = NULL; - CK_RSA_PKCS_PSS_PARAMS *pssParms = NULL; - - UNUSED(sess); - - /* check the arguments */ - if (!in_data || !sig) { - TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); - return CKR_ARGUMENTS_BAD; - } - - if (!ctx) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - return CKR_FUNCTION_FAILED; - } - - pssParms = (CK_RSA_PKCS_PSS_PARAMS *) ctx->mech.pParameter; - - /* get the key */ - rc = object_mgr_find_in_map1(tokdata, ctx->key, &key_obj, READ_LOCK); - if (rc != CKR_OK) { - TRACE_DEVEL("object_mgr_find_in_map1 failed\n"); - return rc; - } - - rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, - &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); - goto done; - } else { - modbytes = attr->ulValueLen; - } - - emdata = (CK_BYTE *) malloc(modbytes); - if (emdata == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - - rc = emsa_pss_encode(tokdata, pssParms, in_data, in_data_len, emdata, - &modbytes); - if (rc != CKR_OK) - goto done; - - /* signing is a private key operation --> decrypt */ - rc = os_specific_rsa_decrypt(emdata, modbytes, sig, key_obj); - if (rc == CKR_OK) - *sig_len = modbytes; - else - TRACE_DEVEL("os_specific_rsa_decrypt failed\n"); - -done: - if (emdata) - free(emdata); - - object_put(tokdata, key_obj, TRUE); - key_obj = NULL; - - return rc; + return openssl_specific_rsa_pss_sign(tokdata, sess, ctx, in_data, + in_data_len, sig, sig_len, + openssl_specific_rsa_decrypt); } - CK_RV token_specific_rsa_pss_verify(STDLL_TokData_t *tokdata, SESSION *sess, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG sig_len) { - CK_RV rc; - CK_ULONG modbytes; - OBJECT *key_obj = NULL; - CK_ATTRIBUTE *attr = NULL; - CK_BYTE out[MAX_RSA_KEYLEN]; - CK_RSA_PKCS_PSS_PARAMS *pssParms = NULL; - - UNUSED(sess); - - /* check the arguments */ - if (!in_data || !signature) { - TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); - return CKR_ARGUMENTS_BAD; - } - - if (!ctx) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - return CKR_FUNCTION_FAILED; - } - - pssParms = (CK_RSA_PKCS_PSS_PARAMS *) ctx->mech.pParameter; - - /* get the key */ - rc = object_mgr_find_in_map1(tokdata, ctx->key, &key_obj, READ_LOCK); - if (rc != CKR_OK) { - TRACE_DEVEL("object_mgr_find_in_map1 failed\n"); - return rc; - } - - /* verify is a public key operation ... encrypt */ - rc = os_specific_rsa_encrypt(signature, sig_len, out, key_obj); - if (rc != CKR_OK) { - TRACE_DEVEL("os_specific_rsa_encrypt failed: %lx\n", rc); - /* - * Return CKR_SIGNATURE_INVALID in case of CKR_ARGUMENTS_BAD or - * CKR_FUNCTION_FAILED because we dont know why the RSA op failed and - * it may have failed due to a tampered signature being greater or equal - * to the modulus. - */ - if (rc == CKR_ARGUMENTS_BAD || rc == CKR_FUNCTION_FAILED) { - TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); - rc = CKR_SIGNATURE_INVALID; - } - goto done; - } - - rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, - &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); - goto done; - } else { - modbytes = attr->ulValueLen; - } - - /* call the pss verify scheme */ - rc = emsa_pss_verify(tokdata, pssParms, in_data, in_data_len, out, - modbytes); - -done: - object_put(tokdata, key_obj, TRUE); - key_obj = NULL; - - return rc; + return openssl_specific_rsa_pss_verify(tokdata, sess, ctx, in_data, + in_data_len, signature, sig_len, + openssl_specific_rsa_encrypt); } - CK_RV token_specific_rsa_x509_encrypt(STDLL_TokData_t *tokdata, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj) { - CK_ATTRIBUTE *attr = NULL; - CK_BYTE clear[MAX_RSA_KEYLEN], cipher[MAX_RSA_KEYLEN]; - CK_ULONG modulus_bytes; - CK_RV rc; - - UNUSED(tokdata); - - rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, - &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); - goto done; - } - - modulus_bytes = attr->ulValueLen; - - // prepad with zeros - // - memset(clear, 0x0, modulus_bytes - in_data_len); - memcpy(&clear[modulus_bytes - in_data_len], in_data, in_data_len); - - rc = os_specific_rsa_encrypt(clear, modulus_bytes, cipher, key_obj); - if (rc == CKR_OK) { - memcpy(out_data, cipher, modulus_bytes); - *out_data_len = modulus_bytes; - } else { - TRACE_DEVEL("os_specific_rsa_encrypt failed\n"); - } - -done: - OPENSSL_cleanse(clear, sizeof(clear)); - return rc; + return openssl_specific_rsa_x509_encrypt(tokdata, in_data, in_data_len, + out_data, out_data_len, key_obj, + openssl_specific_rsa_encrypt); } CK_RV token_specific_rsa_x509_decrypt(STDLL_TokData_t *tokdata, @@ -2069,82 +463,18 @@ CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj) { - CK_ATTRIBUTE *attr = NULL; - CK_BYTE out[MAX_RSA_KEYLEN]; - CK_ULONG modulus_bytes; - CK_RV rc; - - UNUSED(tokdata); - UNUSED(in_data_len); - - rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, - &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); - goto done; - } - - modulus_bytes = attr->ulValueLen; - - rc = os_specific_rsa_decrypt(in_data, modulus_bytes, out, key_obj); - if (rc == CKR_OK) { - memcpy(out_data, out, modulus_bytes); - *out_data_len = modulus_bytes; - } else { - TRACE_DEVEL("os_specific_rsa_decrypt failed\n"); - } - -done: - OPENSSL_cleanse(out, sizeof(out)); - return rc; + return openssl_specific_rsa_x509_decrypt(tokdata, in_data, in_data_len, + out_data, out_data_len, key_obj, + openssl_specific_rsa_decrypt); } - CK_RV token_specific_rsa_x509_sign(STDLL_TokData_t *tokdata, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj) { - CK_ATTRIBUTE *attr = NULL; - CK_BYTE data[MAX_RSA_KEYLEN], sig[MAX_RSA_KEYLEN]; - CK_ULONG modulus_bytes; - CK_RV rc; - - UNUSED(tokdata); - - rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, - &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); - return rc; - } else { - modulus_bytes = attr->ulValueLen; - } - - // prepad with zeros - // - - memset(data, 0x0, modulus_bytes - in_data_len); - memcpy(&data[modulus_bytes - in_data_len], in_data, in_data_len); - - rc = os_specific_rsa_decrypt(data, modulus_bytes, sig, key_obj); - if (rc == CKR_OK) { - memcpy(out_data, sig, modulus_bytes); - *out_data_len = modulus_bytes; - } else { - TRACE_DEVEL("os_specific_rsa_encrypt failed: %lx\n", rc); - /* - * Return CKR_SIGNATURE_INVALID in case of CKR_ARGUMENTS_BAD or - * CKR_FUNCTION_FAILED because we dont know why the RSA op failed and - * it may have failed due to a tampered signature being greater or equal - * to the modulus. - */ - if (rc == CKR_ARGUMENTS_BAD || rc == CKR_FUNCTION_FAILED) { - TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); - rc = CKR_SIGNATURE_INVALID; - } - } - - return rc; + return openssl_specific_rsa_x509_sign(tokdata, in_data, in_data_len, + out_data, out_data_len, key_obj, + openssl_specific_rsa_decrypt); } CK_RV token_specific_rsa_x509_verify(STDLL_TokData_t *tokdata, @@ -2152,66 +482,9 @@ CK_BYTE *signature, CK_ULONG sig_len, OBJECT *key_obj) { - CK_ATTRIBUTE *attr = NULL; - CK_BYTE out[MAX_RSA_KEYLEN]; - CK_ULONG modulus_bytes; - CK_RV rc; - - UNUSED(tokdata); - UNUSED(sig_len); - - rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, - &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); - return rc; - } else { - modulus_bytes = attr->ulValueLen; - } - - rc = os_specific_rsa_encrypt(signature, modulus_bytes, out, key_obj); - if (rc == CKR_OK) { - CK_ULONG pos1, pos2, len; - // it should be noted that in_data_len is not necessarily - // the same as the modulus length - // - for (pos1 = 0; pos1 < in_data_len; pos1++) - if (in_data[pos1] != 0) - break; - - for (pos2 = 0; pos2 < modulus_bytes; pos2++) - if (out[pos2] != 0) - break; - - // at this point, pos1 and pos2 point to the first non-zero - // bytes in the input data and the decrypted signature - // (the recovered data), respectively. - if ((in_data_len - pos1) != (modulus_bytes - pos2)) { - TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); - return CKR_SIGNATURE_INVALID; - } - len = in_data_len - pos1; - - if (CRYPTO_memcmp(&in_data[pos1], &out[pos2], len) != 0) { - TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); - return CKR_SIGNATURE_INVALID; - } - return CKR_OK; - } else { - TRACE_DEVEL("os_specific_rsa_encrypt failed: %lx\n", rc); - /* - * Return CKR_SIGNATURE_INVALID in case of CKR_ARGUMENTS_BAD or - * CKR_FUNCTION_FAILED because we dont know why the RSA op failed and - * it may have failed due to a tampered signature being greater or equal - * to the modulus. - */ - if (rc == CKR_ARGUMENTS_BAD || rc == CKR_FUNCTION_FAILED) { - TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); - rc = CKR_SIGNATURE_INVALID; - } - } - - return rc; + return openssl_specific_rsa_x509_verify(tokdata, in_data, in_data_len, + signature, sig_len, key_obj, + openssl_specific_rsa_encrypt); } CK_RV token_specific_rsa_x509_verify_recover(STDLL_TokData_t *tokdata, @@ -2221,32 +494,10 @@ CK_ULONG *out_data_len, OBJECT *key_obj) { - CK_ATTRIBUTE *attr = NULL; - CK_BYTE out[MAX_RSA_KEYLEN]; - CK_ULONG modulus_bytes; - CK_RV rc; - - UNUSED(tokdata); - UNUSED(sig_len); - - rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, - &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); - return rc; - } else { - modulus_bytes = attr->ulValueLen; - } - - rc = os_specific_rsa_encrypt(signature, modulus_bytes, out, key_obj); - if (rc == CKR_OK) { - memcpy(out_data, out, modulus_bytes); - *out_data_len = modulus_bytes; - } else { - TRACE_DEVEL("os_specific_rsa_encrypt failed\n"); - } - - return rc; + return openssl_specific_rsa_x509_verify_recover(tokdata, signature, sig_len, + out_data, out_data_len, + key_obj, + openssl_specific_rsa_encrypt); } CK_RV token_specific_rsa_oaep_encrypt(STDLL_TokData_t *tokdata, @@ -2256,69 +507,10 @@ CK_ULONG *out_data_len, CK_BYTE *hash, CK_ULONG hlen) { - CK_RV rc; - CK_BYTE cipher[MAX_RSA_KEYLEN]; - CK_ULONG modulus_bytes; - CK_ATTRIBUTE *attr = NULL; - CK_BYTE *em_data = NULL; - OBJECT *key_obj = NULL; - CK_RSA_PKCS_OAEP_PARAMS_PTR oaepParms = NULL; - - if (!in_data || !out_data || !hash) { - TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); - return CKR_ARGUMENTS_BAD; - } - - oaepParms = (CK_RSA_PKCS_OAEP_PARAMS_PTR) ctx->mech.pParameter; - - rc = object_mgr_find_in_map1(tokdata, ctx->key, &key_obj, READ_LOCK); - if (rc != CKR_OK) { - TRACE_DEVEL("object_mgr_find_in_map1 failed\n"); - return rc; - } - - rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, - &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); - goto done; - } - - modulus_bytes = attr->ulValueLen; - - /* pkcs1v2.2, section 7.1.1 Step 2: - * EME-OAEP encoding. - */ - em_data = (CK_BYTE *) malloc(modulus_bytes * sizeof(CK_BYTE)); - if (em_data == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - - rc = encode_eme_oaep(tokdata, in_data, in_data_len, em_data, - modulus_bytes, oaepParms->mgf, hash, hlen); - if (rc != CKR_OK) - goto done; - - rc = os_specific_rsa_encrypt(em_data, modulus_bytes, cipher, key_obj); - if (rc == CKR_OK) { - memcpy(out_data, cipher, modulus_bytes); - *out_data_len = modulus_bytes; - } else { - TRACE_DEVEL("os_specific_rsa_encrypt failed\n"); - } - -done: - if (em_data) { - OPENSSL_cleanse(em_data, modulus_bytes * sizeof(CK_BYTE)); - free(em_data); - } - - object_put(tokdata, key_obj, TRUE); - key_obj = NULL; - - return rc; + return openssl_specific_rsa_oaep_encrypt(tokdata, ctx, in_data, + in_data_len, out_data, + out_data_len, hash, hlen, + openssl_specific_rsa_encrypt); } CK_RV token_specific_rsa_oaep_decrypt(STDLL_TokData_t *tokdata, @@ -2328,61 +520,10 @@ CK_ULONG *out_data_len, CK_BYTE *hash, CK_ULONG hlen) { - CK_RV rc; - CK_BYTE *decr_data = NULL; - OBJECT *key_obj = NULL; - CK_ATTRIBUTE *attr = NULL; - CK_RSA_PKCS_OAEP_PARAMS_PTR oaepParms = NULL; - - if (!in_data || !out_data || !hash) { - TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); - return CKR_ARGUMENTS_BAD; - } - - oaepParms = (CK_RSA_PKCS_OAEP_PARAMS_PTR) ctx->mech.pParameter; - - rc = object_mgr_find_in_map1(tokdata, ctx->key, &key_obj, READ_LOCK); - if (rc != CKR_OK) { - TRACE_DEVEL("object_mgr_find_in_map1 failed\n"); - return rc; - } - - rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS, - &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); - goto error; - } - - *out_data_len = attr->ulValueLen; - - decr_data = (CK_BYTE *) malloc(in_data_len); - if (decr_data == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto error; - } - - rc = os_specific_rsa_decrypt(in_data, in_data_len, decr_data, key_obj); - if (rc != CKR_OK) - goto error; - - /* pkcs1v2.2, section 7.1.2 Step 2: - * EME-OAEP decoding. - */ - rc = decode_eme_oaep(tokdata, decr_data, in_data_len, out_data, - out_data_len, oaepParms->mgf, hash, hlen); - -error: - if (decr_data) { - OPENSSL_cleanse(decr_data, in_data_len); - free(decr_data); - } - - object_put(tokdata, key_obj, TRUE); - key_obj = NULL; - - return rc; + return openssl_specific_rsa_oaep_decrypt(tokdata, ctx, in_data, + in_data_len, out_data, + out_data_len, hash, hlen, + openssl_specific_rsa_decrypt); } #ifndef NOAES @@ -2407,105 +548,8 @@ CK_ULONG *out_data_len, OBJECT *key, CK_BYTE encrypt) { -#if OPENSSL_VERSION_NUMBER < 0x10100000L - AES_KEY ssl_aes_key; - unsigned int i; - CK_ATTRIBUTE *attr = NULL; - /* There's a previous check that in_data_len % AES_BLOCK_SIZE == 0, - * so this is fine */ - CK_ULONG loops = (CK_ULONG) (in_data_len / AES_BLOCK_SIZE); - CK_RV rc; - - UNUSED(tokdata); - - memset(&ssl_aes_key, 0, sizeof(AES_KEY)); - - // get key value - rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_VALUE for the key\n"); - return rc; - } - // AES_ecb_encrypt encrypts only a single block, so we have to break up the - // input data here - if (encrypt) { - AES_set_encrypt_key((unsigned char *) attr->pValue, - (attr->ulValueLen * 8), &ssl_aes_key); - for (i = 0; i < loops; i++) { - AES_ecb_encrypt((unsigned char *) in_data + (i * AES_BLOCK_SIZE), - (unsigned char *) out_data + (i * AES_BLOCK_SIZE), - &ssl_aes_key, AES_ENCRYPT); - } - } else { - AES_set_decrypt_key((unsigned char *) attr->pValue, - (attr->ulValueLen * 8), &ssl_aes_key); - for (i = 0; i < loops; i++) { - AES_ecb_encrypt((unsigned char *) in_data + (i * AES_BLOCK_SIZE), - (unsigned char *) out_data + (i * AES_BLOCK_SIZE), - &ssl_aes_key, AES_DECRYPT); - } - } - *out_data_len = in_data_len; - - return CKR_OK; -#else - CK_RV rc; - int outlen; - unsigned char akey[32]; - const EVP_CIPHER *cipher = NULL; - EVP_CIPHER_CTX *ctx = NULL; - CK_ATTRIBUTE *attr = NULL; - CK_ULONG keylen; - - UNUSED(tokdata); - - // get the key value - rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); - return rc; - } - - keylen = attr->ulValueLen; - if (keylen == 128 / 8) - cipher = EVP_aes_128_ecb(); - else if (keylen == 192 / 8) - cipher = EVP_aes_192_ecb(); - else if (keylen == 256 / 8) - cipher = EVP_aes_256_ecb(); - - memcpy(akey, attr->pValue, keylen); - - if (in_data_len % AES_BLOCK_SIZE || in_data_len > INT_MAX) { - TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); - rc = CKR_DATA_LEN_RANGE; - goto done; - } - - ctx = EVP_CIPHER_CTX_new(); - if (ctx == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - - if (EVP_CipherInit_ex(ctx, cipher, - NULL, akey, NULL, encrypt ? 1 : 0) != 1 - || EVP_CIPHER_CTX_set_padding(ctx, 0) != 1 - || EVP_CipherUpdate(ctx, out_data, &outlen, in_data, in_data_len) != 1 - || EVP_CipherFinal_ex(ctx, out_data, &outlen) != 1) { - TRACE_ERROR("%s\n", ock_err(ERR_GENERAL_ERROR)); - rc = CKR_GENERAL_ERROR; - goto done; - } - - *out_data_len = in_data_len; - rc = CKR_OK; -done: - OPENSSL_cleanse(akey, sizeof(akey)); - EVP_CIPHER_CTX_free(ctx); - return rc; -#endif + return openssl_specific_aes_ecb(tokdata, in_data, in_data_len, + out_data, out_data_len, key, encrypt); } CK_RV token_specific_aes_cbc(STDLL_TokData_t *tokdata, @@ -2515,120 +559,99 @@ CK_ULONG *out_data_len, OBJECT *key, CK_BYTE *init_v, CK_BYTE encrypt) { -#if OPENSSL_VERSION_NUMBER < 0x10100000L - AES_KEY ssl_aes_key; - CK_ATTRIBUTE *attr = NULL; - CK_RV rc; - - UNUSED(tokdata); - - memset(&ssl_aes_key, 0, sizeof(AES_KEY)); - - // get key value - rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_VALUE for the key\n"); - return rc; - } - // AES_cbc_encrypt chunks the data into AES_BLOCK_SIZE blocks, unlike - // AES_ecb_encrypt, so no looping required. - if (encrypt) { - AES_set_encrypt_key((unsigned char *) attr->pValue, - (attr->ulValueLen * 8), &ssl_aes_key); - AES_cbc_encrypt((unsigned char *) in_data, (unsigned char *) out_data, - in_data_len, &ssl_aes_key, init_v, AES_ENCRYPT); - } else { - AES_set_decrypt_key((unsigned char *) attr->pValue, - (attr->ulValueLen * 8), &ssl_aes_key); - AES_cbc_encrypt((unsigned char *) in_data, (unsigned char *) out_data, - in_data_len, &ssl_aes_key, init_v, AES_DECRYPT); - } - *out_data_len = in_data_len; + return openssl_specific_aes_cbc(tokdata, in_data, in_data_len, + out_data, out_data_len, key, + init_v, encrypt); +} - return CKR_OK; -#else - CK_RV rc; - int outlen; - unsigned char akey[32]; - const EVP_CIPHER *cipher = NULL; - EVP_CIPHER_CTX *ctx = NULL; - CK_ATTRIBUTE *attr = NULL; - CK_ULONG keylen; +CK_RV token_specific_aes_ctr(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, + CK_ULONG *out_data_len, + OBJECT *key, + CK_BYTE *counterblock, + CK_ULONG counter_width, CK_BYTE encrypt) +{ + return openssl_specific_aes_ctr(tokdata, in_data, in_data_len, + out_data, out_data_len, key, + counterblock, counter_width, encrypt); +} - UNUSED(tokdata); +CK_RV token_specific_aes_ofb(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, + OBJECT *key, + CK_BYTE *init_v, uint_32 direction) +{ + return openssl_specific_aes_ofb(tokdata, in_data, in_data_len, + out_data, key, init_v, direction); +} - // get the key value - rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_VALUE for the key\n"); - return rc; - } +CK_RV token_specific_aes_cfb(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, + OBJECT *key, + CK_BYTE *init_v, uint_32 cfb_len, + uint_32 direction) +{ + return openssl_specific_aes_cfb(tokdata, in_data, in_data_len, + out_data, key, init_v, cfb_len, + direction); +} - keylen = attr->ulValueLen; - if (keylen == 128 / 8) - cipher = EVP_aes_128_cbc(); - else if (keylen == 192 / 8) - cipher = EVP_aes_192_cbc(); - else if (keylen == 256 / 8) - cipher = EVP_aes_256_cbc(); - - memcpy(akey, attr->pValue, keylen); - - if (in_data_len % AES_BLOCK_SIZE || in_data_len > INT_MAX) { - TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); - rc = CKR_DATA_LEN_RANGE; - goto done; - } +CK_RV token_specific_aes_gcm_init(STDLL_TokData_t *tokdata, SESSION *sess, + ENCR_DECR_CONTEXT *ctx, CK_MECHANISM *mech, + CK_OBJECT_HANDLE key, CK_BYTE encrypt) +{ + return openssl_specific_aes_gcm_init(tokdata, sess, ctx, mech, + key, encrypt); +} - ctx = EVP_CIPHER_CTX_new(); - if (ctx == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } +CK_RV token_specific_aes_gcm(STDLL_TokData_t *tokdata, SESSION *sess, + ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, + CK_ULONG in_data_len, CK_BYTE *out_data, + CK_ULONG *out_data_len, CK_BYTE encrypt) +{ + return openssl_specific_aes_gcm(tokdata, sess, ctx, in_data, in_data_len, + out_data, out_data_len, encrypt); +} - if (EVP_CipherInit_ex(ctx, cipher, - NULL, akey, init_v, encrypt ? 1 : 0) != 1 - || EVP_CIPHER_CTX_set_padding(ctx, 0) != 1 - || EVP_CipherUpdate(ctx, out_data, &outlen, in_data, in_data_len) != 1 - || EVP_CipherFinal_ex(ctx, out_data, &outlen) != 1) { - TRACE_ERROR("%s\n", ock_err(ERR_GENERAL_ERROR)); - rc = CKR_GENERAL_ERROR; - goto done; - } +CK_RV token_specific_aes_gcm_update(STDLL_TokData_t *tokdata, SESSION *sess, + ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, + CK_ULONG in_data_len, CK_BYTE *out_data, + CK_ULONG *out_data_len, CK_BYTE encrypt) +{ + return openssl_specific_aes_gcm_update(tokdata, sess, ctx, in_data, + in_data_len, out_data, out_data_len, + encrypt); +} - *out_data_len = in_data_len; - rc = CKR_OK; -done: - OPENSSL_cleanse(akey, sizeof(akey)); - EVP_CIPHER_CTX_free(ctx); - return rc; -#endif +CK_RV token_specific_aes_gcm_final(STDLL_TokData_t *tokdata, SESSION *sess, + ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, + CK_ULONG *out_data_len, CK_BYTE encrypt) +{ + return openssl_specific_aes_gcm_final(tokdata, sess, ctx, out_data, + out_data_len, encrypt); } CK_RV token_specific_aes_mac(STDLL_TokData_t *tokdata, CK_BYTE *message, CK_ULONG message_len, OBJECT *key, CK_BYTE *mac) { - CK_BYTE *out_buf; - CK_ULONG out_len; - CK_RV rc; - - out_buf = malloc(message_len); - if (out_buf == NULL) { - TRACE_ERROR("Malloc failed.\n"); - return CKR_HOST_MEMORY; - } - - rc = token_specific_aes_cbc(tokdata, message, message_len, out_buf, - &out_len, key, mac, 1); - - if (rc == CKR_OK && out_len >= AES_BLOCK_SIZE) - memcpy(mac, out_buf + out_len - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + return openssl_specific_aes_mac(tokdata, message, message_len, key, mac); +} - free(out_buf); +CK_RV token_specific_aes_cmac(STDLL_TokData_t *tokdata, CK_BYTE *message, + CK_ULONG message_len, OBJECT *key, CK_BYTE *mac, + CK_BBOOL first, CK_BBOOL last, CK_VOID_PTR *ctx) +{ - return rc; + return openssl_specific_aes_cmac(tokdata, message, message_len, key, mac, + first, last, ctx); } + #endif /* Begin code contributed by Corrent corp. */ @@ -2716,181 +739,6 @@ TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl) { -#if OPENSSL_VERSION_NUMBER < 0x10100000L - CK_RV rv; - CK_BBOOL rc; - CK_ATTRIBUTE *prime_attr = NULL; - CK_ATTRIBUTE *base_attr = NULL; - CK_ATTRIBUTE *temp_attr = NULL; - CK_ATTRIBUTE *value_bits_attr = NULL; - CK_BYTE *temp_byte; - CK_ULONG temp_bn_len; - DH *dh; - BIGNUM *bn_p; - BIGNUM *bn_g; - const BIGNUM *temp_bn; - - UNUSED(tokdata); - - rv = template_attribute_get_non_empty(publ_tmpl, CKA_PRIME, &prime_attr); - if (rv != CKR_OK) { - TRACE_ERROR("Could not find CKA_PRIME for the key.\n"); - return rv; - } - rv = template_attribute_get_non_empty(publ_tmpl, CKA_BASE, &base_attr); - if (rv != CKR_OK) { - TRACE_ERROR("Could not find CKA_BASE for the key.\n"); - return rv; - } - - if ((prime_attr->ulValueLen > 256) || (prime_attr->ulValueLen < 64)) { - TRACE_ERROR("CKA_PRIME attribute value is invalid.\n"); - return CKR_ATTRIBUTE_VALUE_INVALID; - } - - dh = DH_new(); - if (dh == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - return CKR_FUNCTION_FAILED; - } - // Create and init BIGNUM structs to stick in the DH struct - bn_p = BN_new(); - bn_g = BN_new(); - if (bn_g == NULL || bn_p == NULL) { - if (bn_g) - BN_free(bn_g); - if (bn_p) - BN_free(bn_p); - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - return CKR_HOST_MEMORY; - } - // Convert from strings to BIGNUMs and stick them in the DH struct - BN_bin2bn((unsigned char *) prime_attr->pValue, prime_attr->ulValueLen, - bn_p); - BN_bin2bn((unsigned char *) base_attr->pValue, base_attr->ulValueLen, bn_g); - dh->p = bn_p; - dh->g = bn_g; - - // Generate the DH Key - if (!DH_generate_key(dh)) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - DH_free(dh); - return CKR_FUNCTION_FAILED; - } - // Extract the public and private key components from the DH struct, - // and insert them in the publ_tmpl and priv_tmpl - - // - // pub_key - // - //temp_bn = BN_new(); - temp_bn = dh->pub_key; - temp_bn_len = BN_num_bytes(temp_bn); - temp_byte = malloc(temp_bn_len); - temp_bn_len = BN_bn2bin(temp_bn, temp_byte); - // in bytes - rc = build_attribute(CKA_VALUE, temp_byte, temp_bn_len, &temp_attr); - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute failed\n"); - DH_free(dh); - free(temp_byte); - return CKR_FUNCTION_FAILED; - } - rc = template_update_attribute(publ_tmpl, temp_attr); - if (rc != CKR_OK) { - TRACE_ERROR("template_update_attribute failed\n"); - free(temp_attr); - DH_free(dh); - free(temp_byte); - return rc; - } - free(temp_byte); - - // - // priv_key - // - //temp_bn = BN_new(); - temp_bn = dh->priv_key; - temp_bn_len = BN_num_bytes(temp_bn); - temp_byte = malloc(temp_bn_len); - temp_bn_len = BN_bn2bin(temp_bn, temp_byte); - // in bytes - rc = build_attribute(CKA_VALUE, temp_byte, temp_bn_len, &temp_attr); - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute failed\n"); - DH_free(dh); - free(temp_byte); - return CKR_FUNCTION_FAILED; - } - rc = template_update_attribute(priv_tmpl, temp_attr); - if (rc != CKR_OK) { - TRACE_ERROR("template_update_attribute failed\n"); - free(temp_attr); - DH_free(dh); - free(temp_byte); - return rc; - } - free(temp_byte); - - // Update CKA_VALUE_BITS attribute in the private key - value_bits_attr = - (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG)); - if (value_bits_attr == NULL) { - TRACE_ERROR("malloc failed\n"); - DH_free(dh); - return CKR_HOST_MEMORY; - } - value_bits_attr->type = CKA_VALUE_BITS; - value_bits_attr->ulValueLen = sizeof(CK_ULONG); - value_bits_attr->pValue = - (CK_BYTE *) value_bits_attr + sizeof(CK_ATTRIBUTE); - *(CK_ULONG *) value_bits_attr->pValue = 8 * temp_bn_len; - rc = template_update_attribute(priv_tmpl, value_bits_attr); - if (rc != CKR_OK) { - TRACE_ERROR("template_update_attribute failed\n"); - free(value_bits_attr); - DH_free(dh); - return rc; - } - - // Add prime and base to the private key template - rc = build_attribute(CKA_PRIME, - (unsigned char *) prime_attr->pValue, - prime_attr->ulValueLen, &temp_attr); // in bytes - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute failed\n"); - DH_free(dh); - return CKR_FUNCTION_FAILED; - } - rc = template_update_attribute(priv_tmpl, temp_attr); - if (rc != CKR_OK) { - TRACE_ERROR("template_update_attribute failed\n"); - free(temp_attr); - DH_free(dh); - return rc; - } - - rc = build_attribute(CKA_BASE, - (unsigned char *) base_attr->pValue, - base_attr->ulValueLen, &temp_attr); // in bytes - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute failed\n"); - DH_free(dh); - return CKR_FUNCTION_FAILED; - } - rc = template_update_attribute(priv_tmpl, temp_attr); - if (rc != CKR_OK) { - TRACE_ERROR("template_update_attribute failed\n"); - free(temp_attr); - DH_free(dh); - return rc; - } - - // Cleanup DH key - DH_free(dh); - - return CKR_OK; -#else CK_RV rv; CK_BBOOL rc; CK_ATTRIBUTE *prime_attr = NULL; @@ -2899,10 +747,20 @@ CK_ATTRIBUTE *value_bits_attr = NULL; CK_BYTE *temp_byte = NULL, *temp_byte2 = NULL; CK_ULONG temp_bn_len; +#if !OPENSSL_VERSION_PREREQ(3, 0) DH *dh = NULL; +#else + EVP_PKEY_CTX *pctx = NULL; + OSSL_PARAM_BLD *tmpl = NULL; + OSSL_PARAM *osparams = NULL; +#endif BIGNUM *bn_p = NULL; BIGNUM *bn_g = NULL; +#if !OPENSSL_VERSION_PREREQ(3, 0) const BIGNUM *temp_bn = NULL; +#else + BIGNUM *temp_bn = NULL; +#endif EVP_PKEY *params = NULL, *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; @@ -2925,13 +783,7 @@ goto done; } - dh = DH_new(); - if (dh == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - rv = CKR_FUNCTION_FAILED; - goto done; - } - // Create and init BIGNUM structs to stick in the DH struct + // Create and init BIGNUM structs bn_p = BN_new(); bn_g = BN_new(); if (bn_g == NULL || bn_p == NULL) { @@ -2939,10 +791,18 @@ rv = CKR_HOST_MEMORY; goto done; } - // Convert from strings to BIGNUMs and stick them in the DH struct + // Convert from strings to BIGNUMs BN_bin2bn((unsigned char *) prime_attr->pValue, prime_attr->ulValueLen, bn_p); BN_bin2bn((unsigned char *) base_attr->pValue, base_attr->ulValueLen, bn_g); +#if !OPENSSL_VERSION_PREREQ(3, 0) + dh = DH_new(); + if (dh == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rv = CKR_FUNCTION_FAILED; + goto done; + } + DH_set0_pqg(dh, bn_p, NULL, bn_g); /* bn_p and bn_q freed together with dh */ bn_p = NULL; @@ -2961,6 +821,27 @@ goto done; } dh = NULL; /* freed together with params */ +#else + tmpl = OSSL_PARAM_BLD_new(); + if (tmpl == NULL) + goto done; + + if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P, bn_p) || + !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_G, bn_g)) + goto done; + + osparams = OSSL_PARAM_BLD_to_param(tmpl); + if (osparams == NULL) + goto done; + + pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DH, NULL); + if (pctx == NULL) + goto done; + + if (!EVP_PKEY_fromdata_init(pctx) || + !EVP_PKEY_fromdata(pctx, ¶ms, EVP_PKEY_PUBLIC_KEY, osparams)) + goto done; +#endif ctx = EVP_PKEY_CTX_new(params, NULL); if (ctx == NULL) { @@ -2971,8 +852,12 @@ if (EVP_PKEY_keygen_init(ctx) != 1 || EVP_PKEY_keygen(ctx, &pkey) != 1 +#if !OPENSSL_VERSION_PREREQ(3, 0) /* dh is freed together with pkey */ - || (dh = EVP_PKEY_get0_DH(pkey)) == NULL) { + || (dh = (DH *)EVP_PKEY_get0_DH(pkey)) == NULL) { +#else + ) { +#endif TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); rv = CKR_FUNCTION_FAILED; goto done; @@ -2984,7 +869,15 @@ // // pub_key // +#if !OPENSSL_VERSION_PREREQ(3, 0) DH_get0_key(dh, &temp_bn, NULL); +#else + if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PUB_KEY, &temp_bn)) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rc = CKR_FUNCTION_FAILED; + goto done; + } +#endif temp_bn_len = BN_num_bytes(temp_bn); temp_byte = malloc(temp_bn_len); @@ -3001,11 +894,23 @@ free(temp_attr); goto done; } +#if OPENSSL_VERSION_PREREQ(3, 0) + BN_free(temp_bn); + temp_bn = NULL; +#endif // // priv_key // +#if !OPENSSL_VERSION_PREREQ(3, 0) DH_get0_key(dh, NULL, &temp_bn); +#else + if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY, &temp_bn)) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rc = CKR_FUNCTION_FAILED; + goto done; + } +#endif temp_bn_len = BN_num_bytes(temp_bn); temp_byte2 = malloc(temp_bn_len); temp_bn_len = BN_bn2bin(temp_bn, temp_byte2); @@ -3022,6 +927,10 @@ free(temp_attr); goto done; } +#if OPENSSL_VERSION_PREREQ(3, 0) + BN_free(temp_bn); + temp_bn = NULL; +#endif // Update CKA_VALUE_BITS attribute in the private key value_bits_attr = @@ -3086,8 +995,17 @@ EVP_PKEY_free(params); free(temp_byte); free(temp_byte2); - return rv; +#if OPENSSL_VERSION_PREREQ(3, 0) + if (pctx != NULL) + EVP_PKEY_CTX_free(pctx); + if (tmpl != NULL) + OSSL_PARAM_BLD_free(tmpl); + if (osparams != NULL) + OSSL_PARAM_free(osparams); + if (temp_bn != NULL) + BN_free(temp_bn); #endif + return rv; } /* end token_specific_dh_key_pair_gen() */ #endif /* End code contributed by Corrent corp. */ @@ -3106,541 +1024,43 @@ return ock_generic_get_mechanism_info(tokdata, type, pInfo); } -#ifdef OLDER_OPENSSL -#define EVP_MD_meth_get_app_datasize(md) md->ctx_size -#define EVP_MD_CTX_md_data(ctx) ctx->md_data -#endif - -static const EVP_MD *md_from_mech(CK_MECHANISM *mech) -{ - const EVP_MD *md = NULL; - - switch (mech->mechanism) { - case CKM_SHA_1: - md = EVP_sha1(); - break; - case CKM_SHA224: - md = EVP_sha224(); - break; - case CKM_SHA256: - md = EVP_sha256(); - break; - case CKM_SHA384: - md = EVP_sha384(); - break; - case CKM_SHA512: - md = EVP_sha512(); - break; -#ifdef NID_sha512_224WithRSAEncryption - case CKM_SHA512_224: - md = EVP_sha512_224(); - break; -#endif -#ifdef NID_sha512_256WithRSAEncryption - case CKM_SHA512_256: - md = EVP_sha512_256(); - break; -#endif -#ifdef NID_sha3_224 - case CKM_IBM_SHA3_224: - md = EVP_sha3_224(); - break; -#endif -#ifdef NID_sha3_256 - case CKM_IBM_SHA3_256: - md = EVP_sha3_256(); - break; -#endif -#ifdef NID_sha3_384 - case CKM_IBM_SHA3_384: - md = EVP_sha3_384(); - break; -#endif -#ifdef NID_sha3_512 - case CKM_IBM_SHA3_512: - md = EVP_sha3_512(); - break; -#endif - default: - break; - } - - return md; -} - -static EVP_MD_CTX *md_ctx_from_context(DIGEST_CONTEXT *ctx) -{ - const EVP_MD *md; - EVP_MD_CTX *md_ctx; - -#if OPENSSL_VERSION_NUMBER < 0x10101000L - md_ctx = EVP_MD_CTX_create(); -#else - md_ctx = EVP_MD_CTX_new(); -#endif - if (md_ctx == NULL) - return NULL; - - md = md_from_mech(&ctx->mech); - if (md == NULL || - !EVP_DigestInit_ex(md_ctx, md, NULL)) { - TRACE_ERROR("md_from_mech or EVP_DigestInit_ex failed\n"); -#if OPENSSL_VERSION_NUMBER < 0x10101000L - EVP_MD_CTX_destroy(md_ctx); -#else - EVP_MD_CTX_free(md_ctx); -#endif - return NULL; - } - - if (ctx->context_len == 0) { - ctx->context_len = EVP_MD_meth_get_app_datasize(EVP_MD_CTX_md(md_ctx)); - ctx->context = malloc(ctx->context_len); - if (ctx->context == NULL) { - TRACE_ERROR("malloc failed\n"); - #if OPENSSL_VERSION_NUMBER < 0x10101000L - EVP_MD_CTX_destroy(md_ctx); - #else - EVP_MD_CTX_free(md_ctx); - #endif - ctx->context_len = 0; - return NULL; - } - - /* Save context data for later use */ - memcpy(ctx->context, EVP_MD_CTX_md_data(md_ctx), ctx->context_len); - } else { - if (ctx->context_len != - (CK_ULONG)EVP_MD_meth_get_app_datasize(EVP_MD_CTX_md(md_ctx))) { - TRACE_ERROR("context size mismatcht\n"); - return NULL; - } - /* restore the MD context data */ - memcpy(EVP_MD_CTX_md_data(md_ctx), ctx->context, ctx->context_len); - } - - return md_ctx; -} - CK_RV token_specific_sha_init(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx, CK_MECHANISM *mech) { - EVP_MD_CTX *md_ctx; - - UNUSED(tokdata); - - ctx->mech.ulParameterLen = mech->ulParameterLen; - ctx->mech.mechanism = mech->mechanism; - - md_ctx = md_ctx_from_context(ctx); - if (md_ctx == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - return CKR_HOST_MEMORY; - } - -#if OPENSSL_VERSION_NUMBER < 0x10101000L - EVP_MD_CTX_destroy(md_ctx); -#else - EVP_MD_CTX_free(md_ctx); -#endif - - return CKR_OK; + return openssl_specific_sha_init(tokdata, ctx, mech); } CK_RV token_specific_sha(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { - unsigned int len; - CK_RV rc = CKR_OK; - EVP_MD_CTX *md_ctx; - - UNUSED(tokdata); - - if (!ctx || !ctx->context) - return CKR_OPERATION_NOT_INITIALIZED; - - if (!in_data || !out_data) - return CKR_ARGUMENTS_BAD; - - /* Recreate the OpenSSL MD context from the saved context */ - md_ctx = md_ctx_from_context(ctx); - if (md_ctx == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - return CKR_HOST_MEMORY; - } - - if (*out_data_len < (CK_ULONG)EVP_MD_CTX_size(md_ctx)) - return CKR_BUFFER_TOO_SMALL; - - if (!EVP_DigestUpdate(md_ctx, in_data, in_data_len) || - !EVP_DigestFinal(md_ctx, out_data, &len)) { - rc = CKR_FUNCTION_FAILED; - goto out; - } - - *out_data_len = len; - -out: -#if OPENSSL_VERSION_NUMBER < 0x10101000L - EVP_MD_CTX_destroy(md_ctx); -#else - EVP_MD_CTX_free(md_ctx); -#endif - free(ctx->context); - ctx->context = NULL; - ctx->context_len = 0; - - return rc; + return openssl_specific_sha(tokdata, ctx, in_data, in_data_len, + out_data, out_data_len); } CK_RV token_specific_sha_update(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len) { - EVP_MD_CTX *md_ctx; - - UNUSED(tokdata); - - if (!ctx || !ctx->context) - return CKR_OPERATION_NOT_INITIALIZED; - - if (!in_data) - return CKR_ARGUMENTS_BAD; - - /* Recreate the OpenSSL MD context from the saved context */ - md_ctx = md_ctx_from_context(ctx); - if (md_ctx == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - return CKR_HOST_MEMORY; - } - - if (!EVP_DigestUpdate(md_ctx, in_data, in_data_len)) { -#if OPENSSL_VERSION_NUMBER < 0x10101000L - EVP_MD_CTX_destroy(md_ctx); -#else - EVP_MD_CTX_free(md_ctx); -#endif - free(ctx->context); - ctx->context = NULL; - ctx->context_len = 0; - return CKR_FUNCTION_FAILED; - } - - /* Save context data for later use */ - memcpy(ctx->context, EVP_MD_CTX_md_data(md_ctx), ctx->context_len); - -#if OPENSSL_VERSION_NUMBER < 0x10101000L - EVP_MD_CTX_destroy(md_ctx); -#else - EVP_MD_CTX_free(md_ctx); -#endif - - return CKR_OK; + return openssl_specific_sha_update(tokdata, ctx, in_data, in_data_len); } CK_RV token_specific_sha_final(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len) { - unsigned int len; - CK_RV rc = CKR_OK; - EVP_MD_CTX *md_ctx; - - UNUSED(tokdata); - - if (!ctx || !ctx->context) - return CKR_OPERATION_NOT_INITIALIZED; - - if (!out_data) - return CKR_ARGUMENTS_BAD; - - /* Recreate the OpenSSL MD context from the saved context */ - md_ctx = md_ctx_from_context(ctx); - if (md_ctx == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - return CKR_HOST_MEMORY; - } - - if (*out_data_len < (CK_ULONG)EVP_MD_CTX_size(md_ctx)) - return CKR_BUFFER_TOO_SMALL; - - if (!EVP_DigestFinal(md_ctx, out_data, &len)) { - rc = CKR_FUNCTION_FAILED; - goto out; - } - *out_data_len = len; - -out: -#if OPENSSL_VERSION_NUMBER < 0x10101000L - EVP_MD_CTX_destroy(md_ctx); -#else - EVP_MD_CTX_free(md_ctx); -#endif - free(ctx->context); - ctx->context = NULL; - ctx->context_len = 0; - - return rc; -} - -static CK_RV softtok_hmac_init(STDLL_TokData_t *tokdata, - SIGN_VERIFY_CONTEXT *ctx, CK_MECHANISM_PTR mech, - CK_OBJECT_HANDLE Hkey) -{ - int rc; - OBJECT *key = NULL; - CK_ATTRIBUTE *attr = NULL; - EVP_MD_CTX *mdctx = NULL; - EVP_PKEY *pkey = NULL; - - rc = object_mgr_find_in_map1(tokdata, Hkey, &key, READ_LOCK); - if (rc != CKR_OK) { - TRACE_ERROR("Failed to find specified object.\n"); - return rc; - } - - rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); - goto done; - } - - pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, attr->pValue, - attr->ulValueLen); - if (pkey == NULL) { - TRACE_ERROR("EVP_PKEY_new_mac_key() failed.\n"); - rc = CKR_FUNCTION_FAILED; - goto done; - } - - mdctx = EVP_MD_CTX_create(); - if (mdctx == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - - switch (mech->mechanism) { - case CKM_SHA_1_HMAC_GENERAL: - case CKM_SHA_1_HMAC: - rc = EVP_DigestSignInit(mdctx, NULL, EVP_sha1(), NULL, pkey); - break; - case CKM_SHA224_HMAC_GENERAL: - case CKM_SHA224_HMAC: - rc = EVP_DigestSignInit(mdctx, NULL, EVP_sha224(), NULL, pkey); - break; - case CKM_SHA256_HMAC_GENERAL: - case CKM_SHA256_HMAC: - rc = EVP_DigestSignInit(mdctx, NULL, EVP_sha256(), NULL, pkey); - break; - case CKM_SHA384_HMAC_GENERAL: - case CKM_SHA384_HMAC: - rc = EVP_DigestSignInit(mdctx, NULL, EVP_sha384(), NULL, pkey); - break; - case CKM_SHA512_HMAC_GENERAL: - case CKM_SHA512_HMAC: - rc = EVP_DigestSignInit(mdctx, NULL, EVP_sha512(), NULL, pkey); - break; -#ifdef NID_sha512_224WithRSAEncryption - case CKM_SHA512_224_HMAC_GENERAL: - case CKM_SHA512_224_HMAC: - rc = EVP_DigestSignInit(mdctx, NULL, EVP_sha512_224(), NULL, pkey); - break; -#endif -#ifdef NID_sha512_256WithRSAEncryption - case CKM_SHA512_256_HMAC_GENERAL: - case CKM_SHA512_256_HMAC: - rc = EVP_DigestSignInit(mdctx, NULL, EVP_sha512_256(), NULL, pkey); - break; -#endif -#ifdef NID_sha3_224 - case CKM_IBM_SHA3_224_HMAC: - rc = EVP_DigestSignInit(mdctx, NULL, EVP_sha3_224(), NULL, pkey); - break; -#endif -#ifdef NID_sha3_256 - case CKM_IBM_SHA3_256_HMAC: - rc = EVP_DigestSignInit(mdctx, NULL, EVP_sha3_256(), NULL, pkey); - break; -#endif -#ifdef NID_sha3_384 - case CKM_IBM_SHA3_384_HMAC: - rc = EVP_DigestSignInit(mdctx, NULL, EVP_sha3_384(), NULL, pkey); - break; -#endif -#ifdef NID_sha3_512 - case CKM_IBM_SHA3_512_HMAC: - rc = EVP_DigestSignInit(mdctx, NULL, EVP_sha3_512(), NULL, pkey); - break; -#endif - default: - EVP_MD_CTX_destroy(mdctx); - TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); - rc = CKR_MECHANISM_INVALID; - goto done; - } - - if (rc != 1) { - EVP_MD_CTX_destroy(mdctx); - ctx->context = NULL; - TRACE_ERROR("EVP_DigestSignInit failed.\n"); - rc = CKR_FUNCTION_FAILED; - goto done; - } else { - ctx->context = (CK_BYTE *) mdctx; - } - - rc = CKR_OK; -done: - if (pkey != NULL) - EVP_PKEY_free(pkey); - - object_put(tokdata, key, TRUE); - key = NULL; - return rc; + return openssl_specific_sha_final(tokdata, ctx, out_data, out_data_len); } CK_RV token_specific_hmac_sign_init(STDLL_TokData_t *tokdata, SESSION *sess, CK_MECHANISM *mech, CK_OBJECT_HANDLE Hkey) { - return softtok_hmac_init(tokdata, &sess->sign_ctx, mech, Hkey); + return openssl_specific_hmac_init(tokdata, &sess->sign_ctx, mech, Hkey); } CK_RV token_specific_hmac_verify_init(STDLL_TokData_t *tokdata, SESSION *sess, CK_MECHANISM *mech, CK_OBJECT_HANDLE Hkey) { - return softtok_hmac_init(tokdata, &sess->verify_ctx, mech, Hkey); -} - -static CK_RV softtok_hmac(SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, - CK_ULONG in_data_len, CK_BYTE *signature, - CK_ULONG *sig_len, CK_BBOOL sign) -{ - int rc; - size_t mac_len, len; - unsigned char mac[MAX_SHA_HASH_SIZE]; - EVP_MD_CTX *mdctx = NULL; - CK_RV rv = CKR_OK; - CK_BBOOL general = FALSE; - - if (!ctx || !ctx->context) { - TRACE_ERROR("%s received bad argument(s)\n", __func__); - return CKR_FUNCTION_FAILED; - } - - if (sign && !sig_len) { - TRACE_ERROR("%s received bad argument(s)\n", __func__); - return CKR_FUNCTION_FAILED; - } - - switch (ctx->mech.mechanism) { - case CKM_SHA_1_HMAC_GENERAL: - general = TRUE; - /* fallthrough */ - case CKM_SHA_1_HMAC: - mac_len = SHA1_HASH_SIZE; - break; - case CKM_SHA224_HMAC_GENERAL: -#ifdef NID_sha512_224WithRSAEncryption - case CKM_SHA512_224_HMAC_GENERAL: -#endif - general = TRUE; - /* fallthrough */ - case CKM_SHA224_HMAC: -#ifdef NID_sha512_224WithRSAEncryption - case CKM_SHA512_224_HMAC: -#endif - mac_len = SHA224_HASH_SIZE; - break; - case CKM_SHA256_HMAC_GENERAL: -#ifdef NID_sha512_256WithRSAEncryption - case CKM_SHA512_256_HMAC_GENERAL: -#endif - general = TRUE; - /* fallthrough */ - case CKM_SHA256_HMAC: -#ifdef NID_sha512_256WithRSAEncryption - case CKM_SHA512_256_HMAC: -#endif - mac_len = SHA256_HASH_SIZE; - break; - case CKM_SHA384_HMAC_GENERAL: - general = TRUE; - /* fallthrough */ - case CKM_SHA384_HMAC: - mac_len = SHA384_HASH_SIZE; - break; - case CKM_SHA512_HMAC_GENERAL: - general = TRUE; - /* fallthrough */ - case CKM_SHA512_HMAC: - mac_len = SHA512_HASH_SIZE; - break; -#ifdef NID_sha3_224 - case CKM_IBM_SHA3_224_HMAC: - mac_len = SHA3_224_HASH_SIZE; - break; -#endif -#ifdef NID_sha3_256 - case CKM_IBM_SHA3_256_HMAC: - mac_len = SHA3_256_HASH_SIZE; - break; -#endif -#ifdef NID_sha3_384 - case CKM_IBM_SHA3_384_HMAC: - mac_len = SHA3_384_HASH_SIZE; - break; -#endif -#ifdef NID_sha3_512 - case CKM_IBM_SHA3_512_HMAC: - mac_len = SHA3_512_HASH_SIZE; - break; -#endif - default: - TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); - return CKR_MECHANISM_INVALID; - } - - mdctx = (EVP_MD_CTX *) ctx->context; - - rc = EVP_DigestSignUpdate(mdctx, in_data, in_data_len); - if (rc != 1) { - TRACE_ERROR("EVP_DigestSignUpdate failed.\n"); - rv = CKR_FUNCTION_FAILED; - goto done; - } - - rc = EVP_DigestSignFinal(mdctx, mac, &mac_len); - if (rc != 1) { - TRACE_ERROR("EVP_DigestSignFinal failed.\n"); - rv = CKR_FUNCTION_FAILED; - goto done; - } - - if (sign) { - if (general) - *sig_len = *(CK_ULONG *) ctx->mech.pParameter; - else - *sig_len = mac_len; - - memcpy(signature, mac, *sig_len); - - } else { - if (general) - len = *(CK_ULONG *) ctx->mech.pParameter; - else - len = mac_len; - - if (CRYPTO_memcmp(signature, mac, len) != 0) { - TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); - rv = CKR_SIGNATURE_INVALID; - } - } -done: - EVP_MD_CTX_destroy(mdctx); - ctx->context = NULL; - - return rv; + return openssl_specific_hmac_init(tokdata, &sess->verify_ctx, mech, Hkey); } CK_RV token_specific_hmac_sign(STDLL_TokData_t *tokdata, SESSION *sess, @@ -3649,8 +1069,8 @@ { UNUSED(tokdata); - return softtok_hmac(&sess->sign_ctx, in_data, in_data_len, signature, - sig_len, TRUE); + return openssl_specific_hmac(&sess->sign_ctx, in_data, in_data_len, + signature, sig_len, TRUE); } CK_RV token_specific_hmac_verify(STDLL_TokData_t *tokdata, SESSION *sess, @@ -3659,36 +1079,8 @@ { UNUSED(tokdata); - return softtok_hmac(&sess->verify_ctx, in_data, in_data_len, signature, - &sig_len, FALSE); -} - -static CK_RV softtok_hmac_update(SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, - CK_ULONG in_data_len, CK_BBOOL sign) -{ - int rc; - EVP_MD_CTX *mdctx = NULL; - CK_RV rv = CKR_OK; - - UNUSED(sign); - - if (!ctx || !ctx->context) - return CKR_OPERATION_NOT_INITIALIZED; - - mdctx = (EVP_MD_CTX *) ctx->context; - - rc = EVP_DigestSignUpdate(mdctx, in_data, in_data_len); - if (rc != 1) { - TRACE_ERROR("EVP_DigestSignUpdate failed.\n"); - rv = CKR_FUNCTION_FAILED; - } else { - ctx->context = (CK_BYTE *) mdctx; - return CKR_OK; - } - - EVP_MD_CTX_destroy(mdctx); - ctx->context = NULL; - return rv; + return openssl_specific_hmac(&sess->verify_ctx, in_data, in_data_len, + signature, &sig_len, FALSE); } CK_RV token_specific_hmac_sign_update(STDLL_TokData_t *tokdata, SESSION *sess, @@ -3696,7 +1088,8 @@ { UNUSED(tokdata); - return softtok_hmac_update(&sess->sign_ctx, in_data, in_data_len, TRUE); + return openssl_specific_hmac_update(&sess->sign_ctx, in_data, in_data_len, + TRUE); } CK_RV token_specific_hmac_verify_update(STDLL_TokData_t *tokdata, @@ -3705,125 +1098,8 @@ { UNUSED(tokdata); - return softtok_hmac_update(&sess->verify_ctx, in_data, in_data_len, FALSE); -} - -static CK_RV softtok_hmac_final(SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *signature, - CK_ULONG *sig_len, CK_BBOOL sign) -{ - int rc; - size_t mac_len, len; - unsigned char mac[MAX_SHA_HASH_SIZE]; - EVP_MD_CTX *mdctx = NULL; - CK_RV rv = CKR_OK; - CK_BBOOL general = FALSE; - - if (!ctx || !ctx->context) - return CKR_OPERATION_NOT_INITIALIZED; - - if (sign && !sig_len) { - TRACE_ERROR("%s received bad argument(s)\n", __func__); - return CKR_FUNCTION_FAILED; - } - - switch (ctx->mech.mechanism) { - case CKM_SHA_1_HMAC_GENERAL: - general = TRUE; - /* fallthrough */ - case CKM_SHA_1_HMAC: - mac_len = SHA1_HASH_SIZE; - break; - case CKM_SHA224_HMAC_GENERAL: - general = TRUE; - /* fallthrough */ - case CKM_SHA224_HMAC: - mac_len = SHA224_HASH_SIZE; - break; - case CKM_SHA256_HMAC_GENERAL: - general = TRUE; - /* fallthrough */ - case CKM_SHA256_HMAC: - mac_len = SHA256_HASH_SIZE; - break; - case CKM_SHA384_HMAC_GENERAL: - general = TRUE; - /* fallthrough */ - case CKM_SHA384_HMAC: - mac_len = SHA384_HASH_SIZE; - break; - case CKM_SHA512_HMAC_GENERAL: - general = TRUE; - /* fallthrough */ - case CKM_SHA512_HMAC: - mac_len = SHA512_HASH_SIZE; - break; -#ifdef NID_sha3_224 - case CKM_IBM_SHA3_224_HMAC: - mac_len = SHA3_224_HASH_SIZE; - break; -#endif -#ifdef NID_sha3_256 - case CKM_IBM_SHA3_256_HMAC: - mac_len = SHA3_256_HASH_SIZE; - break; -#endif -#ifdef NID_sha3_384 - case CKM_IBM_SHA3_384_HMAC: - mac_len = SHA3_384_HASH_SIZE; - break; -#endif -#ifdef NID_sha3_512 - case CKM_IBM_SHA3_512_HMAC: - mac_len = SHA3_512_HASH_SIZE; - break; -#endif - default: - TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); - return CKR_MECHANISM_INVALID; - } - - if (signature == NULL) { - if (sign) { - if (general) - *sig_len = *(CK_ULONG *) ctx->mech.pParameter; - else - *sig_len = (CK_ULONG) mac_len; - } - return CKR_OK; - } - - mdctx = (EVP_MD_CTX *) ctx->context; - - rc = EVP_DigestSignFinal(mdctx, mac, &mac_len); - if (rc != 1) { - TRACE_ERROR("EVP_DigestSignFinal failed.\n"); - rv = CKR_FUNCTION_FAILED; - goto done; - } - - if (sign) { - if (general) - *sig_len = *(CK_ULONG *) ctx->mech.pParameter; - else - *sig_len = mac_len; - - memcpy(signature, mac, *sig_len); - - } else { - if (general) - len = *(CK_ULONG *) ctx->mech.pParameter; - else - len = mac_len; - - if (CRYPTO_memcmp(signature, mac, len) != 0) { - TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); - rv = CKR_SIGNATURE_INVALID; - } - } -done: - EVP_MD_CTX_destroy(mdctx); - ctx->context = NULL; - return rv; + return openssl_specific_hmac_update(&sess->verify_ctx, in_data, in_data_len, + FALSE); } CK_RV token_specific_hmac_sign_final(STDLL_TokData_t *tokdata, SESSION *sess, @@ -3831,7 +1107,8 @@ { UNUSED(tokdata); - return softtok_hmac_final(&sess->sign_ctx, signature, sig_len, TRUE); + return openssl_specific_hmac_final(&sess->sign_ctx, signature, sig_len, + TRUE); } CK_RV token_specific_hmac_verify_final(STDLL_TokData_t *tokdata, @@ -3840,7 +1117,8 @@ { UNUSED(tokdata); - return softtok_hmac_final(&sess->verify_ctx, signature, &sig_len, FALSE); + return openssl_specific_hmac_final(&sess->verify_ctx, signature, &sig_len, + FALSE); } CK_RV token_specific_generic_secret_key_gen(STDLL_TokData_t *tokdata, @@ -3893,709 +1171,13 @@ return rc; } -CK_RV token_specific_tdes_cmac(STDLL_TokData_t *tokdata, CK_BYTE *message, - CK_ULONG message_len, OBJECT *key, CK_BYTE *mac, - CK_BBOOL first, CK_BBOOL last, CK_VOID_PTR *ctx) -{ -#if OPENSSL_VERSION_NUMBER < 0x10101000L - int rc; - CK_RV rv = CKR_OK; - CK_ATTRIBUTE *attr = NULL; - CK_KEY_TYPE keytype; - CMAC_CTX *cmac_ctx; - const EVP_CIPHER *cipher; - size_t maclen; - - UNUSED(tokdata); - - if (first) { - // get the key type - rc = template_attribute_get_ulong(key->template, CKA_KEY_TYPE, &keytype); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); - return CKR_FUNCTION_FAILED; - } - - // get the key value - rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); - return rc; - } - switch (keytype) { - case CKK_DES2: - cipher = EVP_des_ede_cbc(); - break; - case CKK_DES3: - cipher = EVP_des_ede3_cbc(); - break; - default: - TRACE_ERROR("Invalid key type: %lu\n", keytype); - return CKR_KEY_TYPE_INCONSISTENT; - } - if (cipher == NULL) { - TRACE_ERROR("Failed to allocate cipher\n"); - return CKR_HOST_MEMORY; - } - - cmac_ctx = CMAC_CTX_new(); - if (cmac_ctx == NULL) { - TRACE_ERROR("Failed to allocate CMAC context\n"); - return CKR_HOST_MEMORY; - } - - rc = CMAC_Init(cmac_ctx, attr->pValue, attr->ulValueLen, cipher, NULL); - if (rc != 1) { - TRACE_ERROR("CMAC_Init failed\n"); - CMAC_CTX_free(cmac_ctx); - return CKR_FUNCTION_FAILED; - } - - *ctx = cmac_ctx; - } - - cmac_ctx = (CMAC_CTX *)*ctx; - - rc = CMAC_Update(cmac_ctx, message, message_len); - if (rc != 1) { - TRACE_ERROR("CMAC_Update failed\n"); - rv = CKR_FUNCTION_FAILED; - } - - if (last) { - maclen = AES_BLOCK_SIZE; - rc = CMAC_Final(cmac_ctx, mac, &maclen); - if (rc != 1) { - TRACE_ERROR("CMAC_Final failed\n"); - rv = CKR_FUNCTION_FAILED; - } - } - - if (last || (first && rv != CKR_OK)) { - CMAC_CTX_free(cmac_ctx); - *ctx = NULL; - } - - return rv; -#else - int rc; - size_t maclen; - CK_RV rv = CKR_OK; - CK_ATTRIBUTE *attr = NULL; - CK_KEY_TYPE keytype; - const EVP_CIPHER *cipher; - struct cmac_ctx { - EVP_MD_CTX *mctx; - EVP_PKEY_CTX *pctx; - EVP_PKEY *pkey; - }; - struct cmac_ctx *cmac = NULL; - - UNUSED(tokdata); - - if (first) { - // get the key type - rv = template_attribute_get_ulong(key->template, CKA_KEY_TYPE, &keytype); - if (rv != CKR_OK) { - TRACE_ERROR("Could not find CKA_KEY_TYPE for the key\n"); - return rv; - } - - // get the key value - rv = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); - if (rv != CKR_OK) { - TRACE_ERROR("Could not find CKA_VALUE for the key\n"); - return rv; - } - - switch (keytype) { - case CKK_DES2: - cipher = EVP_des_ede_cbc(); - break; - case CKK_DES3: - cipher = EVP_des_ede3_cbc(); - break; - default: - TRACE_ERROR("Invalid key type: %lu\n", keytype); - rv = CKR_KEY_TYPE_INCONSISTENT; - goto err; - } - - cmac = calloc(1, sizeof(*cmac)); - if (cmac == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rv = ERR_HOST_MEMORY; - goto err; - } - - cmac->mctx = EVP_MD_CTX_new(); - if (cmac->mctx == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rv = ERR_HOST_MEMORY; - goto err; - } - - cmac->pkey = EVP_PKEY_new_CMAC_key(NULL, - attr->pValue, attr->ulValueLen, - cipher); - if (cmac->pkey == NULL) { - TRACE_ERROR("EVP_DigestSignInit failed\n"); - rv = CKR_FUNCTION_FAILED; - goto err; - } - - if (EVP_DigestSignInit(cmac->mctx, &cmac->pctx, - NULL, NULL, cmac->pkey) != 1) { - TRACE_ERROR("EVP_DigestSignInit failed\n"); - rv = CKR_FUNCTION_FAILED; - goto err; - } - - *ctx = cmac; - } - - cmac = (struct cmac_ctx *)*ctx; - if (cmac == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - rv = CKR_FUNCTION_FAILED; - goto err; - } - - rc = EVP_DigestSignUpdate(cmac->mctx, message, message_len); - if (rc != 1 || message_len > INT_MAX) { - TRACE_ERROR("EVP_DigestSignUpdate failed\n"); - rv = CKR_FUNCTION_FAILED; - goto err; - } - - if (last) { - maclen = AES_BLOCK_SIZE; - - rc = EVP_DigestSignFinal(cmac->mctx, mac, &maclen); - if (rc != 1) { - TRACE_ERROR("EVP_DigestSignFinal failed\n"); - rv = CKR_FUNCTION_FAILED; - goto err; - } - - EVP_MD_CTX_free(cmac->mctx); /* frees pctx */ - EVP_PKEY_free(cmac->pkey); - free(cmac); - *ctx = NULL; - } - - return CKR_OK; -err: - if (cmac != NULL) { - if (cmac->mctx != NULL) - EVP_MD_CTX_free(cmac->mctx); /* frees pctx */ - if (cmac->pkey != NULL) - EVP_PKEY_free(cmac->pkey); - free(cmac); - } - *ctx = NULL; - return rv; -#endif -} - - -CK_RV token_specific_aes_cmac(STDLL_TokData_t *tokdata, CK_BYTE *message, - CK_ULONG message_len, OBJECT *key, CK_BYTE *mac, - CK_BBOOL first, CK_BBOOL last, CK_VOID_PTR *ctx) -{ -#if OPENSSL_VERSION_NUMBER < 0x10101000L - int rc; - CK_RV rv = CKR_OK; - CK_ATTRIBUTE *attr = NULL; - CMAC_CTX *cmac_ctx; - const EVP_CIPHER *cipher; - size_t maclen; - - UNUSED(tokdata); - - if (first) { - rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); - return rc; - } - - switch (attr->ulValueLen * 8) { - case 128: - cipher = EVP_aes_128_cbc(); - break; - case 192: - cipher = EVP_aes_192_cbc(); - break; - case 256: - cipher = EVP_aes_256_cbc(); - break; - default: - TRACE_ERROR("Invalid key size: %lu\n", attr->ulValueLen); - return CKR_KEY_TYPE_INCONSISTENT; - } - if (cipher == NULL) { - TRACE_ERROR("Failed to allocate cipher\n"); - return CKR_HOST_MEMORY; - } - - cmac_ctx = CMAC_CTX_new(); - if (cmac_ctx == NULL) { - TRACE_ERROR("Failed to allocate CMAC context\n"); - return CKR_HOST_MEMORY; - } - - rc = CMAC_Init(cmac_ctx, attr->pValue, attr->ulValueLen, cipher, NULL); - if (rc != 1) { - TRACE_ERROR("CMAC_Init failed\n"); - CMAC_CTX_free(cmac_ctx); - return CKR_FUNCTION_FAILED; - } - - *ctx = cmac_ctx; - } - - cmac_ctx = (CMAC_CTX *)*ctx; - - rc = CMAC_Update(cmac_ctx, message, message_len); - if (rc != 1) { - TRACE_ERROR("CMAC_Update failed\n"); - rv = CKR_FUNCTION_FAILED; - } - - if (last) { - maclen = AES_BLOCK_SIZE; - rc = CMAC_Final(cmac_ctx, mac, &maclen); - if (rc != 1) { - TRACE_ERROR("CMAC_Final failed\n"); - rv = CKR_FUNCTION_FAILED; - } - } - - if (last || (first && rv != CKR_OK)) { - CMAC_CTX_free(cmac_ctx); - *ctx = NULL; - } - - return rv; -#else - int rc; - size_t maclen; - CK_RV rv = CKR_OK; - CK_ATTRIBUTE *attr = NULL; - const EVP_CIPHER *cipher; - struct cmac_ctx { - EVP_MD_CTX *mctx; - EVP_PKEY_CTX *pctx; - EVP_PKEY *pkey; - }; - struct cmac_ctx *cmac = NULL; - - UNUSED(tokdata); - - if (first) { - // get the key value - rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); - goto err; - } - - switch (attr->ulValueLen * 8) { - case 128: - cipher = EVP_aes_128_cbc(); - break; - case 192: - cipher = EVP_aes_192_cbc(); - break; - case 256: - cipher = EVP_aes_256_cbc(); - break; - default: - TRACE_ERROR("Invalid key size: %lu\n", attr->ulValueLen); - return CKR_KEY_TYPE_INCONSISTENT; - } - - cmac = calloc(1, sizeof(*cmac)); - if (cmac == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rv = ERR_HOST_MEMORY; - goto err; - } - - cmac->mctx = EVP_MD_CTX_new(); - if (cmac->mctx == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rv = ERR_HOST_MEMORY; - goto err; - } - - cmac->pkey = EVP_PKEY_new_CMAC_key(NULL, - attr->pValue, attr->ulValueLen, - cipher); - if (cmac->pkey == NULL) { - TRACE_ERROR("EVP_DigestSignInit failed\n"); - rv = CKR_FUNCTION_FAILED; - goto err; - } - - if (EVP_DigestSignInit(cmac->mctx, &cmac->pctx, - NULL, NULL, cmac->pkey) != 1) { - TRACE_ERROR("EVP_DigestSignInit failed\n"); - rv = CKR_FUNCTION_FAILED; - goto err; - } - - *ctx = cmac; - } - - cmac = (struct cmac_ctx *)*ctx; - if (cmac == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - rv = CKR_FUNCTION_FAILED; - goto err; - } - - rc = EVP_DigestSignUpdate(cmac->mctx, message, message_len); - if (rc != 1 || message_len > INT_MAX) { - TRACE_ERROR("EVP_DigestSignUpdate failed\n"); - rv = CKR_FUNCTION_FAILED; - goto err; - } - - if (last) { - maclen = AES_BLOCK_SIZE; - - rc = EVP_DigestSignFinal(cmac->mctx, mac, &maclen); - if (rc != 1) { - TRACE_ERROR("EVP_DigestSignFinal failed\n"); - rv = CKR_FUNCTION_FAILED; - goto err; - } - - EVP_MD_CTX_free(cmac->mctx); /* frees pctx */ - EVP_PKEY_free(cmac->pkey); - free(cmac); - *ctx = NULL; - } - - return CKR_OK; -err: - if (cmac != NULL) { - if (cmac->mctx != NULL) - EVP_MD_CTX_free(cmac->mctx); /* frees pctx */ - if (cmac->pkey != NULL) - EVP_PKEY_free(cmac->pkey); - free(cmac); - } - *ctx = NULL; - return rv; -#endif -} - #ifndef NO_EC -static CK_RV make_ec_key_from_params(const CK_BYTE *params, CK_ULONG params_len, - EC_KEY **key) -{ - const unsigned char *oid; - ASN1_OBJECT *obj = NULL; - EC_KEY *ec_key = NULL; - int nid; - CK_RV rc = CKR_OK; - - oid = params; - obj = d2i_ASN1_OBJECT(NULL, &oid, params_len); - if (obj == NULL) { - TRACE_ERROR("curve not supported by OpenSSL.\n"); - rc = CKR_CURVE_NOT_SUPPORTED; - goto out; - } - - nid = OBJ_obj2nid(obj); - if (nid == NID_undef) { - TRACE_ERROR("curve not supported by OpenSSL.\n"); - rc = CKR_CURVE_NOT_SUPPORTED; - goto out; - } - - ec_key = EC_KEY_new_by_curve_name(nid); - if (ec_key == NULL) { - TRACE_ERROR("curve not supported by OpenSSL.\n"); - rc = CKR_CURVE_NOT_SUPPORTED; - goto out; - } - -out: - if (obj != NULL) - ASN1_OBJECT_free(obj); - - if (rc != CKR_OK) { - if (ec_key != NULL) - EC_KEY_free(ec_key); - - return rc; - } - - *key = ec_key; - - return CKR_OK; -} - -static CK_RV fill_ec_key_from_pubkey(EC_KEY *ec_key, const CK_BYTE *data, - CK_ULONG data_len, CK_BBOOL allow_raw) -{ - CK_BYTE *ecpoint = NULL; - CK_ULONG ecpoint_len, privlen; - CK_BBOOL allocated = FALSE; - CK_RV rc; - - privlen = (EC_GROUP_order_bits(EC_KEY_get0_group(ec_key)) + 7) / 8; - - rc = ec_point_from_public_data(data, data_len, privlen, allow_raw, - &allocated, &ecpoint, &ecpoint_len); - if (rc != CKR_OK) { - TRACE_DEVEL("ec_point_from_public_data failed\n"); - goto out; - } - - if (!EC_KEY_oct2key(ec_key, ecpoint, ecpoint_len, NULL)) { - TRACE_ERROR("EC_KEY_oct2key failed\n"); - rc = CKR_FUNCTION_FAILED; - goto out; - } - -out: - if (allocated && ecpoint != NULL) - free(ecpoint); - - return rc; -} - -static CK_RV fill_ec_key_from_privkey(EC_KEY *ec_key, const CK_BYTE *data, - CK_ULONG data_len) -{ - EC_POINT *point = NULL; - CK_RV rc = CKR_OK; - - if (!EC_KEY_oct2priv(ec_key, data, data_len)) { - TRACE_ERROR("EC_KEY_oct2priv failed\n"); - rc = CKR_FUNCTION_FAILED; - goto out; - } - - point = EC_POINT_new(EC_KEY_get0_group(ec_key)); - if (point == NULL) { - TRACE_ERROR("EC_POINT_new failed\n"); - rc = CKR_FUNCTION_FAILED; - goto out; - } - - if (!EC_POINT_mul(EC_KEY_get0_group(ec_key), point, - EC_KEY_get0_private_key(ec_key), NULL, NULL, NULL)) { - TRACE_ERROR("EC_POINT_mul failed\n"); - rc = CKR_FUNCTION_FAILED; - goto out; - } - - if (!EC_KEY_set_public_key(ec_key, point)) { - TRACE_ERROR("EC_KEY_set_public_key failed\n"); - rc = CKR_FUNCTION_FAILED; - goto out; - } - -out: - if (point != NULL) - EC_POINT_free(point); - - return rc; -} - -static CK_RV make_ec_key_from_template(TEMPLATE *template, EC_KEY **key) -{ - CK_ATTRIBUTE *attr = NULL; - CK_OBJECT_CLASS keyclass; - EC_KEY *ec_key = NULL; - CK_RV rc; - - rc = template_attribute_get_ulong(template, CKA_CLASS, &keyclass); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_CLASS in the template\n"); - goto out; - } - - rc = template_attribute_get_non_empty(template, CKA_ECDSA_PARAMS, &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_ECDSA_PARAMS in the template\n"); - goto out; - } - - rc = make_ec_key_from_params(attr->pValue, attr->ulValueLen, &ec_key); - if (rc != CKR_OK) - goto out; - - switch (keyclass) { - case CKO_PUBLIC_KEY: - rc = template_attribute_get_non_empty(template, CKA_EC_POINT, &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_EC_POINT in the template\n"); - goto out; - } - - rc = fill_ec_key_from_pubkey(ec_key, attr->pValue, attr->ulValueLen, - FALSE); - if (rc != CKR_OK) { - TRACE_DEVEL("fill_ec_key_from_pubkey failed\n"); - goto out; - } - break; - - case CKO_PRIVATE_KEY: - rc = template_attribute_get_non_empty(template, CKA_VALUE, &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_VALUE in the template\n"); - goto out; - } - - rc = fill_ec_key_from_privkey(ec_key, attr->pValue, attr->ulValueLen); - if (rc != CKR_OK) { - TRACE_DEVEL("fill_ec_key_from_privkey failed\n"); - goto out; - } - break; - - default: - rc = CKR_KEY_FUNCTION_NOT_PERMITTED; - goto out; - } - - rc = CKR_OK; - -out: - if (rc != CKR_OK) { - if (ec_key != NULL) - EC_KEY_free(ec_key); - - return rc; - } - - *key = ec_key; - - return CKR_OK; -} - CK_RV token_specific_ec_generate_keypair(STDLL_TokData_t *tokdata, TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl) { - - CK_ATTRIBUTE *attr = NULL, *ec_point_attr, *value_attr, *parms_attr; - EC_KEY *ec_key = NULL; - BN_CTX *ctx = NULL; - CK_BYTE *ecpoint = NULL, *enc_ecpoint = NULL, *d = NULL; - CK_ULONG ecpoint_len, enc_ecpoint_len, d_len; - CK_RV rc; - - UNUSED(tokdata); - - rc = template_attribute_get_non_empty(publ_tmpl, CKA_ECDSA_PARAMS, &attr); - if (rc != CKR_OK) - goto out; - - rc = make_ec_key_from_params(attr->pValue, attr->ulValueLen, &ec_key); - if (rc != CKR_OK) - goto out; - - if (!EC_KEY_generate_key(ec_key)) { - TRACE_ERROR("Failed to generate an EC key.\n"); - rc = CKR_FUNCTION_FAILED; - goto out; - } - - ctx = BN_CTX_new(); - if (ctx == NULL) { - rc = CKR_HOST_MEMORY; - goto out; - } - - ecpoint_len = EC_KEY_key2buf(ec_key, POINT_CONVERSION_UNCOMPRESSED, - &ecpoint, ctx); - if (ecpoint_len == 0) { - TRACE_ERROR("Failed to get the EC Point compressed.\n"); - rc = CKR_FUNCTION_FAILED; - goto out; - } - - rc = ber_encode_OCTET_STRING(FALSE, &enc_ecpoint, &enc_ecpoint_len, - ecpoint, ecpoint_len); - if (rc != CKR_OK) { - TRACE_DEVEL("ber_encode_OCTET_STRING failed\n"); - goto out; - } - - rc = build_attribute(CKA_EC_POINT, enc_ecpoint, enc_ecpoint_len, - &ec_point_attr); - if (rc != CKR_OK) { - TRACE_ERROR("build_attribute for CKA_EC_POINT failed rc=0x%lx\n", rc); - goto out; - } - rc = template_update_attribute(publ_tmpl, ec_point_attr); - if (rc != CKR_OK) { - TRACE_ERROR("template_update_attribute failed\n"); - free(ec_point_attr); - goto out; - } - - d_len = EC_KEY_priv2buf(ec_key, &d); - if (d_len == 0) { - TRACE_ERROR("Failed to get the EC private key.\n"); - rc = CKR_FUNCTION_FAILED; - goto out; - } - - rc = build_attribute(CKA_VALUE, d, d_len, &value_attr); - if (rc != CKR_OK) { - TRACE_ERROR("build_attribute for CKA_VALUE failed, rc=0x%lx\n", rc); - goto out; - } - rc = template_update_attribute(priv_tmpl, value_attr); - if (rc != CKR_OK) { - TRACE_ERROR("template_update_attribute failed\n"); - free(value_attr); - goto out; - } - - - /* Add CKA_ECDSA_PARAMS to private template also */ - rc = build_attribute(CKA_ECDSA_PARAMS, attr->pValue, attr->ulValueLen, - &parms_attr); - if (rc != CKR_OK) { - TRACE_ERROR("build_attribute for CKA_ECDSA_PARAMS failed, rc=0x%lx\n", - rc); - goto out; - } - rc = template_update_attribute(priv_tmpl, parms_attr); - if (rc != CKR_OK) { - TRACE_ERROR("template_update_attribute failed\n"); - free(parms_attr); - goto out; - } - - rc = CKR_OK; - -out: - if (ctx) - BN_CTX_free(ctx); - if (ec_key != NULL) - EC_KEY_free(ec_key); - if (ecpoint != NULL) - OPENSSL_free(ecpoint); - if (enc_ecpoint != NULL) - free(enc_ecpoint); - if (d != NULL) - OPENSSL_free(d); - - return rc; + return openssl_specific_ec_generate_keypair(tokdata, publ_tmpl, priv_tmpl); } CK_RV token_specific_ec_sign(STDLL_TokData_t *tokdata, SESSION *sess, @@ -4603,50 +1185,8 @@ CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj) { - EC_KEY *ec_key; - ECDSA_SIG *sig; - const BIGNUM *r, *s; - CK_ULONG privlen, n; - CK_RV rc = CKR_OK; - - UNUSED(tokdata); - UNUSED(sess); - - *out_data_len = 0; - - rc = make_ec_key_from_template(key_obj->template, &ec_key); - if (rc != CKR_OK) - return rc; - - sig = ECDSA_do_sign(in_data, in_data_len, ec_key); - if (sig == NULL) { - TRACE_ERROR("ECDSA_do_sign failed\n"); - rc = CKR_FUNCTION_FAILED; - goto out; - } - - ECDSA_SIG_get0(sig, &r, &s); - - privlen = (EC_GROUP_order_bits(EC_KEY_get0_group(ec_key)) + 7) / 8; - - /* Insert leading 0x00's if r or s shorter than privlen */ - n = privlen - BN_num_bytes(r); - memset(out_data, 0x00, n); - BN_bn2bin(r, &out_data[n]); - - n = privlen - BN_num_bytes(s); - memset(out_data + privlen, 0x00, n); - BN_bn2bin(s, &out_data[privlen + n]); - - *out_data_len = 2 * privlen; - -out: - if (sig != NULL) - ECDSA_SIG_free(sig); - if (ec_key != NULL) - EC_KEY_free(ec_key); - - return rc; + return openssl_specific_ec_sign(tokdata, sess, in_data, in_data_len, + out_data, out_data_len, key_obj); } CK_RV token_specific_ec_verify(STDLL_TokData_t *tokdata, @@ -4656,67 +1196,8 @@ CK_BYTE *signature, CK_ULONG signature_len, OBJECT *key_obj) { - EC_KEY *ec_key; - CK_ULONG privlen; - ECDSA_SIG *sig = NULL; - BIGNUM *r = NULL, *s = NULL; - CK_RV rc = CKR_OK; - - UNUSED(tokdata); - UNUSED(sess); - - rc = make_ec_key_from_template(key_obj->template, &ec_key); - if (rc != CKR_OK) - return rc; - - privlen = (EC_GROUP_order_bits(EC_KEY_get0_group(ec_key)) + 7) / 8; - - if (signature_len < 2 * privlen) { - TRACE_ERROR("Signature is too short\n"); - rc = CKR_SIGNATURE_LEN_RANGE; - goto out; - } - - sig = ECDSA_SIG_new(); - if (sig == NULL) { - rc = CKR_HOST_MEMORY; - goto out; - } - - r = BN_bin2bn(signature, privlen, NULL); - s = BN_bin2bn(signature + privlen, privlen, NULL); - if (r == NULL || s == NULL) { - TRACE_ERROR("BN_bin2bn failed\n"); - rc = CKR_FUNCTION_FAILED; - goto out; - } - - if (!ECDSA_SIG_set0(sig, r, s)) { - TRACE_ERROR("ECDSA_SIG_set0 failed\n"); - rc = CKR_FUNCTION_FAILED; - goto out; - } - - rc = ECDSA_do_verify(in_data, in_data_len, sig, ec_key); - switch (rc) { - case 0: - rc = CKR_SIGNATURE_INVALID; - break; - case 1: - rc = CKR_OK; - break; - default: - rc = CKR_FUNCTION_FAILED; - break; - } - -out: - if (sig != NULL) - ECDSA_SIG_free(sig); - if (ec_key != NULL) - EC_KEY_free(ec_key); - - return rc; + return openssl_specific_ec_verify(tokdata, sess, in_data, in_data_len, + signature, signature_len, key_obj); } CK_RV token_specific_ecdh_pkcs_derive(STDLL_TokData_t *tokdata, @@ -4728,58 +1209,10 @@ CK_ULONG *secret_value_len, CK_BYTE *oid, CK_ULONG oid_length) { - EC_KEY *ec_pub = NULL, *ec_priv = NULL; - CK_ULONG privlen; - int secret_len; - CK_RV rc; - - UNUSED(tokdata); - - rc = make_ec_key_from_params(oid, oid_length, &ec_priv); - if (rc != CKR_OK) { - TRACE_DEVEL("make_ec_key_from_params failed\n"); - goto out; - } - - rc = fill_ec_key_from_privkey(ec_priv, priv_bytes, priv_length); - if (rc != CKR_OK) { - TRACE_DEVEL("fill_ec_key_from_privkey failed\n"); - goto out; - } - - rc = make_ec_key_from_params(oid, oid_length, &ec_pub); - if (rc != CKR_OK) { - TRACE_DEVEL("make_ec_key_from_params failed\n"); - goto out; - } - - rc = fill_ec_key_from_pubkey(ec_pub, pub_bytes, pub_length, TRUE); - if (rc != CKR_OK) { - TRACE_DEVEL("fill_ec_key_from_pubkey failed\n"); - goto out; - } - - privlen = (EC_GROUP_order_bits(EC_KEY_get0_group(ec_priv)) + 7) / 8; - - secret_len = ECDH_compute_key(secret_value, privlen, - EC_KEY_get0_public_key(ec_pub), ec_priv, - NULL); - if (secret_len <= 0) { - TRACE_DEVEL("ECDH_compute_key failed\n"); - rc = CKR_FUNCTION_FAILED; - *secret_value_len = 0; - goto out; - } - - *secret_value_len = secret_len; - -out: - if (ec_priv != NULL) - EC_KEY_free(ec_priv); - if (ec_pub != NULL) - EC_KEY_free(ec_pub); - - return rc; + return openssl_specific_ecdh_pkcs_derive(tokdata, priv_bytes, priv_length, + pub_bytes, pub_length, + secret_value, secret_value_len, + oid, oid_length); } #endif @@ -4789,7 +1222,7 @@ { CK_KEY_TYPE keytype; #ifndef NO_EC - EC_KEY *ec_key = NULL; + EVP_PKEY *ec_key = NULL; #endif CK_RV rc; @@ -4804,14 +1237,14 @@ #ifndef NO_EC case CKK_EC: /* Check if OpenSSL supports the curve */ - rc = make_ec_key_from_template(obj->template, &ec_key); + rc = openssl_make_ec_key_from_template(obj->template, &ec_key); if (ec_key != NULL) - EC_KEY_free(ec_key); + EVP_PKEY_free(ec_key); return rc; #endif default: - return CKR_OK;; + return CKR_OK; } } diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/soft_stdll/soft_stdll.mk opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/soft_stdll/soft_stdll.mk --- opencryptoki-3.16.0+dfsg/usr/lib/soft_stdll/soft_stdll.mk 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/soft_stdll/soft_stdll.mk 2022-02-02 15:05:41.000000000 +0100 @@ -7,7 +7,8 @@ -DNOMD2 -DNODSA -DNORIPE -fPIC -I${srcdir}/usr/lib/soft_stdll \ -DTOK_NEW_DATA_STORE=0x0003000c \ -I${srcdir}/usr/lib/common -I${srcdir}/usr/include \ - -DSTDLL_NAME=\"swtok\" + -DSTDLL_NAME=\"swtok\" -I${top_builddir}/usr/lib/api \ + -I${srcdir}/usr/lib/api opencryptoki_stdll_libpkcs11_sw_la_LDFLAGS = \ -shared -Wl,-z,defs,-Bsymbolic -lc -lpthread -lcrypto -lrt \ @@ -32,7 +33,10 @@ usr/lib/common/utility.c usr/lib/common/verify_mgr.c \ usr/lib/common/trace.c usr/lib/common/mech_list.c \ usr/lib/common/shared_memory.c usr/lib/common/profile_obj.c \ - usr/lib/soft_stdll/soft_specific.c usr/lib/common/attributes.c + usr/lib/soft_stdll/soft_specific.c usr/lib/common/attributes.c \ + usr/lib/common/dlist.c usr/lib/common/mech_openssl.c \ + usr/lib/common/utility_common.c usr/lib/common/ec_supported.c \ + usr/lib/api/policyhelper.c if ENABLE_LOCKS opencryptoki_stdll_libpkcs11_sw_la_SOURCES += \ diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/soft_stdll/tok_struct.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/soft_stdll/tok_struct.h --- opencryptoki-3.16.0+dfsg/usr/lib/soft_stdll/tok_struct.h 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/soft_stdll/tok_struct.h 2022-02-02 15:05:41.000000000 +0100 @@ -80,8 +80,8 @@ // Triple DES &token_specific_tdes_ecb, &token_specific_tdes_cbc, - NULL, // des3_ofb - NULL, // des3_cfb + &token_specific_tdes_ofb, + &token_specific_tdes_cfb, &token_specific_tdes_mac, &token_specific_tdes_cmac, // RSA @@ -141,24 +141,28 @@ &token_specific_aes_key_gen, &token_specific_aes_ecb, &token_specific_aes_cbc, + &token_specific_aes_ctr, + &token_specific_aes_gcm_init, + &token_specific_aes_gcm, + &token_specific_aes_gcm_update, + &token_specific_aes_gcm_final, + &token_specific_aes_ofb, + &token_specific_aes_cfb, + &token_specific_aes_mac, + &token_specific_aes_cmac, #else NULL, // aes_key_gen NULL, // aes_ecb NULL, // aes_cbc -#endif NULL, // aes_ctr NULL, // aes_gcm_init NULL, // aes_gcm NULL, // aes_gcm_update NULL, // aes_gcm_final - NULL, // aes_ofb - NULL, // aes_cfb -#ifndef NOAES - &token_specific_aes_mac, - &token_specific_aes_cmac, -#else NULL, // aes_mac NULL, // aes_cmac + NULL, // aes_ofb + NULL, // aes_cfb #endif // DSA NULL, // dsa_generate_keypair @@ -172,6 +176,7 @@ NULL, // reencrypt_single NULL, // set_attribute_values NULL, // set_attrs_for_new_object + NULL, // handle_event }; #endif diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/tpm_stdll/tok_struct.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/tpm_stdll/tok_struct.h --- opencryptoki-3.16.0+dfsg/usr/lib/tpm_stdll/tok_struct.h 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/tpm_stdll/tok_struct.h 2022-02-02 15:05:41.000000000 +0100 @@ -120,4 +120,5 @@ NULL, // reencrypt_single NULL, // set_attribute_values NULL, // set_attrs_for_new_object + NULL, // handle_event }; diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/tpm_stdll/tpm_openssl.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/tpm_stdll/tpm_openssl.c --- opencryptoki-3.16.0+dfsg/usr/lib/tpm_stdll/tpm_openssl.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/tpm_stdll/tpm_openssl.c 2022-02-02 15:05:41.000000000 +0100 @@ -39,50 +39,33 @@ #include "tpm_specific.h" -/* - * In order to make opencryptoki compatible with - * OpenSSL 1.1 API Changes and backward compatible - * we need to check for its version - */ -#if OPENSSL_VERSION_NUMBER < 0x10100000L -#define OLDER_OPENSSL +#if OPENSSL_VERSION_PREREQ(3, 0) +#include #endif #ifdef DEBUG void openssl_print_errors() { +#if !OPENSSL_VERSION_PREREQ(3, 0) ERR_load_ERR_strings(); +#endif ERR_load_crypto_strings(); ERR_print_errors_fp(stderr); } #endif -RSA *openssl_gen_key(STDLL_TokData_t *tokdata) +EVP_PKEY *openssl_gen_key(STDLL_TokData_t *tokdata) { - RSA *rsa = NULL; int rc = 0, counter = 0; char buf[32]; -#ifndef OLDER_OPENSSL EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; BIGNUM *bne = NULL; -#endif token_specific_rng(tokdata, (CK_BYTE *) buf, 32); RAND_seed(buf, 32); regen_rsa_key: -#ifdef OLDER_OPENSSL - rsa = RSA_generate_key(2048, 65537, NULL, NULL); - if (rsa == NULL) { - fprintf(stderr, "Error generating user's RSA key\n"); - ERR_load_crypto_strings(); - ERR_print_errors_fp(stderr); - goto err; - } - - rc = RSA_check_key(rsa); -#else bne = BN_new(); rc = BN_set_word(bne, 65537); if (!rc) { @@ -98,35 +81,36 @@ if (EVP_PKEY_keygen_init(ctx) <= 0 || EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 2048) <= 0 +#if !OPENSSL_VERSION_PREREQ(3, 0) || EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, bne) <= 0) { +#else + || EVP_PKEY_CTX_set1_rsa_keygen_pubexp(ctx, bne) <= 0) { +#endif fprintf(stderr, "Error generating user's RSA key\n"); ERR_load_crypto_strings(); ERR_print_errors_fp(stderr); goto err; } +#if !OPENSSL_VERSION_PREREQ(3, 0) bne = NULL; // will be freed as part of the context - if (EVP_PKEY_keygen(ctx, &pkey) <= 0 - || (rsa = EVP_PKEY_get1_RSA(pkey)) == NULL) { +#else + BN_free(bne); + bne = NULL; +#endif + if (EVP_PKEY_keygen(ctx, &pkey) <= 0) { fprintf(stderr, "Error generating user's RSA key\n"); ERR_load_crypto_strings(); ERR_print_errors_fp(stderr); goto err; } -#if OPENSSL_VERSION_NUMBER < 0x10101000L - rc = RSA_check_key(rsa); -#else EVP_PKEY_CTX_free(ctx); ctx = EVP_PKEY_CTX_new(pkey, NULL); if (ctx == NULL) goto err; rc = (EVP_PKEY_check(ctx) == 1 ? 1 : 0); -#endif -#endif switch (rc) { case 0: /* rsa is not a valid RSA key */ - RSA_free(rsa); - rsa = NULL; counter++; if (counter == KEYGEN_RETRY) { TRACE_DEVEL("Tried %d times to generate a " @@ -145,30 +129,23 @@ break; } -#ifndef OLDER_OPENSSL - if (pkey != NULL) - EVP_PKEY_free(pkey); if (ctx != NULL) EVP_PKEY_CTX_free(ctx); if (bne != NULL) BN_free(bne); -#endif - return rsa; + return pkey; err: - if (rsa != NULL) - RSA_free(rsa); -#ifndef OLDER_OPENSSL if (pkey != NULL) EVP_PKEY_free(pkey); if (ctx != NULL) EVP_PKEY_CTX_free(ctx); if (bne != NULL) BN_free(bne); -#endif + return NULL; } -int openssl_write_key(STDLL_TokData_t * tokdata, RSA * rsa, char *filename, +int openssl_write_key(STDLL_TokData_t * tokdata, EVP_PKEY *pkey, char *filename, CK_BYTE * pPin) { BIO *b = NULL; @@ -193,8 +170,8 @@ return -1; } - if (!PEM_write_bio_RSAPrivateKey(b, rsa, - EVP_aes_256_cbc(), NULL, 0, 0, pPin)) { + if (!PEM_write_bio_PrivateKey(b, pkey, + EVP_aes_256_cbc(), NULL, 0, 0, pPin)) { BIO_free(b); TRACE_ERROR("Writing key %s to disk failed.\n", loc); DEBUG_openssl_print_errors(); @@ -211,10 +188,10 @@ } CK_RV openssl_read_key(STDLL_TokData_t * tokdata, char *filename, - CK_BYTE * pPin, RSA ** ret) + CK_BYTE * pPin, EVP_PKEY **ret) { BIO *b = NULL; - RSA *rsa = NULL; + EVP_PKEY *pkey = NULL; char loc[PATH_MAX]; struct passwd *pw = NULL; CK_RV rc = CKR_FUNCTION_FAILED; @@ -242,7 +219,7 @@ return CKR_FILE_NOT_FOUND; } - if ((rsa = PEM_read_bio_RSAPrivateKey(b, NULL, 0, pPin)) == NULL) { + if ((pkey = PEM_read_bio_PrivateKey(b, NULL, 0, pPin)) == NULL) { TRACE_ERROR("Reading key %s from disk failed.\n", loc); DEBUG_openssl_print_errors(); if (ERR_GET_REASON(ERR_get_error()) == PEM_R_BAD_DECRYPT) { @@ -253,40 +230,54 @@ } BIO_free(b); - *ret = rsa; + *ret = pkey; return CKR_OK; } -int openssl_get_modulus_and_prime(RSA * rsa, unsigned int *size_n, +int openssl_get_modulus_and_prime(EVP_PKEY *pkey, unsigned int *size_n, unsigned char *n, unsigned int *size_p, unsigned char *p) { -#ifndef OLDER_OPENSSL +#if !OPENSSL_VERSION_PREREQ(3, 0) const BIGNUM *n_tmp, *p_tmp; + RSA *rsa; +#else + BIGNUM *n_tmp, *p_tmp; #endif +#if !OPENSSL_VERSION_PREREQ(3, 0) + rsa = EVP_PKEY_get0_RSA(pkey); /* get the modulus from the RSA object */ -#ifdef OLDER_OPENSSL - if ((*size_n = BN_bn2bin(rsa->n, n)) <= 0) { -#else RSA_get0_key(rsa, &n_tmp, NULL, NULL); if ((*size_n = BN_bn2bin(n_tmp, n)) <= 0) { -#endif DEBUG_openssl_print_errors(); return -1; } /* get one of the primes from the RSA object */ -#ifdef OLDER_OPENSSL - if ((*size_p = BN_bn2bin(rsa->p, p)) <= 0) { -#else RSA_get0_factors(rsa, &p_tmp, NULL); if ((*size_p = BN_bn2bin(p_tmp, p)) <= 0) { -#endif DEBUG_openssl_print_errors(); return -1; } +#else + if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, &n_tmp) || + (*size_n = BN_bn2bin(n_tmp, n)) <= 0) { + DEBUG_openssl_print_errors(); + BN_free(n_tmp); + return -1; + } + BN_free(n_tmp); + + if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_FACTOR1, &p_tmp) || + (*size_p = BN_bn2bin(p_tmp, p)) <= 0) { + DEBUG_openssl_print_errors(); + BN_free(p_tmp); + return -1; + } + BN_free(p_tmp); +#endif return 0; } diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/tpm_stdll/tpm_specific.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/tpm_stdll/tpm_specific.c --- opencryptoki-3.16.0+dfsg/usr/lib/tpm_stdll/tpm_specific.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/tpm_stdll/tpm_specific.c 2022-02-02 15:05:41.000000000 +0100 @@ -213,6 +213,10 @@ } tpm_data = (tpm_private_data_t *)calloc(1, sizeof(tpm_private_data_t)); + if (tpm_data == NULL) { + TRACE_ERROR("calloc failed\n"); + return CKR_HOST_MEMORY; + } tokdata->private_data = tpm_data; tpm_data->tspContext = NULL_HCONTEXT; @@ -221,12 +225,15 @@ result = Tspi_Context_Create(&tpm_data->tspContext); if (result) { TRACE_ERROR("Tspi_Context_Create failed. rc=0x%x\n", result); + free(tpm_data); return CKR_FUNCTION_FAILED; } result = Tspi_Context_Connect(tpm_data->tspContext, NULL); if (result) { TRACE_ERROR("Tspi_Context_Connect failed. rc=0x%x\n", result); + Tspi_Context_Close(tpm_data->tspContext); + free(tpm_data); return CKR_FUNCTION_FAILED; } @@ -234,6 +241,8 @@ &tpm_data->hDefaultPolicy); if (result) { TRACE_ERROR("Tspi_Context_GetDefaultPolicy failed. rc=0x%x\n", result); + Tspi_Context_Close(tpm_data->tspContext); + free(tpm_data); return CKR_FUNCTION_FAILED; } @@ -1451,15 +1460,15 @@ tpm_private_data_t *tpm_data = (tpm_private_data_t *)tokdata->private_data; CK_RV rc; TSS_RESULT result; - RSA *rsa; + EVP_PKEY *pkey; unsigned int size_n, size_p; unsigned char n[256], p[256]; /* all sw generated keys are 2048 bits */ - if ((rsa = openssl_gen_key(tokdata)) == NULL) + if ((pkey = openssl_gen_key(tokdata)) == NULL) return CKR_HOST_MEMORY; - if (openssl_get_modulus_and_prime(rsa, &size_n, n, &size_p, p) != 0) { + if (openssl_get_modulus_and_prime(pkey, &size_n, n, &size_p, p) != 0) { TRACE_DEVEL("openssl_get_modulus_and_prime failed\n"); return CKR_FUNCTION_FAILED; } @@ -1473,13 +1482,13 @@ return rc; } - if (openssl_write_key(tokdata, rsa, TPMTOK_PRIV_ROOT_KEY_FILE, pPin)) { + if (openssl_write_key(tokdata, pkey, TPMTOK_PRIV_ROOT_KEY_FILE, pPin)) { TRACE_DEVEL("openssl_write_key failed.\n"); - RSA_free(rsa); + EVP_PKEY_free(pkey); return CKR_FUNCTION_FAILED; } - RSA_free(rsa); + EVP_PKEY_free(pkey); /* store the user base key in a PKCS#11 object internally */ rc = token_store_tss_key(tokdata, tpm_data->hPrivateRootKey, @@ -1529,15 +1538,15 @@ tpm_private_data_t *tpm_data = (tpm_private_data_t *)tokdata->private_data; CK_RV rc; TSS_RESULT result; - RSA *rsa; + EVP_PKEY *pkey; unsigned int size_n, size_p; unsigned char n[256], p[256]; /* all sw generated keys are 2048 bits */ - if ((rsa = openssl_gen_key(tokdata)) == NULL) + if ((pkey = openssl_gen_key(tokdata)) == NULL) return CKR_HOST_MEMORY; - if (openssl_get_modulus_and_prime(rsa, &size_n, n, &size_p, p) != 0) { + if (openssl_get_modulus_and_prime(pkey, &size_n, n, &size_p, p) != 0) { TRACE_DEVEL("openssl_get_modulus_and_prime failed\n"); return CKR_FUNCTION_FAILED; } @@ -1551,13 +1560,13 @@ return rc; } - if (openssl_write_key(tokdata, rsa, TPMTOK_PUB_ROOT_KEY_FILE, pPin)) { + if (openssl_write_key(tokdata, pkey, TPMTOK_PUB_ROOT_KEY_FILE, pPin)) { TRACE_DEVEL("openssl_write_key\n"); - RSA_free(rsa); + EVP_PKEY_free(pkey); return CKR_FUNCTION_FAILED; } - RSA_free(rsa); + EVP_PKEY_free(pkey); result = Tspi_Key_LoadKey(tpm_data->hPublicRootKey, tpm_data->hSRK); if (result) { @@ -1602,7 +1611,7 @@ CK_RV token_migrate(STDLL_TokData_t * tokdata, int key_type, CK_BYTE * pin) { tpm_private_data_t *tpm_data = (tpm_private_data_t *)tokdata->private_data; - RSA *rsa; + EVP_PKEY *pkey; char *backup_loc; unsigned int size_n, size_p; unsigned char n[256], p[256]; @@ -1630,7 +1639,7 @@ } /* read the backup key with the old pin */ - if ((rc = openssl_read_key(tokdata, backup_loc, pin, &rsa))) { + if ((rc = openssl_read_key(tokdata, backup_loc, pin, &pkey))) { if (rc == CKR_FILE_NOT_FOUND) rc = CKR_FUNCTION_FAILED; TRACE_DEVEL("openssl_read_key failed\n"); @@ -1640,8 +1649,9 @@ /* So, reading the backup openssl key off disk succeeded with the SOs PIN. * We will now try to re-wrap that key with the current SRK */ - if (openssl_get_modulus_and_prime(rsa, &size_n, n, &size_p, p) != 0) { + if (openssl_get_modulus_and_prime(pkey, &size_n, n, &size_p, p) != 0) { TRACE_DEVEL("openssl_get_modulus_and_prime failed\n"); + EVP_PKEY_free(pkey); return CKR_FUNCTION_FAILED; } @@ -1650,10 +1660,10 @@ phKey); if (rc != CKR_OK) { TRACE_DEVEL("token_wrap_sw_key failed. rc=0x%lx\n", rc); - RSA_free(rsa); + EVP_PKEY_free(pkey); return rc; } - RSA_free(rsa); + EVP_PKEY_free(pkey); result = Tspi_Key_LoadKey(*phKey, tpm_data->hSRK); if (result) { @@ -1998,7 +2008,7 @@ tpm_private_data_t *tpm_data = (tpm_private_data_t *)tokdata->private_data; CK_BYTE oldpin_hash[SHA1_HASH_SIZE], newpin_hash[SHA1_HASH_SIZE]; CK_RV rc; - RSA *rsa_root; + EVP_PKEY *pkey_root; TSS_RESULT result; if (!sess) { @@ -2094,7 +2104,7 @@ /* read the backup key with the old pin */ rc = openssl_read_key(tokdata, TPMTOK_PRIV_ROOT_KEY_FILE, pOldPin, - &rsa_root); + &pkey_root); if (rc != CKR_OK) { if (rc == CKR_FILE_NOT_FOUND) { /* If the user has moved his backup PEM file off site, allow a @@ -2107,14 +2117,14 @@ } /* write it out using the new pin */ - rc = openssl_write_key(tokdata, rsa_root, TPMTOK_PRIV_ROOT_KEY_FILE, + rc = openssl_write_key(tokdata, pkey_root, TPMTOK_PRIV_ROOT_KEY_FILE, pNewPin); if (rc != CKR_OK) { - RSA_free(rsa_root); + EVP_PKEY_free(pkey_root); TRACE_DEVEL("openssl_write_key failed\n"); return CKR_FUNCTION_FAILED; } - RSA_free(rsa_root); + EVP_PKEY_free(pkey_root); } else if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) { if (tpm_data->not_initialized) { if (memcmp(default_so_pin_sha, oldpin_hash, SHA1_HASH_SIZE)) { @@ -2166,7 +2176,7 @@ /* change auth on the public root key's openssl backup */ rc = openssl_read_key(tokdata, TPMTOK_PUB_ROOT_KEY_FILE, pOldPin, - &rsa_root); + &pkey_root); if (rc != CKR_OK) { if (rc == CKR_FILE_NOT_FOUND) { /* If the user has moved his backup PEM file off site, allow a @@ -2179,14 +2189,14 @@ } /* write it out using the new pin */ - rc = openssl_write_key(tokdata, rsa_root, TPMTOK_PUB_ROOT_KEY_FILE, + rc = openssl_write_key(tokdata, pkey_root, TPMTOK_PUB_ROOT_KEY_FILE, pNewPin); if (rc != CKR_OK) { - RSA_free(rsa_root); + EVP_PKEY_free(pkey_root); TRACE_DEVEL("openssl_write_key failed\n"); return CKR_FUNCTION_FAILED; } - RSA_free(rsa_root); + EVP_PKEY_free(pkey_root); } else { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_READ_ONLY)); rc = CKR_SESSION_READ_ONLY; @@ -2394,504 +2404,50 @@ return CKR_OK; } -CK_RV token_specific_des_ecb(STDLL_TokData_t * tokdata, - CK_BYTE * in_data, +CK_RV token_specific_des_ecb(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, CK_ULONG in_data_len, - CK_BYTE * out_data, - CK_ULONG * out_data_len, - OBJECT * key, CK_BYTE encrypt) + CK_BYTE *out_data, + CK_ULONG *out_data_len, + OBJECT *key, CK_BYTE encrypt) { -#if OPENSSL_VERSION_NUMBER < 0x10100000L - CK_RV rc; - CK_ATTRIBUTE *attr = NULL; - - DES_key_schedule des_key2; - const_DES_cblock key_val_SSL, in_key_data; - DES_cblock out_key_data; - unsigned int i, j; - - UNUSED(tokdata); - - // get the key value - rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); - return rc; - } - - // Create the key schedule - memcpy(&key_val_SSL, attr->pValue, 8); - DES_set_key_unchecked(&key_val_SSL, &des_key2); - - // the des decrypt will only fail if the data length is not evenly divisible - // by 8 - if (in_data_len % DES_BLOCK_SIZE) { - TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); - return CKR_DATA_LEN_RANGE; - } - // Both the encrypt and the decrypt are done 8 bytes at a time - if (encrypt) { - for (i = 0; i < in_data_len; i = i + 8) { - memcpy(in_key_data, in_data + i, 8); - DES_ecb_encrypt(&in_key_data, &out_key_data, &des_key2, - DES_ENCRYPT); - memcpy(out_data + i, out_key_data, 8); - } - - *out_data_len = in_data_len; - rc = CKR_OK; - } else { - - for (j = 0; j < in_data_len; j = j + 8) { - memcpy(in_key_data, in_data + j, 8); - DES_ecb_encrypt(&in_key_data, &out_key_data, &des_key2, - DES_DECRYPT); - memcpy(out_data + j, out_key_data, 8); - } - - *out_data_len = in_data_len; - rc = CKR_OK; - } - - return rc; -#else - const EVP_CIPHER *cipher = EVP_des_ecb(); - EVP_CIPHER_CTX *ctx = NULL; - CK_ATTRIBUTE *attr = NULL; - unsigned char dkey[8]; - CK_ULONG rc; - int outlen; - - UNUSED(tokdata); - - // get the key value - rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); - return rc; - } - - memcpy(dkey, attr->pValue, sizeof(dkey)); - - if (in_data_len % DES_BLOCK_SIZE || in_data_len > INT_MAX) { - TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); - return CKR_DATA_LEN_RANGE; - } - - ctx = EVP_CIPHER_CTX_new(); - if (ctx == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - - if (EVP_CipherInit_ex(ctx, cipher, - NULL, dkey, NULL, encrypt ? 1 : 0) != 1 - || EVP_CIPHER_CTX_set_padding(ctx, 0) != 1 - || EVP_CipherUpdate(ctx, out_data, &outlen, in_data, in_data_len) != 1 - || EVP_CipherFinal_ex(ctx, out_data, &outlen) != 1) { - TRACE_ERROR("%s\n", ock_err(ERR_GENERAL_ERROR)); - rc = CKR_GENERAL_ERROR; - goto done; - } - - *out_data_len = in_data_len; - rc = CKR_OK; -done: - OPENSSL_cleanse(dkey, sizeof(dkey)); - EVP_CIPHER_CTX_free(ctx); - return rc; -#endif + return openssl_specific_des_ecb(tokdata, in_data, in_data_len, + out_data, out_data_len, key, encrypt); } -CK_RV token_specific_des_cbc(STDLL_TokData_t * tokdata, - CK_BYTE * in_data, +CK_RV token_specific_des_cbc(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, CK_ULONG in_data_len, - CK_BYTE * out_data, - CK_ULONG * out_data_len, - OBJECT * key, CK_BYTE * init_v, CK_BYTE encrypt) + CK_BYTE *out_data, + CK_ULONG *out_data_len, + OBJECT *key, CK_BYTE *init_v, CK_BYTE encrypt) { -#if OPENSSL_VERSION_NUMBER < 0x10100000L - CK_RV rc; - CK_ATTRIBUTE *attr = NULL; - - DES_cblock ivec; - - DES_key_schedule des_key2; - const_DES_cblock key_val_SSL; - - UNUSED(tokdata); - - // get the key value - rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); - return rc; - } - - // Create the key schedule - memcpy(&key_val_SSL, attr->pValue, 8); - DES_set_key_unchecked(&key_val_SSL, &des_key2); - - memcpy(&ivec, init_v, 8); - // the des decrypt will only fail if the data length is not evenly divisible - // by 8 - if (in_data_len % DES_BLOCK_SIZE) { - TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); - return CKR_DATA_LEN_RANGE; - } - - - if (encrypt) { - DES_ncbc_encrypt(in_data, out_data, in_data_len, &des_key2, &ivec, - DES_ENCRYPT); - *out_data_len = in_data_len; - rc = CKR_OK; - } else { - DES_ncbc_encrypt(in_data, out_data, in_data_len, &des_key2, &ivec, - DES_DECRYPT); - *out_data_len = in_data_len; - rc = CKR_OK; - } - return rc; -#else - const EVP_CIPHER *cipher = EVP_des_cbc(); - EVP_CIPHER_CTX *ctx = NULL; - CK_ATTRIBUTE *attr = NULL; - unsigned char dkey[DES_KEY_SIZE]; - CK_ULONG rc; - int outlen; - - UNUSED(tokdata); - - // get the key value - rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); - return rc; - } - - if (in_data_len % DES_BLOCK_SIZE || in_data_len > INT_MAX) { - TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); - return CKR_DATA_LEN_RANGE; - } - - memcpy(dkey, attr->pValue, sizeof(dkey)); - - ctx = EVP_CIPHER_CTX_new(); - if (ctx == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - - if (EVP_CipherInit_ex(ctx, cipher, - NULL, dkey, init_v, encrypt ? 1 : 0) != 1 - || EVP_CIPHER_CTX_set_padding(ctx, 0) != 1 - || EVP_CipherUpdate(ctx, out_data, &outlen, in_data, in_data_len) != 1 - || EVP_CipherFinal_ex(ctx, out_data, &outlen) != 1) { - TRACE_ERROR("%s\n", ock_err(ERR_GENERAL_ERROR)); - rc = CKR_GENERAL_ERROR; - goto done; - } - - *out_data_len = in_data_len; - rc = CKR_OK; -done: - OPENSSL_cleanse(dkey, sizeof(dkey)); - EVP_CIPHER_CTX_free(ctx); - return rc; -#endif + return openssl_specific_des_cbc(tokdata, in_data, in_data_len, + out_data, out_data_len, key, + init_v, encrypt); } -CK_RV token_specific_tdes_ecb(STDLL_TokData_t * tokdata, - CK_BYTE * in_data, +CK_RV token_specific_tdes_ecb(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, CK_ULONG in_data_len, - CK_BYTE * out_data, - CK_ULONG * out_data_len, - OBJECT * key, CK_BYTE encrypt) + CK_BYTE *out_data, + CK_ULONG *out_data_len, + OBJECT *key, CK_BYTE encrypt) { -#if OPENSSL_VERSION_NUMBER < 0x10100000L - CK_RV rc; - CK_ATTRIBUTE *attr = NULL; - CK_KEY_TYPE keytype; - CK_BYTE key_value[3 * DES_KEY_SIZE]; - - unsigned int k, j; - DES_key_schedule des_key1; - DES_key_schedule des_key2; - DES_key_schedule des_key3; - - const_DES_cblock key_SSL1, key_SSL2, key_SSL3, in_key_data; - DES_cblock out_key_data; - - UNUSED(tokdata); - - // get the key type - rc = template_attribute_get_ulong(key->template, CKA_KEY_TYPE, &keytype); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_KEY_TYPE for the key\n"); - return rc; - } - - // get the key value - rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_VALUE for the key\n"); - return rc; - } - - if (keytype == CKK_DES2) { - memcpy(key_value, attr->pValue, 2 * DES_KEY_SIZE); - memcpy(key_value + (2 * DES_KEY_SIZE), attr->pValue, DES_KEY_SIZE); - } else { - memcpy(key_value, attr->pValue, 3 * DES_KEY_SIZE); - } - - // The key as passed is a 24 byte long string containing three des keys - // pick them apart and create the 3 corresponding key schedules - memcpy(&key_SSL1, key_value, 8); - memcpy(&key_SSL2, key_value + 8, 8); - memcpy(&key_SSL3, key_value + 16, 8); - DES_set_key_unchecked(&key_SSL1, &des_key1); - DES_set_key_unchecked(&key_SSL2, &des_key2); - DES_set_key_unchecked(&key_SSL3, &des_key3); - - // the des decrypt will only fail if the data length is not evenly divisible - // by 8 - if (in_data_len % DES_BLOCK_SIZE) { - TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); - return CKR_DATA_LEN_RANGE; - } - // the encrypt and decrypt are done 8 bytes at a time - if (encrypt) { - for (k = 0; k < in_data_len; k = k + 8) { - memcpy(in_key_data, in_data + k, 8); - DES_ecb3_encrypt((const_DES_cblock *) & in_key_data, - (DES_cblock *) & out_key_data, - &des_key1, &des_key2, &des_key3, DES_ENCRYPT); - memcpy(out_data + k, out_key_data, 8); - } - *out_data_len = in_data_len; - rc = CKR_OK; - } else { - for (j = 0; j < in_data_len; j = j + 8) { - memcpy(in_key_data, in_data + j, 8); - DES_ecb3_encrypt((const_DES_cblock *) & in_key_data, - (DES_cblock *) & out_key_data, - &des_key1, &des_key2, &des_key3, DES_DECRYPT); - memcpy(out_data + j, out_key_data, 8); - } - *out_data_len = in_data_len; - rc = CKR_OK; - } - - return rc; -#else - const EVP_CIPHER *cipher = EVP_des_ede3_ecb(); - EVP_CIPHER_CTX *ctx = NULL; - CK_ATTRIBUTE *attr = NULL; - unsigned char dkey[3 * DES_KEY_SIZE]; - CK_KEY_TYPE keytype; - CK_RV rc; - int outlen; - - UNUSED(tokdata); - - // get the key type - rc = template_attribute_get_ulong(key->template, CKA_KEY_TYPE, &keytype); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_KEY_TYPE for the key\n"); - return rc; - } - - // get the key value - rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_VALUE for the key\n"); - return rc; - } - - if (in_data_len % DES_BLOCK_SIZE || in_data_len > INT_MAX) { - TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); - return CKR_DATA_LEN_RANGE; - } - - if (keytype == CKK_DES2) { - memcpy(dkey, attr->pValue, 2 * DES_KEY_SIZE); - memcpy(dkey + (2 * DES_KEY_SIZE), attr->pValue, DES_KEY_SIZE); - } else { - memcpy(dkey, attr->pValue, 3 * DES_KEY_SIZE); - } - - ctx = EVP_CIPHER_CTX_new(); - if (ctx == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - - if (EVP_CipherInit_ex(ctx, cipher, - NULL, dkey, NULL, encrypt ? 1 : 0) != 1 - || EVP_CIPHER_CTX_set_padding(ctx, 0) != 1 - || EVP_CipherUpdate(ctx, out_data, &outlen, in_data, in_data_len) != 1 - || EVP_CipherFinal_ex(ctx, out_data, &outlen) != 1) { - TRACE_ERROR("%s\n", ock_err(ERR_GENERAL_ERROR)); - rc = CKR_GENERAL_ERROR; - goto done; - } - - *out_data_len = in_data_len; - rc = CKR_OK; -done: - OPENSSL_cleanse(dkey, sizeof(dkey)); - EVP_CIPHER_CTX_free(ctx); - return rc; -#endif + return openssl_specific_tdes_ecb(tokdata, in_data, in_data_len, + out_data, out_data_len, key, encrypt); } -CK_RV token_specific_tdes_cbc(STDLL_TokData_t * tokdata, - CK_BYTE * in_data, +CK_RV token_specific_tdes_cbc(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, CK_ULONG in_data_len, - CK_BYTE * out_data, - CK_ULONG * out_data_len, - OBJECT * key, CK_BYTE * init_v, CK_BYTE encrypt) -{ -#if OPENSSL_VERSION_NUMBER < 0x10100000L - CK_RV rc = CKR_OK; - CK_ATTRIBUTE *attr = NULL; - CK_KEY_TYPE keytype; - CK_BYTE key_value[3 * DES_KEY_SIZE]; - - DES_key_schedule des_key1; - DES_key_schedule des_key2; - DES_key_schedule des_key3; - - const_DES_cblock key_SSL1, key_SSL2, key_SSL3; - DES_cblock ivec; - - UNUSED(tokdata); - - // get the key type - rc = template_attribute_get_ulong(key->template, CKA_KEY_TYPE, &keytype); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_KEY_TYPE for the key\n"); - return rc; - } - - // get the key value - rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_VALUE for the key\n"); - return rc; - } - - if (keytype == CKK_DES2) { - memcpy(key_value, attr->pValue, 2 * DES_KEY_SIZE); - memcpy(key_value + (2 * DES_KEY_SIZE), attr->pValue, DES_KEY_SIZE); - } else { - memcpy(key_value, attr->pValue, 3 * DES_KEY_SIZE); - } - - // The key as passed in is a 24 byte string containing 3 keys - // pick it apart and create the key schedules - memcpy(&key_SSL1, key_value, 8); - memcpy(&key_SSL2, key_value + 8, 8); - memcpy(&key_SSL3, key_value + 16, 8); - DES_set_key_unchecked(&key_SSL1, &des_key1); - DES_set_key_unchecked(&key_SSL2, &des_key2); - DES_set_key_unchecked(&key_SSL3, &des_key3); - - memcpy(ivec, init_v, sizeof(ivec)); - - // the des decrypt will only fail if the data length is not evenly divisible - // by 8 - if (in_data_len % DES_BLOCK_SIZE) { - TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); - return CKR_DATA_LEN_RANGE; - } - // Encrypt or decrypt the data - if (encrypt) { - DES_ede3_cbc_encrypt(in_data, - out_data, - in_data_len, - &des_key1, - &des_key2, &des_key3, &ivec, DES_ENCRYPT); - *out_data_len = in_data_len; - rc = CKR_OK; - } else { - DES_ede3_cbc_encrypt(in_data, - out_data, - in_data_len, - &des_key1, - &des_key2, &des_key3, &ivec, DES_DECRYPT); - - *out_data_len = in_data_len; - rc = CKR_OK; - } - - return rc; -#else - const EVP_CIPHER *cipher = EVP_des_ede3_cbc(); - EVP_CIPHER_CTX *ctx = NULL; - CK_ATTRIBUTE *attr = NULL; - unsigned char dkey[3 * DES_KEY_SIZE]; - CK_KEY_TYPE keytype; - CK_RV rc; - int outlen; - - UNUSED(tokdata); - - // get the key type - rc = template_attribute_get_ulong(key->template, CKA_KEY_TYPE, &keytype); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_KEY_TYPE for the key\n"); - return rc; - } - - // get the key value - rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_VALUE for the key\n"); - return rc; - } - - if (in_data_len % DES_BLOCK_SIZE || in_data_len > INT_MAX) { - TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); - return CKR_DATA_LEN_RANGE; - } - - if (keytype == CKK_DES2) { - memcpy(dkey, attr->pValue, 2 * DES_KEY_SIZE); - memcpy(dkey + (2 * DES_KEY_SIZE), attr->pValue, DES_KEY_SIZE); - } else { - memcpy(dkey, attr->pValue, 3 * DES_KEY_SIZE); - } - - ctx = EVP_CIPHER_CTX_new(); - if (ctx == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - - if (EVP_CipherInit_ex(ctx, cipher, - NULL, dkey, init_v, encrypt ? 1 : 0) != 1 - || EVP_CIPHER_CTX_set_padding(ctx, 0) != 1 - || EVP_CipherUpdate(ctx, out_data, &outlen, in_data, in_data_len) != 1 - || EVP_CipherFinal_ex(ctx, out_data, &outlen) != 1) { - TRACE_ERROR("%s\n", ock_err(ERR_GENERAL_ERROR)); - rc = CKR_GENERAL_ERROR; - goto done; - } - - *out_data_len = in_data_len; - rc = CKR_OK; -done: - OPENSSL_cleanse(dkey, sizeof(dkey)); - EVP_CIPHER_CTX_free(ctx); - return rc; -#endif + CK_BYTE *out_data, + CK_ULONG *out_data_len, + OBJECT *key, CK_BYTE *init_v, CK_BYTE encrypt) +{ + return openssl_specific_tdes_cbc(tokdata, in_data, in_data_len, + out_data, out_data_len, key, + init_v, encrypt); } /* wrap the 20 bytes of auth data @authData and store in an attribute of the two @@ -3619,220 +3175,27 @@ return rng_generate(tokdata, *key, keysize); } -CK_RV token_specific_aes_ecb(STDLL_TokData_t * tokdata, - CK_BYTE * in_data, +CK_RV token_specific_aes_ecb(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, CK_ULONG in_data_len, - CK_BYTE * out_data, - CK_ULONG * out_data_len, - OBJECT * key, CK_BYTE encrypt) + CK_BYTE *out_data, + CK_ULONG *out_data_len, + OBJECT *key, CK_BYTE encrypt) { -#if OPENSSL_VERSION_NUMBER < 0x10100000L - CK_ATTRIBUTE *attr = NULL; - AES_KEY ssl_aes_key; - unsigned int i; - /* There's a previous check that in_data_len % AES_BLOCK_SIZE == 0, - * so this is fine */ - CK_ULONG loops = (CK_ULONG) (in_data_len / AES_BLOCK_SIZE); - CK_RV rc; - - UNUSED(tokdata); - - // get the key value - rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); - return rc; - } - - memset(&ssl_aes_key, 0, sizeof(AES_KEY)); - - // AES_ecb_encrypt encrypts only a single block, so we have to break up the - // input data here - if (encrypt) { - AES_set_encrypt_key((unsigned char *) attr->pValue, - (attr->ulValueLen * 8), &ssl_aes_key); - for (i = 0; i < loops; i++) { - AES_ecb_encrypt((unsigned char *) in_data + (i * AES_BLOCK_SIZE), - (unsigned char *) out_data + (i * AES_BLOCK_SIZE), - &ssl_aes_key, AES_ENCRYPT); - } - } else { - AES_set_decrypt_key((unsigned char *) attr->pValue, - (attr->ulValueLen * 8), &ssl_aes_key); - for (i = 0; i < loops; i++) { - AES_ecb_encrypt((unsigned char *) in_data + (i * AES_BLOCK_SIZE), - (unsigned char *) out_data + (i * AES_BLOCK_SIZE), - &ssl_aes_key, AES_DECRYPT); - } - } - *out_data_len = in_data_len; - - return CKR_OK; -#else - CK_RV rc; - int outlen; - unsigned char akey[AES_KEY_SIZE_256]; - const EVP_CIPHER *cipher = NULL; - EVP_CIPHER_CTX *ctx = NULL; - CK_ATTRIBUTE *attr = NULL; - CK_ULONG keylen; - - UNUSED(tokdata); - - // get the key value - rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); - return rc; - } - - keylen = attr->ulValueLen; - if (keylen == 128 / 8) { - cipher = EVP_aes_128_ecb(); - } else if (keylen == 192 / 8) { - cipher = EVP_aes_192_ecb(); - } else if (keylen == 256 / 8) { - cipher = EVP_aes_256_ecb(); - } else { - TRACE_ERROR("Invalid AES key size.\n"); - return CKR_FUNCTION_FAILED; - } - - memcpy(akey, attr->pValue, keylen); - - if (in_data_len % AES_BLOCK_SIZE || in_data_len > INT_MAX) { - TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); - rc = CKR_DATA_LEN_RANGE; - goto done; - } - - ctx = EVP_CIPHER_CTX_new(); - if (ctx == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - - if (EVP_CipherInit_ex(ctx, cipher, - NULL, akey, NULL, encrypt ? 1 : 0) != 1 - || EVP_CIPHER_CTX_set_padding(ctx, 0) != 1 - || EVP_CipherUpdate(ctx, out_data, &outlen, in_data, in_data_len) != 1 - || EVP_CipherFinal_ex(ctx, out_data, &outlen) != 1) { - TRACE_ERROR("%s\n", ock_err(ERR_GENERAL_ERROR)); - rc = CKR_GENERAL_ERROR; - goto done; - } - - *out_data_len = in_data_len; - rc = CKR_OK; -done: - OPENSSL_cleanse(akey, sizeof(akey)); - EVP_CIPHER_CTX_free(ctx); - return rc; -#endif + return openssl_specific_aes_ecb(tokdata, in_data, in_data_len, + out_data, out_data_len, key, encrypt); } -CK_RV token_specific_aes_cbc(STDLL_TokData_t * tokdata, - CK_BYTE * in_data, +CK_RV token_specific_aes_cbc(STDLL_TokData_t *tokdata, + CK_BYTE *in_data, CK_ULONG in_data_len, - CK_BYTE * out_data, - CK_ULONG * out_data_len, - OBJECT * key, CK_BYTE * init_v, CK_BYTE encrypt) -{ -#if OPENSSL_VERSION_NUMBER < 0x10100000L - AES_KEY ssl_aes_key; - CK_ATTRIBUTE *attr = NULL; - CK_RV rc; - - UNUSED(tokdata); - - // get the key value - rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); - return rc; - } - - memset(&ssl_aes_key, 0, sizeof(AES_KEY)); - - // AES_cbc_encrypt chunks the data into AES_BLOCK_SIZE blocks, unlike - // AES_ecb_encrypt, so no looping required. - if (encrypt) { - AES_set_encrypt_key((unsigned char *) attr->pValue, - (attr->ulValueLen * 8), &ssl_aes_key); - AES_cbc_encrypt((unsigned char *) in_data, (unsigned char *) out_data, - in_data_len, &ssl_aes_key, init_v, AES_ENCRYPT); - } else { - AES_set_decrypt_key((unsigned char *) attr->pValue, - (attr->ulValueLen * 8), &ssl_aes_key); - AES_cbc_encrypt((unsigned char *) in_data, (unsigned char *) out_data, - in_data_len, &ssl_aes_key, init_v, AES_DECRYPT); - } - *out_data_len = in_data_len; - - return CKR_OK; -#else - CK_RV rc; - int outlen; - unsigned char akey[AES_KEY_SIZE_256]; - const EVP_CIPHER *cipher = NULL; - EVP_CIPHER_CTX *ctx = NULL; - CK_ATTRIBUTE *attr = NULL; - CK_ULONG keylen; - - UNUSED(tokdata); - - // get the key value - rc = template_attribute_get_non_empty(key->template, CKA_IBM_OPAQUE, &attr); - if (rc != CKR_OK) { - TRACE_ERROR("Could not find CKA_IBM_OPAQUE for the key.\n"); - return rc; - } - - keylen = attr->ulValueLen; - if (keylen == 128 / 8) { - cipher = EVP_aes_128_cbc(); - } else if (keylen == 192 / 8) { - cipher = EVP_aes_192_cbc(); - } else if (keylen == 256 / 8) { - cipher = EVP_aes_256_cbc(); - } else { - TRACE_ERROR("Invalid AES key size.\n"); - return CKR_FUNCTION_FAILED; - } - - memcpy(akey, attr->pValue, keylen); - - if (in_data_len % AES_BLOCK_SIZE || in_data_len > INT_MAX) { - TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); - rc = CKR_DATA_LEN_RANGE; - goto done; - } - - ctx = EVP_CIPHER_CTX_new(); - if (ctx == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - - if (EVP_CipherInit_ex(ctx, cipher, - NULL, akey, init_v, encrypt ? 1 : 0) != 1 - || EVP_CIPHER_CTX_set_padding(ctx, 0) != 1 - || EVP_CipherUpdate(ctx, out_data, &outlen, in_data, in_data_len) != 1 - || EVP_CipherFinal_ex(ctx, out_data, &outlen) != 1) { - TRACE_ERROR("%s\n", ock_err(ERR_GENERAL_ERROR)); - rc = CKR_GENERAL_ERROR; - goto done; - } - - *out_data_len = in_data_len; - rc = CKR_OK; -done: - OPENSSL_cleanse(akey, sizeof(akey)); - EVP_CIPHER_CTX_free(ctx); - return rc; -#endif + CK_BYTE *out_data, + CK_ULONG *out_data_len, + OBJECT *key, CK_BYTE *init_v, CK_BYTE encrypt) +{ + return openssl_specific_aes_cbc(tokdata, in_data, in_data_len, + out_data, out_data_len, key, + init_v, encrypt); } CK_RV token_specific_get_mechanism_list(STDLL_TokData_t * tokdata, diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/tpm_stdll/tpm_specific.h opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/tpm_stdll/tpm_specific.h --- opencryptoki-3.16.0+dfsg/usr/lib/tpm_stdll/tpm_specific.h 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/tpm_stdll/tpm_specific.h 2022-02-02 15:05:41.000000000 +0100 @@ -56,10 +56,10 @@ /* retry count for generating software RSA keys */ #define KEYGEN_RETRY 5 -RSA *openssl_gen_key(STDLL_TokData_t *); -int openssl_write_key(STDLL_TokData_t *, RSA *, char *, CK_BYTE *); -CK_RV openssl_read_key(STDLL_TokData_t *, char *, CK_BYTE *, RSA **); -int openssl_get_modulus_and_prime(RSA *, unsigned int *, unsigned char *, +EVP_PKEY *openssl_gen_key(STDLL_TokData_t *); +int openssl_write_key(STDLL_TokData_t *, EVP_PKEY *, char *, CK_BYTE *); +CK_RV openssl_read_key(STDLL_TokData_t *, char *, CK_BYTE *, EVP_PKEY **); +int openssl_get_modulus_and_prime(EVP_PKEY *, unsigned int *, unsigned char *, unsigned int *, unsigned char *); int util_set_file_mode(char *, mode_t); CK_BYTE *util_create_id(int); diff -Nru opencryptoki-3.16.0+dfsg/usr/lib/tpm_stdll/tpm_stdll.mk opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/tpm_stdll/tpm_stdll.mk --- opencryptoki-3.16.0+dfsg/usr/lib/tpm_stdll/tpm_stdll.mk 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/lib/tpm_stdll/tpm_stdll.mk 2022-02-02 15:05:41.000000000 +0100 @@ -8,7 +8,8 @@ -DLINUX -DNOCDMF -DNODSA -DNODH -DMMAP \ -DTOK_NEW_DATA_STORE=0xffffffff \ -I${srcdir}/usr/lib/tpm_stdll -I${srcdir}/usr/lib/common \ - -I${srcdir}/usr/include -DSTDLL_NAME=\"tpmtok\" + -I${srcdir}/usr/include -DSTDLL_NAME=\"tpmtok\" \ + -I${top_builddir}/usr/lib/api -I${srcdir}/usr/lib/api opencryptoki_stdll_libpkcs11_tpm_la_LDFLAGS = \ -shared -Wl,-z,defs,-Bsymbolic -lcrypto -ltspi -lpthread -lrt \ @@ -34,7 +35,10 @@ usr/lib/common/verify_mgr.c usr/lib/common/mech_list.c \ usr/lib/common/shared_memory.c usr/lib/common/profile_obj.c \ usr/lib/tpm_stdll/tpm_specific.c usr/lib/common/attributes.c \ - usr/lib/tpm_stdll/tpm_openssl.c usr/lib/tpm_stdll/tpm_util.c + usr/lib/tpm_stdll/tpm_openssl.c usr/lib/tpm_stdll/tpm_util.c \ + usr/lib/common/dlist.c usr/lib/common/mech_openssl.c \ + usr/lib/common/utility_common.c usr/lib/common/ec_supported.c \ + usr/lib/api/policyhelper.c if ENABLE_LOCKS opencryptoki_stdll_libpkcs11_tpm_la_SOURCES += \ diff -Nru opencryptoki-3.16.0+dfsg/usr/sbin/p11sak/p11sak.c opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/sbin/p11sak/p11sak.c --- opencryptoki-3.16.0+dfsg/usr/sbin/p11sak/p11sak.c 2021-03-31 10:05:05.000000000 +0200 +++ opencryptoki-3.17.0+dfsg+20220202.b40982e/usr/sbin/p11sak/p11sak.c 2022-02-02 15:05:41.000000000 +0100 @@ -16,16 +16,58 @@ #include #include #include +#include "cfgparser.h" +#include "configuration.h" +#include +#include + +#include +#include +#include #include #include "p11util.h" #include "p11sak.h" +#include "mechtable.h" static const char *default_pkcs11lib = "libopencryptoki.so"; static void *pkcs11lib = NULL; static CK_FUNCTION_LIST *funcs = NULL; +static struct ConfigBaseNode *cfg = NULL; + +static void error_hook(int line, int col, const char *msg) +{ + fprintf(stderr, "PARSE ERROR: %d:%d: %s\n", line, col, msg); +} + +void dump_attr(CK_ATTRIBUTE_PTR a) +{ + const char *typestr; + typestr = p11_get_cka(a->type); + unsigned char *p = a->pValue; + unsigned int z; + + switch (a->ulValueLen) { + case 0: + printf(" %s: no value\n", typestr); + break; + default: + printf(" %s: len=%lu value:", typestr, a->ulValueLen); + for (z = 0; z < a->ulValueLen; z++) { + if (z % 16 == 0) { + printf("\n %02X ", p[z]); + } + else { + printf("%02X ", p[z]); + } + } + printf("\n"); + break; + } +} + static void unload_pkcs11lib(void) { if (pkcs11lib) @@ -46,7 +88,7 @@ /* try to load the pkcs11 lib */ pkcs11lib = dlopen(libname, RTLD_NOW); if (!pkcs11lib) { - printf("Error: failed to open pkcs11 lib '%s'\n", libname); + fprintf(stderr, "Error: failed to open pkcs11 lib '%s'\n", libname); exit(99); } @@ -54,15 +96,14 @@ *(void**) (&pfoo) = dlsym(pkcs11lib, "C_GetFunctionList"); if (!pfoo) { dlclose(pkcs11lib); - printf("Error: failed to resolve symbol '%s' from pkcs11 lib '%s'\n", + fprintf(stderr, "Error: failed to resolve symbol '%s' from pkcs11 lib '%s'\n", "C_GetFunctionList", libname); exit(99); } rc = pfoo(&funcs); if (rc != CKR_OK) { dlclose(pkcs11lib); - printf( - "Error: C_GetFunctionList() on pkcs11 lib '%s' failed with rc = 0x%lX - %s)\n", + fprintf(stderr, "Error: C_GetFunctionList() on pkcs11 lib '%s' failed with rc = 0x%lX - %s)\n", libname, rc, p11_get_ckr(rc)); exit(99); } @@ -75,7 +116,7 @@ struct termios old, new; int nread; char *user_input = NULL; - size_t buflen; + size_t buflen = 0; CK_RV rc = 0; /* turn echoing off */ @@ -103,23 +144,14 @@ printf("\n"); fflush(stdout); - /* Allocate PIN. - * Note: nread includes carriage return. - * Replace with terminating NULL. - */ - *pin = (char*) malloc(nread); - if (*pin == NULL) { - rc = -ENOMEM; - goto done; - } - - /* strip the carriage return since not part of pin. */ - user_input[nread - 1] = '\0'; - memcpy(*pin, user_input, nread); - /* don't include the terminating null in the pinlen */ - *pinlen = nread - 1; + /* strip the carriage return (if any) since not part of pin. */ + if (user_input[nread - 1] == '\n') + user_input[nread - 1] = '\0'; + *pinlen = strlen(user_input); + *pin = user_input; - done: if (user_input) +done: + if (rc != 0 && user_input) free(user_input); return rc; @@ -148,6 +180,8 @@ return "PUBLIC"; case kt_PRIVATE: return "PRIVATE"; + case kt_ALL: + return "ALL"; case no_key_type: return "NO_KEYTYPE"; default: @@ -334,8 +368,8 @@ } } *len = sizeof(CK_ULONG) - s; - - return &bytes[s]; + memmove(&bytes[0], &bytes[s], *len); + return &bytes[0]; } /** * print help functions @@ -363,6 +397,7 @@ printf(" public\n"); printf(" private\n"); printf(" secret\n"); + printf(" all\n"); printf("\n Options:\n"); printf(" -l, --long list output with long format\n"); printf( @@ -379,7 +414,11 @@ printf(" 3des\n"); printf(" aes [128 | 192 | 256]\n"); printf(" rsa [1024 | 2048 | 4096]\n"); - printf(" ec [prime256v1 | secp384r1 | secp521r1]\n"); + printf(" ec [prime256v1 | prime192v1 | secp224r1 | secp384r1 | secp521r1 | secp256k1 | \n"); + printf(" brainpoolP160r1 | brainpoolP160t1 | brainpoolP192r1 | brainpoolP192t1 | \n"); + printf(" brainpoolP224r1 | brainpoolP224t1 | brainpoolP256r1 | brainpoolP256t1 | \n"); + printf(" brainpoolP320r1 | brainpoolP320t1 | brainpoolP384r1 | brainpoolP384t1 | \n"); + printf(" brainpoolP512r1 | brainpoolP512t1]\n"); printf("\n Options:\n"); printf( " --slot SLOTID openCryptoki repository token SLOTID.\n"); @@ -390,6 +429,9 @@ " --exponent EXP set RSA exponent EXP\n"); printf( " --attr [M R L S E D G V W U A X N] set key attributes\n"); + printf( + " --attr [[pub_attrs]:[priv_attrs]] \n"); + printf( " for asymmetric keys: set individual key attributes, values see above\n"); printf(" -h, --help Show this help\n\n"); } @@ -469,8 +511,25 @@ printf("\n Usage: p11sak generate-key ec [ARGS] [OPTIONS]\n"); printf("\n Args:\n"); printf(" prime256v1\n"); + printf(" prime192v1\n"); + printf(" secp224r1\n"); printf(" secp384r1\n"); printf(" secp521r1\n"); + printf(" secp265k1\n"); + printf(" brainpoolP160r1\n"); + printf(" brainpoolP160t1\n"); + printf(" brainpoolP192r1\n"); + printf(" brainpoolP192t1\n"); + printf(" brainpoolP224r1\n"); + printf(" brainpoolP224t1\n"); + printf(" brainpoolP256r1\n"); + printf(" brainpoolP256t1\n"); + printf(" brainpoolP320r1\n"); + printf(" brainpoolP320t1\n"); + printf(" brainpoolP384r1\n"); + printf(" brainpoolP384t1\n"); + printf(" brainpoolP512r1\n"); + printf(" brainpoolP512t1\n"); printf("\n Options:\n"); printf( " --slot SLOTID openCryptoki repository token SLOTID.\n"); @@ -522,6 +581,7 @@ printf("\n"); printf(" Setting CK_ATTRIBUTE\n"); printf("\n"); + printf(" 'P': CKA_PRIVATE\n"); printf(" 'M': CKA_MODIFIABLE\n"); printf(" 'R': CKA_DERIVE\n"); printf(" 'L': CKA_LOCAL\n"); @@ -536,7 +596,7 @@ printf(" 'X': CKA_EXTRACTABLE\n"); printf(" 'N': CKA_NEVER_EXTRACTABLE\n"); printf("\n"); - printf(" CKA_TOKEN and CKA_PRIVATE are set by default.\n"); + printf(" CKA_TOKEN is set by default.\n"); printf( " If an attribute is not set explicitly, the default values are used.\n"); printf( @@ -559,7 +619,7 @@ CK_ULONG spubexplen; if (!(mod_bits = malloc(sizeof(CK_ULONG)))) { - printf("Error: failed to allocate memory for mod_bits.\n"); + fprintf(stderr, "Error: failed to allocate memory for mod_bits.\n"); return CKR_HOST_MEMORY; } *mod_bits = modulusbits; @@ -575,7 +635,8 @@ ulpubexp = 65537; /* default for RSA_PKCS */ if (!(pubexp = malloc(sizeof(CK_ULONG)))) { - printf("Error: failed to allocate memory for public exponent.\n"); + fprintf(stderr, "Error: failed to allocate memory for public exponent.\n"); + free(mod_bits); return CKR_HOST_MEMORY; } @@ -591,72 +652,92 @@ * Builds the CKA_EC_PARAMS attribute from the given ECcurve. */ static CK_RV read_ec_args(const char *ECcurve, CK_ATTRIBUTE *pubattr, - CK_ULONG *pubcount) + CK_ULONG *pubcount, CK_ULONG *keybits) { pubattr[*pubcount].type = CKA_EC_PARAMS; if (strcmp(ECcurve, "prime256v1") == 0) { pubattr[*pubcount].pValue = (CK_BYTE*) prime256v1; pubattr[*pubcount].ulValueLen = sizeof(prime256v1); - } else if (strcmp(ECcurve, "prime192") == 0) { - pubattr[*pubcount].pValue = (CK_BYTE*) prime192; - pubattr[*pubcount].ulValueLen = sizeof(prime192); - } else if (strcmp(ECcurve, "secp224") == 0) { - pubattr[*pubcount].pValue = (CK_BYTE*) secp224; - pubattr[*pubcount].ulValueLen = sizeof(secp224); + *keybits = 256; + } else if (strcmp(ECcurve, "prime192v1") == 0) { + pubattr[*pubcount].pValue = (CK_BYTE*) prime192v1; + pubattr[*pubcount].ulValueLen = sizeof(prime192v1); + *keybits = 192; + } else if (strcmp(ECcurve, "secp224r1") == 0) { + pubattr[*pubcount].pValue = (CK_BYTE*) secp224r1; + pubattr[*pubcount].ulValueLen = sizeof(secp224r1); + *keybits = 224; } else if (strcmp(ECcurve, "secp384r1") == 0) { pubattr[*pubcount].pValue = (CK_BYTE*) secp384r1; pubattr[*pubcount].ulValueLen = sizeof(secp384r1); + *keybits = 384; } else if (strcmp(ECcurve, "secp521r1") == 0) { pubattr[*pubcount].pValue = (CK_BYTE*) secp521r1; pubattr[*pubcount].ulValueLen = sizeof(secp521r1); + *keybits = 521; } else if (strcmp(ECcurve, "secp265k1") == 0) { pubattr[*pubcount].pValue = (CK_BYTE*) secp256k1; pubattr[*pubcount].ulValueLen = sizeof(secp256k1); + *keybits = 256; } else if (strcmp(ECcurve, "brainpoolP160r1") == 0) { pubattr[*pubcount].pValue = (CK_BYTE*) brainpoolP160r1; pubattr[*pubcount].ulValueLen = sizeof(brainpoolP160r1); + *keybits = 160; } else if (strcmp(ECcurve, "brainpoolP160t1") == 0) { pubattr[*pubcount].pValue = (CK_BYTE*) brainpoolP160t1; pubattr[*pubcount].ulValueLen = sizeof(brainpoolP160t1); + *keybits = 160; } else if (strcmp(ECcurve, "brainpoolP192r1") == 0) { pubattr[*pubcount].pValue = (CK_BYTE*) brainpoolP192r1; pubattr[*pubcount].ulValueLen = sizeof(brainpoolP192r1); + *keybits = 192; } else if (strcmp(ECcurve, "brainpoolP192t1") == 0) { pubattr[*pubcount].pValue = (CK_BYTE*) brainpoolP192t1; pubattr[*pubcount].ulValueLen = sizeof(brainpoolP192t1); + *keybits = 192; } else if (strcmp(ECcurve, "brainpoolP224r1") == 0) { pubattr[*pubcount].pValue = (CK_BYTE*) brainpoolP224r1; pubattr[*pubcount].ulValueLen = sizeof(brainpoolP224r1); + *keybits = 224; } else if (strcmp(ECcurve, "brainpoolP224t1") == 0) { pubattr[*pubcount].pValue = (CK_BYTE*) brainpoolP224t1; pubattr[*pubcount].ulValueLen = sizeof(brainpoolP224t1); + *keybits = 224; } else if (strcmp(ECcurve, "brainpoolP256r1") == 0) { pubattr[*pubcount].pValue = (CK_BYTE*) brainpoolP256r1; pubattr[*pubcount].ulValueLen = sizeof(brainpoolP256r1); + *keybits = 256; } else if (strcmp(ECcurve, "brainpoolP256t1") == 0) { pubattr[*pubcount].pValue = (CK_BYTE*) brainpoolP256t1; pubattr[*pubcount].ulValueLen = sizeof(brainpoolP256t1); + *keybits = 256; } else if (strcmp(ECcurve, "brainpoolP320r1") == 0) { pubattr[*pubcount].pValue = (CK_BYTE*) brainpoolP320r1; pubattr[*pubcount].ulValueLen = sizeof(brainpoolP320r1); + *keybits = 320; } else if (strcmp(ECcurve, "brainpoolP320t1") == 0) { pubattr[*pubcount].pValue = (CK_BYTE*) brainpoolP320t1; pubattr[*pubcount].ulValueLen = sizeof(brainpoolP320t1); + *keybits = 320; } else if (strcmp(ECcurve, "brainpoolP384r1") == 0) { pubattr[*pubcount].pValue = (CK_BYTE*) brainpoolP384r1; pubattr[*pubcount].ulValueLen = sizeof(brainpoolP384r1); + *keybits = 384; } else if (strcmp(ECcurve, "brainpoolP384t1") == 0) { pubattr[*pubcount].pValue = (CK_BYTE*) brainpoolP384t1; pubattr[*pubcount].ulValueLen = sizeof(brainpoolP384t1); + *keybits = 384; } else if (strcmp(ECcurve, "brainpoolP512r1") == 0) { pubattr[*pubcount].pValue = (CK_BYTE*) brainpoolP512r1; pubattr[*pubcount].ulValueLen = sizeof(brainpoolP512r1); + *keybits = 512; } else if (strcmp(ECcurve, "brainpoolP512t1") == 0) { pubattr[*pubcount].pValue = (CK_BYTE*) brainpoolP512t1; pubattr[*pubcount].ulValueLen = sizeof(brainpoolP512t1); + *keybits = 512; } else { - printf("Unexpected case while parsing EC curves.\n"); - printf("Note: not all tokens support all curves.\n"); + fprintf(stderr, "Unexpected case while parsing EC curves.\n"); + fprintf(stderr, "Note: not all tokens support all curves.\n"); return CKR_ARGUMENTS_BAD; } (*pubcount)++; @@ -674,14 +755,15 @@ char *prvlabel; if (!(publabel = malloc(strlen(label) + 5))) { - printf("Error allocating space for publabel\n"); + fprintf(stderr, "Error allocating space for publabel\n"); return CKR_HOST_MEMORY; } publabel = strcpy(publabel, label); publabel = strcat(publabel, ":pub"); if (!(prvlabel = malloc(strlen(label) + 5))) { - printf("Error allocating space for prvlabel\n"); + fprintf(stderr, "Error allocating space for prvlabel\n"); + free(publabel); return CKR_HOST_MEMORY; } prvlabel = strcpy(prvlabel, label); @@ -689,12 +771,12 @@ pubattr[*pubcount].type = CKA_LABEL; pubattr[*pubcount].pValue = publabel; - pubattr[*pubcount].ulValueLen = strlen(publabel) + 1; + pubattr[*pubcount].ulValueLen = strlen(publabel); (*pubcount)++; prvattr[*prvcount].type = CKA_LABEL; prvattr[*prvcount].pValue = prvlabel; - prvattr[*prvcount].ulValueLen = strlen(prvlabel) + 1; + prvattr[*prvcount].ulValueLen = strlen(prvlabel); (*prvcount)++; return CKR_OK; @@ -729,86 +811,53 @@ return CKR_OK; } + /** - * Set default asymmetric key attributes. + * returns 1 if the given attribute is not applicable for the + * given key type, 0 otherwise. */ -static CK_RV set_battr(const char *attr_string, CK_ATTRIBUTE *pubattr, - CK_ULONG *pubcount, CK_ATTRIBUTE *prvattr, - CK_ULONG *prvcount) +static CK_BBOOL attr_na(const CK_ULONG attr_type, p11sak_kt ktype) { - int i = 0; - - pubattr[*pubcount].type = CKA_TOKEN; - pubattr[*pubcount].pValue = &ckb_true; - pubattr[*pubcount].ulValueLen = sizeof(CK_BBOOL); - (*pubcount)++; - pubattr[*pubcount].type = CKA_PRIVATE; - pubattr[*pubcount].pValue = &ckb_true; - pubattr[*pubcount].ulValueLen = sizeof(CK_BBOOL); - (*pubcount)++; - - prvattr[*prvcount].type = CKA_TOKEN; - prvattr[*prvcount].pValue = &ckb_true; - prvattr[*prvcount].ulValueLen = sizeof(CK_BBOOL); - (*prvcount)++; - prvattr[*prvcount].type = CKA_PRIVATE; - prvattr[*prvcount].pValue = &ckb_true; - prvattr[*prvcount].ulValueLen = sizeof(CK_BBOOL); - (*prvcount)++; - - if (attr_string) { - for (i = 0; i < (int) strlen(attr_string); i++) { - - switch (attr_string[i]) { - case 'S': /* private sensitive */ - prvattr[*prvcount].type = CKA_SENSITIVE; - prvattr[*prvcount].pValue = &ckb_true; - prvattr[*prvcount].ulValueLen = sizeof(CK_BBOOL); - (*prvcount)++; - break; - case 'D': /* private decrypt RSA only*/ - prvattr[*prvcount].type = CKA_DECRYPT; - prvattr[*prvcount].pValue = &ckb_true; - prvattr[*prvcount].ulValueLen = sizeof(CK_BBOOL); - (*prvcount)++; - pubattr[*pubcount].type = CKA_ENCRYPT; - pubattr[*pubcount].pValue = &ckb_true; - pubattr[*pubcount].ulValueLen = sizeof(CK_BBOOL); - (*pubcount)++; - break; - case 'G': /* private sign */ - prvattr[*prvcount].type = CKA_SIGN; - prvattr[*prvcount].pValue = &ckb_true; - prvattr[*prvcount].ulValueLen = sizeof(CK_BBOOL); - (*prvcount)++; - pubattr[*pubcount].type = CKA_VERIFY; - pubattr[*pubcount].pValue = &ckb_true; - pubattr[*pubcount].ulValueLen = sizeof(CK_BBOOL); - (*pubcount)++; - break; - case 'U': /* private unwrap RSA only */ - prvattr[*prvcount].type = CKA_UNWRAP; - prvattr[*prvcount].pValue = &ckb_true; - prvattr[*prvcount].ulValueLen = sizeof(CK_BBOOL); - (*prvcount)++; - pubattr[*pubcount].type = CKA_WRAP; - pubattr[*pubcount].pValue = &ckb_true; - pubattr[*pubcount].ulValueLen = sizeof(CK_BBOOL); - (*pubcount)++; - break; - case 'X': /* private extractable */ - prvattr[*prvcount].type = CKA_EXTRACTABLE; - prvattr[*prvcount].pValue = &ckb_true; - prvattr[*prvcount].ulValueLen = sizeof(CK_BBOOL); - (*prvcount)++; - break; - default: - printf("Ignoring attribute '%c', n/a for asymmetric keys\n", - attr_string[i]); - } + switch (ktype) { + case kt_DES: + case kt_3DES: + case kt_AES: + case kt_SECRET: + switch (attr_type) { + case CKA_TRUSTED: + return 1; + default: + return 0; + } + break; + case kt_PUBLIC: + switch (attr_type) { + case CKA_SENSITIVE: + case CKA_DECRYPT: + case CKA_SIGN: + case CKA_UNWRAP: + case CKA_EXTRACTABLE: + case CKA_ALWAYS_SENSITIVE: + case CKA_NEVER_EXTRACTABLE: + return 1; + default: + return 0; + } + break; + case kt_PRIVATE: + switch (attr_type) { + case CKA_ENCRYPT: + case CKA_VERIFY: + case CKA_WRAP: + return 1; + default: + return 0; } + break; + default: + /* key type not handled here */ + return 0; } - return CKR_OK; } static CK_ULONG char2attrtype(char c) @@ -849,99 +898,186 @@ } } -static void set_bool_attr_from_string(CK_ATTRIBUTE *attr, char *attr_string) +static void set_bool_attr_from_string(CK_ATTRIBUTE *attr, char attr_char) { - int i; - - if (!attr_string) + if (!attr_char) return; + + attr->type = char2attrtype(toupper(attr_char)); + attr->ulValueLen = sizeof(CK_BBOOL); + if (isupper(attr_char) == 0) { + attr->pValue = &ckb_false; + } else { + attr->pValue = &ckb_true; + } +} + +/** + * Set default asymmetric key attributes. + */ +static CK_RV set_battr(const char *attr_string, CK_ATTRIBUTE *attr, + CK_ULONG *count, int prv) +{ + int i = 0; + + attr[*count].type = CKA_TOKEN; + attr[*count].pValue = &ckb_true; + attr[*count].ulValueLen = sizeof(CK_BBOOL); + (*count)++; + + if (attr_string) { + for (i = 0; i < (int) strlen(attr_string); i++) { + // attr_string length is checked in parse_gen_key_args to avoid memory problems + if (prv == 1 && attr_na(char2attrtype(toupper(attr_string[i])), kt_PRIVATE) == 0) { + printf("private: %d\n", attr_string[i]); + set_bool_attr_from_string(&attr[*count], attr_string[i]); + (*count)++; + } + if (prv == 0 && attr_na(char2attrtype(toupper(attr_string[i])), kt_PUBLIC) == 0) { + printf("public: %d\n", attr_string[i]); + set_bool_attr_from_string(&attr[*count], attr_string[i]); + (*count)++; + } + } + } + return CKR_OK; +} + +CK_BBOOL is_rejected_by_policy(CK_RV ret_code, CK_SESSION_HANDLE session) +{ + CK_SESSION_INFO info; + CK_RV rc; + + if (ret_code != CKR_FUNCTION_FAILED) + return CK_FALSE; + + rc = funcs->C_GetSessionInfo(session, &info); + if (rc != CKR_OK) { + fprintf(stderr, "C_GetSessionInfo failed (error code 0x%lX: %s)\n", rc, + p11_get_ckr(rc)); + return CK_FALSE; + } + + return (info.ulDeviceError == CKR_POLICY_VIOLATION) ? CK_TRUE : CK_FALSE; +} - for (i = 0; i < (int) strlen(attr_string); i++) { - if (char2attrtype(attr_string[i]) == attr->type) { - attr->pValue = &ckb_true; +CK_BBOOL is_mech_supported(CK_SLOT_ID slot, CK_MECHANISM *pmech, + CK_ULONG keybits) +{ + CK_MECHANISM_INFO mech_info; + int rc; + + rc = funcs->C_GetMechanismInfo(slot, pmech->mechanism, &mech_info); + if (rc != CKR_OK) + return CK_FALSE; + + if ((mech_info.flags & (CKF_GENERATE | CKF_GENERATE_KEY_PAIR)) == 0) + return CK_FALSE; + + if (keybits > 0) { + switch (pmech->mechanism) { + case CKM_DES_KEY_GEN: + case CKM_DES3_KEY_GEN: + case CKM_AES_KEY_GEN: + keybits /= 8; /* mechinfo reports key size in bytes */ + break; } + + if (mech_info.ulMinKeySize == 0 && mech_info.ulMaxKeySize == 0) + return CK_TRUE; + if (mech_info.ulMinKeySize > keybits) + return CK_FALSE; + if (mech_info.ulMaxKeySize < keybits) + return CK_FALSE; } + + return CK_TRUE; } + /** * Generation of the symmetric key */ -static CK_RV tok_key_gen(CK_SESSION_HANDLE session, CK_ULONG keylength, - CK_MECHANISM *pmech, char *attr_string, - CK_OBJECT_HANDLE *phkey, char *label) +static CK_RV tok_key_gen(CK_SESSION_HANDLE session, CK_SLOT_ID slot, + CK_ULONG keylength, CK_MECHANISM *pmech, + char *attr_string, CK_OBJECT_HANDLE *phkey, + char *label) { CK_RV rc; int i = 0; /* Boolean attributes (cannot be specified by user) */ CK_BBOOL a_token = ckb_true; // always true - CK_BBOOL a_private = ckb_true; // always true - - /* Boolean attributes from user input */ - CK_BBOOL a_modifiable = ckb_false; - CK_BBOOL a_derive = ckb_false; - CK_BBOOL a_sensitive = ckb_false; - CK_BBOOL a_encrypt = ckb_false; - CK_BBOOL a_decrypt = ckb_false; - CK_BBOOL a_sign = ckb_false; - CK_BBOOL a_verify = ckb_false; - CK_BBOOL a_wrap = ckb_false; - CK_BBOOL a_unwrap = ckb_false; - CK_BBOOL a_extractable = ckb_false; - CK_ULONG bs = sizeof(CK_BBOOL); /* Non-boolean attributes */ CK_ULONG a_value_len = keylength / 8; - CK_ATTRIBUTE tmplt[] = { - // boolean attrs - { CKA_TOKEN, &a_token, bs }, { CKA_PRIVATE, &a_private, bs }, { - CKA_MODIFIABLE, &a_modifiable, bs }, { CKA_DERIVE, &a_derive, bs }, - { CKA_SENSITIVE, &a_sensitive, bs }, { - CKA_ENCRYPT, &a_encrypt, bs }, { CKA_DECRYPT, &a_decrypt, bs }, { - CKA_SIGN, &a_sign, bs }, { - CKA_VERIFY, &a_verify, bs }, { CKA_WRAP, &a_wrap, bs }, { - CKA_UNWRAP, &a_unwrap, bs }, - { CKA_EXTRACTABLE, &a_extractable, bs }, - // non-boolean attrs - { CKA_VALUE_LEN, &a_value_len, sizeof(CK_ULONG) }, { CKA_LABEL, - label, strlen(label) } }; - CK_ULONG num_attrs = sizeof(tmplt) / sizeof(CK_ATTRIBUTE); - CK_ULONG num_bools = num_attrs - 2; - - /* set boolean attributes */ - for (i = 0; i < (int) num_bools; i++) { - set_bool_attr_from_string(&tmplt[i], attr_string); + /* Standard template */ + CK_ATTRIBUTE key_attr[3 + KEY_MAX_BOOL_ATTR_COUNT] = { + { CKA_TOKEN, &a_token, sizeof(CK_BBOOL) }, + { CKA_VALUE_LEN, &a_value_len, sizeof(CK_ULONG) }, + { CKA_LABEL, label, strlen(label) } + }; + CK_ULONG num_attrs = 3; + + /* set boolean attributes, set template from string + attr_string length is checked in parse_gen_key_args to avoid memory problems */ + if (attr_string) { + for (i = 0; i < (int) strlen(attr_string); i++) { + set_bool_attr_from_string(&key_attr[i+num_attrs], attr_string[i]); + } + num_attrs += strlen(attr_string); + } + + if (!is_mech_supported(slot, pmech, keylength)) { + fprintf(stderr, "Key generation mechanism %s with key length %lu is not supported by slot %lu\n", + p11_get_ckm(&mechtable_funcs, pmech->mechanism), a_value_len, + slot); + return CKR_MECHANISM_INVALID; } /* generate key */ - rc = funcs->C_GenerateKey(session, pmech, tmplt, num_attrs, phkey); + rc = funcs->C_GenerateKey(session, pmech, key_attr, num_attrs, phkey); if (rc != CKR_OK) { - printf("Key generation of key of length %ld bytes failed\n", - a_value_len); - printf("in tok_key_gen() (error code 0x%lX: %s)\n", rc, - p11_get_ckr(rc)); + if (is_rejected_by_policy(rc, session)) { + fprintf(stderr, "Key generation of key of length %ld bytes is rejected by policy\n", + a_value_len); + } else { + fprintf(stderr, "Key generation of key of length %ld bytes failed\n", + a_value_len); + fprintf(stderr, "in tok_key_gen() (error code 0x%lX: %s)\n", rc, + p11_get_ckr(rc)); + } } return rc; } /** * Generation of the asymmetric key pair */ -static CK_RV key_pair_gen(CK_SESSION_HANDLE session, p11sak_kt kt, - CK_MECHANISM_PTR pmech, CK_ATTRIBUTE *pubattr, - CK_ULONG pubcount, CK_ATTRIBUTE *prvattr, - CK_ULONG prvcount, CK_OBJECT_HANDLE_PTR phpubkey, - CK_OBJECT_HANDLE_PTR phprvkey) +static CK_RV key_pair_gen(CK_SESSION_HANDLE session, CK_SLOT_ID slot, + p11sak_kt kt, CK_MECHANISM_PTR pmech, + CK_ATTRIBUTE *pubattr, CK_ULONG pubcount, + CK_ATTRIBUTE *prvattr, CK_ULONG prvcount, + CK_OBJECT_HANDLE_PTR phpubkey, + CK_OBJECT_HANDLE_PTR phprvkey, CK_ULONG keybits) { - CK_RV rc; printf("Generate asymmetric key: %s\n", kt2str(kt)); + if (!is_mech_supported(slot, pmech, keybits)) { + fprintf(stderr, "Key generation mechanism %s with key length %lu is not supported by slot %lu\n", + p11_get_ckm(&mechtable_funcs, pmech->mechanism), keybits, slot); + return CKR_MECHANISM_INVALID; + } + rc = funcs->C_GenerateKeyPair(session, pmech, pubattr, pubcount, prvattr, prvcount, phpubkey, phprvkey); if (rc != CKR_OK) { - printf("Key pair generation failed (error code 0x%lX: %s)\n", rc, - p11_get_ckr(rc)); + if (is_rejected_by_policy(rc, session)) + fprintf(stderr, "Key pair generation rejected by policy\n"); + else + fprintf(stderr, "Key pair generation failed (error code 0x%lX: %s)\n", rc, + p11_get_ckr(rc)); return rc; } @@ -960,35 +1096,38 @@ /* Boolean Attributes */ CK_BBOOL a_token; - CK_BBOOL a_private; CK_ULONG bs = sizeof(CK_BBOOL); /* key Type attributes */ CK_KEY_TYPE a_key_type; CK_OBJECT_CLASS a_cko; - CK_ATTRIBUTE tmplt[4]; + CK_ATTRIBUTE tmplt[3]; a_token = CK_TRUE; tmplt[0].type = CKA_TOKEN; tmplt[0].pValue = &a_token; tmplt[0].ulValueLen = bs; - a_private = CK_TRUE; - tmplt[1].type = CKA_PRIVATE; - tmplt[1].pValue = &a_private; - tmplt[1].ulValueLen = bs; if (kt < kt_SECRET) { rc = kt2CKK(kt, &a_key_type); if (rc != CKR_OK) { - printf("Keytype could not be set (error code 0x%lX: %s)\n", rc, + fprintf(stderr, "Keytype could not be set (error code 0x%lX: %s)\n", rc, + p11_get_ckr(rc)); + return rc; + } + } else if (kt == kt_ALL) { + rc = funcs->C_FindObjectsInit(session, NULL, 0); + if (rc != CKR_OK) { + fprintf(stderr, "C_FindObjectInit failed in tok_key_list_init() (error code 0x%lX: %s)\n", rc, p11_get_ckr(rc)); return rc; } + return rc; } else { rc = kt2CKO(kt, &a_cko); if (rc != CKR_OK) { - printf("Keyobject could not be set (error code 0x%lX: %s)\n", rc, + fprintf(stderr, "Keyobject could not be set (error code 0x%lX: %s)\n", rc, p11_get_ckr(rc)); return rc; } @@ -1002,89 +1141,43 @@ case kt_GENERIC: case kt_RSAPKCS: case kt_EC: - tmplt[2].type = CKA_KEY_TYPE; - tmplt[2].pValue = &a_key_type; - tmplt[2].ulValueLen = sizeof(CK_KEY_TYPE); + tmplt[1].type = CKA_KEY_TYPE; + tmplt[1].pValue = &a_key_type; + tmplt[1].ulValueLen = sizeof(CK_KEY_TYPE); break; case kt_SECRET: case kt_PUBLIC: case kt_PRIVATE: - tmplt[2].type = CKA_CLASS; - tmplt[2].pValue = &a_cko; - tmplt[2].ulValueLen = sizeof(CK_OBJECT_CLASS); + tmplt[1].type = CKA_CLASS; + tmplt[1].pValue = &a_cko; + tmplt[1].ulValueLen = sizeof(CK_OBJECT_CLASS); break; default: - printf("Unknown key type\n"); + fprintf(stderr, "Unknown key type\n"); return CKR_ARGUMENTS_BAD; } if (label != NULL_PTR) { - tmplt[3].type = CKA_LABEL; - tmplt[3].pValue = label; - tmplt[3].ulValueLen = strlen(label) + 1; - count = 4; - } else + tmplt[2].type = CKA_LABEL; + tmplt[2].pValue = label; + tmplt[2].ulValueLen = strlen(label); count = 3; + } else + count = 2; rc = funcs->C_FindObjectsInit(session, tmplt, count); if (rc != CKR_OK) { - printf("C_FindObjectInit failed\n"); - printf("in tok_key_list_init() (error code 0x%lX: %s)\n", rc, + fprintf(stderr, "C_FindObjectInit failed\n"); + fprintf(stderr, "in tok_key_list_init() (error code 0x%lX: %s)\n", rc, p11_get_ckr(rc)); return rc; } return CKR_OK; } + /** - * returns 1 if the given attribute is not applicable for the - * given key type, 0 otherwise. - */ -static CK_BBOOL attr_na(const CK_ATTRIBUTE attr, p11sak_kt ktype) -{ - switch (ktype) { - case kt_DES: - case kt_3DES: - case kt_AES: - case kt_SECRET: - switch (attr.type) { - case CKA_TRUSTED: - return 1; - default: - return 0; - } - break; - case kt_PUBLIC: - switch (attr.type) { - case CKA_SENSITIVE: - case CKA_DECRYPT: - case CKA_SIGN: - case CKA_UNWRAP: - case CKA_EXTRACTABLE: - case CKA_ALWAYS_SENSITIVE: - case CKA_NEVER_EXTRACTABLE: - return 1; - default: - return 0; - } - break; - case kt_PRIVATE: - switch (attr.type) { - case CKA_ENCRYPT: - case CKA_VERIFY: - case CKA_WRAP: - return 1; - default: - return 0; - } - break; - default: - /* key type not handled here */ - return 0; - } -} -/** - * Columns: T P M R L S E D G V W U X A N + * Columns: T P M R L S E D G V W U X A N * */ static CK_ATTRIBUTE_TYPE col2type(int col) { @@ -1124,6 +1217,152 @@ } } +/** + * Print in p11sak_defined_attrs.conf defined attributes in long format + */ +static CK_RV print_custom_attrs(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE hkey, int long_print) +{ + CK_RV rc = CKR_OK; + int f; + struct ConfigBaseNode *c, *name, *hex_string, *type; + struct ConfigStructNode *structnode; + int def_attr; + + if (cfg != NULL) + { + confignode_foreach(c, cfg, f) { + if (confignode_hastype(c, CT_STRUCT) && strcmp(c->key, "attribute") == 0) { + // parse... + structnode = confignode_to_struct(c); + name = confignode_find(structnode->value, "name"); + hex_string = confignode_find(structnode->value, "id"); + type = confignode_find(structnode->value, "type"); + + // checking syntax of attribute... + if (name == NULL) { + fprintf(stderr, "Missing name in Attribute in line %hu\n", c->line); + return CKR_DATA_INVALID; + } else if (!confignode_hastype(name, CT_BAREVAL)) { + fprintf(stderr, "Invalid name in Attribute in line %hu\n", name->line); + return CKR_DATA_INVALID; + } else if (hex_string == NULL) { + fprintf(stderr, "Missing value in Attribute in line %hu\n", c->line); + return CKR_DATA_INVALID; + } else if (!confignode_hastype(hex_string, CT_INTVAL)) { + fprintf(stderr, "Invalid name in Attribute in line %hu\n", hex_string->line); + return CKR_DATA_INVALID; + } else if (type == NULL) { + fprintf(stderr, "Missing type in Attribute in line %hu\n", c->line); + return CKR_DATA_INVALID; + } else if (!confignode_hastype(type, CT_BAREVAL)) { + fprintf(stderr, "Invalid name in Attribute in line %hu\n", type->line); + return CKR_DATA_INVALID; + } + + def_attr = 1; + + // print attribute by type + unsigned int hex = confignode_to_intval(hex_string)->value; + if (strcmp(confignode_to_bareval(type)->value, "CK_BBOOL") == 0) { + // build template + CK_BBOOL a_bool; + CK_ATTRIBUTE temp = {hex, &a_bool, sizeof(a_bool)}; + + // get attribute value + rc = funcs->C_GetAttributeValue(session, hkey, &temp, 1); + if (rc == CKR_OK) { + if (temp.ulValueLen != sizeof(CK_BBOOL)) { + fprintf(stderr, " Error in retrieving Attribute %s: %lu\n", + confignode_to_bareval(name)->value, temp.ulValueLen); + } else { + if (long_print) { + printf(" %s: %s\n", confignode_to_bareval(name)->value, + CK_BBOOL2a(*(CK_BBOOL*) temp.pValue)); + } else if (strcmp(CK_BBOOL2a(*(CK_BBOOL*) temp.pValue), "CK_TRUE") == 0) { + printf(" 1 "); + return CKR_OK; + } + } + } else if (rc == CKR_ATTRIBUTE_SENSITIVE && long_print) { + printf(" %s: SENSITIVE\n", confignode_to_bareval(name)->value); + } else if (rc != CKR_ATTRIBUTE_TYPE_INVALID) { + return rc; + } + } else if (strcmp((confignode_to_bareval(type)->value), "CK_ULONG") == 0) { + // build template + CK_ULONG a_ulong; + CK_ATTRIBUTE temp = {hex, &a_ulong, sizeof(a_ulong)}; + + // get attribute value + rc = funcs->C_GetAttributeValue(session, hkey, &temp, 1); + if (rc == CKR_OK) { + if (temp.ulValueLen != sizeof(CK_ULONG)) { + fprintf(stderr, " Error in retrieving Attribute %s: %lu\n", + confignode_to_bareval(name)->value, temp.ulValueLen); + } else { + if (long_print) { + printf(" %s: %lu (0x%lX)\n", confignode_to_bareval(name)->value, + *(CK_ULONG*) temp.pValue, *(CK_ULONG*) temp.pValue); + } else { + printf(" 1 "); + return CKR_OK; + } + } + } else if (rc == CKR_ATTRIBUTE_SENSITIVE && long_print) { + printf(" %s: SENSITIVE\n", confignode_to_bareval(name)->value); + } else if (rc != CKR_ATTRIBUTE_TYPE_INVALID) { + return rc; + } + } else if (strcmp((confignode_to_bareval(type)->value), "CK_BYTE") == 0) { + // get length + CK_ATTRIBUTE temp = {hex, NULL, 0}; + rc = funcs->C_GetAttributeValue(session, hkey, &temp, 1); + if (rc == CKR_ATTRIBUTE_SENSITIVE && long_print) { + printf(" %s: SENSITIVE\n", confignode_to_bareval(name)->value); + } else if (rc != CKR_ATTRIBUTE_TYPE_INVALID && rc != CKR_OK) { + return rc; + } else if (rc == CKR_OK && temp.ulValueLen != CK_UNAVAILABLE_INFORMATION) { + // build template + unsigned long a_byte_array = temp.ulValueLen; + temp.pValue = malloc(a_byte_array); + if (!temp.pValue) { + fprintf(stderr, "Error: cannot malloc storage for attribute value.\n"); + return CKR_HOST_MEMORY; + } + + // get attribute value + rc = funcs->C_GetAttributeValue(session, hkey, &temp, 1); + if (rc == CKR_OK) { + if (temp.ulValueLen != a_byte_array) { + fprintf(stderr, " Error in retrieving Attribute %s: %lu\n", + confignode_to_bareval(name)->value, temp.ulValueLen); + } else { + if (long_print) { + dump_attr(&temp); + } else { + printf(" 1 "); + free(temp.pValue); + return CKR_OK; + } + } + } + free(temp.pValue); + } + } else { + fprintf(stderr, "Error: Attribute type [%s] invalid.\n", confignode_to_bareval(type)->value); + } + } + } + } + if (!long_print) + printf(" %s ", def_attr ? "0" : "-"); + + return CKR_OK; +} + +/** + * Print standard attributes + */ static void short_print(int col, CK_ATTRIBUTE attr[], p11sak_kt ktype) { int j = 0; @@ -1144,7 +1383,7 @@ } for (j = 0; j < attr_count; j++) { - if (attr[j].type == col2type(col) && !attr_na(attr[j], ktype)) { + if (attr[j].type == col2type(col) && !attr_na(attr[j].type, ktype)) { printf(" %d ", *(CK_BBOOL*) attr[j].pValue); return; } @@ -1178,22 +1417,28 @@ CK_BBOOL a_extractable; CK_BBOOL a_always_sensitive; CK_BBOOL a_never_extractable; - CK_ULONG bs = sizeof(CK_BBOOL); - CK_ATTRIBUTE bool_tmplt[] = { { CKA_TOKEN, &a_token, bs }, { CKA_PRIVATE, - &a_private, bs }, { CKA_MODIFIABLE, &a_modifiable, bs }, { - CKA_DERIVE, &a_derive, bs }, { CKA_LOCAL, &a_local, bs }, { - CKA_SENSITIVE, &a_sensitive, bs }, { CKA_ENCRYPT, &a_encrypt, bs }, { - CKA_DECRYPT, &a_decrypt, bs }, { CKA_SIGN, &a_sign, bs }, { - CKA_VERIFY, &a_verify, bs }, { CKA_WRAP, &a_wrap, bs }, { - CKA_UNWRAP, &a_unwrap, bs }, { CKA_EXTRACTABLE, &a_extractable, bs }, { - CKA_ALWAYS_SENSITIVE, &a_always_sensitive, bs }, { - CKA_NEVER_EXTRACTABLE, &a_never_extractable, bs }, }; + CK_ATTRIBUTE bool_tmplt[] = { + { CKA_TOKEN, &a_token, sizeof(a_token) }, + { CKA_PRIVATE, &a_private, sizeof(a_private) }, + { CKA_MODIFIABLE, &a_modifiable, sizeof(a_modifiable) }, + { CKA_DERIVE, &a_derive, sizeof(a_derive) }, + { CKA_LOCAL, &a_local, sizeof(a_local) }, + { CKA_SENSITIVE, &a_sensitive, sizeof(a_sensitive) }, + { CKA_ENCRYPT, &a_encrypt, sizeof(a_encrypt) }, + { CKA_DECRYPT, &a_decrypt, sizeof(a_decrypt) }, + { CKA_SIGN, &a_sign, sizeof(a_sign) }, + { CKA_VERIFY, &a_verify, sizeof(a_verify) }, + { CKA_WRAP, &a_wrap, sizeof(a_wrap) }, + { CKA_UNWRAP, &a_unwrap, sizeof(a_unwrap) }, + { CKA_EXTRACTABLE, &a_extractable, sizeof(a_extractable) }, + { CKA_ALWAYS_SENSITIVE, &a_always_sensitive, sizeof(a_always_sensitive) }, + { CKA_NEVER_EXTRACTABLE, &a_never_extractable, sizeof(a_never_extractable) } }; CK_ULONG count = sizeof(bool_tmplt) / sizeof(CK_ATTRIBUTE); rc = funcs->C_GetAttributeValue(session, hkey, bool_tmplt, count); if (rc != CKR_OK) { - printf("Attribute retrieval failed (error code 0x%lX: %s)\n", rc, + fprintf(stderr, "Attribute retrieval failed (error code 0x%lX: %s)\n", rc, p11_get_ckr(rc)); return rc; } @@ -1201,18 +1446,29 @@ if (long_print) { for (i = 0; i < (int) count; i++) { if (bool_tmplt[i].ulValueLen != sizeof(CK_BBOOL)) { - printf(" Error in retrieving Attribute %s\n", + fprintf(stderr, " Error in retrieving Attribute %s\n", CKA2a(bool_tmplt[i].type)); } else { printf(" %s: %s\n", CKA2a(bool_tmplt[i].type), CK_BBOOL2a(*(CK_BBOOL*) bool_tmplt[i].pValue)); } } - printf("|\n"); + rc = print_custom_attrs(session, hkey, long_print); + if (rc != CKR_OK) { + fprintf(stderr, "Attribute retrieval failed (error code 0x%lX: %s)\n", rc, + p11_get_ckr(rc)); + return rc; + } } else { printf(" |"); - for (i = 2; i < KEY_MAX_BOOL_ATTR_COUNT; i++) + for (i = 1; i < KEY_MAX_BOOL_ATTR_COUNT; i++) short_print(i, bool_tmplt, kt_SECRET); + rc = print_custom_attrs(session, hkey, long_print); + if (rc != CKR_OK) { + fprintf(stderr, "Attribute retrieval failed (error code 0x%lX: %s)\n", rc, + p11_get_ckr(rc)); + return rc; + } printf("|"); } @@ -1240,21 +1496,25 @@ CK_BBOOL a_extractable; CK_BBOOL a_always_sensitive; CK_BBOOL a_never_extractable; - CK_ULONG bs = sizeof(CK_BBOOL); - CK_ATTRIBUTE bool_tmplt[] = { { CKA_TOKEN, &a_token, bs }, { CKA_PRIVATE, - &a_private, bs }, { CKA_MODIFIABLE, &a_modifiable, bs }, { - CKA_DERIVE, &a_derive, bs }, { CKA_LOCAL, &a_local, bs }, { - CKA_SENSITIVE, &a_sensitive, bs }, { CKA_DECRYPT, &a_decrypt, bs }, { - CKA_SIGN, &a_sign, bs }, { CKA_UNWRAP, &a_unwrap, bs }, { - CKA_EXTRACTABLE, &a_extractable, bs }, { - CKA_ALWAYS_SENSITIVE, &a_always_sensitive, bs }, { - CKA_NEVER_EXTRACTABLE, &a_never_extractable, bs } }; + CK_ATTRIBUTE bool_tmplt[] = { + { CKA_TOKEN, &a_token, sizeof(a_token) }, + { CKA_PRIVATE, &a_private, sizeof(a_private) }, + { CKA_MODIFIABLE, &a_modifiable, sizeof(a_modifiable) }, + { CKA_DERIVE, &a_derive, sizeof(a_derive) }, + { CKA_LOCAL, &a_local, sizeof(a_local) }, + { CKA_SENSITIVE, &a_sensitive, sizeof(a_sensitive) }, + { CKA_DECRYPT, &a_decrypt, sizeof(a_decrypt) }, + { CKA_SIGN, &a_sign, sizeof(a_sign) }, + { CKA_UNWRAP, &a_unwrap, sizeof(a_unwrap) }, + { CKA_EXTRACTABLE, &a_extractable, sizeof(a_extractable) }, + { CKA_ALWAYS_SENSITIVE, &a_always_sensitive, sizeof(a_always_sensitive) }, + { CKA_NEVER_EXTRACTABLE, &a_never_extractable, sizeof(a_never_extractable) } }; CK_ULONG count = sizeof(bool_tmplt) / sizeof(CK_ATTRIBUTE); rc = funcs->C_GetAttributeValue(session, hkey, bool_tmplt, count); if (rc != CKR_OK) { - printf("Attribute retrieval failed (error code 0x%lX: %s)\n", rc, + fprintf(stderr, "Attribute retrieval failed (error code 0x%lX: %s)\n", rc, p11_get_ckr(rc)); return rc; } @@ -1263,19 +1523,30 @@ if (long_print) { for (i = 0; i < (int) count; i++) { if (bool_tmplt[i].ulValueLen != sizeof(CK_BBOOL)) { - printf(" Error in retrieving Attribute %s\n", + fprintf(stderr, " Error in retrieving Attribute %s\n", CKA2a(bool_tmplt[i].type)); } else { printf(" %s: %s\n", CKA2a(bool_tmplt[i].type), CK_BBOOL2a(*(CK_BBOOL*) bool_tmplt[i].pValue)); } } - printf("|\n"); + rc = print_custom_attrs(session, hkey, long_print); + if (rc != CKR_OK) { + fprintf(stderr, "Attribute retrieval failed (error code 0x%lX: %s)\n", rc, + p11_get_ckr(rc)); + return rc; + } } else { /* Short print */ printf(" |"); - for (i = 2; i < KEY_MAX_BOOL_ATTR_COUNT; i++) + for (i = 1; i < KEY_MAX_BOOL_ATTR_COUNT; i++) short_print(i, bool_tmplt, kt_PRIVATE); + rc = print_custom_attrs(session, hkey, long_print); + if (rc != CKR_OK) { + fprintf(stderr, "Attribute retrieval failed (error code 0x%lX: %s)\n", rc, + p11_get_ckr(rc)); + return rc; + } printf("|"); } @@ -1299,18 +1570,21 @@ CK_BBOOL a_encrypt; CK_BBOOL a_verify; CK_BBOOL a_wrap; - CK_ULONG bs = sizeof(CK_BBOOL); - CK_ATTRIBUTE bool_tmplt[] = { { CKA_TOKEN, &a_token, bs }, { CKA_PRIVATE, - &a_private, bs }, { CKA_MODIFIABLE, &a_modifiable, bs }, { - CKA_DERIVE, &a_derive, bs }, { CKA_LOCAL, &a_local, bs }, { - CKA_ENCRYPT, &a_encrypt, bs }, { CKA_VERIFY, &a_verify, bs }, { - CKA_WRAP, &a_wrap, bs } }; + CK_ATTRIBUTE bool_tmplt[] = { + { CKA_TOKEN, &a_token, sizeof(a_token) }, + { CKA_PRIVATE, &a_private, sizeof(a_private) }, + { CKA_MODIFIABLE, &a_modifiable, sizeof(a_modifiable) }, + { CKA_DERIVE, &a_derive, sizeof(a_derive) }, + { CKA_LOCAL, &a_local, sizeof(a_local) }, + { CKA_ENCRYPT, &a_encrypt, sizeof(a_encrypt) }, + { CKA_VERIFY, &a_verify, sizeof(a_verify) }, + { CKA_WRAP, &a_wrap, sizeof(a_wrap) }, }; CK_ULONG count = sizeof(bool_tmplt) / sizeof(CK_ATTRIBUTE); rc = funcs->C_GetAttributeValue(session, hkey, bool_tmplt, count); if (rc != CKR_OK) { - printf("Attribute retrieval failed (error code 0x%lX: %s)\n", rc, + fprintf(stderr, "Attribute retrieval failed (error code 0x%lX: %s)\n", rc, p11_get_ckr(rc)); return rc; } @@ -1319,19 +1593,30 @@ if (long_print) { for (i = 0; i < (int) count; i++) { if (bool_tmplt[i].ulValueLen != sizeof(CK_BBOOL)) { - printf(" Error in retrieving Attribute %s\n", + fprintf(stderr, " Error in retrieving Attribute %s\n", CKA2a(bool_tmplt[i].type)); } else { printf(" %s: %s\n", CKA2a(bool_tmplt[i].type), CK_BBOOL2a(*(CK_BBOOL*) bool_tmplt[i].pValue)); } } - printf("|\n"); + rc = print_custom_attrs(session, hkey, long_print); + if (rc != CKR_OK) { + fprintf(stderr, "Attribute retrieval failed (error code 0x%lX: %s)\n", rc, + p11_get_ckr(rc)); + return rc; + } } else { /* Short print */ printf(" |"); - for (i = 2; i < KEY_MAX_BOOL_ATTR_COUNT; i++) + for (i = 1; i < KEY_MAX_BOOL_ATTR_COUNT; i++) short_print(i, bool_tmplt, kt_PUBLIC); + rc = print_custom_attrs(session, hkey, long_print); + if (rc != CKR_OK) { + fprintf(stderr, "Attribute retrieval failed (error code 0x%lX: %s)\n", rc, + p11_get_ckr(rc)); + return rc; + } printf("|"); } @@ -1346,29 +1631,42 @@ CK_RV rc; char *label; CK_ATTRIBUTE template[1] = { { CKA_LABEL, NULL_PTR, 0 } }; + CK_ULONG label_len; rc = funcs->C_GetAttributeValue(session, hkey, template, 1); if (rc != CKR_OK) { - printf("Key cannot show CKA_LABEL attribute (error code 0x%lX: %s)\n", + fprintf(stderr, "Key cannot show CKA_LABEL attribute (error code 0x%lX: %s)\n", rc, p11_get_ckr(rc)); return rc; } - label = malloc(template[0].ulValueLen + 1); + if (template[0].ulValueLen == CK_UNAVAILABLE_INFORMATION) { + /* assume empty label */ + *plabel = strdup(""); + if (!*plabel) { + fprintf(stderr, "Error: cannot malloc storage for label.\n"); + return CKR_HOST_MEMORY; + } + return CKR_OK; + } + + label_len = template[0].ulValueLen; + label = malloc(label_len + 1); if (!label) { - printf("Error: cannot malloc storage for label.\n"); + fprintf(stderr, "Error: cannot malloc storage for label.\n"); return CKR_HOST_MEMORY; } template[0].pValue = label; rc = funcs->C_GetAttributeValue(session, hkey, template, 1); if (rc != CKR_OK) { - printf("Error retrieving CKA_LABEL attribute (error code 0x%lX: %s)\n", + fprintf(stderr, "Error retrieving CKA_LABEL attribute (error code 0x%lX: %s)\n", rc, p11_get_ckr(rc)); + free(label); return rc; } - label[template[0].ulValueLen] = 0; + label[label_len] = 0; *plabel = label; return CKR_OK; @@ -1391,7 +1689,7 @@ rc = funcs->C_GetAttributeValue(session, hkey, template, 1); if (rc != CKR_OK) { - printf( + fprintf(stderr, "Object does not have CKA_CLASS attribute (error code 0x%lX: %s)\n", rc, p11_get_ckr(rc)); return rc; @@ -1420,7 +1718,7 @@ default: // FIXIT - return code to represent object class invalid rc = CKR_KEY_HANDLE_INVALID; - printf("Object handle invalid (error code 0x%lX: %s)\n", + fprintf(stderr, "Object handle invalid (error code 0x%lX: %s)\n", rc, p11_get_ckr(rc)); free(buffer); return rc; @@ -1431,7 +1729,7 @@ template[0].ulValueLen = sizeof(CK_KEY_TYPE); rc = funcs->C_GetAttributeValue(session, hkey, template, 1); if (rc != CKR_OK) { - printf("Object does not have CKA_KEY_TYPE attribute (error code 0x%lX: %s)\n", + fprintf(stderr, "Object does not have CKA_KEY_TYPE attribute (error code 0x%lX: %s)\n", rc, p11_get_ckr(rc)); free(buffer); return rc; @@ -1448,7 +1746,7 @@ template[0].ulValueLen = sizeof(CK_ULONG); rc = funcs->C_GetAttributeValue(session, hkey, template, 1); if (rc != CKR_OK) { - printf("Object does not have CKA_VALUE_LEN attribute (error code 0x%lX: %s)\n", + fprintf(stderr, "Object does not have CKA_VALUE_LEN attribute (error code 0x%lX: %s)\n", rc, p11_get_ckr(rc)); free(buffer); return rc; @@ -1480,7 +1778,7 @@ if ((keylength == 128) || (keylength == 192) || (keylength == 256)) { break; } else { - printf( + fprintf(stderr, "Cipher key type [%d] and key bit length %ld is not supported. Try adding argument -bits <128|192|256>\n", *kt, keylength); return CKR_ARGUMENTS_BAD; @@ -1490,14 +1788,14 @@ if ((keylength == 1024) || (keylength == 2048) || (keylength == 4096)) { break; } else { - printf( + fprintf(stderr, "[%d] RSA modulus bit length %ld NOT supported. Try adding argument -bits <1024|2048|4096>\n", *kt, keylength); } break; case kt_EC: if (ECcurve == NULL) { - printf( + fprintf(stderr, "Cipher key type [%d] supported but EC curve not set in arguments. Try argument -curve \n", *kt); return CKR_ARGUMENTS_BAD; @@ -1509,7 +1807,7 @@ case kt_PRIVATE: break; default: - printf("Cipher key type [%d] is not set or not supported\n", *kt); + fprintf(stderr, "Cipher key type [%d] is not set or not supported\n", *kt); print_gen_help(); return CKR_ARGUMENTS_BAD; } @@ -1531,9 +1829,10 @@ case kt_SECRET: case kt_PUBLIC: case kt_PRIVATE: + case kt_ALL: break; default: - printf("Cipher key type [%d] is not set or not supported\n", *kt); + fprintf(stderr, "Cipher key type [%d] is not set or not supported\n", *kt); print_listkeys_help(); return CKR_ARGUMENTS_BAD; } @@ -1557,7 +1856,7 @@ case kt_PRIVATE: break; default: - printf("Cipher key type [%d] is not set or not supported\n", *kt); + fprintf(stderr, "Cipher key type [%d] is not set or not supported\n", *kt); print_gen_help(); return CKR_ARGUMENTS_BAD; } @@ -1581,7 +1880,7 @@ || (strcmp(arg, "rm") == 0)) { cmd = remove_key; } else { - printf("Unknown command %s\n", cmd2str(cmd)); + fprintf(stderr, "Unknown command %s\n", cmd2str(cmd)); cmd = no_cmd; } return cmd; @@ -1657,6 +1956,9 @@ } else if (strcmp(argv[i], "PRIVATE") == 0 || strcmp(argv[i], "private") == 0) { *kt = kt_PRIVATE; + } else if (strcmp(argv[i], "ALL") == 0 + || strcmp(argv[i], "all") == 0) { + *kt = kt_ALL; /* Get options */ } else if (strcmp(argv[i], "--slot") == 0) { if (i + 1 < argc) { @@ -1666,23 +1968,23 @@ if (errno != 0) { perror("strtol"); - printf("--slot argument must be specified correctly.\n"); + fprintf(stderr, "--slot argument must be specified correctly.\n"); return CKR_ARGUMENTS_BAD; } if (endptr == str) { - printf("--slot argument must be specified correctly.\n"); + fprintf(stderr, "--slot argument must be specified correctly.\n"); return CKR_ARGUMENTS_BAD; } if (*endptr != '\0') { - printf("--slot argument must be specified correctly.\n"); + fprintf(stderr, "--slot argument must be specified correctly.\n"); return CKR_ARGUMENTS_BAD; } slotIDset = CK_TRUE; } else { - printf("--slot argument is missing.\n"); + fprintf(stderr, "--slot argument is missing.\n"); return CKR_ARGUMENTS_BAD; } i++; @@ -1690,7 +1992,7 @@ if (i + 1 < argc) { *pin = argv[i + 1]; } else { - printf("--pin argument is missing.\n"); + fprintf(stderr, "--pin argument is missing.\n"); return CKR_ARGUMENTS_BAD; } i++; @@ -1702,7 +2004,7 @@ print_listkeys_help(); return CKR_ARGUMENTS_BAD; } else { - printf("Unknown argument or option %s for command list-key\n", + fprintf(stderr, "Unknown argument or option %s for command list-key\n", argv[i]); return CKR_ARGUMENTS_BAD; } @@ -1711,7 +2013,7 @@ rc = check_args_list_key(kt); if (!slotIDset) { - printf("--slot must be specified.\n"); + fprintf(stderr, "--slot must be specified.\n"); rc = CKR_ARGUMENTS_BAD; } @@ -1762,23 +2064,23 @@ if (errno != 0) { perror("strtol"); - printf("--slot argument must be specified correctly.\n"); + fprintf(stderr, "--slot argument must be specified correctly.\n"); return CKR_ARGUMENTS_BAD; } if (endptr == str) { - printf("--slot argument must be specified correctly.\n"); + fprintf(stderr, "--slot argument must be specified correctly.\n"); return CKR_ARGUMENTS_BAD; } if (*endptr != '\0') { - printf("--slot argument must be specified correctly.\n"); + fprintf(stderr, "--slot argument must be specified correctly.\n"); return CKR_ARGUMENTS_BAD; } slotIDset = CK_TRUE; } else { - printf("--slot argument is missing.\n"); + fprintf(stderr, "--slot argument is missing.\n"); return CKR_ARGUMENTS_BAD; } i++; @@ -1786,7 +2088,7 @@ if (i + 1 < argc) { *pin = argv[i + 1]; } else { - printf("--pin argument is missing.\n"); + fprintf(stderr, "--pin argument is missing.\n"); return CKR_ARGUMENTS_BAD; } i++; @@ -1794,7 +2096,7 @@ if (i + 1 < argc) { *label = argv[i + 1]; } else { - printf("--label