From 8aa27dc2edbd225ad179b0db77a7f01cbfdeff9a Mon Sep 17 00:00:00 2001 From: Packit Service Date: Dec 08 2020 10:13:22 +0000 Subject: opencryptoki-3.15.1 base --- diff --git a/.gitignore b/.gitignore index 4400b26..6ecc154 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,7 @@ usr/sbin/pkcsep11_session/.deps/ usr/sbin/pkcsicsf/.deps/ usr/sbin/pkcsslotd/.deps/ usr/sbin/p11sak/.deps/ +usr/sbin/pkcstok_migrate/.deps/ misc/pkcsslotd @@ -447,4 +448,5 @@ usr/sbin/pkcsslotd/usr_sbin_pkcsslotd_pkcsslotd-slotmgr.o usr/sbin/pkcsslotd/usr_sbin_pkcsslotd_pkcsslotd-socket_server.o usr/sbin/p11sak/.dirstamp usr/sbin/p11sak/p11sak -usr/sbin/p11sak/usr_sbin_p11sak_p11sak-p11sak.o \ No newline at end of file +usr/sbin/p11sak/usr_sbin_p11sak_p11sak-p11sak.o +usr/sbin/pkcstok_migrate/.dirstamp \ No newline at end of file diff --git a/ChangeLog b/ChangeLog index d59a0a4..e9c6e7a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,16 @@ -+ Opencryptoki 3.14 ++ openCryptoki 3.15.1 +- Bug fixes + ++ openCryptoki 3.15 +- common: conform to PKCS 11 3.0 Baseline Provider profile +- Introduce new vendor defined interface named "Vendor IBM" +- Support C_IBM_ReencryptSingle via "Vendor IBM" interface +- CCA: support key wrapping +- SOFT: support ECC +- p11sak tool: add remove-key command +- Bug fixes + ++ openCryptoki 3.14 - EP11: Dilitium support stage 2 - Common: Rework on process and thread locking - Common: Rework on btree and object locking diff --git a/Makefile.am b/Makefile.am index 6f6826f..28a90b2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -165,6 +165,8 @@ if ENABLE_EP11TOK if test -d $(DESTDIR)$(libdir)/opencryptoki/stdll; then \ cd $(DESTDIR)$(libdir)/opencryptoki/stdll && \ rm -f PKCS11_EP11.so; fi + rm -f $(DESTDIR)$(sysconfdir)/opencryptoki/ep11tok.conf + rm -f $(DESTDIR)$(sysconfdir)/opencryptoki/ep11cpfilter.conf endif if ENABLE_ICATOK if test -d $(DESTDIR)$(libdir)/opencryptoki/stdll; then \ diff --git a/README.md b/README.md index 9a72606..ac6858d 100644 --- a/README.md +++ b/README.md @@ -3,13 +3,13 @@ # openCryptoki -Package version 3.14 +Package version 3.15 Please see [ChangeLog](ChangeLog) for release specific information. ## OVERVIEW -openCryptoki version 3.14 implements the PKCS#11 specification version 2.20. +openCryptoki version 3.15 implements the PKCS#11 specification version 3.0. This package includes several cryptographic tokens: CCA, ICA, TPM , SWToken, ICSF and EP11. diff --git a/configure.ac b/configure.ac index 289c505..f30e126 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) -AC_INIT([openCryptoki],[3.14.0],[opencryptoki-tech@lists.sourceforge.net],[],[https://github.com/opencryptoki/opencryptoki]) +AC_INIT([openCryptoki],[3.15.1],[opencryptoki-tech@lists.sourceforge.net],[],[https://github.com/opencryptoki/opencryptoki]) AC_CONFIG_SRCDIR([testcases/common/common.c]) dnl Needed for $target! @@ -16,7 +16,7 @@ AC_HEADER_STDC AC_CHECK_HEADER_STDBOOL AC_CHECK_HEADERS([arpa/inet.h fcntl.h libintl.h limits.h locale.h malloc.h \ nl_types.h stddef.h sys/file.h sys/socket.h sys/time.h \ - sys/timeb.h syslog.h termios.h]) + syslog.h termios.h]) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_INLINE @@ -189,6 +189,12 @@ AC_ARG_ENABLE([p11sak], [], [enable_p11sak=yes]) +dnl --- pkcstok_migrate +AC_ARG_ENABLE([pkcstok_migrate], + AS_HELP_STRING([--enable-pkcstok_migrate],[build pkcstok_migrate tool @<:@default=enabled@:>@]), + [], + [enable_pkcstok_migrate=yes]) + dnl --- dnl --- Check for external software dnl --- Define what to check based on enabled features @@ -592,6 +598,9 @@ AM_CONDITIONAL([ENABLE_PKCSEP11_SESSION], [test "x$enable_pkcsep11_session" = "x dnl --- enable_p11sak AM_CONDITIONAL([ENABLE_P11SAK], [test "x$enable_p11sak" = "xyes"]) +dnl --- enable_pkcstok_migrate +AM_CONDITIONAL([ENABLE_PKCSTOK_MIGRATE], [test "x$enable_pkcstok_migrate" = "xyes"]) + dnl --- enable_locks if test "x$enable_locks" != "xno"; then enable_locks=yes @@ -625,6 +634,7 @@ AC_CONFIG_FILES([Makefile \ man/man1/p11sak.1 \ man/man1/pkcsep11_migrate.1 \ man/man1/pkcsep11_session.1 \ + man/man1/pkcstok_migrate.1 \ man/man5/opencryptoki.conf.5 \ man/man7/opencryptoki.7 \ man/man8/pkcsslotd.8]) @@ -639,6 +649,7 @@ echo " Library build: $enable_library" echo " Systemd service: $enable_systemd" echo " Build with locks: $enable_locks" echo " Build p11sak tool: $enable_p11sak" +echo " token migrate tool: $enable_pkcstok_migrate" echo echo "Enabled token types:" echo " ICA token: $enable_icatok" diff --git a/man/man1/man1.mk b/man/man1/man1.mk index 51d23d3..6102340 100644 --- a/man/man1/man1.mk +++ b/man/man1/man1.mk @@ -1,5 +1,9 @@ man1_MANS += man/man1/pkcsconf.1 man/man1/pkcsicsf.1 +if ENABLE_PKCSTOK_MIGRATE +man1_MANS += man/man1/pkcstok_migrate.1 +endif + if ENABLE_PKCSEP11_MIGRATE man1_MANS += man/man1/pkcsep11_migrate.1 endif diff --git a/man/man1/p11sak.1.in b/man/man1/p11sak.1.in index 1837ad1..3542f46 100644 --- a/man/man1/p11sak.1.in +++ b/man/man1/p11sak.1.in @@ -15,19 +15,22 @@ p11sak \- generate and list token keys in an openCryptoki token repository. .br .SH DESCRIPTION -.B p11sak can be used to generate and list the token keys in an openCryptoki token repository. +.B p11sak can be used to generate, list and delete the token keys in an openCryptoki token repository. The utility provides a flexible key management tool in openCryptoki to list and generate symmetric (DES; 3DES, AES) and asymetric (RSA, EC) keys. This tool is especially capable of a well defined listing of keys with their PKCS #11 attributes. . . . .SH COMMANDS -The \fBp11sak\fP tool can operate in two modes: when command +The \fBp11sak\fP tool can operate in three modes: when command .I generate-key is specified, it operates in the mode to generate a token key in the openCryptoki token repository. -When command +If command .I list-key is given, it lists the keys specified in the arguments. +If command +.I remove-key +is given, it removes the keys specified in the arguments. . .PP .SS "generate-key" @@ -54,7 +57,19 @@ and The .BR \-\-help | \-h option will show the arguments and options available. - +. +.PP +.SS "list-key" +.PP +Use the +.B remove-key|rm-key|rm +command and key argument to delete token keys given the respective +.RI [ ARGS ] +and +.RB [ OPTIONS ]. +The +.BR \-\-help | \-h +option will show the arguments and options available. . .PP .SS "Generating DES/3DES keys" @@ -240,6 +255,31 @@ Use the 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. . .PP +.SS "Deleting symmetric and asymmetric keys" +. +.B p11sak +.BR remove-key | rm-key | rm +.BR des | 3des | aes | rsa | ec +.B \-\-slot +.IR SLOTID +.B \-\-pin +.IR PIN +.B \-\-label +.IR LABEL +.B \-\-force | \-f +.B \-\-help | \-h +.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 +a specific key with the +.B \-\-label +.IR LABEL +argument is selected. The user will be promted to confirm the deletion of the key. To suppress the promt, use the +.B \-\-force | \-f +option. +. +.PP . . . @@ -379,6 +419,14 @@ output in long format. If omitted, the output is in a short, tabular format. . . . +.SS "\-\-force | \-f" +to be used with the +.B remove-key +command to suppress the promt whether the user wants to delete the specified keys. +.PP +. +. +. .SS "\-\-help | \-h" prints help for the usage of .B p11sak diff --git a/man/man1/pkcstok_migrate.1.in b/man/man1/pkcstok_migrate.1.in new file mode 100644 index 0000000..b17d10b --- /dev/null +++ b/man/man1/pkcstok_migrate.1.in @@ -0,0 +1,69 @@ +.\" pkcstok_migrate.1 +.\" +.\" Copyright IBM Corp. 2020 +.\" See LICENSE for details. +.\" +.TH PKCSTOK_MIGRATE 1 "June 2020" "@PACKAGE_VERSION@" "openCryptoki" +.SH NAME +pkcstok_migrate \- utility to migrate an ICA, CCA, Soft, or EP11 token repository +to the FIPS compliant format introduced with openCryptoki 3.12. + +.SH SYNOPSIS +\fBpkcstok_migrate\fP [\fB-h\fP] +.br +\fBpkcstok_migrate\fP \fB--slotid\fP \fIslot-number\fP \fB--datastore\fP \fIdatastore\fP +\fB--confdir\fP \fIconfdir\fP [\fB--sopin\fP \fIsopin\fP] [\fB--userpin\fP +\fIuserpin\fP] [\fB--verbose\fP \fIlevel\fP] + +.SH DESCRIPTION +Convert all objects inside a token repository to the new format introduced with +version 3.12. All encrypted data inside the new format is stored using FIPS +compliant methods. The new format affects the token's master key files (MK_SO +and MK_USER), the NVTOK.DAT, and the token object files in the TOK_OBJ folder. + +While using this tool no process using the token to be migrated must be running. +Especially the pkcsslotd must be stopped before running this tool. + +The tool creates a backup of the token repository to be migrated, and performs +all migration actions on this backup, leaving the original repository folder +completely untouched. The backup folder is located in the same directory as the +original repository and is suffixed with _PKCSTOK_MIGRATE_TMP. + +After a successful migration, the original repository is renamed with a suffix +of _BAK and the backup folder is renamed to the original repository name, so +that the migrated repository can immediately be used. The old folder may be +deleted by the user manually later. + +After a successful migration, the tool adds parameter 'tokversion = 3.12' to the +token's slot configuration in the opencryptoki.conf file. The original config +file is still available as opencryptoki.conf_BAK and may be removed by the user +manually. + +After an unsuccessful migration, the original repository is still available +unchanged. + +.SH "OPTIONS SUMMARY" +.IP "\fB--slotid -s\fP \fISLOT-NUMBER\fP" 10 +specifies the token slot number of the token repository to be migrated +.IP "\fB--datastore -d\fP \fIDATASTORE\fP" 10 +specifies the directory of the token repository to be migrated. +.IP "\fB--confdir -c\fP \fICONFDIR\fP" 10 +specifies the directory where the opencryptoki.conf file is located. +.IP "\fB--sopin -p\fP \fISOPIN\fP" 10 +specifies the SO pin. If not specified, the SO pin is prompted. +.IP "\fB--userpin -u\fP \fIUSERPIN\fP" 10 +specifies the user pin. If not specified, the user pin is prompted. +.IP "\fB--verbose -v\fP \fILEVEL\fP" 10 +specifies the verbose level: \fInone\fP, error, warn, info, devel, debug +.IP "\fB--help -h\fP" 10 +show usage information + +.SH SEE ALSO +.PD 0 +.TP +\fBpkcsconf\fP(1), +.TP +\fBopencryptoki\fP(7), +.TP +\fBpkcsslotd\fP(8). +.PD diff --git a/misc/rsa_parser.pl b/misc/rsa_parser.pl index 5bd8f30..27412b2 100644 --- a/misc/rsa_parser.pl +++ b/misc/rsa_parser.pl @@ -78,7 +78,7 @@ $begin_siglen = "\t\t.sig_len = "; # giant block of generated tests that I copy-pasted here. # this could be replaced with some functions that generate the data below -# TODO: CKM_CDMF_KEY_GEN doesn't seem to be supported by ICA, CCA or SoftTok, +# TODO: CKM_CDMF_KEY_GEN doesn't seem to be supported by ICA, CCA or Soft, # so those tests can be removed $defheader = "#include \"pkcs11types.h\" #define MAX_MODULUS_SIZE 256 diff --git a/opencryptoki.map b/opencryptoki.map index d182817..40ae614 100644 --- a/opencryptoki.map +++ b/opencryptoki.map @@ -59,6 +59,7 @@ OPENCRYPTOKI_3.10 { C_SignRecover; C_SignRecoverInit; C_SignUpdate; + C_WrapKey; C_UnwrapKey; C_Verify; C_VerifyFinal; @@ -67,6 +68,32 @@ OPENCRYPTOKI_3.10 { C_VerifyRecoverInit; C_VerifyUpdate; C_WaitForSlotEvent; - C_WrapKey; + + C_GetInterfaceList; + C_GetInterface; + C_LoginUser; + C_SessionCancel; + C_MessageEncryptInit; + C_EncryptMessage; + C_EncryptMessageBegin; + C_EncryptMessageNext; + C_MessageEncryptFinal; + C_MessageDecryptInit; + C_DecryptMessage; + C_DecryptMessageBegin; + C_DecryptMessageNext; + C_MessageDecryptFinal; + C_MessageSignInit; + C_SignMessage; + C_SignMessageBegin; + C_SignMessageNext; + C_MessageSignFinal; + C_MessageVerifyInit; + C_VerifyMessage; + C_VerifyMessageBegin; + C_VerifyMessageNext; + C_MessageVerifyFinal; + + C_IBM_ReencryptSingle; local: *; }; diff --git a/opencryptoki_tok.map b/opencryptoki_tok.map index 2713f74..771d35a 100644 --- a/opencryptoki_tok.map +++ b/opencryptoki_tok.map @@ -64,6 +64,7 @@ OPENCRYPTOKI_TOK_3.10 { SC_VerifyUpdate; SC_WaitForSlotEvent; SC_WrapKey; + SC_IBM_ReencryptSingle; ST_Initialize; local: *; }; diff --git a/rpm/opencryptoki.spec b/rpm/opencryptoki.spec index fa4b989..fa4efa5 100644 --- a/rpm/opencryptoki.spec +++ b/rpm/opencryptoki.spec @@ -1,8 +1,8 @@ %global _hardened_build 1 Name: opencryptoki -Summary: Implementation of the PKCS#11 (Cryptoki) specification v2.20 -Version: 3.14.0 +Summary: Implementation of the PKCS#11 (Cryptoki) specification v3.0 +Version: 3.15.1 Release: 1%{?dist} License: CPL Group: System Environment/Base @@ -238,7 +238,11 @@ exit 0 %{_unitdir}/pkcsslotd.service %{_sbindir}/pkcsconf %{_sbindir}/pkcsslotd +%{_sbindir}/p11sak +%{_sbindir}/pkcstok_migrate %{_mandir}/man1/pkcsconf.1* +%{_mandir}/man1/p11sak.1* +%{_mandir}/man1/pkcstok_migrate.1* %{_mandir}/man5/%{name}.conf.5* %{_mandir}/man7/%{name}.7* %{_mandir}/man8/pkcsslotd.8* diff --git a/testcases/common/common.c b/testcases/common/common.c index 444dc61..a0ea525 100644 --- a/testcases/common/common.c +++ b/testcases/common/common.c @@ -17,6 +17,8 @@ #include "regress.h" CK_FUNCTION_LIST *funcs; +CK_FUNCTION_LIST_3_0 *funcs3; +CK_INTERFACE *ifs; CK_SLOT_ID SLOT_ID; CK_BBOOL skip_token_obj; @@ -45,6 +47,12 @@ static void unload_pkcslib(void) } } +static void free_ifs(void) +{ + free(ifs); + ifs = NULL; +} + int mech_supported(CK_SLOT_ID slot_id, CK_ULONG mechanism) { CK_MECHANISM_INFO mech_info; @@ -412,6 +420,43 @@ CK_RV generate_RSA_PKCS_KeyPair(CK_SESSION_HANDLE session, // see rsa_func.c } +/** Generate an EC key pair **/ +CK_RV generate_EC_KeyPair(CK_SESSION_HANDLE session, + CK_BYTE* ec_params, CK_ULONG ec_params_len, + CK_OBJECT_HANDLE * publ_key, + CK_OBJECT_HANDLE * priv_key) +{ + CK_RV rc; + 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, ec_params, ec_params_len}, + }; + 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)}, + }; + CK_ULONG num_publ_attrs = sizeof(publicKeyTemplate)/sizeof(CK_ATTRIBUTE); + CK_ULONG num_priv_attrs = sizeof(privateKeyTemplate)/sizeof(CK_ATTRIBUTE); + + // generate keys + rc = funcs->C_GenerateKeyPair(session, + &mech, + publicKeyTemplate, num_publ_attrs, + privateKeyTemplate, num_priv_attrs, + publ_key, priv_key); + + return rc; +} + /** Create an EC private key using private value 'd' and ec parameter values (alg id of curve) **/ CK_RV create_ECPrivateKey(CK_SESSION_HANDLE session, @@ -830,7 +875,8 @@ int is_icsf_token(CK_SLOT_ID slot_id) if ((strstr((const char *) tokinfo.model, "ICA") == NULL) && (strstr((const char *) tokinfo.model, "EP11") == NULL) && (strstr((const char *) tokinfo.model, "CCA") == NULL) && - (strstr((const char *) tokinfo.model, "SoftTok") == NULL)) + (strstr((const char *) tokinfo.model, "Soft") == NULL) && + (strstr((const char *) tokinfo.model, "TPM") == NULL)) return TRUE; return FALSE; @@ -870,7 +916,7 @@ int is_cca_token(CK_SLOT_ID slot_id) return strstr((const char *) tokinfo.model, "CCA") != NULL; } -/** Returns true if slot_id is a SoftTok Token **/ +/** Returns true if slot_id is a Soft Token **/ int is_soft_token(CK_SLOT_ID slot_id) { CK_RV rc; @@ -880,7 +926,7 @@ int is_soft_token(CK_SLOT_ID slot_id) if (rc != CKR_OK) return FALSE; - return strstr((const char *) tokinfo.model, "SoftTok") != NULL; + return strstr((const char *) tokinfo.model, "Soft") != NULL; } /** Returns true if slot_id is a TPM Token **/ @@ -966,8 +1012,8 @@ int get_user_pin(CK_BYTE * dest) void process_time(SYSTEMTIME t1, SYSTEMTIME t2) { - long ms = t2.millitm - t1.millitm; - long s = t2.time - t1.time; + long ms = (t2.tv_usec - t1.tv_usec) / 1000; + long s = t2.tv_sec - t1.tv_sec; while (ms < 0) { ms += 1000; @@ -1062,36 +1108,84 @@ int do_ParseArgs(int argc, char **argv) // // -int do_GetFunctionList(void) +CK_BBOOL do_GetFunctionList(void) { + CK_INTERFACE *interface; + CK_VERSION version; + CK_FLAGS flags; + CK_BBOOL rv; CK_RV rc; CK_RV(*pfoo) (); char *e; char *f = "libopencryptoki.so"; + CK_ULONG nmemb = 0; + + rv = FALSE; e = getenv("PKCSLIB"); - if (e == NULL) { + if (e == NULL) e = f; - // return FALSE; - } + pkcs11lib = dlopen(e, RTLD_NOW); - if (pkcs11lib == NULL) { - return FALSE; - } + if (pkcs11lib == NULL) + goto ret; *(void **)(&pfoo) = dlsym(pkcs11lib, "C_GetFunctionList"); + if (pfoo == NULL) + goto ret; + + rc = pfoo(&funcs); + if (rc != CKR_OK) { + testcase_error("C_GetFunctionList rc=%s", p11_get_ckr(rc)); + goto ret; + } + + *(void **)(&pfoo) = dlsym(pkcs11lib, "C_GetInterfaceList"); if (pfoo == NULL) { - dlclose(pkcs11lib); - return FALSE; + goto ret; + } + rc = pfoo(NULL, &nmemb); + if (rc != CKR_OK) { + testcase_error("C_GetInterfaceList rc=%s", p11_get_ckr(rc)); + goto ret; + } + ifs = calloc(nmemb, sizeof(*ifs)); + if (ifs == NULL) { + goto ret; + } + rc = pfoo(ifs, &nmemb); + if (rc != CKR_OK) { + testcase_error("C_GetInterfaceList rc=%s", p11_get_ckr(rc)); + goto ret; } - rc = pfoo(&funcs); + *(void **)(&pfoo) = dlsym(pkcs11lib, "C_GetInterface"); + if (pfoo == NULL) { + goto ret; + } + version.major = 0x03; + version.minor = 0x00; + flags = CKF_INTERFACE_FORK_SAFE; + rc = pfoo((CK_UTF8CHAR *)"PKCS 11", &version, &interface, flags); if (rc != CKR_OK) { - testcase_error("C_GetFunctionList rc=%s", p11_get_ckr(rc)); - dlclose(pkcs11lib); - return FALSE; + testcase_error("C_GetInterface rc=%s", p11_get_ckr(rc)); + goto ret; } + funcs3 = interface->pFunctionList; - atexit(unload_pkcslib); - return TRUE; + rv = TRUE; +ret: + if (rv == TRUE) { + atexit(free_ifs); + atexit(unload_pkcslib); + } else { + free(ifs); + ifs = NULL; + + if (pkcs11lib != NULL) { + dlclose(pkcs11lib); + pkcs11lib = NULL; + } + } + return rv; } diff --git a/testcases/crypto/aes.h b/testcases/crypto/aes.h index cdd365c..8a6019a 100644 --- a/testcases/crypto/aes.h +++ b/testcases/crypto/aes.h @@ -95,7 +95,7 @@ struct CK_MECHANISM aes_keygen = { .pParameter = NULL, }; -struct cmac_test_vector { +struct mac_test_vector { unsigned char key[MAX_KEY_SIZE]; unsigned char klen; unsigned char msg[MAX_TEXT_SIZE]; @@ -106,10 +106,10 @@ struct cmac_test_vector { int num_chunks_message; }; -struct published_cmac_test_suite_info { +struct published_mac_test_suite_info { const char *name; unsigned int tvcount; - struct cmac_test_vector *tv; + struct mac_test_vector *tv; CK_MECHANISM mech; }; @@ -940,7 +940,7 @@ static struct aes_test_vector aes_ofb_tv[] = { * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/ * CAVP-TESTING-BLOCK-CIPHER-MODES#CMAC **/ -static struct cmac_test_vector aes128_cmac_tv[] = { +static struct mac_test_vector aes128_cmac_tv[] = { { // 0 (0) .key = { 0xe4,0xb7,0x64,0x5b,0x2f,0x7d,0x63,0xb4,0x67, 0x4c,0xd0,0x19,0x70,0xc9,0xd1,0xec }, @@ -1211,7 +1211,7 @@ static struct cmac_test_vector aes128_cmac_tv[] = { * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/ * CAVP-TESTING-BLOCK-CIPHER-MODES#CMAC **/ -static struct cmac_test_vector aes192_cmac_tv[] = { +static struct mac_test_vector aes192_cmac_tv[] = { { // 0 (0) .key = { 0xaf,0x18,0x9e,0xb9,0x93,0xee,0xd7,0x22,0x5b, 0xd3,0xb6,0x1a,0xf2,0xd3,0xa9,0xa8,0x54,0xc8, @@ -1510,7 +1510,7 @@ static struct cmac_test_vector aes192_cmac_tv[] = { * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/ * CAVP-TESTING-BLOCK-CIPHER-MODES#CMAC **/ -static struct cmac_test_vector aes256_cmac_tv[] = { +static struct mac_test_vector aes256_cmac_tv[] = { { // 0 (0) .key = { 0x95,0xd8,0xaf,0xb8,0xa4,0xb7,0x24,0x5c,0xe7, 0x9f,0x9f,0x9c,0x5d,0xdd,0x40,0xde,0x61,0xb3, @@ -1705,6 +1705,339 @@ static struct cmac_test_vector aes256_cmac_tv[] = { } }; +/** + * Derived CBC-MAC test vectors from AES-CBC test vectors + * https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/ + * block-ciphers#AES + **/ +static struct mac_test_vector aes128_cbc_mac_tv[] = { + { // 0 + .key = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + .klen = 16, + .msg = { 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + .mlen = 16, + .mac = { 0x3a,0xd7,0x8e,0x72,0x6c,0x1e,0xc0,0x2b,0x7e, + 0xbf,0xe9,0x2b,0x23,0xd9,0xec,0x34 }, + .tlen = 4, + }, { // 1 + .key = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + .klen = 16, + .msg = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + .mlen = 16, + .mac = { 0xf8,0x07,0xc3,0xe7,0x98,0x5f,0xe0,0xf5,0xa5, + 0x0e,0x2c,0xdb,0x25,0xc5,0x10,0x9e }, + .tlen = 15, + }, { // 2 + .key = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + .klen = 16, + .msg = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff }, + .mlen = 16, + .mac = { 0x3f,0x5b,0x8c,0xc9,0xea,0x85,0x5a,0x0a,0xfa, + 0x73,0x47,0xd2,0x3e,0x8d,0x66,0x4e }, + .tlen = 10, + }, { // 3 + .key = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + .klen = 16, + .msg = { 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + .mlen = 16, + .mac = { 0x3a,0xd7,0x8e,0x72,0x6c,0x1e,0xc0,0x2b,0x7e, + 0xbf,0xe9,0x2b,0x23,0xd9,0xec,0x34 }, + .tlen = 4, + .chunks_msg = { 7, 7, 2 }, + .num_chunks_message = 3, + }, { // 4 + .key = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + .klen = 16, + .msg = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + .mlen = 16, + .mac = { 0xf8,0x07,0xc3,0xe7,0x98,0x5f,0xe0,0xf5,0xa5, + 0x0e,0x2c,0xdb,0x25,0xc5,0x10,0x9e }, + .tlen = 15, + .chunks_msg = { 5, 7, 4 }, + .num_chunks_message = 3, + }, { // 5 + .key = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + .klen = 16, + .msg = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff }, + .mlen = 16, + .mac = { 0x3f,0x5b,0x8c,0xc9,0xea,0x85,0x5a,0x0a,0xfa, + 0x73,0x47,0xd2,0x3e,0x8d,0x66,0x4e }, + .tlen = 10, + .chunks_msg = { 1, 2, 3, 4, 6 }, + .num_chunks_message = 5, + }, { // 6 + .key = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + .klen = 16, + .msg = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff }, + .mlen = 32, + .mac = { 0x7e,0x75,0x51,0x49,0x15,0x3e,0x01,0x75,0xfb, + 0x9e,0x26,0x6e,0xe8,0x04,0x4d,0x0d }, + .tlen = 10, + .chunks_msg = { 10, 2, 8, 10, 2 }, + .num_chunks_message = 5, + }, { // 7 + .key = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + .klen = 16, + .msg = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff }, + .mlen = 30, + .mac = { 0x3d,0x40,0xa3,0x24,0x33,0x75,0xcc,0x40,0xb6, + 0xa8,0x63,0xdd,0x05,0x8b,0xe6,0x04 }, + .tlen = 10, + .chunks_msg = { 10, 2, 8, 10 }, + .num_chunks_message = 4, + } +}; + +/** + * Derived CBC-MAC test vectors from AES-CBC test vectors + * https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/ + * block-ciphers#AES + **/ +static struct mac_test_vector aes192_cbc_mac_tv[] = { + { // 0 + .key = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00 }, + .klen = 24, + .msg = { 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + .mlen = 16, + .mac = { 0x6c,0xd0,0x25,0x13,0xe8,0xd4,0xdc,0x98,0x6b, + 0x4a,0xfe,0x08,0x7a,0x60,0xbd,0x0c }, + .tlen = 4, + }, { // 1 + .key = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00 }, + .klen = 24, + .msg = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + .mlen = 16, + .mac = { 0x93,0xba,0xaf,0xfb,0x35,0xfb,0xe7,0x39,0xc1, + 0x7c,0x6a,0xc2,0x2e,0xec,0xf1,0x8f }, + .tlen = 15, + }, { // 2 + .key = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00 }, + .klen = 24, + .msg = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff }, + .mlen = 16, + .mac = { 0xb1,0x3d,0xb4,0xda,0x1f,0x71,0x8b,0xc6,0x90, + 0x47,0x97,0xc8,0x2b,0xcf,0x2d,0x32 }, + .tlen = 10, + }, { // 3 + .key = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00 }, + .klen = 24, + .msg = { 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + .mlen = 16, + .mac = { 0x6c,0xd0,0x25,0x13,0xe8,0xd4,0xdc,0x98,0x6b, + 0x4a,0xfe,0x08,0x7a,0x60,0xbd,0x0c }, + .tlen = 4, + .chunks_msg = { 7, 7, 2 }, + .num_chunks_message = 3, + }, { // 4 + .key = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00 }, + .klen = 24, + .msg = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + .mlen = 16, + .mac = { 0x93,0xba,0xaf,0xfb,0x35,0xfb,0xe7,0x39,0xc1, + 0x7c,0x6a,0xc2,0x2e,0xec,0xf1,0x8f }, + .tlen = 15, + .chunks_msg = { 5, 7, 4 }, + .num_chunks_message = 3, + }, { // 5 + .key = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00 }, + .klen = 24, + .msg = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff }, + .mlen = 16, + .mac = { 0xb1,0x3d,0xb4,0xda,0x1f,0x71,0x8b,0xc6,0x90, + 0x47,0x97,0xc8,0x2b,0xcf,0x2d,0x32 }, + .tlen = 10, + .chunks_msg = { 1, 2, 3, 4, 6 }, + .num_chunks_message = 5, + }, { // 6 + .key = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00 }, + .klen = 24, + .msg = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff }, + .mlen = 32, + .mac = { 0x60,0x4f,0x50,0xbc,0xdc,0x29,0x13,0xce,0xc7, + 0xb5,0x94,0xcc,0xd3,0x3e,0x6b,0xaa }, + .tlen = 10, + .chunks_msg = { 10, 2, 8, 10, 2 }, + .num_chunks_message = 5, + }, { // 7 + .key = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00 }, + .klen = 24, + .msg = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff }, + .mlen = 30, + .mac = { 0x79,0x64,0xcf,0x7d,0x8f,0x2d,0xee,0x93,0x99, + 0x5f,0x8e,0xb7,0xa7,0x3f,0xb0,0xab }, + .tlen = 10, + .chunks_msg = { 10, 2, 8, 10 }, + .num_chunks_message = 4, + } +}; + +/** + * Derived CBC-MAC test vectors from AES-CBC test vectors + * https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/ + * block-ciphers#AES + **/ +static struct mac_test_vector aes256_cbc_mac_tv[] = { + { // 0 + .key = { 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 }, + .klen = 32, + .msg = { 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + .mlen = 16, + .mac = { 0xdd,0xc6,0xbf,0x79,0x0c,0x15,0x76,0x0d,0x8d, + 0x9a,0xeb,0x6f,0x9a,0x75,0xfd,0x4e }, + .tlen = 4, + }, { // 1 + .key = { 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 }, + .klen = 32, + .msg = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + .mlen = 16, + .mac = { 0x9b,0x58,0xdb,0xfd,0x77,0xfe,0x5a,0xca,0x9c, + 0xfc,0x19,0x0c,0xd1,0xb8,0x2d,0x19 }, + .tlen = 15, + }, { // 2 + .key = { 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 }, + .klen = 32, + .msg = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff }, + .mlen = 16, + .mac = { 0xac,0xda,0xce,0x80,0x78,0xa3,0x2b,0x1a,0x18, + 0x2b,0xfa,0x49,0x87,0xca,0x13,0x47 }, + .tlen = 10, + }, { // 3 + .key = { 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 }, + .klen = 32, + .msg = { 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + .mlen = 16, + .mac = { 0xdd,0xc6,0xbf,0x79,0x0c,0x15,0x76,0x0d,0x8d, + 0x9a,0xeb,0x6f,0x9a,0x75,0xfd,0x4e }, + .tlen = 4, + .chunks_msg = { 7, 7, 2 }, + .num_chunks_message = 3, + }, { // 4 + .key = { 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 }, + .klen = 32, + .msg = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + .mlen = 16, + .mac = { 0x9b,0x58,0xdb,0xfd,0x77,0xfe,0x5a,0xca,0x9c, + 0xfc,0x19,0x0c,0xd1,0xb8,0x2d,0x19 }, + .tlen = 15, + .chunks_msg = { 5, 7, 4 }, + .num_chunks_message = 3, + }, { // 5 + .key = { 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 }, + .klen = 32, + .msg = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff }, + .mlen = 16, + .mac = { 0xac,0xda,0xce,0x80,0x78,0xa3,0x2b,0x1a,0x18, + 0x2b,0xfa,0x49,0x87,0xca,0x13,0x47 }, + .tlen = 10, + .chunks_msg = { 1, 2, 3, 4, 6 }, + .num_chunks_message = 5, + }, { // 6 + .key = { 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 }, + .klen = 32, + .msg = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff }, + .mlen = 32, + .mac = { 0xc4,0xa5,0x8e,0xcb,0x0d,0x79,0x41,0xd2,0xa5, + 0x90,0xc1,0xcb,0x95,0xd3,0x1d,0xfc }, + .tlen = 10, + .chunks_msg = { 10, 2, 8, 10, 2 }, + .num_chunks_message = 5, + }, { // 7 + .key = { 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 }, + .klen = 32, + .msg = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff }, + .mlen = 30, + .mac = { 0xca,0x87,0x7f,0x3d,0x45,0x0b,0x8a,0x09,0x0a, + 0xad,0xf5,0xb9,0xab,0xe6,0x06,0xaf }, + .tlen = 10, + .chunks_msg = { 10, 2, 8, 10 }, + .num_chunks_message = 4, + } +}; + #define NUM_OF_PUBLISHED_TESTSUITES 7 struct published_test_suite_info published_test_suites[] = { @@ -1783,9 +2116,9 @@ struct generated_test_suite_info generated_err_test_suites[] = { } }; -#define NUM_OF_PUBLISHED_CMAC_TESTSUITES 9 +#define NUM_OF_PUBLISHED_MAC_TESTSUITES 15 -struct published_cmac_test_suite_info published_cmac_test_suites[] = { +struct published_mac_test_suite_info published_mac_test_suites[] = { { .name = "AES_CMAC_GENERAL (128)", .tvcount = 22, @@ -1831,5 +2164,35 @@ struct published_cmac_test_suite_info published_cmac_test_suites[] = { .tvcount = 14, .tv = aes256_cmac_tv, .mech = {CKM_IBM_CMAC, 0, 0}, - } + }, { + .name = "AES_MAC_GENERAL (128)", + .tvcount = 8, + .tv = aes128_cbc_mac_tv, + .mech = {CKM_AES_MAC_GENERAL, 0, 0}, + }, { + .name = "AES_MAC_GENERAL (192)", + .tvcount = 8, + .tv = aes192_cbc_mac_tv, + .mech = {CKM_AES_MAC_GENERAL, 0, 0}, + }, { + .name = "AES_MAC_GENERAL (256)", + .tvcount = 8, + .tv = aes256_cbc_mac_tv, + .mech = {CKM_AES_MAC_GENERAL, 0, 0}, + }, { + .name = "AES_MAC (128)", + .tvcount = 8, + .tv = aes128_cbc_mac_tv, + .mech = {CKM_AES_MAC, 0, 0}, + }, { + .name = "AES_MAC (192)", + .tvcount = 8, + .tv = aes192_cbc_mac_tv, + .mech = {CKM_AES_MAC, 0, 0}, + }, { + .name = "AES_MAC (256)", + .tvcount = 8, + .tv = aes256_cbc_mac_tv, + .mech = {CKM_AES_MAC, 0, 0}, + }, }; diff --git a/testcases/crypto/aes_func.c b/testcases/crypto/aes_func.c index 20b7d68..7c34314 100644 --- a/testcases/crypto/aes_func.c +++ b/testcases/crypto/aes_func.c @@ -1734,7 +1734,7 @@ testcase_cleanup: return rc; } -CK_RV do_SignVerifyCMAC(struct published_cmac_test_suite_info *tsuite) +CK_RV do_SignVerifyMAC(struct published_mac_test_suite_info *tsuite) { unsigned int i; int k; @@ -1749,9 +1749,9 @@ CK_RV do_SignVerifyCMAC(struct published_cmac_test_suite_info *tsuite) CK_MAC_GENERAL_PARAMS mac_param; CK_ULONG ofs; CK_BYTE actual[MAX_KEY_SIZE]; - CK_ULONG actual_len; + CK_ULONG actual_len, mac_len; - testsuite_begin("%s Sign/Verify CMAC.", tsuite->name); + testsuite_begin("%s Sign/Verify MAC.", tsuite->name); testcase_rw_session(); testcase_user_login(); @@ -1767,7 +1767,7 @@ CK_RV do_SignVerifyCMAC(struct published_cmac_test_suite_info *tsuite) for (i = 0; i < tsuite->tvcount; i++) { - testcase_begin("%s Sign/Verify CMAC with published test vector %d.", + testcase_begin("%s Sign/Verify MAC with published test vector %d.", tsuite->name, i); /** create key handle **/ @@ -1781,10 +1781,25 @@ CK_RV do_SignVerifyCMAC(struct published_cmac_test_suite_info *tsuite) /** get mech **/ mech = tsuite->mech; - if (mech.mechanism == CKM_AES_CMAC_GENERAL) { + switch (mech.mechanism) { + case CKM_AES_CMAC_GENERAL: + case CKM_AES_MAC_GENERAL: mac_param = tsuite->tv[i].tlen; mech.pParameter = &mac_param; mech.ulParameterLen = sizeof(mac_param); + mac_len = mac_param; + break; + case CKM_AES_CMAC: + case CKM_IBM_CMAC: + mac_len = AES_BLOCK_SIZE; + break; + case CKM_AES_MAC: + mac_len = AES_BLOCK_SIZE / 2; + break; + default: + testcase_error("Invalid mechanism: %s", + p11_get_ckm(mech.mechanism)); + goto error; } /** initialize signing **/ @@ -1860,20 +1875,24 @@ CK_RV do_SignVerifyCMAC(struct published_cmac_test_suite_info *tsuite) /** compare sign/verify results with expected results **/ testcase_new_assertion(); - if (mech.mechanism == CKM_AES_CMAC_GENERAL && + if ((mech.mechanism == CKM_AES_CMAC_GENERAL || + mech.mechanism == CKM_AES_MAC_GENERAL) && actual_len != tsuite->tv[i].tlen) { testcase_fail("signature length does not match test vector's " "signature length\nexpected length=%d, found " "length=%ld", tsuite->tv[i].tlen, actual_len); } else if (mech.mechanism != CKM_AES_CMAC_GENERAL && - actual_len != AES_BLOCK_SIZE) { + mech.mechanism != CKM_AES_MAC_GENERAL && + actual_len != mac_len) { testcase_fail("signature length does not match test vector's " - "signature length\nexpected length=%d, found " - "length=%ld", AES_BLOCK_SIZE, actual_len); - } else if (memcmp(actual, tsuite->tv[i].mac, tsuite->tv[i].tlen)) { + "signature length\nexpected length=%ld, found " + "length=%ld", mac_len, actual_len); + } else if (memcmp(actual, tsuite->tv[i].mac, + tsuite->tv[i].tlen < mac_len ? tsuite->tv[i].tlen : + mac_len)) { testcase_fail("signature does not match test vector's signature"); } else { - testcase_pass("%s Sign/Verify CMAC with test vector %d " + testcase_pass("%s Sign/Verify MAC with test vector %d " "passed.", tsuite->name, i); } @@ -1949,9 +1968,9 @@ CK_RV aes_funcs() break; } - /* CMAC test cases */ - for (i = 0; i < NUM_OF_PUBLISHED_CMAC_TESTSUITES; i++) { - rv = do_SignVerifyCMAC(&published_cmac_test_suites[i]); + /* MAC test cases */ + for (i = 0; i < NUM_OF_PUBLISHED_MAC_TESTSUITES; i++) { + rv = do_SignVerifyMAC(&published_mac_test_suites[i]); if (rv != CKR_OK && (!no_stop)) break; } diff --git a/testcases/crypto/des3.h b/testcases/crypto/des3.h index b5213cb..1d10842 100644 --- a/testcases/crypto/des3.h +++ b/testcases/crypto/des3.h @@ -54,7 +54,7 @@ struct CK_MECHANISM des3_keygen = { .pParameter = NULL, }; -struct cmac_test_vector { +struct mac_test_vector { unsigned char key[MAX_KEY_SIZE]; unsigned char klen; unsigned char msg[MAX_TEXT_SIZE]; @@ -65,10 +65,10 @@ struct cmac_test_vector { int num_chunks_message; }; -struct published_cmac_test_suite_info { +struct published_mac_test_suite_info { const char *name; unsigned int tvcount; - struct cmac_test_vector *tv; + struct mac_test_vector *tv; CK_MECHANISM mech; CK_KEY_TYPE key_type; }; @@ -1061,7 +1061,7 @@ static struct des3_test_vector des3_ofb64_tv[] = { * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/ * CAVP-TESTING-BLOCK-CIPHER-MODES#CMAC **/ -static struct cmac_test_vector des2_cmac_tv[] = { +static struct mac_test_vector des2_cmac_tv[] = { { // 0 (0) .key = { 0xdc,0x04,0x73,0x68,0x02,0x32,0x52,0xd9,0x0e, 0xbc,0xcd,0xc2,0x16,0x61,0xe3,0xab }, @@ -1170,7 +1170,7 @@ static struct cmac_test_vector des2_cmac_tv[] = { * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/ * CAVP-TESTING-BLOCK-CIPHER-MODES#CMAC **/ -static struct cmac_test_vector des3_cmac_tv[] = { +static struct mac_test_vector des3_cmac_tv[] = { { // 0 (0) .key = { 0xc4,0x79,0xf8,0x13,0xad,0x1a,0x45,0xd5,0xdc, 0x43,0x45,0x9d,0xa4,0xc8,0x5e,0x85,0x1c,0xda, @@ -1324,6 +1324,99 @@ static struct cmac_test_vector des3_cmac_tv[] = { } }; +/** + * Derived CBC-MAC test vectors from DES3-CBC test vectors + * http://csrc.nist.gov/groups/STM/cavp/documents/des/tdesmmt.zip + * TCBCMMT3.rsp + **/ +static struct mac_test_vector des3_cbc_mac_tv[] = { + { // 0 + .key = {0x46, 0x13, 0x3d, 0xcb, 0xf2, 0x32, 0xb5, 0x19, 0x64, + 0xe0, 0xd9, 0x5e, 0x83, 0x20, 0x8f, 0x15, 0x67, 0x32, + 0xbf, 0x75, 0xb6, 0x73, 0xab, 0xf1}, + .klen = 24, + .msg = { 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + .mlen = 8, + .mac = { 0x36,0x77,0x03,0x73}, + .tlen = 4, + }, { // 1 + .key = {0x46, 0x13, 0x3d, 0xcb, 0xf2, 0x32, 0xb5, 0x19, 0x64, + 0xe0, 0xd9, 0x5e, 0x83, 0x20, 0x8f, 0x15, 0x67, 0x32, + 0xbf, 0x75, 0xb6, 0x73, 0xab, 0xf1}, + .klen = 24, + .msg = { 0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00 }, + .mlen = 8, + .mac = { 0x97,0x6a,0x35,0x19,0xeb,0xcd}, + .tlen = 6, + }, { // 2 + .key = {0x46, 0x13, 0x3d, 0xcb, 0xf2, 0x32, 0xb5, 0x19, 0x64, + 0xe0, 0xd9, 0x5e, 0x83, 0x20, 0x8f, 0x15, 0x67, 0x32, + 0xbf, 0x75, 0xb6, 0x73, 0xab, 0xf1}, + .klen = 24, + .msg = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 }, + .mlen = 8, + .mac = { 0xd2,0x36,0x82,0x9a,0x4c}, + .tlen = 5, + }, { // 3 + .key = {0x46, 0x13, 0x3d, 0xcb, 0xf2, 0x32, 0xb5, 0x19, 0x64, + 0xe0, 0xd9, 0x5e, 0x83, 0x20, 0x8f, 0x15, 0x67, 0x32, + 0xbf, 0x75, 0xb6, 0x73, 0xab, 0xf1}, + .klen = 24, + .msg = { 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + .mlen = 8, + .mac = { 0x36,0x77,0x03,0x73}, + .tlen = 4, + .chunks_msg = { 2, 3, 3 }, + .num_chunks_message = 3, + }, { // 4 + .key = {0x46, 0x13, 0x3d, 0xcb, 0xf2, 0x32, 0xb5, 0x19, 0x64, + 0xe0, 0xd9, 0x5e, 0x83, 0x20, 0x8f, 0x15, 0x67, 0x32, + 0xbf, 0x75, 0xb6, 0x73, 0xab, 0xf1}, + .klen = 24, + .msg = { 0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00 }, + .mlen = 8, + .mac = { 0x97,0x6a,0x35,0x19,0xeb,0xcd}, + .tlen = 6, + .chunks_msg = { 1, 1, 6 }, + .num_chunks_message = 3, + }, { // 5 + .key = {0x46, 0x13, 0x3d, 0xcb, 0xf2, 0x32, 0xb5, 0x19, 0x64, + 0xe0, 0xd9, 0x5e, 0x83, 0x20, 0x8f, 0x15, 0x67, 0x32, + 0xbf, 0x75, 0xb6, 0x73, 0xab, 0xf1}, + .klen = 24, + .msg = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 }, + .mlen = 8, + .mac = { 0xd2,0x36,0x82,0x9a,0x4c}, + .tlen = 5, + .chunks_msg = { 1, 2, 1, 2, 2 }, + .num_chunks_message = 5, + }, { // 6 + .key = {0x46, 0x13, 0x3d, 0xcb, 0xf2, 0x32, 0xb5, 0x19, 0x64, + 0xe0, 0xd9, 0x5e, 0x83, 0x20, 0x8f, 0x15, 0x67, 0x32, + 0xbf, 0x75, 0xb6, 0x73, 0xab, 0xf1}, + .klen = 24, + .msg = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01 }, + .mlen = 16, + .mac = { 0xcd,0x02,0xf0,0xd2,0xb4}, + .tlen = 5, + .chunks_msg = { 5, 5, 1, 2, 3 }, + .num_chunks_message = 5, + }, { // 7 + .key = {0x46, 0x13, 0x3d, 0xcb, 0xf2, 0x32, 0xb5, 0x19, 0x64, + 0xe0, 0xd9, 0x5e, 0x83, 0x20, 0x8f, 0x15, 0x67, 0x32, + 0xbf, 0x75, 0xb6, 0x73, 0xab, 0xf1}, + .klen = 24, + .msg = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x01 }, + .mlen = 14, + .mac = { 0x59,0x45,0x53,0xd5,0x67}, + .tlen = 5, + .chunks_msg = { 7, 2, 1, 2, 2 }, + .num_chunks_message = 5, + } +}; + #define NUM_OF_PUBLISHED_TESTSUITES 5 @@ -1376,9 +1469,9 @@ static struct generated_test_suite_info generated_test_suites[] = { } }; -#define NUM_OF_PUBLISHED_CMAC_TESTSUITES 5 +#define NUM_OF_PUBLISHED_MAC_TESTSUITES 7 -struct published_cmac_test_suite_info published_cmac_test_suites[] = { +struct published_mac_test_suite_info published_mac_test_suites[] = { { .name = "2DES_CMAC_GENERAL", .tvcount = 11, @@ -1409,5 +1502,17 @@ struct published_cmac_test_suite_info published_cmac_test_suites[] = { .tv = des3_cmac_tv, .mech = {CKM_IBM_CMAC, 0, 0}, .key_type = CKK_DES3, + }, { + .name = "3DES_MAC_GENERAL", + .tvcount = 8, + .tv = des3_cbc_mac_tv, + .mech = {CKM_DES3_MAC_GENERAL, 0, 0}, + .key_type = CKK_DES3, + }, { + .name = "3DES_MAC", + .tvcount = 8, + .tv = des3_cbc_mac_tv, + .mech = {CKM_DES3_MAC, 0, 0}, + .key_type = CKK_DES3, } }; diff --git a/testcases/crypto/des3_func.c b/testcases/crypto/des3_func.c index 7f564a7..8ab2ae9 100644 --- a/testcases/crypto/des3_func.c +++ b/testcases/crypto/des3_func.c @@ -1109,7 +1109,7 @@ testcase_cleanup: return rc; } -CK_RV do_SignVerifyCMAC(struct published_cmac_test_suite_info *tsuite) +CK_RV do_SignVerifyMAC(struct published_mac_test_suite_info *tsuite) { unsigned int i; int k; @@ -1124,9 +1124,9 @@ CK_RV do_SignVerifyCMAC(struct published_cmac_test_suite_info *tsuite) CK_MAC_GENERAL_PARAMS mac_param; CK_ULONG ofs; CK_BYTE actual[MAX_KEY_SIZE]; - CK_ULONG actual_len; + CK_ULONG actual_len, mac_len; - testsuite_begin("%s Sign/Verify CMAC.", tsuite->name); + testsuite_begin("%s Sign/Verify MAC.", tsuite->name); testcase_rw_session(); testcase_user_login(); @@ -1148,7 +1148,7 @@ CK_RV do_SignVerifyCMAC(struct published_cmac_test_suite_info *tsuite) } for (i = 0; i < tsuite->tvcount; i++) { - testcase_begin("%s Sign/Verify CMAC with published test vector %d.", + testcase_begin("%s Sign/Verify MAC with published test vector %d.", tsuite->name, i); /** create key handle **/ @@ -1167,10 +1167,25 @@ CK_RV do_SignVerifyCMAC(struct published_cmac_test_suite_info *tsuite) /** get mech **/ mech = tsuite->mech; - if (mech.mechanism == CKM_DES3_CMAC_GENERAL) { + switch (mech.mechanism) { + case CKM_DES3_CMAC_GENERAL: + case CKM_DES3_MAC_GENERAL: mac_param = tsuite->tv[i].tlen; mech.pParameter = &mac_param; mech.ulParameterLen = sizeof(mac_param); + mac_len = mac_param; + break; + case CKM_DES3_CMAC: + case CKM_IBM_CMAC: + mac_len = DES3_BLOCK_SIZE; + break; + case CKM_DES3_MAC: + mac_len = DES3_BLOCK_SIZE / 2; + break; + default: + testcase_error("Invalid mechanism: %s", + p11_get_ckm(mech.mechanism)); + goto error; } /** initialize signing **/ @@ -1246,20 +1261,24 @@ CK_RV do_SignVerifyCMAC(struct published_cmac_test_suite_info *tsuite) /** compare sign/verify results with expected results **/ testcase_new_assertion(); - if (mech.mechanism == CKM_DES3_CMAC_GENERAL && + if ((mech.mechanism == CKM_DES3_CMAC_GENERAL || + mech.mechanism == CKM_DES3_MAC_GENERAL) && actual_len != tsuite->tv[i].tlen) { testcase_fail("signature length does not match test vector's " "signature length\nexpected length=%d, found " "length=%ld", tsuite->tv[i].tlen, actual_len); } else if (mech.mechanism != CKM_DES3_CMAC_GENERAL && - actual_len != DES3_BLOCK_SIZE) { + mech.mechanism != CKM_DES3_MAC_GENERAL && + actual_len != mac_len) { testcase_fail("signature length does not match test vector's " - "signature length\nexpected length=%d, found " - "length=%ld", DES3_BLOCK_SIZE, actual_len); - } else if (memcmp(actual, tsuite->tv[i].mac, tsuite->tv[i].tlen)) { + "signature length\nexpected length=%ld, found " + "length=%ld", mac_len, actual_len); + } else if (memcmp(actual, tsuite->tv[i].mac, + tsuite->tv[i].tlen < mac_len ? tsuite->tv[i].tlen : + mac_len)) { testcase_fail("signature does not match test vector's signature"); } else { - testcase_pass("%s Sign/Verify CMAC with test vector %d " + testcase_pass("%s Sign/Verify MAC with test vector %d " "passed.", tsuite->name, i); } @@ -1320,9 +1339,9 @@ CK_RV des3_funcs() break; } - /* CMAC test cases */ - for (i = 0; i < NUM_OF_PUBLISHED_CMAC_TESTSUITES; i++) { - rv = do_SignVerifyCMAC(&published_cmac_test_suites[i]); + /* MAC test cases */ + for (i = 0; i < NUM_OF_PUBLISHED_MAC_TESTSUITES; i++) { + rv = do_SignVerifyMAC(&published_mac_test_suites[i]); if (rv != CKR_OK && (!no_stop)) break; } diff --git a/testcases/crypto/dh_func.c b/testcases/crypto/dh_func.c index 9214dd2..9a4ecfd 100644 --- a/testcases/crypto/dh_func.c +++ b/testcases/crypto/dh_func.c @@ -260,15 +260,8 @@ CK_RV do_DeriveDHKey(CK_BBOOL do_import) testcase_error("C_GetAttributeValue #1: rc = %s", p11_get_ckr(rc)); goto testcase_cleanup; } - // Make sure peer's key is the right size - if ((extr1_tmpl[0].ulValueLen != sizeof(DH_PUBL_PRIME)) && - (extr1_tmpl[0].ulValueLen != sizeof(DH_PUBL_PRIME) - 1)) { - testcase_fail("ERROR:size error peer's key %ld", - extr1_tmpl[0].ulValueLen); - goto testcase_cleanup; - } else { - testcase_pass("Successfully generated DH keys"); - } + + testcase_pass("Successfully generated DH keys"); } else { // First, import the DH key Pair for Party A @@ -320,15 +313,8 @@ CK_RV do_DeriveDHKey(CK_BBOOL do_import) testcase_error("C_GetAttributeValue #1: rc = %s", p11_get_ckr(rc)); goto testcase_cleanup; } - // Make sure peer's key is the right size - if ((extr1_tmpl[0].ulValueLen != sizeof(DH_PUBL_PRIME)) && - (extr1_tmpl[0].ulValueLen != sizeof(DH_PUBL_PRIME) - 1)) { - testcase_fail("ERROR:size error peer's key %ld", - extr1_tmpl[0].ulValueLen); - goto testcase_cleanup; - } else { - testcase_pass("Successfully imported DH keys"); - } + + testcase_pass("Successfully imported DH keys"); } // Testcase #2 - Now derive the secrets... @@ -358,13 +344,6 @@ CK_RV do_DeriveDHKey(CK_BBOOL do_import) testcase_error("C_GetAttributeValue #2: rc = %s", p11_get_ckr(rc)); goto testcase_cleanup; } - // Make sure party A's key is the right size - if ((extr2_tmpl[0].ulValueLen != sizeof(DH_PUBL_PRIME)) && - (extr2_tmpl[0].ulValueLen != sizeof(DH_PUBL_PRIME) - 1)) { - testcase_fail("ERROR:size error party A's key %ld", - extr2_tmpl[0].ulValueLen); - goto testcase_cleanup; - } // Now, derive a generic secret key using peer's private key // and A's public key mech.mechanism = CKM_DH_PKCS_DERIVE; @@ -388,13 +367,6 @@ CK_RV do_DeriveDHKey(CK_BBOOL do_import) goto testcase_cleanup; } - if (extr1_tmpl[0].ulValueLen != sizeof(DH_PUBL_PRIME) || - *((int *) extr1_tmpl[0].pValue) == 0) { - testcase_fail("ERROR:derived key #1 length or value %ld", - extr1_tmpl[0].ulValueLen); - goto testcase_cleanup; - } - memset(key2_value, 0, sizeof(key2_value)); extr2_tmpl[0].ulValueLen = sizeof(key2_value); @@ -405,14 +377,8 @@ CK_RV do_DeriveDHKey(CK_BBOOL do_import) goto testcase_cleanup; } - if (extr2_tmpl[0].ulValueLen != sizeof(DH_PUBL_PRIME) || - *((int *) extr2_tmpl[0].pValue) == 0) { - testcase_fail("ERROR:derived key #2 length or value %ld", - extr2_tmpl[0].ulValueLen); - goto testcase_cleanup; - } - - if (memcmp(key1_value, key2_value, sizeof(DH_PUBL_PRIME)) != 0) { + if (extr1_tmpl[0].ulValueLen != extr2_tmpl[0].ulValueLen || + memcmp(key1_value, key2_value, extr1_tmpl[0].ulValueLen) != 0) { testcase_fail("ERROR:derived key mismatch"); goto testcase_cleanup; } @@ -453,13 +419,6 @@ CK_RV do_DeriveDHKey(CK_BBOOL do_import) testcase_error("C_GetAttributeValue #2: rc = %s", p11_get_ckr(rc)); goto testcase_cleanup; } - // Make sure party A's key is the right size - if ((extr2_tmpl[0].ulValueLen != sizeof(DH_PUBL_PRIME)) && - (extr2_tmpl[0].ulValueLen != sizeof(DH_PUBL_PRIME) - 1)) { - testcase_fail("ERROR:size error party A's key %ld", - extr2_tmpl[0].ulValueLen); - goto testcase_cleanup; - } // Now, derive a generic secret key using peer's private key // and A's public key mech.mechanism = CKM_DH_PKCS_DERIVE; diff --git a/testcases/crypto/digest.h b/testcases/crypto/digest.h index e906a32..4898a4b 100644 --- a/testcases/crypto/digest.h +++ b/testcases/crypto/digest.h @@ -2395,6 +2395,64 @@ struct HMAC_TEST_VECTOR sha512_hmac_test_vector[] = { } }; +/* + * Test vectors for HMAC SHA512/224: + */ +struct HMAC_TEST_VECTOR sha512_224_hmac_test_vector[] = { + { + .key = {0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b, + 0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b, + 0x0b,0x0b}, + .key_len = 20, + .data = {"Hi There"}, + .data_len = 8, + .mac_len = 28, + .mac = {0xb2,0x44,0xba,0x01,0x30,0x7c,0x0e,0x7a,0x8c, + 0xca,0xad,0x13,0xb1,0x06,0x7a,0x4c,0xf6,0xb9, + 0x61,0xfe,0x0c,0x6a,0x20,0xbd,0xa3,0xd9,0x20, + 0x39} + }, { + .key = {'J', 'e', 'f', 'e'}, + .key_len = 4, + .data = {"what do ya want for nothing?"}, + .data_len = 28, + .mac_len = 28, + .mac = {0x4a,0x53,0x0b,0x31,0xa7,0x9e,0xbc,0xce,0x36, + 0x91,0x65,0x46,0x31,0x7c,0x45,0xf2,0x47,0xd8, + 0x32,0x41,0xdf,0xb8,0x18,0xfd,0x37,0x25,0x4b, + 0xde} + } +}; + +/* + * Test vectors for HMAC SHA512/256: + */ +struct HMAC_TEST_VECTOR sha512_256_hmac_test_vector[] = { + { + .key = {0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b, + 0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b, + 0x0b,0x0b}, + .key_len = 20, + .data = {"Hi There"}, + .data_len = 8, + .mac_len = 32, + .mac = {0x9f,0x91,0x26,0xc3,0xd9,0xc3,0xc3,0x30,0xd7, + 0x60,0x42,0x5c,0xa8,0xa2,0x17,0xe3,0x1f,0xea, + 0xe3,0x1b,0xfe,0x70,0x19,0x6f,0xf8,0x16,0x42, + 0xb8,0x68,0x40,0x2e,0xab} + }, { + .key = {'J', 'e', 'f', 'e'}, + .key_len = 4, + .data = {"what do ya want for nothing?"}, + .data_len = 28, + .mac_len = 32, + .mac = {0x6d,0xf7,0xb2,0x46,0x30,0xd5,0xcc,0xb2,0xee, + 0x33,0x54,0x07,0x08,0x1a,0x87,0x18,0x8c,0x22, + 0x14,0x89,0x76,0x8f,0xa2,0x02,0x05,0x13,0xb2, + 0xd5,0x93,0x35,0x94,0x56} + } +}; + /* Test vectors for HMAC SHA3-224: */ struct HMAC_TEST_VECTOR sha3_224_hmac_test_vector[] = { @@ -3437,6 +3495,56 @@ struct HMAC_TEST_VECTOR sha512_hmac_general_test_vector[] = { } }; +/* + * Test vectors for HMAC SHA512/224: + */ +struct HMAC_TEST_VECTOR sha512_224_hmac_general_test_vector[] = { + { + .key = {0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b, + 0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b, + 0x0b,0x0b}, + .key_len = 20, + .data = {"Hi There"}, + .data_len = 8, + .mac_len = 16, + .mac = {0xb2,0x44,0xba,0x01,0x30,0x7c,0x0e,0x7a,0x8c, + 0xca,0xad,0x13,0xb1,0x06,0x7a,0x4c} + }, { + .key = {'J', 'e', 'f', 'e'}, + .key_len = 4, + .data = {"what do ya want for nothing?"}, + .data_len = 28, + .mac_len = 16, + .mac = {0x4a,0x53,0x0b,0x31,0xa7,0x9e,0xbc,0xce,0x36, + 0x91,0x65,0x46,0x31,0x7c,0x45,0xf2} + } +}; + +/* + * Test vectors for HMAC SHA512/256: + */ +struct HMAC_TEST_VECTOR sha512_256_hmac_general_test_vector[] = { + { + .key = {0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b, + 0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b, + 0x0b,0x0b}, + .key_len = 20, + .data = {"Hi There"}, + .data_len = 8, + .mac_len = 16, + .mac = {0x9f,0x91,0x26,0xc3,0xd9,0xc3,0xc3,0x30,0xd7, + 0x60,0x42,0x5c,0xa8,0xa2,0x17,0xe3} + }, { + .key = {'J', 'e', 'f', 'e'}, + .key_len = 4, + .data = {"what do ya want for nothing?"}, + .data_len = 28, + .mac_len = 16, + .mac = {0x6d,0xf7,0xb2,0x46,0x30,0xd5,0xcc,0xb2,0xee, + 0x33,0x54,0x07,0x08,0x1a,0x87,0x18} + } +}; + /* FIPS HMAC test vectors from * http://csrc.nist.gov/groups/STM/cavp/documents/mac/hmactestvectors.zip * Notes: @@ -11024,7 +11132,7 @@ struct HMAC_TEST_SUITE_INFO fips_hmac_general_test_suites[] = { } }; -#define NUM_OF_HMAC_TEST_SUITES 16 +#define NUM_OF_HMAC_TEST_SUITES 20 struct HMAC_TEST_SUITE_INFO hmac_test_suites[] = { { .name = "SHA-1 HMAC", @@ -11057,6 +11165,18 @@ struct HMAC_TEST_SUITE_INFO hmac_test_suites[] = { .mech = { CKM_SHA512_HMAC, 0, 0 }, }, { + .name = "SHA-512/224 HMAC", + .tvcount = 2, + .tv = sha512_224_hmac_test_vector, + .mech = { CKM_SHA512_224_HMAC, 0, 0 }, + }, + { + .name = "SHA-512/256 HMAC", + .tvcount = 2, + .tv = sha512_256_hmac_test_vector, + .mech = { CKM_SHA512_256_HMAC, 0, 0 }, + }, + { .name = "MD5 HMAC", .tvcount = 7, .tv = md5_hmac_test_vector, @@ -11093,6 +11213,18 @@ struct HMAC_TEST_SUITE_INFO hmac_test_suites[] = { .mech = { CKM_SHA512_HMAC_GENERAL,&thirtytwo,sizeof(CK_ULONG) }, }, { + .name = "SHA-512/224 HMAC General", + .tvcount = 2, + .tv = sha512_224_hmac_general_test_vector, + .mech = { CKM_SHA512_224_HMAC_GENERAL,&sixteen,sizeof(CK_ULONG) }, + }, + { + .name = "SHA-512/256 HMAC General", + .tvcount = 2, + .tv = sha512_256_hmac_general_test_vector, + .mech = { CKM_SHA512_256_HMAC_GENERAL,&sixteen,sizeof(CK_ULONG) }, + }, + { .name = "MD5 HMAC General", .tvcount = 7, .tv = md5_hmac_general_test_vector, diff --git a/testcases/crypto/ec_func.c b/testcases/crypto/ec_func.c index 1160f38..f93ad8b 100644 --- a/testcases/crypto/ec_func.c +++ b/testcases/crypto/ec_func.c @@ -236,7 +236,7 @@ _signVerifyParam signVerifyInput[] = { {CKM_ECDSA_SHA384, 100, 4}, {CKM_ECDSA_SHA512, 100, 0}, {CKM_ECDSA_SHA512, 100, 4}, - {CKM_IBM_EDDSA_SHA512, 100, 0}, + {CKM_IBM_ED25519_SHA512, 100, 0}, {CKM_IBM_ED448_SHA3, 100, 0}, }; @@ -349,6 +349,18 @@ CK_RV run_DeriveECDHKey() {CKA_DERIVE, &true, sizeof(true)}, }; CK_ULONG prv_attr_len = sizeof(prv_attr)/sizeof(CK_ATTRIBUTE); + CK_ATTRIBUTE prv_attr_edwards[] = { + {CKA_SIGN, &true, sizeof(true)}, + {CKA_EXTRACTABLE, &true, sizeof(true)}, + }; + CK_ULONG prv_attr_edwards_len = + sizeof(prv_attr_edwards)/sizeof(CK_ATTRIBUTE); + CK_ATTRIBUTE prv_attr_montgomery[] = { + {CKA_DERIVE, &true, sizeof(true)}, + {CKA_EXTRACTABLE, &true, sizeof(true)}, + }; + CK_ULONG prv_attr_montgomery_len = + sizeof(prv_attr_montgomery)/sizeof(CK_ATTRIBUTE); CK_ATTRIBUTE pub_attr[] = { {CKA_ECDSA_PARAMS, (CK_VOID_PTR)der_ec_supported[i].curve, @@ -357,6 +369,19 @@ CK_RV run_DeriveECDHKey() {CKA_MODIFIABLE, &true, sizeof(true)}, }; CK_ULONG pub_attr_len = sizeof(pub_attr)/sizeof(CK_ATTRIBUTE); + CK_ATTRIBUTE pub_attr_montgomery[] = { + {CKA_ECDSA_PARAMS, (CK_VOID_PTR)der_ec_supported[i].curve, + der_ec_supported[i].size}, + {CKA_MODIFIABLE, &true, sizeof(true)}, + {CKA_VERIFY, &true, sizeof(true)}, + }; + CK_ULONG pub_attr_montgomery_len = + sizeof(pub_attr_montgomery)/sizeof(CK_ATTRIBUTE); + + CK_ATTRIBUTE *prv_attr_gen = prv_attr; + CK_ULONG prv_attr_gen_len = prv_attr_len; + CK_ATTRIBUTE *pub_attr_gen = pub_attr; + CK_ULONG pub_attr_gen_len = pub_attr_len; CK_ATTRIBUTE extr1_tmpl[] = { {CKA_EC_POINT, pubkeyA_value, sizeof(pubkeyA_value)}, @@ -398,6 +423,14 @@ CK_RV run_DeriveECDHKey() derive_mech_type = CKM_IBM_EC_C25519; if (der_ec_supported[i].curve == curve448) derive_mech_type = CKM_IBM_EC_C448; + + prv_attr_gen = prv_attr_montgomery; + prv_attr_gen_len = prv_attr_montgomery_len; + pub_attr_gen = pub_attr_montgomery; + pub_attr_gen_len = pub_attr_montgomery_len; + } else if (der_ec_supported[i].type == CURVE_EDWARDS) { + prv_attr_gen = prv_attr_edwards; + prv_attr_gen_len = prv_attr_edwards_len; } if (!mech_supported(SLOT_ID, derive_mech_type)) { testcase_skip("Slot %u doesn't support %s\n", @@ -413,12 +446,13 @@ CK_RV run_DeriveECDHKey() mech.pParameter = NULL; rc = funcs->C_GenerateKeyPair(session, &mech, - pub_attr, pub_attr_len, - prv_attr, prv_attr_len, + pub_attr_gen, pub_attr_gen_len, + prv_attr_gen, prv_attr_gen_len, &publ_keyA, &priv_keyA); if (rc != CKR_OK) { if (rc == CKR_MECHANISM_PARAM_INVALID || - rc == CKR_ATTRIBUTE_VALUE_INVALID) { + rc == CKR_ATTRIBUTE_VALUE_INVALID || + rc == CKR_CURVE_NOT_SUPPORTED) { testcase_skip("Slot %u doesn't support this curve: %s", (unsigned int) SLOT_ID, der_ec_supported[i].name); continue; @@ -443,8 +477,8 @@ CK_RV run_DeriveECDHKey() mech.pParameter = NULL; rc = funcs->C_GenerateKeyPair(session, &mech, - pub_attr, pub_attr_len, - prv_attr, prv_attr_len, + pub_attr_gen, pub_attr_gen_len, + prv_attr_gen, prv_attr_gen_len, &publ_keyB, &priv_keyB); if (rc != CKR_OK) { testcase_fail("C_GenerateKeyPair with valid input failed at i=%lu " @@ -737,6 +771,12 @@ CK_RV run_DeriveECDHKeyKAT() ecdh_tv[i].pubkeyA, ecdh_tv[i].pubkey_len, &priv_keyA); if (rc != CKR_OK) { + 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; + } + testcase_fail("C_CreateObject (EC Private Key) failed at i=%lu, " "rc=%s", i, p11_get_ckr(rc)); goto testcase_cleanup; @@ -747,6 +787,12 @@ CK_RV run_DeriveECDHKeyKAT() ecdh_tv[i].pubkeyA, ecdh_tv[i].pubkey_len, &publ_keyA); if (rc != CKR_OK) { + 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; + } + testcase_fail("C_CreateObject (EC Public Key) failed at i=%lu, " "rc=%s", i, p11_get_ckr(rc)); goto testcase_cleanup; @@ -759,6 +805,12 @@ CK_RV run_DeriveECDHKeyKAT() ecdh_tv[i].pubkeyB, ecdh_tv[i].pubkey_len, &priv_keyB); if (rc != CKR_OK) { + 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; + } + testcase_fail("C_CreateObject (EC Private Key) failed at i=%lu, " "rc=%s", i, p11_get_ckr(rc)); goto testcase_cleanup; @@ -769,6 +821,12 @@ CK_RV run_DeriveECDHKeyKAT() ecdh_tv[i].pubkeyB, ecdh_tv[i].pubkey_len, &publ_keyB); if (rc != CKR_OK) { + 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; + } + testcase_fail("C_CreateObject (EC Public Key) failed at i=%lu, " "rc=%s", i, p11_get_ckr(rc)); goto testcase_cleanup; @@ -935,6 +993,7 @@ CK_RV run_DeriveECDHKeyKAT() testcase_pass("*Derive shared secret i=%lu passed.", i); +testcase_next: if (priv_keyA != CK_INVALID_HANDLE) funcs->C_DestroyObject(session, priv_keyA); if (publ_keyA != CK_INVALID_HANDLE) @@ -975,7 +1034,8 @@ CK_RV run_GenerateSignVerifyECC(CK_SESSION_HANDLE session, CK_ULONG parts, CK_OBJECT_HANDLE priv_key, CK_OBJECT_HANDLE publ_key, - enum curve_type curve_type) + enum curve_type curve_type, + CK_BYTE *params, CK_ULONG params_len) { CK_MECHANISM mech2; CK_BYTE_PTR data = NULL, signature = NULL; @@ -1005,7 +1065,7 @@ CK_RV run_GenerateSignVerifyECC(CK_SESSION_HANDLE session, } } - if ((mechType == CKM_IBM_EDDSA_SHA512 || mechType == CKM_IBM_ED448_SHA3)) { + if ((mechType == CKM_IBM_ED25519_SHA512 || mechType == CKM_IBM_ED448_SHA3)) { if (curve_type != CURVE_EDWARDS) { /* Mechanism does not match to curve type, skip */ testcase_skip("Mechanism %s can only be used with Edwards curves", @@ -1013,6 +1073,22 @@ CK_RV run_GenerateSignVerifyECC(CK_SESSION_HANDLE session, rc = CKR_OK; goto testcase_cleanup; } + if (mechType == CKM_IBM_ED25519_SHA512 && + 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)); + rc = CKR_OK; + goto testcase_cleanup; + } + if (mechType == CKM_IBM_ED448_SHA3 && + 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)); + rc = CKR_OK; + goto testcase_cleanup; + } } else { if (curve_type == CURVE_EDWARDS || curve_type == CURVE_MONTGOMERY) { /* Mechanism does not match to curve type, skip */ @@ -1231,7 +1307,8 @@ CK_RV run_GenerateECCKeyPairSignVerify() testcase_new_assertion(); if (rc != CKR_OK) { if (rc == CKR_MECHANISM_PARAM_INVALID || - rc == CKR_ATTRIBUTE_VALUE_INVALID) { + rc == CKR_ATTRIBUTE_VALUE_INVALID || + rc == CKR_CURVE_NOT_SUPPORTED) { testcase_skip("Slot %u doesn't support this curve: %s", (unsigned int) SLOT_ID, der_ec_supported[i].name); continue; @@ -1251,7 +1328,9 @@ CK_RV run_GenerateECCKeyPairSignVerify() signVerifyInput[j].inputlen, signVerifyInput[j].parts, priv_key, publ_key, - der_ec_supported[i].type); + der_ec_supported[i].type, + (CK_BYTE *)der_ec_supported[i].curve, + der_ec_supported[i].size); if (rc != 0) { testcase_fail("run_GenerateSignVerifyECC failed index=%lu.", j); goto testcase_cleanup; @@ -1342,6 +1421,12 @@ CK_RV run_ImportECCKeyPairSignVerify() testcase_new_assertion(); if (rc != CKR_OK) { + if (rc == CKR_CURVE_NOT_SUPPORTED) { + testcase_skip("Slot %u doesn't support this curve: %s", + (unsigned int) SLOT_ID, ec_tv[i].name); + continue; + } + if (is_ep11_token(SLOT_ID) && rc == CKR_ENCRYPTED_DATA_INVALID && (ec_tv[i].curve_type == CURVE_EDWARDS || @@ -1365,6 +1450,13 @@ CK_RV run_ImportECCKeyPairSignVerify() testcase_new_assertion(); if (rc != CKR_OK) { + if (rc == CKR_CURVE_NOT_SUPPORTED) { + testcase_skip("Slot %u doesn't support this curve: %s", + (unsigned int) SLOT_ID, ec_tv[i].name); + funcs->C_DestroyObject(session, priv_key); + continue; + } + if (is_ep11_token(SLOT_ID) && rc == CKR_ENCRYPTED_DATA_INVALID && (ec_tv[i].curve_type == CURVE_EDWARDS || @@ -1392,7 +1484,9 @@ CK_RV run_ImportECCKeyPairSignVerify() signVerifyInput[j].inputlen, signVerifyInput[j].parts, priv_key, publ_key, - ec_tv[i].curve_type); + ec_tv[i].curve_type, + ec_tv[i].params, + ec_tv[i].params_len); if (rc != 0) { testcase_fail("run_GenerateSignVerifyECC failed index=%lu.", j); goto testcase_cleanup; @@ -1467,6 +1561,39 @@ CK_RV run_TransferECCKeyPairSignVerify() } } + rc = funcs->C_GetMechanismInfo(SLOT_ID, CKM_AES_KEY_GEN, &mech_info); + if (rc != CKR_OK) { + if (rc == CKR_MECHANISM_INVALID) { + /* no support for AES key gen? skip */ + testcase_skip("Slot %u doesn't support CKM_AES_KEY_GEN", + (unsigned int) SLOT_ID); + goto testcase_cleanup; + } else { + testcase_error("C_GetMechanismInfo() rc = %s", p11_get_ckr(rc)); + goto testcase_cleanup; + } + } + + rc = funcs->C_GetMechanismInfo(SLOT_ID, CKM_AES_CBC_PAD, &mech_info); + if (rc != CKR_OK) { + if (rc == CKR_MECHANISM_INVALID) { + /* no support for AES CBC wrap? skip */ + testcase_skip("Slot %u doesn't support CKM_AES_CBC_PAD", + (unsigned int) SLOT_ID); + goto testcase_cleanup; + } else { + testcase_error("C_GetMechanismInfo() rc = %s", p11_get_ckr(rc)); + goto testcase_cleanup; + } + } + if ((mech_info.flags & CKF_WRAP) == 0 || + (mech_info.flags & CKF_UNWRAP) == 0) { + /* no support for AES CBC wrap? skip */ + testcase_skip("Slot %u doesn't support CKM_AES_CBC_PAD for wrapping " + "keys", (unsigned int) SLOT_ID); + goto testcase_cleanup; + } + for (i = 0; i < EC_TV_NUM; i++) { if (!(is_ep11_token(SLOT_ID))) { if (strstr((char *)ec_tv[i].name, "t1") != NULL) { @@ -1489,6 +1616,12 @@ CK_RV run_TransferECCKeyPairSignVerify() testcase_new_assertion(); if (rc != CKR_OK) { + if (rc == CKR_CURVE_NOT_SUPPORTED) { + testcase_skip("Slot %u doesn't support this curve: %s", + (unsigned int) SLOT_ID, ec_tv[i].name); + continue; + } + if (is_ep11_token(SLOT_ID) && rc == CKR_ENCRYPTED_DATA_INVALID && (ec_tv[i].curve_type == CURVE_EDWARDS || @@ -1513,6 +1646,13 @@ CK_RV run_TransferECCKeyPairSignVerify() testcase_new_assertion(); if (rc != CKR_OK) { + if (rc == CKR_CURVE_NOT_SUPPORTED) { + testcase_skip("Slot %u doesn't support this curve: %s", + (unsigned int) SLOT_ID, ec_tv[i].name); + funcs->C_DestroyObject(session, priv_key); + continue; + } + if (is_ep11_token(SLOT_ID) && rc == CKR_ENCRYPTED_DATA_INVALID && (ec_tv[i].curve_type == CURVE_EDWARDS || @@ -1617,7 +1757,7 @@ CK_RV run_TransferECCKeyPairSignVerify() if (wrapped_key) { free(wrapped_key); wrapped_key = NULL; - } + } /* create signature with unwrapped private key and verify with * public key */ @@ -1629,7 +1769,9 @@ CK_RV run_TransferECCKeyPairSignVerify() signVerifyInput[j].inputlen, signVerifyInput[j].parts, unwrapped_key, publ_key, - ec_tv[i].curve_type); + ec_tv[i].curve_type, + ec_tv[i].params, + ec_tv[i].params_len); if (rc != 0) { testcase_fail("run_GenerateSignVerifyECC failed index=%lu.", j); goto testcase_cleanup; diff --git a/testcases/crypto/rsa.h b/testcases/crypto/rsa.h index f59724f..2b873c1 100644 --- a/testcases/crypto/rsa.h +++ b/testcases/crypto/rsa.h @@ -22,6 +22,14 @@ #define PKCS11_MAX_KEY_LEN 512 #define MAX_CHUNKS 8 +#define DES_IV_SIZE 8 +#define AES_IV_SIZE 16 + +char aes_iv[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f +}; + +unsigned char des_iv[] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef }; struct RSA_GENERATED_TEST_VECTOR { CK_ULONG modbits; diff --git a/testcases/crypto/rsa_func.c b/testcases/crypto/rsa_func.c index 05f5872..68bbbb4 100644 --- a/testcases/crypto/rsa_func.c +++ b/testcases/crypto/rsa_func.c @@ -126,6 +126,22 @@ CK_RV do_EncryptDecryptRSA(struct GENERATED_TEST_SUITE_INFO *tsuite) "be used with publ_exp.='%s'", s); continue; } + + if (tsuite->mech.mechanism == CKM_RSA_PKCS_OAEP && + tsuite->tv[i].oaep_params.hashAlg != CKM_SHA_1 && + tsuite->tv[i].oaep_params.hashAlg != CKM_SHA256) { + testcase_skip("CCA Token cannot use RSA OAEP with a hash " + "algorithm other than SHA1 and SHA256"); + continue; + } + + if (tsuite->mech.mechanism == CKM_RSA_PKCS_OAEP && + tsuite->tv[i].oaep_params.source == CKZ_DATA_SPECIFIED && + tsuite->tv[i].oaep_params.ulSourceDataLen > 0) { + testcase_skip("CCA Token cannot use RSA OAEP with non empty " + "source data"); + continue; + } } // tpm special cases: // tpm token can only use public exponent 0x010001 (65537) @@ -913,6 +929,14 @@ CK_RV do_SignVerify_RSAPSS(struct GENERATED_TEST_SUITE_INFO * tsuite) "modbits.='%ld'", SLOT_ID, tsuite->tv[i].modbits); 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); + continue; + } + } // free memory free(s); @@ -1138,6 +1162,44 @@ CK_RV do_WrapUnwrapRSA(struct GENERATED_TEST_SUITE_INFO * tsuite) 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); + 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); + continue; + } + + if (tsuite->tv[i].keytype.mechanism == CKM_GENERIC_SECRET_KEY_GEN) { + testcase_skip("CCA Token cannot wrap CKK_GENERIC_SECRET keys"); + continue; + } + + if (tsuite->mech.mechanism == CKM_RSA_PKCS_OAEP && + tsuite->tv[i].oaep_params.hashAlg != CKM_SHA_1 && + tsuite->tv[i].oaep_params.hashAlg != CKM_SHA256) { + testcase_skip("CCA Token cannot use RSA OAEP with a hash " + "algorithm other than SHA1 and SHA256"); + continue; + } + + if (tsuite->mech.mechanism == CKM_RSA_PKCS_OAEP && + tsuite->tv[i].oaep_params.source == CKZ_DATA_SPECIFIED && + tsuite->tv[i].oaep_params.ulSourceDataLen > 0) { + testcase_skip("CCA Token cannot use RSA OAEP with non empty " + "source data"); + continue; + } + } // begin test testcase_begin("%s Wrap Unwrap with test vector %d, " @@ -1198,22 +1260,33 @@ CK_RV do_WrapUnwrapRSA(struct GENERATED_TEST_SUITE_INFO * tsuite) * by default. So they will not be included in second * assertion. */ + mech.ulParameterLen = 0; + mech.pParameter = NULL; + if (keygen_mech.mechanism != CKM_GENERIC_SECRET_KEY_GEN) { switch (keygen_mech.mechanism) { case CKM_AES_KEY_GEN: - mech.mechanism = CKM_AES_ECB; + mech.mechanism = CKM_AES_CBC; + mech.ulParameterLen = AES_IV_SIZE; + mech.pParameter = &aes_iv; key_type = CKK_AES; break; case CKM_DES3_KEY_GEN: - mech.mechanism = CKM_DES3_ECB; + mech.mechanism = CKM_DES3_CBC; + mech.ulParameterLen = DES_IV_SIZE; + mech.pParameter = &des_iv; key_type = CKK_DES3; break; case CKM_DES_KEY_GEN: - mech.mechanism = CKM_DES_ECB; + mech.mechanism = CKM_DES_CBC; + mech.ulParameterLen = DES_IV_SIZE; + mech.pParameter = &des_iv; key_type = CKK_DES; break; case CKM_CDMF_KEY_GEN: - mech.mechanism = CKM_CDMF_ECB; + mech.mechanism = CKM_CDMF_CBC; + mech.ulParameterLen = DES_IV_SIZE; + mech.pParameter = &des_iv; key_type = CKK_CDMF; break; default: @@ -1221,8 +1294,13 @@ CK_RV do_WrapUnwrapRSA(struct GENERATED_TEST_SUITE_INFO * tsuite) goto error; } - mech.ulParameterLen = 0; - mech.pParameter = NULL; + if (!mech_supported(slot_id, mech.mechanism)) { + testcase_skip("Slot %u doesn't support %s (%u)", + (unsigned int) slot_id, + mech_to_str(mech.mechanism), + (unsigned int)mech.mechanism); + goto tv_cleanup; + } rc = funcs->C_EncryptInit(session, &mech, secret_key); if (rc != CKR_OK) { @@ -1460,6 +1538,16 @@ CK_RV do_SignRSA(struct PUBLISHED_TEST_SUITE_INFO * tsuite) continue; } } + + 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."); + continue; + } + } + // clear buffers memset(message, 0, MAX_MESSAGE_SIZE); memset(actual, 0, MAX_SIGNATURE_SIZE); @@ -1620,6 +1708,16 @@ CK_RV do_VerifyRSA(struct PUBLISHED_TEST_SUITE_INFO * tsuite) continue; } } + + 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."); + continue; + } + } + // clear buffers memset(message, 0, MAX_MESSAGE_SIZE); memset(signature, 0, MAX_SIGNATURE_SIZE); diff --git a/testcases/crypto/rsaupdate_func.c b/testcases/crypto/rsaupdate_func.c index 355aaa0..964af2c 100644 --- a/testcases/crypto/rsaupdate_func.c +++ b/testcases/crypto/rsaupdate_func.c @@ -359,6 +359,16 @@ CK_RV do_SignVerifyUpdate_RSAPSS(struct GENERATED_TEST_SUITE_INFO * tsuite) 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); + continue; + } + } + // free memory free(s); @@ -619,6 +629,16 @@ CK_RV do_VerifyUpdateRSA(struct PUBLISHED_TEST_SUITE_INFO * tsuite) continue; } } + + 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); + continue; + } + } + // free memory free(s); @@ -814,6 +834,15 @@ CK_RV do_SignUpdateRSA(struct PUBLISHED_TEST_SUITE_INFO * tsuite) } } + 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); + continue; + } + } + free(s); rc = CKR_OK; // set return value diff --git a/testcases/include/regress.h b/testcases/include/regress.h index 8c7c536..3a5820f 100644 --- a/testcases/include/regress.h +++ b/testcases/include/regress.h @@ -30,9 +30,9 @@ #define MIN(a, b) ( (a) < (b) ? (a) : (b) ) -#include -#define SYSTEMTIME struct timeb -#define GetSystemTime(x) ftime((x)) +#include +#define SYSTEMTIME struct timeval +#define GetSystemTime(x) gettimeofday((x), NULL) #include @@ -70,7 +70,7 @@ void process_time(SYSTEMTIME t1, SYSTEMTIME t2); void show_error(char *str, CK_RV rc); void print_hex(CK_BYTE * buf, CK_ULONG len); -int do_GetFunctionList(void); +CK_BBOOL do_GetFunctionList(void); void init_coprocessor(void); @@ -80,6 +80,8 @@ CK_RV DummyFunction(CK_SLOT_ID id); int digest_functions(void); extern CK_FUNCTION_LIST *funcs; +extern CK_FUNCTION_LIST_3_0 *funcs3; +extern CK_INTERFACE *ifs; extern CK_SLOT_ID SLOT_ID; void usage(char *fct); diff --git a/testcases/login/digest_init.c b/testcases/login/digest_init.c index aebc826..875d8ed 100644 --- a/testcases/login/digest_init.c +++ b/testcases/login/digest_init.c @@ -14,15 +14,12 @@ #include #include -#include #include "pkcs11types.h" #include "regress.h" #include "common.c" -int do_GetFunctionList(void); - int do_digestInit(CK_FUNCTION_LIST * funcs, CK_SLOT_ID slot_id, CK_USER_TYPE userType, char *pass) { diff --git a/testcases/login/init_pin.c b/testcases/login/init_pin.c index 6cca186..c03b57a 100644 --- a/testcases/login/init_pin.c +++ b/testcases/login/init_pin.c @@ -14,15 +14,12 @@ #include #include -#include #include "pkcs11types.h" #include "regress.h" #include "common.c" -int do_GetFunctionList(void); - int do_InitPIN(CK_FUNCTION_LIST * funcs, CK_SLOT_ID slot_id, char *sologinpass, char *userinitpass) { diff --git a/testcases/login/init_tok.c b/testcases/login/init_tok.c index a1703ca..791a76e 100644 --- a/testcases/login/init_tok.c +++ b/testcases/login/init_tok.c @@ -27,7 +27,7 @@ int do_GetInfo(void); CK_RV C_GetFunctionList(CK_FUNCTION_LIST **); -int do_GetFunctionList(void); +CK_BBOOL do_GetFunctionList(void); int do_inittoken(CK_FUNCTION_LIST * funcs, CK_BYTE * sopass) { diff --git a/testcases/login/login.c b/testcases/login/login.c index 7de4a07..3081b3e 100644 --- a/testcases/login/login.c +++ b/testcases/login/login.c @@ -14,14 +14,11 @@ #include #include -#include #include "pkcs11types.h" #include "regress.h" #include "common.c" -int do_GetFunctionList(void); - int do_LoginLogout(CK_FUNCTION_LIST * funcs, CK_SLOT_ID slot_id, CK_USER_TYPE userType, char *pass) { diff --git a/testcases/login/login_flags.c b/testcases/login/login_flags.c index 5fdd981..909663c 100644 --- a/testcases/login/login_flags.c +++ b/testcases/login/login_flags.c @@ -32,7 +32,6 @@ #define BAD_USER_PIN "534566346" #define BAD_USER_PIN_LEN strlen(BAD_USER_PIN) -int do_GetFunctionList(void); int clean_up(void); CK_SLOT_ID slot_id; diff --git a/testcases/login/set_pin.c b/testcases/login/set_pin.c index 786ba71..b82d99a 100644 --- a/testcases/login/set_pin.c +++ b/testcases/login/set_pin.c @@ -15,15 +15,12 @@ #include #include -#include #include "pkcs11types.h" #include "regress.h" #include "common.c" -int do_GetFunctionList(void); - int do_SetPIN(CK_FUNCTION_LIST * funcs, CK_SLOT_ID slot_id, CK_USER_TYPE userType, char *old, char *new) { diff --git a/testcases/misc_tests/README b/testcases/misc_tests/README index 39a817c..3617ee2 100644 --- a/testcases/misc_tests/README +++ b/testcases/misc_tests/README @@ -104,3 +104,11 @@ multi_instance tokens) exist. Usage: multi_instance -slot1 -slot2 + +tok2tok_transport + This testcase open sessions on two different tokens within one process. + It then generates a keys in the first token, and transports them via + various Wrap/Unwrap mechanisms to the other token. It is checked that + the transported key can still be used in the receiving token. + + Usage: tok2tok_transport -slot1 -slot2 diff --git a/testcases/misc_tests/fork.c b/testcases/misc_tests/fork.c index 40a304b..fc3f4af 100644 --- a/testcases/misc_tests/fork.c +++ b/testcases/misc_tests/fork.c @@ -20,7 +20,6 @@ #include #include -#include #include #include @@ -31,8 +30,6 @@ CK_BYTE user_pin[128]; CK_ULONG user_pin_len; CK_SLOT_ID slot_id = 0; -int do_GetFunctionList(void); - CK_RV do_GenerateTokenRSAKeyPair(CK_SESSION_HANDLE sess, CK_BYTE *label, CK_ULONG bits, CK_OBJECT_HANDLE *hPubKey, CK_OBJECT_HANDLE *hPrivKey) diff --git a/testcases/misc_tests/migration.sh b/testcases/misc_tests/migration.sh new file mode 100755 index 0000000..2afe523 --- /dev/null +++ b/testcases/misc_tests/migration.sh @@ -0,0 +1,79 @@ +#!/bin/bash +# +# 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 + +# - Requires p11tool (gnutls) and pkcs11-tool (opensc). +# - The PKCSLIB environment must point to your system's libopencryptoki.so. +# - The PKCS11_SO_PIN environment variable must hold the SO pin. +# - The PKCS11_USER_PIN environment variable must hold the user pin. +# - The OCK_CONFDIR environment variable must point to your system's openCryptoki configuration directory. +# - The OCK_DATASTORE environment variable must point to the token's datastore directory. +# - The SLOT environment variable must hold the slot id of the token under test. +# - The PKCS11_TOKEN_URL environment variable must hold the the token url of the token under test. +# +# sodo -E ./migrate.sh + +set -x + +# tmp files +PKCSCONF_PRE=pkcsconf-pre.out +PKCSCONF_POST=pkcsconf-post.out +P11TOOL_PRE=p11tool-pre.out +P11TOOL_POST=p11tool-post.out +PKCS11_TOOL_PRE=pkcs11-tool-pre.out +PKCS11_TOOL_POST=pkcs11-tool-post.out +P11SAK_PRE=p11sak-pre.out +P11SAK_POST=p11sak-post.out + +# set p11tool env vars +export GNUTLS_SO_PIN=$PKCS11_SO_PIN +export GNUTLS_PIN=$PKCS11_USER_PIN + +# generate objects +p11tool --provider=$PKCSLIB --login --generate-rsa --bits 2048 --label p11tool-rsa "$PKCS11_TOKEN_URL" +pkcs11-tool --module=$PKCSLIB --slot $SLOT --login --pin $PKCS11_USER_PIN --keypairgen --key-type rsa:2048 --label pkcs11-tool-rsa +p11sak generate-key rsa 2048 --slot $SLOT --pin $PKCS11_USER_PIN --label p11sak-rsa + +# list slots/tokens +pkcsconf -i &>> $PKCSCONF_PRE +pkcsconf -s &>> $PKCSCONF_PRE +pkcsconf -t &>> $PKCSCONF_PRE +p11tool --provider=$PKCSLIB --list-tokens &>> $P11TOOL_PRE +pkcs11-tool --module=$PKCSLIB --list-slots &>> $PKCS11_TOOL_PRE + +# list objects +p11tool --provider=$PKCSLIB --list-all "$PKCS11_TOKEN_URL" &>> $P11TOOL_PRE +p11tool --provider=$PKCSLIB --list-all --login "$PKCS11_TOKEN_URL" &>> $P11TOOL_PRE +pkcs11-tool --module=$PKCSLIB --slot $SLOT -list-objects &>> $PKCS11_TOOL_PRE +pkcs11-tool --module=$PKCSLIB --slot $SLOT --login --pin $PKCS11_USER_PIN --list-objects &>> $PKCS11_TOOL_PRE +p11sak list-key rsa --slot $SLOT --pin $PKCS11_USER_PIN &>> $P11SAK_PRE + +# migrate +killall pkcsslotd +echo -e "y\n" | pkcstok_migrate --verbose debug --slot $SLOT --sopin $PKCS11_SO_PIN --userpin $PKCS11_USER_PIN --confdir $OCK_CONFDIR --datastore $OCK_DATASTORE +pkcsslotd + +# list slots/tokens +pkcsconf -i &>> $PKCSCONF_POST +pkcsconf -s &>> $PKCSCONF_POST +pkcsconf -t &>> $PKCSCONF_POST +p11tool --provider=$PKCSLIB --list-tokens &>> p11tool-post.out +pkcs11-tool --module=$PKCSLIB --list-slots &>> pkcs11-tool-post.out + +# list objects +p11tool --provider=$PKCSLIB --list-all "$PKCS11_TOKEN_URL" &>> $P11TOOL_POST +p11tool --provider=$PKCSLIB --list-all --login "$PKCS11_TOKEN_URL" &>> $P11TOOL_POST +pkcs11-tool --module=$PKCSLIB --slot $SLOT -list-objects &>> $PKCS11_TOOL_POST +pkcs11-tool --module=$PKCSLIB --slot $SLOT --login --pin $PKCS11_USER_PIN --list-objects &>> $PKCS11_TOOL_POST +p11sak list-key rsa --slot $SLOT --pin $PKCS11_USER_PIN &>> $P11SAK_POST + +# compare +cmp $PKCSCONF_PRE $PKCSCONF_POST +cmp $P11TOOL_PRE $P11TOOL_POST +cmp $PKCS11_TOOL_PRE $PKCS11_TOOL_POST +cmp $P11SAK_PRE $P11SAK_POST diff --git a/testcases/misc_tests/misc_tests.mk b/testcases/misc_tests/misc_tests.mk index 0e0ac22..559f06d 100644 --- a/testcases/misc_tests/misc_tests.mk +++ b/testcases/misc_tests/misc_tests.mk @@ -5,7 +5,8 @@ noinst_PROGRAMS += \ testcases/misc_tests/tok_obj testcases/misc_tests/tok_rsa \ testcases/misc_tests/tok_des \ testcases/misc_tests/fork testcases/misc_tests/multi_instance \ - testcases/misc_tests/obj_lock + testcases/misc_tests/obj_lock testcases/misc_tests/tok2tok_transport \ + testcases/misc_tests/obj_lock testcases/misc_tests/reencrypt testcases_misc_tests_obj_mgmt_tests_CFLAGS = ${testcases_inc} testcases_misc_tests_obj_mgmt_tests_LDADD = \ @@ -54,4 +55,14 @@ testcases_misc_tests_multi_instance_SOURCES = \ testcases_misc_tests_obj_lock_CFLAGS = ${testcases_inc} testcases_misc_tests_obj_lock_LDADD = testcases/common/libcommon.la testcases_misc_tests_obj_lock_SOURCES = \ - testcases/misc_tests/obj_lock.c \ No newline at end of file + testcases/misc_tests/obj_lock.c + +testcases_misc_tests_tok2tok_transport_CFLAGS = ${testcases_inc} +testcases_misc_tests_tok2tok_transport_LDADD = testcases/common/libcommon.la +testcases_misc_tests_tok2tok_transport_SOURCES = \ + testcases/misc_tests/tok2tok_transport.c + +testcases_misc_tests_reencrypt_CFLAGS = ${testcases_inc} +testcases_misc_tests_reencrypt_LDADD = testcases/common/libcommon.la +testcases_misc_tests_reencrypt_SOURCES = \ + testcases/misc_tests/reencrypt.c \ No newline at end of file diff --git a/testcases/misc_tests/multi_instance.c b/testcases/misc_tests/multi_instance.c index c965b44..40638fc 100644 --- a/testcases/misc_tests/multi_instance.c +++ b/testcases/misc_tests/multi_instance.c @@ -20,16 +20,12 @@ #include #include -#include #include #include #include "pkcs11types.h" #include "regress.h" - -int do_GetFunctionList(void); - CK_RV do_GenerateTokenRSAKeyPair(CK_SLOT_ID slot_id, CK_SESSION_HANDLE sess, CK_BYTE *label, CK_ULONG bits, CK_OBJECT_HANDLE *hPubKey, diff --git a/testcases/misc_tests/obj_lock.c b/testcases/misc_tests/obj_lock.c index 5de20f2..229aa05 100644 --- a/testcases/misc_tests/obj_lock.c +++ b/testcases/misc_tests/obj_lock.c @@ -21,17 +21,12 @@ #include #include -#include #include #include #include "pkcs11types.h" #include "regress.h" - -int do_GetFunctionList(void); - - void *usage_thread_func(CK_OBJECT_HANDLE *h_key) { CK_RV rv; diff --git a/testcases/misc_tests/obj_mgmt.c b/testcases/misc_tests/obj_mgmt.c index 459b07f..6517511 100644 --- a/testcases/misc_tests/obj_mgmt.c +++ b/testcases/misc_tests/obj_mgmt.c @@ -193,7 +193,7 @@ CK_RV do_CopyObject(void) CK_BYTE false = FALSE; - CK_OBJECT_HANDLE h_data; + CK_OBJECT_HANDLE h_data, h_data2; CK_OBJECT_CLASS data_class = CKO_DATA; CK_BYTE data_application[] = "Test Application"; CK_BYTE data_value[] = "1234567890abcedfghijklmnopqrstuvwxyz"; @@ -202,6 +202,13 @@ CK_RV do_CopyObject(void) {CKA_TOKEN, &false, sizeof(false)}, {CKA_VALUE, &data_value, sizeof(data_value)} }; + /* Invalid: coannot set CKA_UNIQUE_ID */ + CK_ATTRIBUTE data_attribs2[] = { + {CKA_CLASS, &data_class, sizeof(data_class)}, + {CKA_TOKEN, &false, sizeof(false)}, + {CKA_VALUE, &data_value, sizeof(data_value)}, + {CKA_UNIQUE_ID, &data_value, sizeof(data_value)} + }; CK_OBJECT_HANDLE h_copy; CK_ATTRIBUTE copy_attribs[] = { @@ -218,6 +225,16 @@ CK_RV do_CopyObject(void) {CKA_PRIME, &buf2, sizeof(buf2)} }; + CK_BYTE buf3[100]; + CK_ATTRIBUTE unique_id_attribs[] = { + {CKA_UNIQUE_ID, &buf3, sizeof(buf3)} + }; + + CK_BYTE buf4[100]; + CK_ATTRIBUTE unique_id_attribs2[] = { + {CKA_UNIQUE_ID, &buf4, sizeof(buf4)} + }; + testcase_begin("starting..."); if (get_user_pin(user_pin)) @@ -249,6 +266,13 @@ CK_RV do_CopyObject(void) return rc; } + /* try to create invalid object */ + rc = funcs->C_CreateObject(h_session, data_attribs2, 4, &h_data2); + if (rc != CKR_ATTRIBUTE_READ_ONLY) { + testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); + return rc; + } + /* create the copy */ rc = funcs->C_CopyObject(h_session, h_data, copy_attribs, 1, &h_copy); if (rc != CKR_OK) { @@ -301,6 +325,26 @@ CK_RV do_CopyObject(void) return rc; } + /* try to extract the CKA_UNIQUE_ID attribute from the original */ + unique_id_attribs[0].ulValueLen = sizeof(buf3); + rc = funcs->C_GetAttributeValue(h_session, h_data, unique_id_attribs, 1); + if (rc != CKR_OK) { + testcase_fail("C_GetAttributeValue() rc=%s", p11_get_ckr(rc)); + return rc; + } + /* now, try to extract the CKA_UNIQUE_IDattribute from the copy */ + unique_id_attribs2[0].ulValueLen = sizeof(buf4); + rc = funcs->C_GetAttributeValue(h_session, h_copy, unique_id_attribs2, 1); + if (rc != CKR_OK) { + testcase_fail("C_GetAttributeValue() rc=%s", p11_get_ckr(rc)); + return rc; + } + if (memcmp(unique_id_attribs[0].pValue, + unique_id_attribs2[0].pValue, 64) == 0) { + testcase_fail("unique id attributes match"); + return -1; + } + /* now, get the size of the original object */ rc = funcs->C_GetObjectSize(h_session, h_data, &obj_size); if (rc != CKR_OK) { @@ -381,6 +425,7 @@ CK_RV do_SetAttributeValues(void) CK_BYTE cert_id[] = "Certificate ID"; CK_BYTE cert_value[] = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"; + CK_BYTE unique_id[] = "deadbeef"; CK_ATTRIBUTE cert_attribs[] = { {CKA_CLASS, &cert_class, sizeof(cert_class)}, @@ -399,6 +444,10 @@ CK_RV do_SetAttributeValues(void) {CKA_ISSUER, &cert_issuer, sizeof(cert_issuer)}, {CKA_ID, &cert_id2, sizeof(cert_id2)} }; + /* Invalid: update CKA_UNIQUE_ID */ + CK_ATTRIBUTE update_attr2[] = { + {CKA_UNIQUE_ID, &unique_id, sizeof(unique_id)} + }; CK_BYTE cert_value2[] = "Invalid Value"; CK_BYTE cert_id3[] = "ID #3"; @@ -437,6 +486,13 @@ CK_RV do_SetAttributeValues(void) return rc; } + /* Try to change the CKA_UNIQUE_ID */ + rc = funcs->C_SetAttributeValue(h_session, h_cert, update_attr2, 1); + if (rc != CKR_ATTRIBUTE_READ_ONLY) { + testcase_fail("C_SetAttributeValue() rc = %s", p11_get_ckr(rc)); + return rc; + } + /* Add CKA_SERIAL_NUMBER and CKA_ISSUER and change the * existing CKA_ID */ @@ -1399,6 +1455,169 @@ done: return rc; } +/* + * do_ProfileSearch Test: + */ +CK_RV do_ProfileSearch(void) +{ + unsigned int i; + CK_RV rc, loc_rc; + CK_ULONG find_count; + CK_SLOT_ID slot_id; + + CK_SESSION_HANDLE h_session = CK_INVALID_HANDLE; + CK_BYTE user_pin[PKCS11_MAX_PIN_LEN] = {0}; + CK_ULONG user_pin_len = 0; + + /* profile object 1 */ + CK_OBJECT_CLASS profile1_class = CKO_PROFILE; + CK_PROFILE_ID profile1_profile_id = CKP_BASELINE_PROVIDER; + CK_ATTRIBUTE profile1_template[] = { + {CKA_CLASS, &profile1_class, sizeof(profile1_class)}, + {CKA_PROFILE_ID, &profile1_profile_id, sizeof(profile1_profile_id)}, + }; + + /* profile object 2 */ + CK_OBJECT_CLASS profile2_class = CKO_PROFILE; + CK_ATTRIBUTE profile2_template[] = { + {CKA_CLASS, &profile2_class, sizeof(profile2_class)}, + }; + + CK_OBJECT_HANDLE h_obj1 = 0, h_obj2 = 0, obj_list[10] = {0}; + + CK_ATTRIBUTE find_tmpl[] = { + {CKA_CLASS, &profile1_class, sizeof(profile1_class)} + }; + CK_ATTRIBUTE find_tmpl2[] = { + {CKA_CLASS, &profile1_class, sizeof(profile1_class)}, + {CKA_PROFILE_ID, &profile1_profile_id, sizeof(profile1_profile_id)} + }; + + if (skip_token_obj == TRUE) { + testcase_notice("Skipping tests that creates token objects"); + return CKR_OK; + } + + slot_id = SLOT_ID; + + testcase_begin("starting..."); + + if (get_user_pin(user_pin)) + return CKR_FUNCTION_FAILED; + + user_pin_len = (CK_ULONG) strlen((char *) user_pin); + + /* Open a session with the token */ + rc = funcs->C_OpenSession(slot_id, + (CKF_SERIAL_SESSION | CKF_RW_SESSION), + NULL_PTR, NULL_PTR, &h_session); + if (rc != CKR_OK) { + testcase_fail("C_OpenSession() rc = %s", p11_get_ckr(rc)); + goto done; + } + + // Login correctly + rc = funcs->C_Login(h_session, CKU_USER, user_pin, user_pin_len); + if (rc != CKR_OK) { + testcase_fail("C_Login() rc = %s", p11_get_ckr(rc)); + goto session_close; + } + + /* Create the 2 test objects */ + rc = funcs->C_CreateObject(h_session, profile1_template, 2, &h_obj1); + if (rc != 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) { + testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); + goto destroy_1; + } + + // Now find the profile objects + rc = funcs->C_FindObjectsInit(h_session, find_tmpl, 1); + if (rc != CKR_OK) { + testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc)); + goto destroy; + } + rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count); + if (rc != CKR_OK) { + testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc)); + goto destroy; + } + if (find_count != 2) { + testcase_fail("found %ld objects when expected 1", find_count); + funcs->C_FindObjectsFinal(h_session); + rc = -1; + goto destroy; + } + /* Make sure we got the right ones */ + for (i = 0; i < find_count; i++) { + if (obj_list[i] != h_obj1 && obj_list[i] != h_obj2) { + testcase_fail("found the wrong object handles"); + rc = -1; + } + } + rc = funcs->C_FindObjectsFinal(h_session); + if (rc != CKR_OK) { + testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc)); + } + + // Now find only the first profile object + rc = funcs->C_FindObjectsInit(h_session, find_tmpl2, 2); + if (rc != CKR_OK) { + testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc)); + goto destroy; + } + rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count); + if (rc != CKR_OK) { + testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc)); + goto destroy; + } + if (find_count != 1) { + testcase_fail("found %ld objects when expected 1", find_count); + funcs->C_FindObjectsFinal(h_session); + rc = -1; + goto destroy; + } + /* Make sure we got the right ones */ + for (i = 0; i < find_count; i++) { + if (obj_list[i] != h_obj1) { + testcase_fail("found the wrong object handles"); + rc = -1; + } + } + rc = funcs->C_FindObjectsFinal(h_session); + if (rc != CKR_OK) { + testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc)); + } + + testcase_pass("Looks okay..."); + +destroy: + loc_rc = funcs->C_DestroyObject(h_session, h_obj2); + if (loc_rc != CKR_OK) + testcase_fail("C_DestroyObject() rc = %s", p11_get_ckr(loc_rc)); +destroy_1: + loc_rc = funcs->C_DestroyObject(h_session, h_obj1); + if (loc_rc != CKR_OK) + testcase_fail("C_DestroyObject() rc = %s", p11_get_ckr(loc_rc)); + + loc_rc = funcs->C_Logout(h_session); + if (loc_rc != CKR_OK) + testcase_fail("C_Logout() rc = %s", p11_get_ckr(loc_rc)); + +session_close: + /* Close the session */ + loc_rc = funcs->C_CloseSession(h_session); + if (loc_rc != CKR_OK) + testcase_fail("C_CloseSession() rc = %s", p11_get_ckr(loc_rc)); + +done: + return rc; +} + CK_RV obj_mgmt_functions() { int rc; @@ -1423,6 +1642,10 @@ CK_RV obj_mgmt_functions() if (rc && !no_stop) return rc; + rc = do_ProfileSearch(); + if (rc && !no_stop) + return rc; + rc = do_CreateTokenObjects(); if (rc && !no_stop) return rc; diff --git a/testcases/misc_tests/reencrypt.c b/testcases/misc_tests/reencrypt.c new file mode 100644 index 0000000..fa9633f --- /dev/null +++ b/testcases/misc_tests/reencrypt.c @@ -0,0 +1,848 @@ +/* + * 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 + */ + +/* File: reencrypt.c + * + * Test driver. In-depth regression test for PKCS #11 + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "pkcs11types.h" +#include "regress.h" +#include "mech_to_str.h" +#include "common.c" + +CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; +CK_ULONG user_pin_len; +CK_SLOT_ID slot_id = 1; + +CK_SESSION_HANDLE session; +CK_OBJECT_HANDLE sym_key1 = CK_INVALID_HANDLE; +CK_OBJECT_HANDLE sym_key2 = CK_INVALID_HANDLE; +CK_OBJECT_HANDLE publ_key1 = CK_INVALID_HANDLE; +CK_OBJECT_HANDLE priv_key1 = CK_INVALID_HANDLE; +CK_OBJECT_HANDLE publ_key2 = CK_INVALID_HANDLE; +CK_OBJECT_HANDLE priv_key2 = CK_INVALID_HANDLE; + +CK_C_IBM_ReencryptSingle _C_IBM_ReencryptSingle; + +CK_RSA_PKCS_OAEP_PARAMS oaep_params_sha1 = { + .hashAlg = CKM_SHA_1, + .mgf = CKG_MGF1_SHA1, + .source = 0, + .pSourceData = NULL, + .ulSourceDataLen = 0, +}; + +CK_RSA_PKCS_OAEP_PARAMS oaep_params_sha1_source = { + .hashAlg = CKM_SHA_1, + .mgf = CKG_MGF1_SHA1, + .source = CKZ_DATA_SPECIFIED, + .pSourceData = "abc", + .ulSourceDataLen = 3, +}; + +CK_RSA_PKCS_OAEP_PARAMS oaep_params_sha256 = { + .hashAlg = CKM_SHA256, + .mgf = CKG_MGF1_SHA256, + .source = 0, + .pSourceData = NULL, + .ulSourceDataLen = 0, +}; + +CK_RSA_PKCS_OAEP_PARAMS oaep_params_sha256_source = { + .hashAlg = CKM_SHA256, + .mgf = CKG_MGF1_SHA256, + .source = CKZ_DATA_SPECIFIED, + .pSourceData = "abc", + .ulSourceDataLen = 3, +}; + + +CK_BYTE aes_iv[16] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }; + +CK_BYTE des_iv[8] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 }; + +CK_BYTE clear_data[32]; +CK_BYTE encrypted_data1[2048]; +CK_ULONG encrypted_data1_len = sizeof(encrypted_data1); +CK_BYTE encrypted_data2[2048]; +CK_ULONG encrypted_data2_len = sizeof(encrypted_data2); +CK_BYTE decrypted_data[1024]; +CK_ULONG decrypted_data_len = sizeof(decrypted_data); + +struct mech_info { + char *name; + CK_MECHANISM mech; + CK_MECHANISM key_gen_mech; + CK_ULONG rsa_modbits; + CK_ULONG rsa_publ_exp_len; + CK_BYTE rsa_publ_exp[4]; + CK_ULONG sym_keylen; + CK_ULONG clear_data_len; +}; + +struct mech_info reencrypt_tests[] = { + { + .name = "AES 128 ECB", + .mech = { CKM_AES_ECB, 0, 0 }, + .key_gen_mech = { CKM_AES_KEY_GEN, 0, 0 }, + .sym_keylen = 16, + .clear_data_len = 32, + }, + { + .name = "AES 192 ECB", + .mech = { CKM_AES_ECB, 0, 0 }, + .key_gen_mech = { CKM_AES_KEY_GEN, 0, 0 }, + .sym_keylen = 24, + .clear_data_len = 32, + }, + { + .name = "AES 256 ECB", + .mech = { CKM_AES_ECB, 0, 0 }, + .key_gen_mech = { CKM_AES_KEY_GEN, 0, 0 }, + .sym_keylen = 32, + .clear_data_len = 32, + }, + { + .name = "AES 128 CBC", + .mech = { CKM_AES_CBC, aes_iv, sizeof(aes_iv) }, + .key_gen_mech = { CKM_AES_KEY_GEN, 0, 0 }, + .sym_keylen = 16, + .clear_data_len = 32, + }, + { + .name = "AES 192 CBC", + .mech = { CKM_AES_CBC, aes_iv, sizeof(aes_iv) }, + .key_gen_mech = { CKM_AES_KEY_GEN, 0, 0 }, + .sym_keylen = 24, + .clear_data_len = 32, + }, + { + .name = "AES 256 CBC", + .mech = { CKM_AES_CBC, aes_iv, sizeof(aes_iv) }, + .key_gen_mech = { CKM_AES_KEY_GEN, 0, 0 }, + .sym_keylen = 32, + .clear_data_len = 32, + }, + { + .name = "AES 128 CBC PAD", + .mech = { CKM_AES_CBC_PAD, aes_iv, sizeof(aes_iv) }, + .key_gen_mech = { CKM_AES_KEY_GEN, 0, 0 }, + .sym_keylen = 16, + .clear_data_len = 30, + }, + { + .name = "AES 192 CBC PAD", + .mech = { CKM_AES_CBC_PAD, aes_iv, sizeof(aes_iv) }, + .key_gen_mech = { CKM_AES_KEY_GEN, 0, 0 }, + .sym_keylen = 24, + .clear_data_len = 30, + }, + { + .name = "AES 256 CBC PAD", + .mech = { CKM_AES_CBC_PAD, aes_iv, sizeof(aes_iv) }, + .key_gen_mech = { CKM_AES_KEY_GEN, 0, 0 }, + .sym_keylen = 32, + .clear_data_len = 30, + }, + { + .name = "DES ECB", + .mech = { CKM_DES_ECB, 0, 0 }, + .key_gen_mech = { CKM_DES_KEY_GEN, 0, 0 }, + .clear_data_len = 32, + }, + { + .name = "DES CCB", + .mech = { CKM_DES_CBC, des_iv, sizeof(des_iv) }, + .key_gen_mech = { CKM_DES_KEY_GEN, 0, 0 }, + .clear_data_len = 32, + }, + { + .name = "DES CBC PAD", + .mech = { CKM_DES_CBC_PAD, des_iv, sizeof(des_iv) }, + .key_gen_mech = { CKM_DES_KEY_GEN, 0, 0 }, + .clear_data_len = 30, + }, + { + .name = "DES3 ECB", + .mech = { CKM_DES3_ECB, 0, 0 }, + .key_gen_mech = { CKM_DES3_KEY_GEN, 0, 0 }, + .clear_data_len = 32, + }, + { + .name = "DES3 CCB", + .mech = { CKM_DES3_CBC, des_iv, sizeof(des_iv) }, + .key_gen_mech = { CKM_DES3_KEY_GEN, 0, 0 }, + .clear_data_len = 32, + }, + { + .name = "DES3 CBC PAD", + .mech = { CKM_DES3_CBC_PAD, des_iv, sizeof(des_iv) }, + .key_gen_mech = { CKM_DES3_KEY_GEN, 0, 0 }, + .clear_data_len = 30, + }, + { + .name = "RSA 512 PKCS", + .mech = { CKM_RSA_PKCS, 0, 0 }, + .key_gen_mech = { CKM_RSA_PKCS_KEY_PAIR_GEN, 0, 0 }, + .rsa_modbits = 512, + .rsa_publ_exp_len = 3, + .rsa_publ_exp = {0x01, 0x00, 0x01}, + .clear_data_len = 30, + }, + { + .name = "RSA 1024 PKCS", + .mech = { CKM_RSA_PKCS, 0, 0 }, + .key_gen_mech = { CKM_RSA_PKCS_KEY_PAIR_GEN, 0, 0 }, + .rsa_modbits = 1024, + .rsa_publ_exp_len = 3, + .rsa_publ_exp = {0x01, 0x00, 0x01}, + .clear_data_len = 30, + }, + { + .name = "RSA 2048 PKCS", + .mech = { CKM_RSA_PKCS, 0, 0 }, + .key_gen_mech = { CKM_RSA_PKCS_KEY_PAIR_GEN, 0, 0 }, + .rsa_modbits = 2048, + .rsa_publ_exp_len = 3, + .rsa_publ_exp = {0x01, 0x00, 0x01}, + .clear_data_len = 30, + }, + { + .name = "RSA 1024 PKCS OAEP (SHA1)", + .mech = { CKM_RSA_PKCS_OAEP, &oaep_params_sha1, + sizeof(CK_RSA_PKCS_OAEP_PARAMS) }, + .key_gen_mech = { CKM_RSA_PKCS_KEY_PAIR_GEN, 0, 0 }, + .rsa_modbits = 1024, + .rsa_publ_exp_len = 3, + .rsa_publ_exp = {0x01, 0x00, 0x01}, + .clear_data_len = 30, + }, + { + .name = "RSA 1024 PKCS OAEP (SHA1, source data)", + .mech = { CKM_RSA_PKCS_OAEP, &oaep_params_sha1_source, + sizeof(CK_RSA_PKCS_OAEP_PARAMS) }, + .key_gen_mech = { CKM_RSA_PKCS_KEY_PAIR_GEN, 0, 0 }, + .rsa_modbits = 1024, + .rsa_publ_exp_len = 3, + .rsa_publ_exp = {0x01, 0x00, 0x01}, + .clear_data_len = 30, + }, + { + .name = "RSA 1024 PKCS OAEP (SHA256)", + .mech = { CKM_RSA_PKCS_OAEP, &oaep_params_sha256, + sizeof(CK_RSA_PKCS_OAEP_PARAMS) }, + .key_gen_mech = { CKM_RSA_PKCS_KEY_PAIR_GEN, 0, 0 }, + .rsa_modbits = 1024, + .rsa_publ_exp_len = 3, + .rsa_publ_exp = {0x01, 0x00, 0x01}, + .clear_data_len = 30, + }, + { + .name = "RSA 1024 PKCS OAEP (SHA256, source data)", + .mech = { CKM_RSA_PKCS_OAEP, &oaep_params_sha256_source, + sizeof(CK_RSA_PKCS_OAEP_PARAMS) }, + .key_gen_mech = { CKM_RSA_PKCS_KEY_PAIR_GEN, 0, 0 }, + .rsa_modbits = 1024, + .rsa_publ_exp_len = 3, + .rsa_publ_exp = {0x01, 0x00, 0x01}, + .clear_data_len = 30, + }, +}; + +#define NUM_REENCRYPT_TESTS sizeof(reencrypt_tests) / \ + sizeof(struct mech_info) + +CK_RV do_reencrypt(struct mech_info *mech1, struct mech_info *mech2) +{ + CK_RSA_PKCS_OAEP_PARAMS *oaep; + CK_RV loc_rc, rc = CKR_OK; + char *s = NULL; + + 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)", + (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)", + (unsigned int)slot_id, + mech_to_str(mech2->mech.mechanism), + (unsigned int)mech2->mech.mechanism); + goto testcase_cleanup; + } + + switch (mech2->mech.mechanism) { + case CKM_DES_ECB: + case CKM_DES_CBC: + case CKM_DES_CBC_PAD: + if (is_cca_token(slot_id)) { + testcase_skip("CCA does not support DES with reencrypt"); + goto testcase_cleanup; + } + break; + case CKM_DES3_CBC_PAD: + if (is_cca_token(slot_id)) { + testcase_skip("CCA does not support DES3 CBC PAD with reencrypt"); + goto testcase_cleanup; + } + break; + case CKM_RSA_PKCS: + case CKM_RSA_PKCS_OAEP: + if (is_cca_token(slot_id)) { + testcase_skip("CCA does not support RSA with reencrypt"); + goto testcase_cleanup; + } + break; + default: + break; + } + + switch (mech1->mech.mechanism) { + case CKM_AES_CBC_PAD: + case CKM_DES_CBC_PAD: + case CKM_DES3_CBC_PAD: + case CKM_RSA_PKCS: + case CKM_RSA_PKCS_OAEP: + switch (mech2->mech.mechanism) { + case CKM_AES_CBC_PAD: + case CKM_DES_CBC_PAD: + case CKM_DES3_CBC_PAD: + case CKM_RSA_PKCS: + case CKM_RSA_PKCS_OAEP: + break; + default: + testcase_skip("Cannot reencrypt from %s (%u) to %s (%u), because " + "the target mechanism does not pad.", + mech_to_str(mech1->mech.mechanism), + (unsigned int)mech1->mech.mechanism, + mech_to_str(mech2->mech.mechanism), + (unsigned int)mech2->mech.mechanism); + goto testcase_cleanup; + } + break; + default: + break; + } + + /* + * Generate the key 1 + */ + switch (mech2->key_gen_mech.mechanism) { + case CKM_RSA_PKCS_KEY_PAIR_GEN: + if (p11_ahex_dump(&s, mech2->rsa_publ_exp, + mech2->rsa_publ_exp_len) == NULL) { + testcase_error("p11_ahex_dump() failed"); + rc = CKR_FUNCTION_FAILED; + goto testcase_cleanup; + } + + 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); + 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); + 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); + goto testcase_cleanup; + } + } + if (is_tpm_token(slot_id) ) { + 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); + goto testcase_cleanup; + } + } + if (is_icsf_token(slot_id)) { + 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); + goto testcase_cleanup; + } + } + rc = generate_RSA_PKCS_KeyPair(session, mech2->rsa_modbits, + mech2->rsa_publ_exp, + mech2->rsa_publ_exp_len, + &publ_key2, &priv_key2); + break; + + case CKM_AES_KEY_GEN: + rc = generate_AESKey(session, mech2->sym_keylen, + &mech2->key_gen_mech, &sym_key2); + break; + + case CKM_DES3_KEY_GEN: + case CKM_DES2_KEY_GEN: + case CKM_DES_KEY_GEN: + rc = funcs->C_GenerateKey(session, &mech2->key_gen_mech, + NULL, 0, &sym_key2); + break; + + default: + testcase_error("Testcase does not support %s (%u)", + mech_to_str(mech2->key_gen_mech.mechanism), + (unsigned int)mech2->key_gen_mech.mechanism); + goto testcase_cleanup; + } + + if (rc != CKR_OK) { + testcase_error("generate key-2 with mech %s (%u) in slot %lu " + "failed, rc=%s", + mech_to_str(mech2->key_gen_mech.mechanism), + (unsigned int)mech2->key_gen_mech.mechanism, + slot_id, p11_get_ckr(rc)); + goto testcase_cleanup; + } + + encrypted_data2_len = sizeof(encrypted_data2); + rc = _C_IBM_ReencryptSingle(session, &mech1->mech, + sym_key1 != CK_INVALID_HANDLE ? sym_key1 : + priv_key1, + &mech2->mech, sym_key2 != CK_INVALID_HANDLE ? + sym_key2 : publ_key2, + encrypted_data1, encrypted_data1_len, + encrypted_data2, &encrypted_data2_len); + if (rc != CKR_OK) { + oaep = (CK_RSA_PKCS_OAEP_PARAMS *)mech2->mech.pParameter; + if (rc == CKR_MECHANISM_PARAM_INVALID && + mech2->mech.mechanism == CKM_RSA_PKCS_OAEP && + is_ep11_token(slot_id) && + (oaep->hashAlg != CKM_SHA_1 || oaep->mgf != CKG_MGF1_SHA1)) { + testcase_skip("EP11 Token does not support RSA OAEP with hash " + "and/or MGF other than SHA-1"); + goto testcase_cleanup; + } + + if (rc == CKR_FUNCTION_NOT_SUPPORTED) { + testcase_skip("Slot %lu does not support C_IBM_ReencryptSingle", + slot_id); + goto testcase_cleanup; + } + + testcase_error("C_IBM_ReencryptSingle with decr-mech %s (%u) and " + "encr-mech %s (%u) failed, rc=%s", + mech_to_str(mech1->mech.mechanism), + (unsigned int)mech1->mech.mechanism, + mech_to_str(mech2->mech.mechanism), + (unsigned int)mech2->mech.mechanism, + p11_get_ckr(rc)); + goto testcase_cleanup; + } + + rc = funcs->C_DecryptInit(session, &mech2->mech, + sym_key2 != CK_INVALID_HANDLE ? sym_key2 : + priv_key2); + if (rc != CKR_OK) { + testcase_error("C_DecryptInit rc=%s", p11_get_ckr(rc)); + goto testcase_cleanup; + } + + decrypted_data_len = sizeof(decrypted_data); + rc = funcs->C_Decrypt(session, encrypted_data2, encrypted_data2_len, + decrypted_data, &decrypted_data_len); + if (rc != CKR_OK) { + testcase_error("C_Decrypt rc=%s", p11_get_ckr(rc)); + goto testcase_cleanup; + } + + if (decrypted_data_len != mech1->clear_data_len) { + testcase_error("The decrypted data length differs from the original " + "clear data: original: %lu, decrypted: %lu", + mech1->clear_data_len, decrypted_data_len); + rc = CKR_FUNCTION_FAILED; + goto testcase_cleanup; + } + + if (memcmp(clear_data, decrypted_data, mech1->clear_data_len) != 0) { + testcase_error("The decrypted data differs from the original " + "clear data."); + rc = CKR_FUNCTION_FAILED; + goto testcase_cleanup; + } + + testcase_new_assertion(); + testcase_pass("Reencrypt from '%s' to '%s'", mech1->name, mech2->name); + +testcase_cleanup: + if (sym_key2 != CK_INVALID_HANDLE) { + loc_rc = funcs->C_DestroyObject(session, sym_key2); + if (loc_rc != CKR_OK) + testcase_error("C_DestroyObject(), rc=%s.", p11_get_ckr(loc_rc)); + } + sym_key2 = CK_INVALID_HANDLE; + if (publ_key2 != CK_INVALID_HANDLE) { + loc_rc = funcs->C_DestroyObject(session, publ_key2); + if (loc_rc != CKR_OK) + testcase_error("C_DestroyObject(), rc=%s.", p11_get_ckr(loc_rc)); + } + publ_key2 = CK_INVALID_HANDLE; + if (priv_key2 != CK_INVALID_HANDLE) { + loc_rc = funcs->C_DestroyObject(session, priv_key2); + if (loc_rc != CKR_OK) + testcase_error("C_DestroyObject(), rc=%s.", p11_get_ckr(loc_rc)); + } + priv_key2 = CK_INVALID_HANDLE; + + if (s != NULL) + free(s); + + return rc; +} + +CK_RV do_encrypt_reencrypt(struct mech_info *mech1) +{ + CK_RSA_PKCS_OAEP_PARAMS *oaep; + CK_RV loc_rc, rc = CKR_OK; + char *s = NULL; + CK_ULONG i; + + 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)", + (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)", + (unsigned int)slot_id, + mech_to_str(mech1->mech.mechanism), + (unsigned int)mech1->mech.mechanism); + goto testcase_cleanup; + } + + switch (mech1->mech.mechanism) { + case CKM_DES_ECB: + case CKM_DES_CBC: + case CKM_DES_CBC_PAD: + if (is_cca_token(slot_id)) { + testsuite_skip(NUM_REENCRYPT_TESTS, "CCA does not support DES " + "with reencrypt"); + goto testcase_cleanup; + } + break; + case CKM_DES3_CBC_PAD: + if (is_cca_token(slot_id)) { + testsuite_skip(NUM_REENCRYPT_TESTS, "CCA does not support DES3 " + "CBC PAD with reencrypt"); + goto testcase_cleanup; + } + break; + case CKM_RSA_PKCS: + case CKM_RSA_PKCS_OAEP: + if (is_cca_token(slot_id)) { + testsuite_skip(NUM_REENCRYPT_TESTS, "CCA does not support RSA " + "with reencrypt"); + goto testcase_cleanup; + } + break; + default: + break; + } + + /* + * Generate the key 1 + */ + switch (mech1->key_gen_mech.mechanism) { + case CKM_RSA_PKCS_KEY_PAIR_GEN: + if (p11_ahex_dump(&s, mech1->rsa_publ_exp, + mech1->rsa_publ_exp_len) == NULL) { + testcase_error("p11_ahex_dump() failed"); + rc = CKR_FUNCTION_FAILED; + goto testcase_cleanup; + } + + if (!keysize_supported(slot_id, + mech1->key_gen_mech.mechanism, + mech1->rsa_modbits)) { + testsuite_skip(NUM_REENCRYPT_TESTS, "Token in slot %ld cannot be " + "used with modbits.='%ld'", slot_id, + mech1->rsa_modbits); + goto testcase_cleanup; + } + + if (is_ep11_token(slot_id)) { + if (!is_valid_ep11_pubexp(mech1->rsa_publ_exp, + mech1->rsa_publ_exp_len)) { + testsuite_skip(NUM_REENCRYPT_TESTS, "EP11 Token cannot be " + "used with publ_exp.='%s'", s); + goto testcase_cleanup; + } + } + if (is_cca_token(slot_id)) { + if (!is_valid_cca_pubexp(mech1->rsa_publ_exp, + mech1->rsa_publ_exp_len)) { + testsuite_skip(NUM_REENCRYPT_TESTS, "CCA 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) || + !is_valid_tpm_modbits(mech1->rsa_modbits)) { + testsuite_skip(NUM_REENCRYPT_TESTS, "TPM Token cannot be used " + "with publ_exp.='%s'", s); + goto testcase_cleanup; + } + } + if (is_icsf_token(slot_id)) { + if (!is_valid_icsf_pubexp(mech1->rsa_publ_exp, + mech1->rsa_publ_exp_len) || + mech1->rsa_modbits < 1024) { + testsuite_skip(NUM_REENCRYPT_TESTS, "ICSF Token cannot be " + "used with publ_exp='%s'.", s); + goto testcase_cleanup; + } + } + rc = generate_RSA_PKCS_KeyPair(session, mech1->rsa_modbits, + mech1->rsa_publ_exp, + mech1->rsa_publ_exp_len, + &publ_key1, &priv_key1); + break; + + case CKM_AES_KEY_GEN: + rc = generate_AESKey(session, mech1->sym_keylen, + &mech1->key_gen_mech, &sym_key1); + break; + + case CKM_DES3_KEY_GEN: + case CKM_DES2_KEY_GEN: + case CKM_DES_KEY_GEN: + rc = funcs->C_GenerateKey(session, &mech1->key_gen_mech, + NULL, 0, &sym_key1); + break; + + default: + testcase_error("Testcase does not support %s (%u)", + mech_to_str(mech1->key_gen_mech.mechanism), + (unsigned int)mech1->key_gen_mech.mechanism); + goto testcase_cleanup; + } + + if (rc != CKR_OK) { + testcase_error("generate key-1 with mech %s (%u) in slot %lu " + "failed, rc=%s", + mech_to_str(mech1->key_gen_mech.mechanism), + (unsigned int)mech1->key_gen_mech.mechanism, + slot_id, p11_get_ckr(rc)); + goto testcase_cleanup; + } + + rc = funcs->C_EncryptInit(session, &mech1->mech, + sym_key1 != CK_INVALID_HANDLE ? sym_key1 : + publ_key1); + if (rc != CKR_OK) { + oaep = (CK_RSA_PKCS_OAEP_PARAMS *)mech1->mech.pParameter; + if (rc == CKR_MECHANISM_PARAM_INVALID && + mech1->mech.mechanism == CKM_RSA_PKCS_OAEP && + is_ep11_token(slot_id) && + (oaep->hashAlg != CKM_SHA_1 || oaep->mgf != CKG_MGF1_SHA1)) { + testsuite_skip(NUM_REENCRYPT_TESTS, "EP11 Token does not support " + "RSA OAEP with hash and/or MGF other than SHA-1"); + goto testcase_cleanup; + } + + testcase_error("C_EncryptInit rc=%s", p11_get_ckr(rc)); + goto testcase_cleanup; + } + + encrypted_data1_len = sizeof(encrypted_data1); + rc = funcs->C_Encrypt(session, clear_data, mech1->clear_data_len, + encrypted_data1, &encrypted_data1_len); + if (rc != CKR_OK) { + testcase_error("C_Encrypt rc=%s", p11_get_ckr(rc)); + goto testcase_cleanup; + } + + for (i = 0; i < NUM_REENCRYPT_TESTS; i++) { + rc = do_reencrypt(mech1, &reencrypt_tests[i]); + if (rc != CKR_OK) + break; + } + +testcase_cleanup: + if (sym_key1 != CK_INVALID_HANDLE) { + loc_rc = funcs->C_DestroyObject(session, sym_key1); + if (loc_rc != CKR_OK) + testcase_error("C_DestroyObject(), rc=%s.", p11_get_ckr(loc_rc)); + } + sym_key1 = CK_INVALID_HANDLE; + if (publ_key1 != CK_INVALID_HANDLE) { + loc_rc = funcs->C_DestroyObject(session, publ_key1); + if (loc_rc != CKR_OK) + testcase_error("C_DestroyObject(), rc=%s.", p11_get_ckr(loc_rc)); + } + publ_key1 = CK_INVALID_HANDLE; + if (priv_key1 != CK_INVALID_HANDLE) { + loc_rc = funcs->C_DestroyObject(session, priv_key1); + if (loc_rc != CKR_OK) + testcase_error("C_DestroyObject(), rc=%s.", p11_get_ckr(loc_rc)); + } + priv_key1 = CK_INVALID_HANDLE; + + if (s != NULL) + free(s); + + return rc; +} + +CK_RV do_reencrypt_tests() +{ + CK_ULONG i; + CK_RV rc; + + for (i = 0; i < sizeof(clear_data); i++) + clear_data[i] = (CK_BYTE)i; + + for (i = 0; i < NUM_REENCRYPT_TESTS; i++) { + rc = do_encrypt_reencrypt(&reencrypt_tests[i]); + if (rc != CKR_OK) + break; + } + + return CKR_OK; +} + + +int main(int argc, char **argv) +{ + CK_C_INITIALIZE_ARGS cinit_args; + int i, ret = 1; + CK_RV rv; + CK_FLAGS flags; + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-slot") == 0) { + ++i; + slot_id = atoi(argv[i]); + } + + if (strcmp(argv[i], "-h") == 0) { + printf("usage: %s [-slot ] [-h]\n\n", argv[0]); + printf("By default, Slot #1 is used\n\n"); + return -1; + } + } + + if (get_user_pin(user_pin)) + return CKR_FUNCTION_FAILED; + user_pin_len = (CK_ULONG) strlen((char *) user_pin); + + printf("Using slot #%lu...\n\n", slot_id); + + rv = do_GetFunctionList(); + if (rv != TRUE) { + testcase_fail("do_GetFunctionList() rc = %s", p11_get_ckr(rv)); + goto out; + } + + *(void **)(&_C_IBM_ReencryptSingle) = + dlsym(pkcs11lib, "C_IBM_ReencryptSingle"); + if (_C_IBM_ReencryptSingle == NULL) { + testcase_skip("C_IBM_ReencryptSingle not supported"); + goto out; + } + + testcase_setup(0); + testcase_begin("Starting..."); + + // Initialize + memset(&cinit_args, 0x0, sizeof(cinit_args)); + cinit_args.flags = CKF_OS_LOCKING_OK; + + if ((rv = funcs->C_Initialize(&cinit_args))) { + testcase_fail("C_Initialize rc = %s", p11_get_ckr(rv)); + goto out; + } + + flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + rv = funcs->C_OpenSession(slot_id, flags, NULL, NULL, &session); + if (rv != CKR_OK) { + testcase_fail("C_OpenSession rc = %s", p11_get_ckr(rv)); + goto finalize; + } + + rv = funcs->C_Login(session, CKU_USER, user_pin, user_pin_len); + if (rv != CKR_OK) { + testcase_fail("C_Login rc = %s", p11_get_ckr(rv)); + goto close_session; + } + + rv = do_reencrypt_tests(); + if (rv != CKR_OK) + goto close_session; + + rv = funcs->C_CloseSession(session); + if (rv != CKR_OK) { + testcase_fail("C_CloseSession rc = %s", p11_get_ckr(rv)); + goto finalize; + } + + rv = funcs->C_Finalize(NULL); + if (rv != CKR_OK) { + testcase_fail("C_Finalize rc = %s", p11_get_ckr(rv)); + goto out; + } + + ret = 0; + goto out; + +close_session: + rv = funcs->C_CloseSession(session); + if (rv != CKR_OK) { + testcase_fail("C_CloseSession rc = %s", p11_get_ckr(rv)); + ret = 1; + } +finalize: + rv = funcs->C_Finalize(NULL); + if (rv != CKR_OK) { + testcase_fail("C_Finalize rc = %s", p11_get_ckr(rv)); + ret = 1; + } +out: + testcase_print_result(); + return ret; +} diff --git a/testcases/misc_tests/speed.c b/testcases/misc_tests/speed.c index 39fdca0..8f5426b 100644 --- a/testcases/misc_tests/speed.c +++ b/testcases/misc_tests/speed.c @@ -27,7 +27,6 @@ #include #include #include -#include #include "pkcs11types.h" #include "regress.h" @@ -64,9 +63,6 @@ static inline unsigned long delta_time_us(struct timeval *t1, return (d ? d : 1); // return 1us if delta is 0 } - -int do_GetFunctionList(void); - // keylength: 512, 1024, 2048, 4096 int do_RSA_PKCS_EncryptDecrypt(int keylength) { diff --git a/testcases/misc_tests/threadmkobj.c b/testcases/misc_tests/threadmkobj.c index f61bbd0..a92f909 100644 --- a/testcases/misc_tests/threadmkobj.c +++ b/testcases/misc_tests/threadmkobj.c @@ -29,7 +29,6 @@ #include "defs.h" int do_GetInfo(void); -int do_GetFunctionList(void); void init_coprocessor(void); diff --git a/testcases/misc_tests/tok2tok_transport.c b/testcases/misc_tests/tok2tok_transport.c new file mode 100644 index 0000000..1c482c2 --- /dev/null +++ b/testcases/misc_tests/tok2tok_transport.c @@ -0,0 +1,1308 @@ +/* + * 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 + */ + +/* File: tok2tok_transport.c + * + * Test driver. In-depth regression test for PKCS #11 + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "pkcs11types.h" +#include "regress.h" +#include "mech_to_str.h" +#include "ec_curves.h" +#include "common.c" + +CK_RSA_PKCS_OAEP_PARAMS oaep_params_sha1 = { + .hashAlg = CKM_SHA_1, + .mgf = CKG_MGF1_SHA1, + .source = 0, + .pSourceData = NULL, + .ulSourceDataLen = 0, +}; + +CK_RSA_PKCS_OAEP_PARAMS oaep_params_sha1_source = { + .hashAlg = CKM_SHA_1, + .mgf = CKG_MGF1_SHA1, + .source = CKZ_DATA_SPECIFIED, + .pSourceData = "abc", + .ulSourceDataLen = 3, +}; + +CK_RSA_PKCS_OAEP_PARAMS oaep_params_sha256 = { + .hashAlg = CKM_SHA256, + .mgf = CKG_MGF1_SHA256, + .source = 0, + .pSourceData = NULL, + .ulSourceDataLen = 0, +}; + +CK_RSA_PKCS_OAEP_PARAMS oaep_params_sha256_source = { + .hashAlg = CKM_SHA256, + .mgf = CKG_MGF1_SHA256, + .source = CKZ_DATA_SPECIFIED, + .pSourceData = "abc", + .ulSourceDataLen = 3, +}; + +CK_BYTE aes_iv[16] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }; + +CK_BYTE des_iv[8] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 }; + +struct wrapping_mech_info { + char *name; + CK_MECHANISM wrapping_mech; + CK_MECHANISM wrapping_key_gen_mech; + CK_ULONG rsa_modbits; + CK_ULONG rsa_publ_exp_len; + CK_BYTE rsa_publ_exp[4]; + CK_ULONG sym_keylen; +}; + +struct wrapping_mech_info wrapping_tests[] = { + { + .name = "Wrap/Unwrap with RSA 512 PKCS", + .wrapping_mech = { CKM_RSA_PKCS, 0, 0 }, + .wrapping_key_gen_mech = { CKM_RSA_PKCS_KEY_PAIR_GEN, 0, 0 }, + .rsa_modbits = 512, + .rsa_publ_exp_len = 3, + .rsa_publ_exp = {0x01, 0x00, 0x01}, + }, + { + .name = "Wrap/Unwrap with RSA 1024 PKCS", + .wrapping_mech = { CKM_RSA_PKCS, 0, 0 }, + .wrapping_key_gen_mech = { CKM_RSA_PKCS_KEY_PAIR_GEN, 0, 0 }, + .rsa_modbits = 1024, + .rsa_publ_exp_len = 3, + .rsa_publ_exp = {0x01, 0x00, 0x01}, + }, + { + .name = "Wrap/Unwrap with RSA 2048 PKCS", + .wrapping_mech = { CKM_RSA_PKCS, 0, 0 }, + .wrapping_key_gen_mech = { CKM_RSA_PKCS_KEY_PAIR_GEN, 0, 0 }, + .rsa_modbits = 2048, + .rsa_publ_exp_len = 3, + .rsa_publ_exp = {0x01, 0x00, 0x01}, + }, + { + .name = "Wrap/Unwrap with RSA 1024 PKCS OAEP (SHA1)", + .wrapping_mech = { CKM_RSA_PKCS_OAEP, &oaep_params_sha1, + sizeof(CK_RSA_PKCS_OAEP_PARAMS) }, + .wrapping_key_gen_mech = { CKM_RSA_PKCS_KEY_PAIR_GEN, 0, 0 }, + .rsa_modbits = 1024, + .rsa_publ_exp_len = 3, + .rsa_publ_exp = {0x01, 0x00, 0x01}, + }, + { + .name = "Wrap/Unwrap with RSA 1024 PKCS OAEP (SHA1, source data)", + .wrapping_mech = { CKM_RSA_PKCS_OAEP, &oaep_params_sha1_source, + sizeof(CK_RSA_PKCS_OAEP_PARAMS) }, + .wrapping_key_gen_mech = { CKM_RSA_PKCS_KEY_PAIR_GEN, 0, 0 }, + .rsa_modbits = 1024, + .rsa_publ_exp_len = 3, + .rsa_publ_exp = {0x01, 0x00, 0x01}, + }, + { + .name = "Wrap/Unwrap with RSA 1024 PKCS OAEP (SHA256)", + .wrapping_mech = { CKM_RSA_PKCS_OAEP, &oaep_params_sha256, + sizeof(CK_RSA_PKCS_OAEP_PARAMS) }, + .wrapping_key_gen_mech = { CKM_RSA_PKCS_KEY_PAIR_GEN, 0, 0 }, + .rsa_modbits = 1024, + .rsa_publ_exp_len = 3, + .rsa_publ_exp = {0x01, 0x00, 0x01}, + }, + { + .name = "Wrap/Unwrap with RSA 1024 PKCS OAEP (SHA256, source data)", + .wrapping_mech = { CKM_RSA_PKCS_OAEP, &oaep_params_sha256_source, + sizeof(CK_RSA_PKCS_OAEP_PARAMS) }, + .wrapping_key_gen_mech = { CKM_RSA_PKCS_KEY_PAIR_GEN, 0, 0 }, + .rsa_modbits = 1024, + .rsa_publ_exp_len = 3, + .rsa_publ_exp = {0x01, 0x00, 0x01}, + }, + { + .name = "Wrap/Unwrap with AES 128 ECB", + .wrapping_mech = { CKM_AES_ECB, 0, 0 }, + .wrapping_key_gen_mech = { CKM_AES_KEY_GEN, 0, 0 }, + .sym_keylen = 16, + }, + { + .name = "Wrap/Unwrap with AES 192 ECB", + .wrapping_mech = { CKM_AES_ECB, 0, 0 }, + .wrapping_key_gen_mech = { CKM_AES_KEY_GEN, 0, 0 }, + .sym_keylen = 24, + }, + { + .name = "Wrap/Unwrap with AES 256 ECB", + .wrapping_mech = { CKM_AES_ECB, 0, 0 }, + .wrapping_key_gen_mech = { CKM_AES_KEY_GEN, 0, 0 }, + .sym_keylen = 32, + }, + { + .name = "Wrap/Unwrap with AES 128 CBC", + .wrapping_mech = { CKM_AES_CBC, aes_iv, sizeof(aes_iv) }, + .wrapping_key_gen_mech = { CKM_AES_KEY_GEN, 0, 0 }, + .sym_keylen = 16, + }, + { + .name = "Wrap/Unwrap with AES 192 CBC", + .wrapping_mech = { CKM_AES_CBC, aes_iv, sizeof(aes_iv) }, + .wrapping_key_gen_mech = { CKM_AES_KEY_GEN, 0, 0 }, + .sym_keylen = 24, + }, + { + .name = "Wrap/Unwrap with AES 256 CBC", + .wrapping_mech = { CKM_AES_CBC, aes_iv, sizeof(aes_iv) }, + .wrapping_key_gen_mech = { CKM_AES_KEY_GEN, 0, 0 }, + .sym_keylen = 32, + }, + { + .name = "Wrap/Unwrap with AES 128 CBC PAD", + .wrapping_mech = { CKM_AES_CBC_PAD, aes_iv, sizeof(aes_iv) }, + .wrapping_key_gen_mech = { CKM_AES_KEY_GEN, 0, 0 }, + .sym_keylen = 16, + }, + { + .name = "Wrap/Unwrap with AES 192 CBC PAD", + .wrapping_mech = { CKM_AES_CBC_PAD, aes_iv, sizeof(aes_iv) }, + .wrapping_key_gen_mech = { CKM_AES_KEY_GEN, 0, 0 }, + .sym_keylen = 24, + }, + { + .name = "Wrap/Unwrap with AES 256 CBC PAD", + .wrapping_mech = { CKM_AES_CBC_PAD, aes_iv, sizeof(aes_iv) }, + .wrapping_key_gen_mech = { CKM_AES_KEY_GEN, 0, 0 }, + .sym_keylen = 32, + }, { + .name = "Wrap/Unwrap with DES ECB", + .wrapping_mech = { CKM_DES_ECB, 0, 0 }, + .wrapping_key_gen_mech = { CKM_DES_KEY_GEN, 0, 0 }, + }, + { + .name = "Wrap/Unwrap with DES CBC", + .wrapping_mech = { CKM_DES_CBC, des_iv, sizeof(des_iv) }, + .wrapping_key_gen_mech = { CKM_DES_KEY_GEN, 0, 0 }, + }, + { + .name = "Wrap/Unwrap with DES CBC PAD", + .wrapping_mech = { CKM_DES_CBC_PAD, des_iv, sizeof(des_iv) }, + .wrapping_key_gen_mech = { CKM_DES_KEY_GEN, 0, 0 }, + }, + { + .name = "Wrap/Unwrap with DES2 ECB", + .wrapping_mech = { CKM_DES3_ECB, 0, 0 }, + .wrapping_key_gen_mech = { CKM_DES2_KEY_GEN, 0, 0 }, + }, + { + .name = "Wrap/Unwrap with DES2 CBC", + .wrapping_mech = { CKM_DES3_CBC, des_iv, sizeof(des_iv) }, + .wrapping_key_gen_mech = { CKM_DES2_KEY_GEN, 0, 0 }, + }, + { + .name = "Wrap/Unwrap with DES2 CBC PAD", + .wrapping_mech = { CKM_DES3_CBC_PAD, des_iv, sizeof(des_iv) }, + .wrapping_key_gen_mech = { CKM_DES2_KEY_GEN, 0, 0 }, + }, + { + .name = "Wrap/Unwrap with DES3 ECB", + .wrapping_mech = { CKM_DES3_ECB, 0, 0 }, + .wrapping_key_gen_mech = { CKM_DES3_KEY_GEN, 0, 0 }, + }, + { + .name = "Wrap/Unwrap with DES3 CBC", + .wrapping_mech = { CKM_DES3_CBC, des_iv, sizeof(des_iv) }, + .wrapping_key_gen_mech = { CKM_DES3_KEY_GEN, 0, 0 }, + }, + { + .name = "Wrap/Unwrap with DES3 CBC PAD", + .wrapping_mech = { CKM_DES3_CBC_PAD, des_iv, sizeof(des_iv) }, + .wrapping_key_gen_mech = { CKM_DES3_KEY_GEN, 0, 0 }, + }, +}; + +#define NUM_WRAPPING_TESTS sizeof(wrapping_tests) / \ + sizeof(struct wrapping_mech_info) + +CK_BYTE prime256v1[] = OCK_PRIME256V1; + +struct wrapped_mech_info { + char *name; + CK_MECHANISM wrapped_key_gen_mech; + CK_ULONG rsa_modbits; + CK_ULONG rsa_publ_exp_len; + CK_BYTE rsa_publ_exp[4]; + CK_ULONG sym_keylen; + CK_BYTE *ec_params; + CK_ULONG ec_params_len; + CK_MECHANISM operation_mech; +}; + +struct wrapped_mech_info wrapped_key_tests[] = { + { + .name = "key type AES 128", + .wrapped_key_gen_mech = { CKM_AES_KEY_GEN, 0, 0 }, + .operation_mech = { CKM_AES_ECB, 0, 0 }, + .sym_keylen = 16, + }, + { + .name = "key type AES 192", + .wrapped_key_gen_mech = { CKM_AES_KEY_GEN, 0, 0 }, + .operation_mech = { CKM_AES_ECB, 0, 0 }, + .sym_keylen = 24, + }, + { + .name = "key type AES 256", + .wrapped_key_gen_mech = { CKM_AES_KEY_GEN, 0, 0 }, + .operation_mech = { CKM_AES_ECB, 0, 0 }, + .sym_keylen = 32, + }, + { + .name = "key type DES3", + .wrapped_key_gen_mech = { CKM_DES3_KEY_GEN, 0, 0 }, + .operation_mech = { CKM_DES3_ECB, 0, 0 }, + }, + { + .name = "key type DES2", + .wrapped_key_gen_mech = { CKM_DES2_KEY_GEN, 0, 0 }, + .operation_mech = { CKM_DES3_ECB, 0, 0 }, + }, + { + .name = "key type DES", + .wrapped_key_gen_mech = { CKM_DES_KEY_GEN, 0, 0 }, + .operation_mech = { CKM_DES_ECB, 0, 0 }, + }, + { + .name = "key type GENERIC SECRET", + .wrapped_key_gen_mech = { CKM_GENERIC_SECRET_KEY_GEN, 0, 0 }, + .operation_mech = { CKM_SHA_1_HMAC, 0, 0 }, + .sym_keylen = 32, + }, + { + .name = "key type RSA PKCS 512", + .wrapped_key_gen_mech = { CKM_RSA_PKCS_KEY_PAIR_GEN, 0, 0 }, + .operation_mech = { CKM_RSA_PKCS, 0, 0 }, + .rsa_modbits = 512, + .rsa_publ_exp_len = 3, + .rsa_publ_exp = {0x01, 0x00, 0x01}, + }, + { + .name = "key type RSA PKCS 1024", + .wrapped_key_gen_mech = { CKM_RSA_PKCS_KEY_PAIR_GEN, 0, 0 }, + .operation_mech = { CKM_RSA_PKCS, 0, 0 }, + .rsa_modbits = 1024, + .rsa_publ_exp_len = 3, + .rsa_publ_exp = {0x01, 0x00, 0x01}, + }, + { + .name = "key type RSA PKCS 2048", + .wrapped_key_gen_mech = { CKM_RSA_PKCS_KEY_PAIR_GEN, 0, 0 }, + .operation_mech = { CKM_RSA_PKCS, 0, 0 }, + .rsa_modbits = 2048, + .rsa_publ_exp_len = 3, + .rsa_publ_exp = {0x01, 0x00, 0x01}, + }, + { + .name = "key type EC", + .wrapped_key_gen_mech = { CKM_EC_KEY_PAIR_GEN, 0, 0 }, + .operation_mech = { CKM_ECDSA, 0, 0 }, + .ec_params = prime256v1, + .ec_params_len = sizeof(prime256v1), + }, +}; + +#define NUM_WRAPPED_KEY_TESTS sizeof(wrapped_key_tests) / \ + sizeof(struct wrapped_mech_info) + +CK_SLOT_ID slot_id1 = 1, slot_id2 = 2; +CK_SESSION_HANDLE session1 = CK_INVALID_HANDLE; +CK_SESSION_HANDLE session2 = CK_INVALID_HANDLE; +CK_OBJECT_HANDLE sym_wrap_key1 = CK_INVALID_HANDLE; +CK_OBJECT_HANDLE sym_wrap_key2 = CK_INVALID_HANDLE; +CK_OBJECT_HANDLE publ_wrap_key1 = CK_INVALID_HANDLE; +CK_OBJECT_HANDLE publ_wrap_key2 = CK_INVALID_HANDLE; +CK_OBJECT_HANDLE priv_wrap_key2 = CK_INVALID_HANDLE; + +CK_RV do_perform_operation(CK_MECHANISM *mech, + CK_SLOT_ID slot1, + CK_SESSION_HANDLE sess1, + CK_OBJECT_HANDLE sym_key1, + CK_OBJECT_HANDLE publ_key1, + CK_SLOT_ID slot2, + CK_SESSION_HANDLE sess2, + CK_OBJECT_HANDLE sym_key2, + CK_OBJECT_HANDLE priv_key2) +{ + CK_RV rc; + CK_MECHANISM_INFO mech_info; + CK_BBOOL encr = FALSE, decr = FALSE, sign = FALSE, verify = FALSE; + CK_ULONG input_size, cipher_size, output_size; + CK_BYTE input_data[32] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f}; + CK_BYTE cipher_data[512]; + CK_BYTE output_data[512]; + CK_OBJECT_HANDLE encr_key, decr_key, sign_key, verify_key; + + /* Check if Encrypt/Decrypt or Sign/Verify is supported */ + rc = funcs->C_GetMechanismInfo(slot1, mech->mechanism, &mech_info); + if (rc != CKR_OK) { + testcase_error("C_GetMechanismInfo on slot %lu, rc=%s", slot1, + p11_get_ckr(rc)); + return rc; + } + encr = (mech_info.flags & CKF_ENCRYPT) != 0; + sign = (mech_info.flags & CKF_SIGN) != 0; + + rc = funcs->C_GetMechanismInfo(slot2, mech->mechanism, &mech_info); + if (rc != CKR_OK) { + testcase_error("C_GetMechanismInfo on slot %lu, rc=%s", slot2, + p11_get_ckr(rc)); + return rc; + } + + decr = (mech_info.flags & CKF_DECRYPT) != 0; + verify = (mech_info.flags & CKF_VERIFY) != 0; + + if (encr && decr) { + /* Perform Encrypt/Decrypt operation */ + switch (mech->mechanism) { + case CKM_AES_ECB: + input_size = 16; + encr_key = sym_key1; + decr_key = sym_key2; + break; + case CKM_DES_ECB: + case CKM_DES3_ECB: + input_size = 8; + encr_key = sym_key1; + decr_key = sym_key2; + break; + case CKM_RSA_PKCS: + input_size = 16; + encr_key = publ_key1; + decr_key = priv_key2; + break; + default: + testcase_error("Operation not supported by testcase"); + return CKR_FUNCTION_NOT_SUPPORTED; + } + + rc = funcs->C_EncryptInit(sess1, mech, encr_key); + if (rc != CKR_OK) { + testcase_error("C_EncryptInit on slot %lu rc=%s", slot1, + p11_get_ckr(rc)); + return rc; + } + + cipher_size = sizeof(cipher_data); + rc = funcs->C_Encrypt(sess1, input_data, input_size, cipher_data, + &cipher_size); + if (rc != CKR_OK) { + testcase_error("C_Encrypt on slot %lu rc=%s", slot1, + p11_get_ckr(rc)); + return rc; + } + + rc = funcs->C_DecryptInit(sess2, mech, decr_key); + if (rc != CKR_OK) { + testcase_error("C_DecryptInit on slot %lu rc=%s", slot2, + p11_get_ckr(rc)); + return rc; + } + + output_size = sizeof(output_data); + rc = funcs->C_Decrypt(sess2, cipher_data, cipher_size, output_data, + &output_size); + if (rc != CKR_OK) { + testcase_error("C_Decrypt on slot %lu rc=%s", slot2, + p11_get_ckr(rc)); + return rc; + } + + if (output_size != input_size) { + testcase_error("Decrypted data has different size then original " + "data: orig: %lu decr: %lu", input_size, + output_size); + return CKR_FUNCTION_FAILED; + } + if (memcmp(input_data, output_data, input_size) != 0) { + testcase_error("Decrypted data is different then original data"); + return CKR_FUNCTION_FAILED; + } + } else if (sign && verify) { + /* Perform Sign/Verify operation */ + switch (mech->mechanism) { + case CKM_SHA_1_HMAC: + sign_key = sym_key2; + verify_key = sym_key1; + input_size = 20; + break; + case CKM_RSA_PKCS: + case CKM_ECDSA: + sign_key = priv_key2; + verify_key = publ_key1; + input_size = 20; + break; + default: + testcase_error("Operation not supported by testcase"); + return CKR_FUNCTION_NOT_SUPPORTED; + } + + rc = funcs->C_SignInit(sess2, mech, sign_key); + if (rc != CKR_OK) { + testcase_error("C_SignInit on slot %lu rc=%s", slot2, + p11_get_ckr(rc)); + return rc; + } + + output_size = sizeof(output_data); + rc = funcs->C_Sign(sess2, input_data, input_size, output_data, + &output_size); + if (rc != CKR_OK) { + testcase_error("C_Sign on slot %lu rc=%s", slot2, p11_get_ckr(rc)); + return rc; + } + + rc = funcs->C_VerifyInit(sess1, mech, verify_key); + if (rc != CKR_OK) { + testcase_error("C_VerifyInit on slot %lu rc=%s", slot1, + p11_get_ckr(rc)); + return rc; + } + + rc = funcs->C_Verify(sess1, input_data, input_size, output_data, + output_size); + if (rc != CKR_OK) { + testcase_error("C_Verify on slot %lu rc=%s", slot1, p11_get_ckr(rc)); + return rc; + } + } else { + testcase_error("Neither Encrypt/Decrypt, nor Sign/Verify supported"); + return CKR_FUNCTION_NOT_SUPPORTED; + } + + return CKR_OK; +} + +CK_RV do_wrap_key_test(struct wrapped_mech_info *tsuite, + CK_MECHANISM *wrap_mech) +{ + CK_RV loc_rc, rc = CKR_OK; + CK_OBJECT_HANDLE publ_key = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE priv_key = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE sym_key = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE unwrapped_key = CK_INVALID_HANDLE; + CK_BYTE wrapped_key[4096]; + CK_ULONG wrapped_key_size = sizeof(wrapped_key); + CK_OBJECT_CLASS key_class; + CK_KEY_TYPE key_type; + CK_ULONG key_len, unwrapped_keylen; + CK_ATTRIBUTE unwrap_tmpl[] = { + {CKA_CLASS, &key_class, sizeof(CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, &key_type, sizeof(CK_KEY_TYPE)}, + {CKA_VALUE_LEN, &key_len, sizeof(CK_ULONG)} + }; + CK_ULONG unwrap_tmpl_num; + CK_ATTRIBUTE getattr_tmpl[] = { + {CKA_VALUE_LEN, &unwrapped_keylen, sizeof(CK_ULONG)} + }; + char *s = NULL; + CK_RSA_PKCS_OAEP_PARAMS *oaep; + + testcase_begin("Wrap/Unwrap of %s with %s", tsuite->name, + 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)", + (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)", + (unsigned int)slot_id2, + mech_to_str(tsuite->wrapped_key_gen_mech.mechanism), + (unsigned int)tsuite->wrapped_key_gen_mech.mechanism); + goto testcase_cleanup; + } + + if (!mech_supported(slot_id1, tsuite->operation_mech.mechanism)) { + testcase_skip("Slot %u doesn't support %s (%u)", + (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)", + (unsigned int)slot_id2, + mech_to_str(tsuite->operation_mech.mechanism), + (unsigned int)tsuite->operation_mech.mechanism); + goto testcase_cleanup; + } + + if (is_ep11_token(slot_id2) && wrap_mech->mechanism == CKM_AES_CBC && + ((tsuite->wrapped_key_gen_mech.mechanism == CKM_AES_KEY_GEN && + tsuite->sym_keylen == 24) || + tsuite->wrapped_key_gen_mech.mechanism == CKM_DES3_KEY_GEN)) { + testcase_skip("EP11 token in slot %lu doesn't support to unwrap " + "AES-192 or DES3 keys with CKM_AES_CBC", slot_id2); + goto testcase_cleanup; + } + + /* Generate the to be wrapped key in slot 1 */ + switch (tsuite->wrapped_key_gen_mech.mechanism) { + case CKM_RSA_PKCS_KEY_PAIR_GEN: + if (p11_ahex_dump(&s, tsuite->rsa_publ_exp, + tsuite->rsa_publ_exp_len) == NULL) { + testcase_error("p11_ahex_dump() failed"); + rc = CKR_FUNCTION_FAILED; + goto testcase_cleanup; + } + + 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); + 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); + 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); + 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); + goto testcase_cleanup; + } + } + if (is_tpm_token(slot_id1) || is_tpm_token(slot_id2)) { + 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); + goto testcase_cleanup; + } + } + if (is_icsf_token(slot_id1) || is_icsf_token(slot_id2)) { + 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); + goto testcase_cleanup; + } + } + + rc = generate_RSA_PKCS_KeyPair(session1, tsuite->rsa_modbits, + tsuite->rsa_publ_exp, + tsuite->rsa_publ_exp_len, + &publ_key, &priv_key); + break; + + case CKM_AES_KEY_GEN: + rc = generate_AESKey(session1, tsuite->sym_keylen, + &tsuite->wrapped_key_gen_mech, &sym_key); + break; + + case CKM_DES3_KEY_GEN: + case CKM_DES2_KEY_GEN: + case CKM_DES_KEY_GEN: + rc = funcs->C_GenerateKey(session1, &tsuite->wrapped_key_gen_mech, + NULL, 0, &sym_key); + break; + + case CKM_GENERIC_SECRET_KEY_GEN: + rc = generate_SecretKey(session1, tsuite->sym_keylen, + &tsuite->wrapped_key_gen_mech, &sym_key); + break; + + case CKM_EC_KEY_PAIR_GEN: + rc = generate_EC_KeyPair(session1, tsuite->ec_params, + tsuite->ec_params_len, &publ_key, &priv_key); + break; + + default: + testcase_error("Testcase does not support %s (%u)", + mech_to_str(tsuite->wrapped_key_gen_mech.mechanism), + (unsigned int)tsuite->wrapped_key_gen_mech.mechanism); + goto testcase_cleanup; + } + + if (rc != CKR_OK) { + 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), + (unsigned int)tsuite->wrapped_key_gen_mech.mechanism, + slot_id1, p11_get_ckr(rc)); + goto testcase_cleanup; + } + + /* Test the key with a crypto operation on slot 1 */ + rc = do_perform_operation(&tsuite->operation_mech, + slot_id1, session1, sym_key, publ_key, + slot_id1, session1, sym_key, priv_key); + if (rc != CKR_OK) + goto testcase_cleanup; + + /* Wrap the key on slot 1 */ + rc = funcs->C_WrapKey(session1, wrap_mech, + sym_wrap_key1 != CK_INVALID_HANDLE ? + sym_wrap_key1 : publ_wrap_key1, + sym_key != CK_INVALID_HANDLE ? sym_key : priv_key, + wrapped_key, &wrapped_key_size); + if (rc != CKR_OK) { + if (rc == CKR_KEY_NOT_WRAPPABLE) { + testcase_skip("Key not wrappable"); + rc = CKR_OK; + goto testcase_cleanup; + } + if (rc == CKR_MECHANISM_PARAM_INVALID && + wrap_mech->mechanism == CKM_RSA_PKCS_OAEP) { + oaep = (CK_RSA_PKCS_OAEP_PARAMS *)wrap_mech->pParameter; + if (is_cca_token(slot_id1) && + oaep->source == CKZ_DATA_SPECIFIED) { + testcase_skip("CCA does not support RSA OAEP with source data"); + rc = CKR_OK; + goto testcase_cleanup; + } + if (is_cca_token(slot_id1) && + oaep->hashAlg != CKM_SHA_1 && + oaep->hashAlg != CKM_SHA256) { + testcase_skip("CCA does not support RSA OAEP with a hash other " + "than SHA1 or SHA256"); + rc = CKR_OK; + goto testcase_cleanup; + } + if (is_ep11_token(slot_id1) && oaep->hashAlg != CKM_SHA_1 && + oaep->mgf != CKG_MGF1_SHA1) { + testcase_skip("EP11 may not support RSA OAEP with a hash other " + "than SHA1 on older firmware levels"); + rc = CKR_OK; + goto testcase_cleanup; + } + } + if (rc == CKR_ARGUMENTS_BAD) { + if (is_ep11_token(slot_id1) && + publ_wrap_key1 != CK_INVALID_HANDLE && + (wrap_mech->mechanism == CKM_RSA_PKCS || + wrap_mech->mechanism == CKM_RSA_PKCS_OAEP)) { + testcase_skip("EP11 does not support to wrap asymmetric keys " + "with RSA"); + rc = CKR_OK; + goto testcase_cleanup; + } + } + + testcase_error("wrap with mech %s (%u) in slot %lu failed, rc=%s", + mech_to_str(wrap_mech->mechanism), + (unsigned int)wrap_mech->mechanism, + slot_id1, p11_get_ckr(rc)); + goto testcase_cleanup; + } + + /* Get class and key type from original key */ + switch (tsuite->wrapped_key_gen_mech.mechanism) { + case CKM_AES_KEY_GEN: + case CKM_GENERIC_SECRET_KEY_GEN: + unwrap_tmpl_num = 3; + break; + default: + unwrap_tmpl_num = 2; + break; + } + + rc = funcs->C_GetAttributeValue(session1, sym_key != CK_INVALID_HANDLE ? + sym_key : priv_key, + unwrap_tmpl, unwrap_tmpl_num); + if (rc != CKR_OK) { + testcase_error("C_GetAttributeValue() on slot %lu, rc=%s.", slot_id1, + p11_get_ckr(rc)); + goto testcase_cleanup; + } + + /* Unwrap the key on slot 2 */ + rc = funcs->C_UnwrapKey(session2, wrap_mech, + sym_wrap_key2 != CK_INVALID_HANDLE ? + sym_wrap_key2 : priv_wrap_key2, + wrapped_key, wrapped_key_size, unwrap_tmpl, + unwrap_tmpl_num, &unwrapped_key); + if (rc != CKR_OK) { + if (rc == CKR_KEY_NOT_WRAPPABLE || rc == CKR_WRAPPED_KEY_INVALID) { + testcase_skip("Key not (un-)wrappable"); + rc = CKR_OK; + goto testcase_cleanup; + } + if (rc == CKR_MECHANISM_PARAM_INVALID && + wrap_mech->mechanism == CKM_RSA_PKCS_OAEP) { + oaep = (CK_RSA_PKCS_OAEP_PARAMS *)wrap_mech->pParameter; + if (is_cca_token(slot_id2) && + oaep->source == CKZ_DATA_SPECIFIED) { + testcase_skip("CCA does not support RSA OAEP with source data"); + rc = CKR_OK; + goto testcase_cleanup; + } + if (is_cca_token(slot_id2) && + oaep->hashAlg != CKM_SHA_1 && + oaep->hashAlg != CKM_SHA256) { + testcase_skip("CCA does not support RSA OAEP with a hash other " + "than SHA1 or SHA256"); + rc = CKR_OK; + goto testcase_cleanup; + } + if (is_ep11_token(slot_id2) && oaep->hashAlg != CKM_SHA_1 && + oaep->mgf != CKG_MGF1_SHA1) { + testcase_skip("EP11 may not support RSA OAEP with a hash other " + "than SHA1 on older firmware levels"); + rc = CKR_OK; + goto testcase_cleanup; + } + } + if (rc == CKR_MECHANISM_INVALID && is_ep11_token(slot_id2) && + wrap_mech->mechanism == CKM_DES3_CBC) { + testcase_skip("EP11 does not support unwrap with DES3 CBC"); + rc = CKR_OK; + goto testcase_cleanup; + } + + testcase_error("unwrap with mech %s (%u) in slot %lu failed, rc=%s", + mech_to_str(wrap_mech->mechanism), + (unsigned int)wrap_mech->mechanism, + slot_id2, p11_get_ckr(rc)); + goto testcase_cleanup; + } + + if (key_type == CKK_AES || key_type == CKK_GENERIC_SECRET) { + /* Check if the unwrapped key has the desired key length */ + rc = funcs->C_GetAttributeValue(session2, unwrapped_key, + getattr_tmpl, 1); + if (rc != CKR_OK) { + testcase_error("C_GetAttributeValue() on slot %lu, rc=%s.", slot_id2, + p11_get_ckr(rc)); + goto testcase_cleanup; + } + + if (unwrapped_keylen != key_len) { + testcase_error("Unwrapped key size (%lu) differers from original " + "(%lu)", unwrapped_keylen, key_len); + rc = CKR_UNWRAPPING_KEY_SIZE_RANGE; + goto testcase_cleanup; + } + } + + /* Test the unwrapped key with a crypto operation on slot 2 */ + rc = do_perform_operation(&tsuite->operation_mech, + slot_id1, session1, sym_key, publ_key, + slot_id2, session2, unwrapped_key, + unwrapped_key); + if (rc != CKR_OK) + goto testcase_cleanup; + + testcase_new_assertion(); + testcase_pass("Wrap/Unwrap of %s with %s", tsuite->name, + mech_to_str(wrap_mech->mechanism)); + +testcase_cleanup: + if (sym_key != CK_INVALID_HANDLE) { + loc_rc = funcs->C_DestroyObject(session1, sym_key); + if (loc_rc != CKR_OK) + testcase_error("C_DestroyObject(), rc=%s.", p11_get_ckr(loc_rc)); + } + if (publ_key != CK_INVALID_HANDLE) { + loc_rc = funcs->C_DestroyObject(session1, publ_key); + if (loc_rc != CKR_OK) + testcase_error("C_DestroyObject(), rc=%s.", p11_get_ckr(loc_rc)); + } + if (priv_key != CK_INVALID_HANDLE) { + loc_rc = funcs->C_DestroyObject(session1, priv_key); + if (loc_rc != CKR_OK) + testcase_error("C_DestroyObject(), rc=%s.", p11_get_ckr(loc_rc)); + } + if (unwrapped_key != CK_INVALID_HANDLE) { + loc_rc = funcs->C_DestroyObject(session2, unwrapped_key); + if (loc_rc != CKR_OK) + testcase_error("C_DestroyObject(), rc=%s.", p11_get_ckr(loc_rc)); + } + + if (s != NULL) + free(s); + + if (rc != CKR_OK) + testcase_fail("Wrap/Unwrap of %s with %s", tsuite->name, + mech_to_str(wrap_mech->mechanism)); + + return rc; +} + +CK_RV do_wrapping_test(struct wrapping_mech_info *tsuite) +{ + CK_RV loc_rc, rc = CKR_OK; + CK_ULONG i; + char *s = NULL; + CK_BYTE modulus[512]; + CK_BYTE publ_exp[16]; + CK_BYTE key[32]; + CK_ULONG key_size = 0; + CK_BYTE value[32]; + CK_ATTRIBUTE rsa_publ_tmpl[] = { + {CKA_MODULUS, modulus, sizeof(modulus) }, + {CKA_PUBLIC_EXPONENT, publ_exp, sizeof(publ_exp) }, + }; + CK_ATTRIBUTE sym_tmpl[] = { + {CKA_VALUE, value, sizeof(value) }, + }; + + 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)", + (unsigned int)slot_id1, + mech_to_str(tsuite->wrapping_key_gen_mech.mechanism), + (unsigned int)tsuite->wrapping_key_gen_mech.mechanism); + goto testcase_cleanup; + } + + if (!mech_supported(slot_id2, tsuite->wrapping_key_gen_mech.mechanism)) { + testsuite_skip(NUM_WRAPPED_KEY_TESTS, "Slot %u doesn't support %s (%u)", + (unsigned int)slot_id2, + mech_to_str(tsuite->wrapping_key_gen_mech.mechanism), + (unsigned int)tsuite->wrapping_key_gen_mech.mechanism); + goto testcase_cleanup; + } + + if (!mech_supported(slot_id1, tsuite->wrapping_mech.mechanism)) { + testsuite_skip(NUM_WRAPPED_KEY_TESTS, "Slot %u doesn't support %s (%u)", + (unsigned int)slot_id1, + mech_to_str(tsuite->wrapping_mech.mechanism), + (unsigned int)tsuite->wrapping_mech.mechanism); + goto testcase_cleanup; + } + 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, + 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)", + (unsigned int)slot_id2, + mech_to_str(tsuite->wrapping_mech.mechanism), + (unsigned int)tsuite->wrapping_mech.mechanism); + goto testcase_cleanup; + } + 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, + mech_to_str(tsuite->wrapping_mech.mechanism), + (unsigned int)tsuite->wrapping_mech.mechanism); + goto testcase_cleanup; + } + + /* + * Generate the wrapping key in slot 2. + * For symmetric wrapping keys, generate the key from a random clear key + * value, to be able to import the same key in the other token. + * For RSA wrapping keys, the public key can be extracted and imported in + * the other token. + */ + switch (tsuite->wrapping_key_gen_mech.mechanism) { + case CKM_RSA_PKCS_KEY_PAIR_GEN: + if (p11_ahex_dump(&s, tsuite->rsa_publ_exp, + tsuite->rsa_publ_exp_len) == NULL) { + testcase_error("p11_ahex_dump() failed"); + rc = CKR_FUNCTION_FAILED; + goto testcase_cleanup; + } + + 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); + 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); + 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); + 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); + goto testcase_cleanup; + } + } + if (is_tpm_token(slot_id1) || is_tpm_token(slot_id2)) { + 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); + goto testcase_cleanup; + } + } + if (is_icsf_token(slot_id1) || is_icsf_token(slot_id2)) { + 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); + goto testcase_cleanup; + } + } + rc = generate_RSA_PKCS_KeyPair(session2, tsuite->rsa_modbits, + tsuite->rsa_publ_exp, + tsuite->rsa_publ_exp_len, + &publ_wrap_key2, &priv_wrap_key2); + break; + + case CKM_AES_KEY_GEN: + key_size = 32; + rc = funcs->C_GenerateRandom(session2, key, key_size); + if (rc != CKR_OK) { + testcase_error("C_GenerateRandom(), rc=%s.", p11_get_ckr(rc)); + goto testcase_cleanup; + } + + rc = create_AESKey(session2, key, key_size, &sym_wrap_key2); + break; + + case CKM_DES3_KEY_GEN: + key_size = 24; + rc = funcs->C_GenerateRandom(session2, key, key_size); + if (rc != CKR_OK) { + testcase_error("C_GenerateRandom(), rc=%s.", p11_get_ckr(rc)); + goto testcase_cleanup; + } + + rc = create_DES3Key(session2, key, key_size, &sym_wrap_key2); + break; + + case CKM_DES2_KEY_GEN: + key_size = 16; + rc = funcs->C_GenerateRandom(session2, key, key_size); + if (rc != CKR_OK) { + testcase_error("C_GenerateRandom(), rc=%s.", p11_get_ckr(rc)); + goto testcase_cleanup; + } + + rc = create_DES2Key(session2, key, key_size, &sym_wrap_key2); + break; + + case CKM_DES_KEY_GEN: + key_size = 8; + rc = funcs->C_GenerateRandom(session2, key, key_size); + if (rc != CKR_OK) { + testcase_error("C_GenerateRandom(), rc=%s.", p11_get_ckr(rc)); + goto testcase_cleanup; + } + + rc = create_DESKey(session2, key, key_size, &sym_wrap_key2); + break; + + default: + testcase_error("Testcase does not support %s (%u)", + mech_to_str(tsuite->wrapping_key_gen_mech.mechanism), + (unsigned int)tsuite->wrapping_key_gen_mech.mechanism); + goto testcase_cleanup; + } + + if (rc != CKR_OK) { + testcase_error("generate wrapping key with mech %s (%u) in slot %lu " + "failed, rc=%s", + mech_to_str(tsuite->wrapping_key_gen_mech.mechanism), + (unsigned int)tsuite->wrapping_key_gen_mech.mechanism, + slot_id2, p11_get_ckr(rc)); + goto testcase_cleanup; + } + + /* Import the wrapping key into slot 1 */ + switch (tsuite->wrapping_key_gen_mech.mechanism) { + case CKM_RSA_PKCS_KEY_PAIR_GEN: + rc = funcs->C_GetAttributeValue(session2, publ_wrap_key2, + rsa_publ_tmpl, 2); + if (rc != CKR_OK) { + testcase_error("C_GetAttributeValue(), rc=%s.", p11_get_ckr(rc)); + goto testcase_cleanup; + } + + rc = create_RSAPublicKey(session1, rsa_publ_tmpl[0].pValue, + rsa_publ_tmpl[1].pValue, + rsa_publ_tmpl[0].ulValueLen, + rsa_publ_tmpl[1].ulValueLen, &publ_wrap_key1); + break; + + case CKM_AES_KEY_GEN: + memcpy(sym_tmpl[0].pValue, key, key_size); + sym_tmpl[0].ulValueLen = key_size; + + rc = create_AESKey(session1, sym_tmpl[0].pValue, sym_tmpl[0].ulValueLen, + &sym_wrap_key1); + break; + + case CKM_DES3_KEY_GEN: + memcpy(sym_tmpl[0].pValue, key, key_size); + sym_tmpl[0].ulValueLen = key_size; + + rc = create_DES3Key(session1, sym_tmpl[0].pValue, + sym_tmpl[0].ulValueLen, &sym_wrap_key1); + break; + + case CKM_DES2_KEY_GEN: + memcpy(sym_tmpl[0].pValue, key, key_size); + sym_tmpl[0].ulValueLen = key_size; + + rc = create_DES2Key(session1, sym_tmpl[0].pValue, + sym_tmpl[0].ulValueLen, &sym_wrap_key1); + break; + + case CKM_DES_KEY_GEN: + memcpy(sym_tmpl[0].pValue, key, key_size); + sym_tmpl[0].ulValueLen = key_size; + + rc = create_DESKey(session1, sym_tmpl[0].pValue, sym_tmpl[0].ulValueLen, + &sym_wrap_key1); + break; + + default: + testcase_error("Testcase does not support %s (%u)", + mech_to_str(tsuite->wrapping_key_gen_mech.mechanism), + (unsigned int)tsuite->wrapping_key_gen_mech.mechanism); + goto testcase_cleanup; + } + + if (rc != CKR_OK) { + testcase_error("import wrapping key in slot %lu failed, rc=%s", + slot_id1, p11_get_ckr(rc)); + goto testcase_cleanup; + } + + /* Wrap/unwrap different keys with this wrapping key */ + for (i = 0; i< NUM_WRAPPED_KEY_TESTS; i++) { + rc = do_wrap_key_test(&wrapped_key_tests[i], &tsuite->wrapping_mech); + if (rc != CKR_OK) + break; + } + +testcase_cleanup: + if (sym_wrap_key1 != CK_INVALID_HANDLE) { + loc_rc = funcs->C_DestroyObject(session1, sym_wrap_key1); + if (loc_rc != CKR_OK) + testcase_error("C_DestroyObject(), rc=%s.", p11_get_ckr(loc_rc)); + } + sym_wrap_key1 = CK_INVALID_HANDLE; + if (sym_wrap_key2 != CK_INVALID_HANDLE) { + loc_rc = funcs->C_DestroyObject(session2, sym_wrap_key2); + if (loc_rc != CKR_OK) + testcase_error("C_DestroyObject(), rc=%s.", p11_get_ckr(loc_rc)); + } + sym_wrap_key2 = CK_INVALID_HANDLE; + if (publ_wrap_key1 != CK_INVALID_HANDLE) { + loc_rc = funcs->C_DestroyObject(session1, publ_wrap_key1); + if (loc_rc != CKR_OK) + testcase_error("C_DestroyObject(), rc=%s.", p11_get_ckr(loc_rc)); + } + publ_wrap_key1 = CK_INVALID_HANDLE; + if (publ_wrap_key2 != CK_INVALID_HANDLE) { + loc_rc = funcs->C_DestroyObject(session2, publ_wrap_key2); + if (loc_rc != CKR_OK) + testcase_error("C_DestroyObject(), rc=%s.", p11_get_ckr(loc_rc)); + } + publ_wrap_key2 = CK_INVALID_HANDLE; + if (priv_wrap_key2 != CK_INVALID_HANDLE) { + loc_rc = funcs->C_DestroyObject(session2, priv_wrap_key2); + if (loc_rc != CKR_OK) + testcase_error("C_DestroyObject(), rc=%s.", p11_get_ckr(loc_rc)); + } + priv_wrap_key2 = CK_INVALID_HANDLE; + + if (s != NULL) + free(s); + + return rc; +} + +CK_RV do_tok2tok_tests() +{ + CK_ULONG i; + CK_RV rc; + + for (i = 0; i < NUM_WRAPPING_TESTS; i++) { + rc = do_wrapping_test(&wrapping_tests[i]); + if (rc != CKR_OK) + break; + } + + return CKR_OK; +} + +int main(int argc, char **argv) +{ + CK_C_INITIALIZE_ARGS cinit_args; + int i, ret = 1; + CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; + CK_ULONG user_pin_len; + CK_RV rv; + CK_FLAGS flags; + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-slot1") == 0) { + ++i; + slot_id1 = atoi(argv[i]); + } + else if (strcmp(argv[i], "-slot2") == 0) { + ++i; + slot_id2 = atoi(argv[i]); + } + + if (strcmp(argv[i], "-h") == 0) { + printf("usage: %s [-slot1 ] [-slot2 ] [-h]\n\n", + argv[0]); + printf("By default, Slot #1 and #2 are used\n\n"); + return -1; + } + } + + if (get_user_pin(user_pin)) + return CKR_FUNCTION_FAILED; + user_pin_len = (CK_ULONG) strlen((char *) user_pin); + + printf("Using slots #%lu and #%lu...\n\n", slot_id1, slot_id2); + + rv = do_GetFunctionList(); + if (rv != TRUE) { + testcase_fail("do_GetFunctionList() rc = %s", p11_get_ckr(rv)); + goto out; + } + + testcase_setup(0); + testcase_begin("Starting..."); + + // Initialize + memset(&cinit_args, 0x0, sizeof(cinit_args)); + cinit_args.flags = CKF_OS_LOCKING_OK; + + if ((rv = funcs->C_Initialize(&cinit_args))) { + testcase_fail("C_Initialize() rc = %s", p11_get_ckr(rv)); + goto out; + } + + // Open Session and login for slot 1 + testcase_new_assertion(); + flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + rv = funcs->C_OpenSession(slot_id1, flags, NULL, NULL, &session1); + if (rv != CKR_OK) { + testcase_fail("C_OpenSession() on slot %lu rc = %s", slot_id1, + p11_get_ckr(rv)); + goto finalize; + } + testcase_pass("C_OpenSession on slot %lu", slot_id1); + + testcase_new_assertion(); + rv = funcs->C_Login(session1, CKU_USER, user_pin, user_pin_len); + if (rv != CKR_OK) { + testcase_fail("C_Login() on slot %lu rc = %s", slot_id1, + p11_get_ckr(rv)); + goto close_session; + } + testcase_pass("C_Login as User on slot %lu", slot_id1); + + // Open Session and login for slot 2 + testcase_new_assertion(); + flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + rv = funcs->C_OpenSession(slot_id2, flags, NULL, NULL, &session2); + if (rv != CKR_OK) { + testcase_fail("C_OpenSession() on slot %lu rc = %s", slot_id2, + p11_get_ckr(rv)); + goto close_session; + } + testcase_pass("C_OpenSession on slot %lu", slot_id2); + + testcase_new_assertion(); + rv = funcs->C_Login(session2, CKU_USER, user_pin, user_pin_len); + if (rv != CKR_OK) { + testcase_fail("C_Login() on slot %lu rc = %s\n", slot_id2, + p11_get_ckr(rv)); + // ignore error + } else { + testcase_pass("C_Login as User on slot %lu", slot_id2); + } + + rv = do_tok2tok_tests(); + if (rv != CKR_OK) + goto close_session; + + ret = 0; + +close_session: + if (session1 != CK_INVALID_HANDLE) { + rv = funcs->C_CloseSession(session1); + if (rv != CKR_OK) { + testcase_fail("C_CloseSession() on slot %lu rc = %s", slot_id1, + p11_get_ckr(rv)); + } + } + if (session2 != CK_INVALID_HANDLE) { + rv = funcs->C_CloseSession(session2); + if (rv != CKR_OK) { + testcase_fail("C_CloseSession() on slot %lu rc = %s", slot_id2, + p11_get_ckr(rv)); + } + } +finalize: + rv = funcs->C_Finalize(NULL); + if (rv != CKR_OK) { + testcase_fail("C_Finalize() rc = %s", p11_get_ckr(rv)); + } +out: + testcase_print_result(); + return ret; +} diff --git a/testcases/misc_tests/tok_des.c b/testcases/misc_tests/tok_des.c index 4e7f81d..2a0e186 100644 --- a/testcases/misc_tests/tok_des.c +++ b/testcases/misc_tests/tok_des.c @@ -19,14 +19,11 @@ #include #include -#include #include "pkcs11types.h" #include "regress.h" #include "common.c" -int do_GetFunctionList(void); - CK_RV do_VerifyTokenSymKey(CK_SESSION_HANDLE sess, CK_BYTE * label) { CK_OBJECT_HANDLE obj_handles[20]; diff --git a/testcases/misc_tests/tok_obj.c b/testcases/misc_tests/tok_obj.c index c6272cc..d3f73fc 100644 --- a/testcases/misc_tests/tok_obj.c +++ b/testcases/misc_tests/tok_obj.c @@ -23,8 +23,6 @@ #include "regress.h" int do_GetInfo(void); -int do_GetFunctionList(void); - void init_coprocessor(void); CK_RV C_GetFunctionList(CK_FUNCTION_LIST **); diff --git a/testcases/misc_tests/tok_rsa.c b/testcases/misc_tests/tok_rsa.c index b9d34f8..07e24ec 100644 --- a/testcases/misc_tests/tok_rsa.c +++ b/testcases/misc_tests/tok_rsa.c @@ -19,13 +19,10 @@ #include #include -#include #include "pkcs11types.h" #include "regress.h" -int do_GetFunctionList(void); - CK_RV do_Cleanup(CK_SESSION_HANDLE sess) { CK_RV rv; diff --git a/testcases/ock_tests.sh.in b/testcases/ock_tests.sh.in index 1df8f84..970bb64 100755 --- a/testcases/ock_tests.sh.in +++ b/testcases/ock_tests.sh.in @@ -155,7 +155,7 @@ check_slot() echo "ICA Token type detected" TOKTYPE="ICA" ;; - *SoftTok*) + *Soft*) echo "Software Token type detected" TOKTYPE="Software" ;; diff --git a/testcases/pkcs11/get_interface.c b/testcases/pkcs11/get_interface.c new file mode 100644 index 0000000..45e5e2e --- /dev/null +++ b/testcases/pkcs11/get_interface.c @@ -0,0 +1,467 @@ +/* + * 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 + */ + +#include +#include +#include + +#include "pkcs11types.h" +#include "regress.h" + +static int get_interface_test(void) +{ + CK_FUNCTION_LIST_3_0 *tfn; + CK_INTERFACE *interface; + CK_VERSION version, *v; + CK_SLOT_ID slot; + CK_FLAGS flags; + CK_RV rv; + int rc = -1; + + testcase_new_assertion(); + + flags = 0ULL; + rv = funcs3->C_GetInterface(NULL, NULL, NULL, flags); + if (rv != CKR_ARGUMENTS_BAD) { + testcase_fail("C_GetInterface returned %s.\n", p11_get_ckr(rv)); + goto ret; + } + + flags = ~0ULL; + rv = funcs3->C_GetInterface((CK_UTF8CHAR *)"PKCS 11", + NULL, &interface, flags); + if (rv != CKR_FUNCTION_FAILED) { + testcase_fail("C_GetInterface returned %s.\n", p11_get_ckr(rv)); + goto ret; + } + + version.major = 0; + version.minor = 0; + flags = 0ULL; + rv = funcs3->C_GetInterface((CK_UTF8CHAR *)"PKCS 11", + &version, &interface, flags); + if (rv != CKR_FUNCTION_FAILED) { + testcase_fail("C_GetInterface returned %s.\n", p11_get_ckr(rv)); + goto ret; + } + + flags = 0ULL; + rv = funcs3->C_GetInterface((CK_UTF8CHAR *)"INVALID", + NULL, &interface, flags); + if (rv != CKR_FUNCTION_FAILED) { + testcase_fail("C_GetInterface returned %s.\n", p11_get_ckr(rv)); + goto ret; + } + + flags = 0ULL; + rv = funcs3->C_GetInterface(NULL, NULL, &interface, flags); + if (rv != CKR_OK) { + testcase_fail("C_GetInterface returned %s.\n", p11_get_ckr(rv)); + goto ret; + } + v = (CK_VERSION *)interface->pFunctionList; + printf("%s\n", "Default interface:"); + printf("pInterfaceName %s\n", interface->pInterfaceName); + printf("pFunctionList version %u.%u\n", v->major, v->minor); + printf("flags 0x%016lx\n", interface->flags); + + flags = 0ULL; + rv = funcs3->C_GetInterface((CK_UTF8CHAR *)"PKCS 11", + NULL, &interface, flags); + if (rv != CKR_OK) { + testcase_fail("C_GetInterface returned %s.\n", p11_get_ckr(rv)); + goto ret; + } + if (strcmp((char *)interface->pInterfaceName, "PKCS 11") != 0) { + testcase_fail("Returned interface name: %s.\n", + interface->pInterfaceName); + goto ret; + } + v = (CK_VERSION *)interface->pFunctionList; + printf("%s\n", "Default PKCS #11 interface:"); + printf("pInterfaceName %s\n", interface->pInterfaceName); + printf("pFunctionList version %u.%u\n", v->major, v->minor); + printf("flags 0x%016lx\n", interface->flags); + + version.major = 1; + version.minor = 0; + flags = 0ULL; + rv = funcs3->C_GetInterface((CK_UTF8CHAR *)"Vendor IBM", + NULL, &interface, flags); + if (rv != CKR_OK) { + testcase_fail("C_GetInterface returned %s.\n", p11_get_ckr(rv)); + goto ret; + } + if (strcmp((char *)interface->pInterfaceName, "Vendor IBM") != 0) { + testcase_fail("Returned interface name: %s.\n", + interface->pInterfaceName); + goto ret; + } + v = (CK_VERSION *)interface->pFunctionList; + printf("%s\n", "Vendor defined interface (IBM):"); + printf("pInterfaceName %s\n", interface->pInterfaceName); + printf("pFunctionList version %u.%u\n", v->major, v->minor); + printf("flags 0x%016lx\n", interface->flags); + + version.major = 2; + version.minor = 40; + flags = 0ULL; + rv = funcs3->C_GetInterface((CK_UTF8CHAR *)"PKCS 11", + &version, &interface, flags); + if (rv != CKR_OK) { + testcase_fail("C_GetInterface returned %s.\n", p11_get_ckr(rv)); + goto ret; + } + if (strcmp((char *)interface->pInterfaceName, "PKCS 11") != 0) { + testcase_fail("Returned interface name: %s.\n", + interface->pInterfaceName); + goto ret; + } + v = (CK_VERSION *)interface->pFunctionList; + if (v->major != version.major || v->minor != version.minor) { + testcase_fail("Returned version: %u.%u.\n", v->major, v->minor); + goto ret; + } + printf("%s\n", "PKCS #11 version 2.40 interface:"); + printf("pInterfaceName %s\n", interface->pInterfaceName); + printf("pFunctionList version %u.%u\n", v->major, v->minor); + printf("flags 0x%016lx\n", interface->flags); + + version.major = 3; + version.minor = 0; + flags = 0ULL; + rv = funcs3->C_GetInterface((CK_UTF8CHAR *)"PKCS 11", + &version, &interface, flags); + if (rv != CKR_OK) { + testcase_fail("C_GetInterface returned %s.\n", p11_get_ckr(rv)); + goto ret; + } + if (strcmp((char *)interface->pInterfaceName, "PKCS 11") != 0) { + testcase_fail("Returned interface name: %s.\n", + interface->pInterfaceName); + goto ret; + } + v = (CK_VERSION *)interface->pFunctionList; + if (v->major != version.major || v->minor != version.minor) { + testcase_fail("Returned version: %u.%u.\n", v->major, v->minor); + goto ret; + } + printf("%s\n", "PKCS #11 version 3.0 interface:"); + printf("pInterfaceName %s\n", interface->pInterfaceName); + printf("pFunctionList version %u.%u\n", v->major, v->minor); + printf("flags 0x%016lx\n", interface->flags); + + tfn = (CK_FUNCTION_LIST_3_0 *)interface->pFunctionList; + if (tfn->C_Initialize == NULL + || tfn->C_Finalize == NULL + || tfn->C_GetInfo == NULL + || tfn->C_GetFunctionList == NULL + || tfn->C_GetSlotList == NULL + || tfn->C_GetSlotInfo == NULL + || tfn->C_GetTokenInfo == NULL + || tfn->C_GetMechanismList == NULL + || tfn->C_GetMechanismInfo == NULL + || tfn->C_InitToken == NULL + || tfn->C_InitPIN == NULL + || tfn->C_SetPIN == NULL + || tfn->C_OpenSession == NULL + || tfn->C_CloseSession == NULL + || tfn->C_CloseAllSessions == NULL + || tfn->C_GetSessionInfo == NULL + || tfn->C_GetOperationState == NULL + || tfn->C_SetOperationState == NULL + || tfn->C_Login == NULL + || tfn->C_Logout == NULL + || tfn->C_CreateObject == NULL + || tfn->C_CopyObject == NULL + || tfn->C_DestroyObject == NULL + || tfn->C_GetObjectSize == NULL + || tfn->C_GetAttributeValue == NULL + || tfn->C_SetAttributeValue == NULL + || tfn->C_FindObjectsInit == NULL + || tfn->C_FindObjects == NULL + || tfn->C_FindObjectsFinal == NULL + || tfn->C_EncryptInit == NULL + || tfn->C_Encrypt == NULL + || tfn->C_EncryptUpdate == NULL + || tfn->C_EncryptFinal == NULL + || tfn->C_DecryptInit == NULL + || tfn->C_Decrypt == NULL + || tfn->C_DecryptUpdate == NULL + || tfn->C_DecryptFinal == NULL + || tfn->C_DigestInit == NULL + || tfn->C_Digest == NULL + || tfn->C_DigestUpdate == NULL + || tfn->C_DigestKey == NULL + || tfn->C_DigestFinal == NULL + || tfn->C_SignInit == NULL + || tfn->C_Sign == NULL + || tfn->C_SignUpdate == NULL + || tfn->C_SignFinal == NULL + || tfn->C_SignRecoverInit == NULL + || tfn->C_SignRecover == NULL + || tfn->C_VerifyInit == NULL + || tfn->C_Verify == NULL + || tfn->C_VerifyUpdate == NULL + || tfn->C_VerifyFinal == NULL + || tfn->C_VerifyRecoverInit == NULL + || tfn->C_VerifyRecover == NULL + || tfn->C_DigestEncryptUpdate == NULL + || tfn->C_DecryptDigestUpdate == NULL + || tfn->C_SignEncryptUpdate == NULL + || tfn->C_DecryptVerifyUpdate == NULL + || tfn->C_GenerateKey == NULL + || tfn->C_GenerateKeyPair == NULL + || tfn->C_WrapKey == NULL + || tfn->C_UnwrapKey == NULL + || tfn->C_DeriveKey == NULL + || tfn->C_SeedRandom == NULL + || tfn->C_GenerateRandom == NULL + || tfn->C_GetFunctionStatus == NULL + || tfn->C_CancelFunction == NULL + || tfn->C_WaitForSlotEvent == NULL + /* Additional PKCS #11 3.0 functions */ + || tfn->C_GetInterfaceList == NULL + || tfn->C_GetInterface == NULL + || tfn->C_LoginUser == NULL + || tfn->C_SessionCancel == NULL + || tfn->C_MessageEncryptInit == NULL + || tfn->C_EncryptMessage == NULL + || tfn->C_EncryptMessageBegin == NULL + || tfn->C_EncryptMessageNext == NULL + || tfn->C_MessageEncryptFinal == NULL + || tfn->C_MessageDecryptInit == NULL + || tfn->C_DecryptMessage == NULL + || tfn->C_DecryptMessageBegin == NULL + || tfn->C_DecryptMessageNext == NULL + || tfn->C_MessageDecryptFinal == NULL + || tfn->C_MessageSignInit == NULL + || tfn->C_SignMessage == NULL + || tfn->C_SignMessageBegin == NULL + || tfn->C_SignMessageNext == NULL + || tfn->C_MessageSignFinal == NULL + || tfn->C_MessageVerifyInit == NULL + || tfn->C_VerifyMessage == NULL + || tfn->C_VerifyMessageBegin == NULL + || tfn->C_VerifyMessageNext == NULL + || tfn->C_MessageVerifyFinal == NULL) { + testcase_fail("%s", "Returned CK_FUNCTION_LIST_3_0 contains" + " a NULL function pointer.\n"); + goto ret; + } + /* + * Function pointers are != NULL. + * Now check if they are valid. + */ + slot = 0; + tfn->C_Initialize(NULL); + tfn->C_Finalize(NULL); + tfn->C_GetInfo(NULL); + tfn->C_GetFunctionList(NULL); + tfn->C_GetSlotList(CK_FALSE, NULL, NULL); + tfn->C_GetSlotInfo(slot, NULL); + tfn->C_GetTokenInfo(slot, NULL); + tfn->C_GetMechanismList(slot, NULL, NULL); + tfn->C_GetMechanismInfo(slot, 0UL, NULL); + tfn->C_InitToken(slot, NULL, 0UL, NULL); + tfn->C_InitPIN(0UL, NULL, 0UL); + tfn->C_SetPIN(0UL, NULL, 0UL, NULL, 0UL); + tfn->C_OpenSession(slot, 0UL, NULL, NULL, NULL); + tfn->C_CloseSession(0UL); + tfn->C_CloseAllSessions(slot); + tfn->C_GetSessionInfo(0UL, NULL); + tfn->C_GetOperationState(0UL, NULL, NULL); + tfn->C_SetOperationState(0UL, NULL, 0UL, 0UL, 0UL); + tfn->C_Login(0UL, 0UL, NULL, 0UL); + tfn->C_Logout(0UL); + tfn->C_CreateObject(0UL, NULL, 0UL, NULL); + tfn->C_CopyObject(0UL, 0UL, NULL, 0UL, NULL); + tfn->C_DestroyObject(0UL, 0UL); + tfn->C_GetObjectSize(0UL, 0UL, NULL); + tfn->C_GetAttributeValue(0UL, 0UL, NULL, 0UL); + tfn->C_SetAttributeValue(0UL, 0UL, NULL, 0UL); + tfn->C_FindObjectsInit(0UL, NULL, 0UL); + tfn->C_FindObjects(0UL, NULL, 0UL, NULL); + tfn->C_FindObjectsFinal(0UL); + tfn->C_EncryptInit(0UL, NULL, 0UL); + tfn->C_Encrypt(0UL, NULL, 0UL, NULL, NULL); + tfn->C_EncryptUpdate(0UL, NULL, 0UL, NULL, NULL); + tfn->C_EncryptFinal(0UL, NULL, NULL); + tfn->C_DecryptInit(0UL, NULL, 0UL); + tfn->C_Decrypt(0UL, NULL, 0UL, NULL, NULL); + tfn->C_DecryptUpdate(0UL, NULL, 0UL, NULL, NULL); + tfn->C_DecryptFinal(0UL, NULL, NULL); + tfn->C_DigestInit(0UL, NULL); + tfn->C_Digest(0UL, NULL, 0UL, NULL, 0UL); + tfn->C_DigestUpdate(0UL, NULL, 0UL); + tfn->C_DigestKey(0UL, 0UL); + tfn->C_DigestFinal(0UL, NULL, NULL); + tfn->C_SignInit(0UL, NULL, 0UL); + tfn->C_Sign(0UL, NULL, 0UL, NULL, NULL); + tfn->C_SignUpdate(0UL, NULL, 0UL); + tfn->C_SignFinal(0UL, NULL, NULL); + tfn->C_SignRecoverInit(0UL, NULL, 0UL); + tfn->C_SignRecover(0UL, NULL, 0UL, NULL, NULL); + tfn->C_VerifyInit(0UL, NULL, 0UL); + tfn->C_Verify(0UL, NULL, 0UL, NULL, 0UL); + tfn->C_VerifyUpdate(0UL, NULL, 0UL); + tfn->C_VerifyFinal(0UL, NULL, 0UL); + tfn->C_VerifyRecoverInit(0UL, NULL, 0UL); + tfn->C_VerifyRecover(0UL, NULL, 0UL, NULL, NULL); + tfn->C_DigestEncryptUpdate(0UL, NULL, 0UL, NULL, NULL); + tfn->C_DecryptDigestUpdate(0UL, NULL, 0UL, NULL, NULL); + tfn->C_SignEncryptUpdate(0UL, NULL, 0UL, NULL, NULL); + tfn->C_DecryptVerifyUpdate(0UL, NULL, 0UL, NULL, NULL); + tfn->C_GenerateKey(0UL, NULL, NULL, 0UL, NULL); + tfn->C_GenerateKeyPair(0UL, NULL, NULL, 0UL, NULL, 0UL, NULL, NULL); + tfn->C_WrapKey(0UL, NULL, 0UL, 0UL, NULL, NULL); + tfn->C_UnwrapKey(0UL, NULL, 0UL, NULL, 0UL, NULL, 0UL, NULL); + tfn->C_DeriveKey(0UL, NULL, 0UL, NULL, 0UL, NULL); + tfn->C_SeedRandom(0UL, NULL, 0UL); + tfn->C_GenerateRandom(0UL, NULL, 0UL); + tfn->C_GetFunctionStatus(0UL); + tfn->C_CancelFunction(0UL); + tfn->C_WaitForSlotEvent(0UL, &slot, NULL); + /* Additional PKCS #11 3.0 functions */ + tfn->C_GetInterfaceList(NULL, NULL); + tfn->C_GetInterface(NULL, NULL, NULL, 0UL); + tfn->C_LoginUser(0UL, 0UL, NULL, 0UL, NULL, 0UL); + tfn->C_SessionCancel(0UL, 0UL); + tfn->C_MessageEncryptInit(0UL, NULL, 0UL); + tfn->C_EncryptMessage(0UL, NULL, 0UL, NULL, 0UL, NULL, 0UL, NULL, 0UL); + tfn->C_EncryptMessageBegin(0UL, NULL, 0UL, NULL, 0UL); + tfn->C_EncryptMessageNext(0UL, NULL, 0UL, NULL, 0UL, NULL, NULL, 0UL); + tfn->C_MessageEncryptFinal(0UL); + tfn->C_MessageDecryptInit(0UL, NULL, 0UL); + tfn->C_DecryptMessage(0UL, NULL, 0UL, NULL, 0UL, NULL, 0UL, NULL, 0UL); + tfn->C_DecryptMessageBegin(0UL, NULL, 0UL, NULL, 0UL); + tfn->C_DecryptMessageNext(0UL, NULL, 0UL, NULL, 0UL, NULL, NULL, 0UL); + tfn->C_MessageDecryptFinal(0UL); + tfn->C_MessageSignInit(0UL, NULL, 0UL); + tfn->C_SignMessage(0UL, NULL, 0UL, NULL, 0UL, NULL, NULL); + tfn->C_SignMessageBegin(0UL, NULL, 0UL); + tfn->C_SignMessageNext(0UL, NULL, 0UL, NULL, 0UL, NULL, NULL); + tfn->C_MessageSignFinal(0UL); + tfn->C_MessageVerifyInit(0UL, NULL, 0UL); + tfn->C_VerifyMessage(0UL, NULL, 0UL, NULL, 0UL, NULL, 0UL); + tfn->C_VerifyMessageBegin(0UL, NULL, 0UL); + tfn->C_VerifyMessageNext(0UL, NULL, 0UL, NULL, 0UL, NULL, 0UL); + tfn->C_MessageVerifyFinal(0UL); + + testcase_pass("C_GetInterface works.\n"); + rc = 0; +ret: + return rc; +} + +static int get_interface_list_test(void) +{ + CK_INTERFACE *il = NULL; + CK_ULONG nmemb = 0UL, i; + CK_VERSION *version; + CK_RV rv; + int rc = -1; + + testcase_new_assertion(); + + rv = funcs3->C_GetInterfaceList(NULL, NULL); + if (rv != CKR_ARGUMENTS_BAD) { + testcase_fail("C_GetInterfaceList returned %s.\n", p11_get_ckr(rv)); + goto ret; + } + + rv = funcs3->C_GetInterfaceList(NULL, &nmemb); + if (rv != CKR_OK) { + testcase_fail("C_GetInterfaceList returned %s.\n", p11_get_ckr(rv)); + goto ret; + } + if (nmemb == 0) { + testcase_fail("C_GetInterfaceList interface list has" + " %lu elements.\n", nmemb); + goto ret; + } + + il = calloc(nmemb, sizeof(*il)); + if (il == NULL) { + testcase_error("calloc failed.\n"); + goto ret; + } + + nmemb--; + rv = funcs3->C_GetInterfaceList(il, &nmemb); + if (rv != CKR_BUFFER_TOO_SMALL) { + testcase_fail("C_GetInterfaceList returned %s.\n", p11_get_ckr(rv)); + goto ret; + } + + rv = funcs3->C_GetInterfaceList(il, &nmemb); + if (rv != CKR_OK) { + testcase_fail("C_GetInterfaceList returned %s.\n", p11_get_ckr(rv)); + goto ret; + } + + for (i = 0UL; i < nmemb; i++) { + if (strncmp((char *)il[i].pInterfaceName, + "PKCS 11", strlen("PKCS 11")) != 0 + && strncmp((char *)il[i].pInterfaceName, + "Vendor ", strlen("Vendor ")) != 0) { + testcase_fail("Invalid interface name.\n"); + goto ret; + } + + if (il[i].pFunctionList == NULL) { + testcase_fail("%s", "Interface with NULL function list.\n"); + goto ret; + } + + if ((il[i].flags & ~CKF_INTERFACE_FORK_SAFE) != 0) { + testcase_fail("Interface with unknown flags: 0x%016lx.\n", + il[i].flags); + goto ret; + } + + version = (CK_VERSION *)il[i].pFunctionList; + + printf("Interface %lu:\n", i); + printf("pInterfaceName %s\n", il[i].pInterfaceName); + printf("pFunctionList version %u.%u\n", + version->major, version->minor); + printf("flags 0x%016lx\n", il[i].flags); + } + + testcase_pass("C_GetInterfaceList works.\n"); + rc = 0; +ret: + free(il); + return rc; +} + +int main(void) +{ + int rc = -1; + + testcase_setup(0); + + if (do_GetFunctionList() != TRUE) { + testcase_error("%s", "do_GetFunctionList() failed.\n"); + goto ret; + } + + rc = get_interface_list_test(); + if (rc) + goto ret; + + rc = get_interface_test(); + +ret: + testcase_print_result(); + /* make sure we return non-zero if rc is non-zero */ + return ((rc == 0) || (rc % 256) ? (int)rc : -1); +} diff --git a/testcases/pkcs11/hw_fn.c b/testcases/pkcs11/hw_fn.c index b6a79c9..af7e8ec 100644 --- a/testcases/pkcs11/hw_fn.c +++ b/testcases/pkcs11/hw_fn.c @@ -30,7 +30,6 @@ #define AES_KEY_SIZE_128 16 -int do_GetFunctionList(void); int clean_up(void); CK_SLOT_ID slot_id; diff --git a/testcases/pkcs11/pkcs11.mk b/testcases/pkcs11/pkcs11.mk index eb16d5c..5763402 100644 --- a/testcases/pkcs11/pkcs11.mk +++ b/testcases/pkcs11/pkcs11.mk @@ -4,7 +4,8 @@ noinst_PROGRAMS += \ testcases/pkcs11/attribute testcases/pkcs11/findobjects \ testcases/pkcs11/destroyobjects testcases/pkcs11/copyobjects \ testcases/pkcs11/generate_keypair testcases/pkcs11/gen_purpose \ - testcases/pkcs11/getobjectsize + testcases/pkcs11/getobjectsize \ + testcases/pkcs11/get_interface testcases_pkcs11_hw_fn_CFLAGS = ${testcases_inc} testcases_pkcs11_hw_fn_LDADD = testcases/common/libcommon.la @@ -53,3 +54,8 @@ testcases_pkcs11_getobjectsize_CFLAGS = ${testcases_inc} testcases_pkcs11_getobjectsize_LDADD = testcases/common/libcommon.la testcases_pkcs11_getobjectsize_SOURCES = \ testcases/pkcs11/getobjectsize.c + +testcases_pkcs11_get_interface_CFLAGS = ${testcases_inc} +testcases_pkcs11_get_interface_LDADD = testcases/common/libcommon.la +testcases_pkcs11_get_interface_SOURCES = \ + testcases/pkcs11/get_interface.c diff --git a/usr/include/apiclient.h b/usr/include/apiclient.h index 9c1a0bc..649e325 100644 --- a/usr/include/apiclient.h +++ b/usr/include/apiclient.h @@ -14,10 +14,6 @@ #include "pkcs11types.h" - -#define VERSION_MAJOR 2 // Version 2 of the PKCS library -#define VERSION_MINOR 01 // minor revision .10 of PKCS11 - #ifdef __cplusplus extern "C" { #endif @@ -190,6 +186,105 @@ extern "C" { CK_RV C_WrapKey(CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE, CK_OBJECT_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR); + CK_RV C_GetInterfaceList(CK_INTERFACE_PTR, CK_ULONG_PTR); + + CK_RV C_GetInterface(CK_UTF8CHAR_PTR, CK_VERSION_PTR, + CK_INTERFACE_PTR_PTR, CK_FLAGS); + + CK_RV C_LoginUser(CK_SESSION_HANDLE, CK_USER_TYPE, + CK_UTF8CHAR *, CK_ULONG, + CK_UTF8CHAR *, CK_ULONG); + + CK_RV C_SessionCancel(CK_SESSION_HANDLE, CK_FLAGS); + + CK_RV C_MessageEncryptInit(CK_SESSION_HANDLE, + CK_MECHANISM *, CK_OBJECT_HANDLE); + + CK_RV C_EncryptMessage(CK_SESSION_HANDLE , + void *, CK_ULONG, + CK_BYTE *, CK_ULONG, + CK_BYTE *, CK_ULONG, + CK_BYTE *, CK_ULONG *); + + CK_RV C_EncryptMessageBegin(CK_SESSION_HANDLE, + void *, CK_ULONG, + CK_BYTE *, + CK_ULONG); + + CK_RV C_EncryptMessageNext(CK_SESSION_HANDLE, + void *, CK_ULONG, + CK_BYTE *, + CK_ULONG, + CK_BYTE *, + CK_ULONG *, + CK_ULONG); + + CK_RV C_MessageEncryptFinal(CK_SESSION_HANDLE); + + CK_RV C_MessageDecryptInit(CK_SESSION_HANDLE, + CK_MECHANISM *, CK_OBJECT_HANDLE); + + CK_RV C_DecryptMessage(CK_SESSION_HANDLE, + void *, CK_ULONG, + CK_BYTE *, CK_ULONG, + CK_BYTE *, CK_ULONG, + CK_BYTE *, CK_ULONG *); + + CK_RV C_DecryptMessageBegin(CK_SESSION_HANDLE, + void *, CK_ULONG, + CK_BYTE *, + CK_ULONG); + + CK_RV C_DecryptMessageNext(CK_SESSION_HANDLE, + void *, CK_ULONG, + CK_BYTE *, + CK_ULONG, + CK_BYTE *, + CK_ULONG *, + CK_FLAGS); + + CK_RV C_MessageDecryptFinal(CK_SESSION_HANDLE); + + CK_RV C_MessageSignInit(CK_SESSION_HANDLE, + CK_MECHANISM *, CK_OBJECT_HANDLE); + + CK_RV C_SignMessage(CK_SESSION_HANDLE, + void *, CK_ULONG, + CK_BYTE *, CK_ULONG, + CK_BYTE *, CK_ULONG *); + + CK_RV C_SignMessageBegin(CK_SESSION_HANDLE, + void *, CK_ULONG); + + CK_RV C_SignMessageNext(CK_SESSION_HANDLE, + void *, CK_ULONG, + CK_BYTE *, CK_ULONG, + CK_BYTE *, CK_ULONG *); + + CK_RV C_MessageSignFinal(CK_SESSION_HANDLE); + + CK_RV C_MessageVerifyInit(CK_SESSION_HANDLE, + CK_MECHANISM *, CK_OBJECT_HANDLE); + + CK_RV C_VerifyMessage(CK_SESSION_HANDLE, + void *, CK_ULONG, + CK_BYTE *, CK_ULONG, + CK_BYTE *, CK_ULONG); + + CK_RV C_VerifyMessageBegin(CK_SESSION_HANDLE, + void *, CK_ULONG); + + CK_RV C_VerifyMessageNext(CK_SESSION_HANDLE, + void *, CK_ULONG, + CK_BYTE *, CK_ULONG, + CK_BYTE *, CK_ULONG); + + CK_RV C_MessageVerifyFinal(CK_SESSION_HANDLE); + + CK_RV C_IBM_ReencryptSingle(CK_SESSION_HANDLE, CK_MECHANISM_PTR, + CK_OBJECT_HANDLE, CK_MECHANISM_PTR, + CK_OBJECT_HANDLE, CK_BYTE_PTR, + CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR); #ifdef __cplusplus } #endif diff --git a/usr/include/pkcs11types.h b/usr/include/pkcs11types.h index a0e7a50..4cd9ed0 100644 --- a/usr/include/pkcs11types.h +++ b/usr/include/pkcs11types.h @@ -367,10 +367,19 @@ typedef CK_ULONG CK_OBJECT_CLASS; /* CKO_HW_FEATURE and CKO_DOMAIN_PARAMETERS are new for v2.11 */ #define CKO_HW_FEATURE 0x00000005 #define CKO_DOMAIN_PARAMETERS 0x00000006 +#define CKO_PROFILE 0x00000009UL #define CKO_VENDOR_DEFINED 0x80000000 typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR; +/* Profile ID's */ +#define CKP_INVALID_ID 0x00000000UL +#define CKP_BASELINE_PROVIDER 0x00000001UL +#define CKP_EXTENDED_PROVIDER 0x00000002UL +#define CKP_AUTHENTICATION_TOKEN 0x00000003UL +#define CKP_PUBLIC_CERTIFICATES_TOKEN 0x00000004UL +#define CKP_VENDOR_DEFINED 0x80000000UL + /* CK_HW_FEATURE_TYPE is a value that identifies a hardware * feature type of a device. This is new for v2.11. */ @@ -452,6 +461,7 @@ typedef CK_ULONG CK_ATTRIBUTE_TYPE; #define CKA_TOKEN 0x00000001 #define CKA_PRIVATE 0x00000002 #define CKA_LABEL 0x00000003 +#define CKA_UNIQUE_ID 0x00000004UL #define CKA_APPLICATION 0x00000010 #define CKA_VALUE 0x00000011 /* CKA_OBJECT_ID is new for v2.11 */ @@ -525,6 +535,8 @@ typedef CK_ULONG CK_ATTRIBUTE_TYPE; #define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000211UL) #define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000212UL) +#define CKA_PROFILE_ID 0x00000601UL + #define CKA_VENDOR_DEFINED 0x80000000 /* For use in storing objects that have an encrypted or otherwise @@ -580,6 +592,9 @@ typedef struct CK_DATE { CK_CHAR day[2]; /* the day ("01" - "31") */ } CK_DATE; +/* CK_PROFILE_ID is a value that identifies a profile ID. */ +typedef CK_ULONG CK_PROFILE_ID; +typedef CK_PROFILE_ID CK_PTR CK_PROFILE_ID_PTR; /* CK_MECHANISM_TYPE is a value that identifies a mechanism * type */ @@ -882,7 +897,8 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_IBM_SHA3_512_HMAC CKM_VENDOR_DEFINED + 0x00010028 #define CKM_IBM_EC_C25519 CKM_VENDOR_DEFINED + 0x0001001b -#define CKM_IBM_EDDSA_SHA512 CKM_VENDOR_DEFINED + 0x0001001c +#define CKM_IBM_ED25519_SHA512 CKM_VENDOR_DEFINED + 0x0001001c +#define CKM_IBM_EDDSA_SHA512 CKM_IBM_ED25519_SHA512 #define CKM_IBM_EC_C448 CKM_VENDOR_DEFINED + 0x0001001e #define CKM_IBM_ED448_SHA3 CKM_VENDOR_DEFINED + 0x0001001f @@ -1440,16 +1456,35 @@ typedef struct CK_ECDH1_DERIVE_PARAMS { #define CKD_SHA384_KDF 0x00000007UL #define CKD_SHA512_KDF 0x00000008UL +#define CKF_INTERFACE_FORK_SAFE 0x00000001UL + +/* CK_INTERFACE is a structure which contains + * an interface name with a function list and flag. */ +typedef struct CK_INTERFACE { + CK_UTF8CHAR_PTR pInterfaceName; + CK_VOID_PTR pFunctionList; + CK_FLAGS flags; +} CK_INTERFACE; + +typedef CK_INTERFACE CK_PTR CK_INTERFACE_PTR; +typedef CK_INTERFACE_PTR CK_PTR CK_INTERFACE_PTR_PTR; + /* CK_FUNCTION_LIST is a structure holding a Cryptoki spec * version and pointers of appropriate types to all the * Cryptoki functions */ /* CK_FUNCTION_LIST is new for v2.0 */ typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST; - typedef CK_FUNCTION_LIST CK_PTR CK_FUNCTION_LIST_PTR; - typedef CK_FUNCTION_LIST_PTR CK_PTR CK_FUNCTION_LIST_PTR_PTR; +typedef struct CK_FUNCTION_LIST_3_0 CK_FUNCTION_LIST_3_0; +typedef CK_FUNCTION_LIST_3_0 CK_PTR CK_FUNCTION_LIST_3_0_PTR; +typedef CK_FUNCTION_LIST_3_0_PTR CK_PTR CK_FUNCTION_LIST_3_0_PTR_PTR; + +typedef struct CK_IBM_FUNCTION_LIST_1_0 CK_IBM_FUNCTION_LIST_1_0; +typedef struct CK_IBM_FUNCTION_LIST_1_0 CK_PTR CK_IBM_FUNCTION_LIST_1_0_PTR; +typedef struct CK_IBM_FUNCTION_LIST_1_0_PTR CK_PTR CK_IBM_FUNCTION_LIST_1_0_PTR_PTR; + typedef CK_RV (CK_PTR CK_C_Initialize) (CK_VOID_PTR pReserved); typedef CK_RV (CK_PTR CK_C_Finalize) (CK_VOID_PTR pReserved); typedef CK_RV (CK_PTR CK_C_Terminate) (void); @@ -1696,6 +1731,124 @@ typedef CK_RV (CK_PTR CK_C_WaitForSlotEvent) (CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved); +typedef CK_RV (CK_PTR CK_C_GetInterfaceList) (CK_INTERFACE *pInterfaceList, + CK_ULONG *pulCount); +typedef CK_RV (CK_PTR CK_C_GetInterface) (CK_UTF8CHAR *pInterfaceName, + CK_VERSION *pVersion, + CK_INTERFACE **ppInterface, + CK_FLAGS flags); +typedef CK_RV (CK_PTR CK_C_LoginUser) (CK_SESSION_HANDLE hSession, + CK_USER_TYPE userType, + CK_UTF8CHAR *pPin, CK_ULONG ulPinLen, + CK_UTF8CHAR *pUsername, + CK_ULONG ulUsernameLen); +typedef CK_RV (CK_PTR CK_C_SessionCancel) (CK_SESSION_HANDLE hSession, + CK_FLAGS flags); +typedef CK_RV (CK_PTR CK_C_MessageEncryptInit) (CK_SESSION_HANDLE hSession, + CK_MECHANISM *pMechanism, + CK_OBJECT_HANDLE hKey); +typedef CK_RV (CK_PTR CK_C_EncryptMessage) (CK_SESSION_HANDLE hSession, + void *pParameter, + CK_ULONG ulParameterLen, + CK_BYTE *pAssociatedData, + CK_ULONG ulAssociatedDataLen, + CK_BYTE *pPlaintext, + CK_ULONG ulPlaintextLen, + CK_BYTE *pCiphertext, + CK_ULONG *pulCiphertextLen); +typedef CK_RV (CK_PTR CK_C_EncryptMessageBegin) (CK_SESSION_HANDLE hSession, + void *pParameter, + CK_ULONG ulParameterLen, + CK_BYTE *pAssociatedData, + CK_ULONG ulAssociatedDataLen); +typedef CK_RV (CK_PTR CK_C_EncryptMessageNext) (CK_SESSION_HANDLE hSession, + void *pParameter, + CK_ULONG ulParameterLen, + CK_BYTE *pPlaintextPart, + CK_ULONG ulPlaintextPartLen, + CK_BYTE *pCiphertextPart, + CK_ULONG *pulCiphertextPartLen, + CK_ULONG flags); +typedef CK_RV (CK_PTR CK_C_MessageEncryptFinal) (CK_SESSION_HANDLE hSession); +typedef CK_RV (CK_PTR CK_C_MessageDecryptInit) (CK_SESSION_HANDLE hSession, + CK_MECHANISM *pMechanism, + CK_OBJECT_HANDLE hKey); +typedef CK_RV (CK_PTR CK_C_DecryptMessage) (CK_SESSION_HANDLE hSession, + void *pParameter, + CK_ULONG ulParameterLen, + CK_BYTE *pAssociatedData, + CK_ULONG ulAssociatedDataLen, + CK_BYTE *pCiphertext, + CK_ULONG ulCiphertextLen, + CK_BYTE *pPlaintext, + CK_ULONG *pulPlaintextLen); +typedef CK_RV (CK_PTR CK_C_DecryptMessageBegin) (CK_SESSION_HANDLE hSession, + void *pParameter, + CK_ULONG ulParameterLen, + CK_BYTE *pAssociatedData, + CK_ULONG ulAssociatedDataLen); +typedef CK_RV (CK_PTR CK_C_DecryptMessageNext) (CK_SESSION_HANDLE hSession, + void *pParameter, + CK_ULONG ulParameterLen, + CK_BYTE *pCiphertextPart, + CK_ULONG ulCiphertextPartLen, + CK_BYTE *pPlaintextPart, + CK_ULONG *pulPlaintextPartLen, + CK_FLAGS flags); +typedef CK_RV (CK_PTR CK_C_MessageDecryptFinal) (CK_SESSION_HANDLE hSession); +typedef CK_RV (CK_PTR CK_C_MessageSignInit) (CK_SESSION_HANDLE hSession, + CK_MECHANISM *pMechanism, + CK_OBJECT_HANDLE hKey); +typedef CK_RV (CK_PTR CK_C_SignMessage) (CK_SESSION_HANDLE hSession, + void *pParameter, + CK_ULONG ulParameterLen, + CK_BYTE *pData, + CK_ULONG ulDataLen, + CK_BYTE *pSignature, + CK_ULONG *pulSignatureLen); +typedef CK_RV (CK_PTR CK_C_SignMessageBegin) (CK_SESSION_HANDLE hSession, + void *pParameter, + CK_ULONG ulParameterLen); +typedef CK_RV (CK_PTR CK_C_SignMessageNext) (CK_SESSION_HANDLE hSession, + void *pParameter, + CK_ULONG ulParameterLen, + CK_BYTE *pDataPart, + CK_ULONG ulDataPartLen, + CK_BYTE *pSignature, + CK_ULONG *pulSignatureLen); +typedef CK_RV (CK_PTR CK_C_MessageSignFinal) (CK_SESSION_HANDLE hSession); +typedef CK_RV (CK_PTR CK_C_MessageVerifyInit) (CK_SESSION_HANDLE hSession, + CK_MECHANISM *pMechanism, + CK_OBJECT_HANDLE hKey); +typedef CK_RV (CK_PTR CK_C_VerifyMessage) (CK_SESSION_HANDLE hSession, + void *pParameter, + CK_ULONG ulParameterLen, + CK_BYTE *pData, + CK_ULONG ulDataLen, + CK_BYTE *pSignature, + CK_ULONG ulSignatureLen); +typedef CK_RV (CK_PTR CK_C_VerifyMessageBegin) (CK_SESSION_HANDLE hSession, + void *pParameter, + CK_ULONG ulParameterLen); +typedef CK_RV (CK_PTR CK_C_VerifyMessageNext) (CK_SESSION_HANDLE hSession, + void *pParameter, + CK_ULONG ulParameterLen, + CK_BYTE *pDataPart, + CK_ULONG ulDataPartLen, + CK_BYTE *pSignature, + CK_ULONG ulSignatureLen); +typedef CK_RV (CK_PTR CK_C_MessageVerifyFinal) (CK_SESSION_HANDLE hSession); + +typedef CK_RV (CK_PTR CK_C_IBM_ReencryptSingle) (CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pDecrMech, + CK_OBJECT_HANDLE hDecrKey, + CK_MECHANISM_PTR pEncrMech, + CK_OBJECT_HANDLE hEncrKey, + CK_BYTE_PTR pEncryptedData, + CK_ULONG ulEncryptedDataLen, + CK_BYTE_PTR pReencryptedData, + CK_ULONG_PTR pulReencryptedDataLen); + struct CK_FUNCTION_LIST { CK_VERSION version; CK_C_Initialize C_Initialize; @@ -1768,6 +1921,108 @@ struct CK_FUNCTION_LIST { CK_C_WaitForSlotEvent C_WaitForSlotEvent; }; +struct CK_FUNCTION_LIST_3_0 { + CK_VERSION version; + CK_C_Initialize C_Initialize; + CK_C_Finalize C_Finalize; + CK_C_GetInfo C_GetInfo; + CK_C_GetFunctionList C_GetFunctionList; + CK_C_GetSlotList C_GetSlotList; + CK_C_GetSlotInfo C_GetSlotInfo; + CK_C_GetTokenInfo C_GetTokenInfo; + CK_C_GetMechanismList C_GetMechanismList; + CK_C_GetMechanismInfo C_GetMechanismInfo; + CK_C_InitToken C_InitToken; + CK_C_InitPIN C_InitPIN; + CK_C_SetPIN C_SetPIN; + CK_C_OpenSession C_OpenSession; + CK_C_CloseSession C_CloseSession; + CK_C_CloseAllSessions C_CloseAllSessions; + CK_C_GetSessionInfo C_GetSessionInfo; + CK_C_GetOperationState C_GetOperationState; + CK_C_SetOperationState C_SetOperationState; + CK_C_Login C_Login; + CK_C_Logout C_Logout; + CK_C_CreateObject C_CreateObject; + CK_C_CopyObject C_CopyObject; + CK_C_DestroyObject C_DestroyObject; + CK_C_GetObjectSize C_GetObjectSize; + CK_C_GetAttributeValue C_GetAttributeValue; + CK_C_SetAttributeValue C_SetAttributeValue; + CK_C_FindObjectsInit C_FindObjectsInit; + CK_C_FindObjects C_FindObjects; + CK_C_FindObjectsFinal C_FindObjectsFinal; + CK_C_EncryptInit C_EncryptInit; + CK_C_Encrypt C_Encrypt; + CK_C_EncryptUpdate C_EncryptUpdate; + CK_C_EncryptFinal C_EncryptFinal; + CK_C_DecryptInit C_DecryptInit; + CK_C_Decrypt C_Decrypt; + CK_C_DecryptUpdate C_DecryptUpdate; + CK_C_DecryptFinal C_DecryptFinal; + CK_C_DigestInit C_DigestInit; + CK_C_Digest C_Digest; + CK_C_DigestUpdate C_DigestUpdate; + CK_C_DigestKey C_DigestKey; + CK_C_DigestFinal C_DigestFinal; + CK_C_SignInit C_SignInit; + CK_C_Sign C_Sign; + CK_C_SignUpdate C_SignUpdate; + CK_C_SignFinal C_SignFinal; + CK_C_SignRecoverInit C_SignRecoverInit; + CK_C_SignRecover C_SignRecover; + CK_C_VerifyInit C_VerifyInit; + CK_C_Verify C_Verify; + CK_C_VerifyUpdate C_VerifyUpdate; + CK_C_VerifyFinal C_VerifyFinal; + CK_C_VerifyRecoverInit C_VerifyRecoverInit; + CK_C_VerifyRecover C_VerifyRecover; + CK_C_DigestEncryptUpdate C_DigestEncryptUpdate; + CK_C_DecryptDigestUpdate C_DecryptDigestUpdate; + CK_C_SignEncryptUpdate C_SignEncryptUpdate; + CK_C_DecryptVerifyUpdate C_DecryptVerifyUpdate; + CK_C_GenerateKey C_GenerateKey; + CK_C_GenerateKeyPair C_GenerateKeyPair; + CK_C_WrapKey C_WrapKey; + CK_C_UnwrapKey C_UnwrapKey; + CK_C_DeriveKey C_DeriveKey; + CK_C_SeedRandom C_SeedRandom; + CK_C_GenerateRandom C_GenerateRandom; + CK_C_GetFunctionStatus C_GetFunctionStatus; + CK_C_CancelFunction C_CancelFunction; + CK_C_WaitForSlotEvent C_WaitForSlotEvent; + + CK_C_GetInterfaceList C_GetInterfaceList; + CK_C_GetInterface C_GetInterface; + CK_C_LoginUser C_LoginUser; + CK_C_SessionCancel C_SessionCancel; + CK_C_MessageEncryptInit C_MessageEncryptInit; + CK_C_EncryptMessage C_EncryptMessage; + CK_C_EncryptMessageBegin C_EncryptMessageBegin; + CK_C_EncryptMessageNext C_EncryptMessageNext; + CK_C_MessageEncryptFinal C_MessageEncryptFinal; + CK_C_MessageDecryptInit C_MessageDecryptInit; + CK_C_DecryptMessage C_DecryptMessage; + CK_C_DecryptMessageBegin C_DecryptMessageBegin; + CK_C_DecryptMessageNext C_DecryptMessageNext; + CK_C_MessageDecryptFinal C_MessageDecryptFinal; + CK_C_MessageSignInit C_MessageSignInit; + CK_C_SignMessage C_SignMessage; + CK_C_SignMessageBegin C_SignMessageBegin; + CK_C_SignMessageNext C_SignMessageNext; + CK_C_MessageSignFinal C_MessageSignFinal; + CK_C_MessageVerifyInit C_MessageVerifyInit; + CK_C_VerifyMessage C_VerifyMessage; + CK_C_VerifyMessageBegin C_VerifyMessageBegin; + CK_C_VerifyMessageNext C_VerifyMessageNext; + CK_C_MessageVerifyFinal C_MessageVerifyFinal; +}; + +struct CK_IBM_FUNCTION_LIST_1_0 { + CK_VERSION version; + CK_C_IBM_ReencryptSingle C_IBM_ReencryptSingle; +}; + #ifdef __cplusplus } #endif diff --git a/usr/include/slotmgr.h b/usr/include/slotmgr.h index 0abbdff..3950a9a 100644 --- a/usr/include/slotmgr.h +++ b/usr/include/slotmgr.h @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include "local_types.h" @@ -230,16 +232,12 @@ typedef Slot_Info_t SLOT_INFO; #define MFG "IBM " #define LIB "openCryptoki " - -#define MAJOR_V 1 -#define MINOR_V 2 - #ifndef CRYPTOKI_API_MAJOR_V -#define CRYPTOKI_API_MAJOR_V 0x2 +#define CRYPTOKI_API_MAJOR_V 0x3 #endif #ifndef CRYPTOKI_API_MINOR_V -#define CRYPTOKI_API_MINOR_V 0x14 +#define CRYPTOKI_API_MINOR_V 0x0 #endif #define LIB_MAJOR_V 1 @@ -247,4 +245,23 @@ typedef Slot_Info_t SLOT_INFO; #define RESTART_SYS_CALLS 1 +#if defined(__GNUC__) || defined(__clang__) +__attribute__((__format__ (__printf__, 3, 4))) +#endif +static inline int ock_snprintf(char *buf, size_t buflen, const char *fmt, ...) +{ + va_list ap; + int n; + + va_start(ap, fmt); + n = vsnprintf(buf, buflen, fmt, ap); + va_end(ap); + + if (n < 0 || (size_t)n >= buflen) + return -1; + + return 0; +} + + #endif /* _SLOTMGR_H */ diff --git a/usr/include/stdll.h b/usr/include/stdll.h index cafdf82..57f6c6e 100644 --- a/usr/include/stdll.h +++ b/usr/include/stdll.h @@ -339,6 +339,16 @@ typedef CK_RV (CK_PTR ST_C_WaitForSlotEvent) (STDLL_TokData_t *tokdata, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved); +typedef CK_RV (CK_PTR ST_C_IBM_ReencryptSingle)(STDLL_TokData_t *tokdata, + ST_SESSION_T *hSession, + CK_MECHANISM_PTR pDecrMech, + CK_OBJECT_HANDLE hDecrKey, + CK_MECHANISM_PTR pEncrMech, + CK_OBJECT_HANDLE hEncrKey, + CK_BYTE_PTR pEncryptedData, + CK_ULONG ulEncryptedDataLen, + CK_BYTE_PTR pReencryptedData, + CK_ULONG_PTR pulReencryptedDataLen); struct ST_FCN_LIST { @@ -413,6 +423,7 @@ struct ST_FCN_LIST { ST_C_GetFunctionStatus ST_GetFunctionStatus; ST_C_CancelFunction ST_CancelFunction; + ST_C_IBM_ReencryptSingle ST_IBM_ReencryptSingle; }; typedef struct ST_FCN_LIST STDLL_FcnList_t; diff --git a/usr/lib/api/api_interface.c b/usr/lib/api/api_interface.c index 51ab30f..f22460b 100644 --- a/usr/lib/api/api_interface.c +++ b/usr/lib/api/api_interface.c @@ -57,13 +57,208 @@ void api_init(); API_Proc_Struct_t *Anchor = NULL; // Initialized to NULL unsigned int Initialized = 0; // Initialized flag pthread_mutex_t GlobMutex = PTHREAD_MUTEX_INITIALIZER; // Global Mutex -CK_FUNCTION_LIST FuncList; + +static CK_IBM_FUNCTION_LIST_1_0 func_list_ibm_1_0 = { + {1, 0}, + C_IBM_ReencryptSingle +}; + +static CK_FUNCTION_LIST func_list_pkcs11_2_40 = { + {2, 40}, + C_Initialize, + C_Finalize, + C_GetInfo, + C_GetFunctionList, + C_GetSlotList, + C_GetSlotInfo, + C_GetTokenInfo, + C_GetMechanismList, + C_GetMechanismInfo, + C_InitToken, + C_InitPIN, + C_SetPIN, + C_OpenSession, + C_CloseSession, + C_CloseAllSessions, + C_GetSessionInfo, + C_GetOperationState, + C_SetOperationState, + C_Login, + C_Logout, + C_CreateObject, + C_CopyObject, + C_DestroyObject, + C_GetObjectSize, + C_GetAttributeValue, + C_SetAttributeValue, + C_FindObjectsInit, + C_FindObjects, + C_FindObjectsFinal, + C_EncryptInit, + C_Encrypt, + C_EncryptUpdate, + C_EncryptFinal, + C_DecryptInit, + C_Decrypt, + C_DecryptUpdate, + C_DecryptFinal, + C_DigestInit, + C_Digest, + C_DigestUpdate, + C_DigestKey, + C_DigestFinal, + C_SignInit, + C_Sign, + C_SignUpdate, + C_SignFinal, + C_SignRecoverInit, + C_SignRecover, + C_VerifyInit, + C_Verify, + C_VerifyUpdate, + C_VerifyFinal, + C_VerifyRecoverInit, + C_VerifyRecover, + C_DigestEncryptUpdate, + C_DecryptDigestUpdate, + C_SignEncryptUpdate, + C_DecryptVerifyUpdate, + C_GenerateKey, + C_GenerateKeyPair, + C_WrapKey, + C_UnwrapKey, + C_DeriveKey, + C_SeedRandom, + C_GenerateRandom, + C_GetFunctionStatus, + C_CancelFunction, + C_WaitForSlotEvent +}; + +static CK_FUNCTION_LIST_3_0 func_list_pkcs11_3_0 = { + {3, 0}, + C_Initialize, + C_Finalize, + C_GetInfo, + C_GetFunctionList, + C_GetSlotList, + C_GetSlotInfo, + C_GetTokenInfo, + C_GetMechanismList, + C_GetMechanismInfo, + C_InitToken, + C_InitPIN, + C_SetPIN, + C_OpenSession, + C_CloseSession, + C_CloseAllSessions, + C_GetSessionInfo, + C_GetOperationState, + C_SetOperationState, + C_Login, + C_Logout, + C_CreateObject, + C_CopyObject, + C_DestroyObject, + C_GetObjectSize, + C_GetAttributeValue, + C_SetAttributeValue, + C_FindObjectsInit, + C_FindObjects, + C_FindObjectsFinal, + C_EncryptInit, + C_Encrypt, + C_EncryptUpdate, + C_EncryptFinal, + C_DecryptInit, + C_Decrypt, + C_DecryptUpdate, + C_DecryptFinal, + C_DigestInit, + C_Digest, + C_DigestUpdate, + C_DigestKey, + C_DigestFinal, + C_SignInit, + C_Sign, + C_SignUpdate, + C_SignFinal, + C_SignRecoverInit, + C_SignRecover, + C_VerifyInit, + C_Verify, + C_VerifyUpdate, + C_VerifyFinal, + C_VerifyRecoverInit, + C_VerifyRecover, + C_DigestEncryptUpdate, + C_DecryptDigestUpdate, + C_SignEncryptUpdate, + C_DecryptVerifyUpdate, + C_GenerateKey, + C_GenerateKeyPair, + C_WrapKey, + C_UnwrapKey, + C_DeriveKey, + C_SeedRandom, + C_GenerateRandom, + C_GetFunctionStatus, + C_CancelFunction, + C_WaitForSlotEvent, + + C_GetInterfaceList, + C_GetInterface, + C_LoginUser, + C_SessionCancel, + C_MessageEncryptInit, + C_EncryptMessage, + C_EncryptMessageBegin, + C_EncryptMessageNext, + C_MessageEncryptFinal, + C_MessageDecryptInit, + C_DecryptMessage, + C_DecryptMessageBegin, + C_DecryptMessageNext, + C_MessageDecryptFinal, + C_MessageSignInit, + C_SignMessage, + C_SignMessageBegin, + C_SignMessageNext, + C_MessageSignFinal, + C_MessageVerifyInit, + C_VerifyMessage, + C_VerifyMessageBegin, + C_VerifyMessageNext, + C_MessageVerifyFinal +}; int slot_loaded[NUMBER_SLOTS_MANAGED]; // Array of flags to indicate // if the STDLL loaded CK_BBOOL in_child_fork_initializer = FALSE; +/* + * Ordered array of interfaces: If more than one interface matches + * interface_get's arguments, the interface at lowest index is returned. + */ +static CK_INTERFACE interface_list[] = { + { + (CK_UTF8CHAR *)"PKCS 11", + &func_list_pkcs11_3_0, + CKF_INTERFACE_FORK_SAFE /*XXX*/ + }, + { + (CK_UTF8CHAR *)"PKCS 11", + &func_list_pkcs11_2_40, + CKF_INTERFACE_FORK_SAFE /*XXX*/ + }, + { + (CK_UTF8CHAR *)"Vendor IBM", + &func_list_ibm_1_0, + CKF_INTERFACE_FORK_SAFE /*XXX*/ + } +}; + void child_fork_initializer() { /* @@ -543,8 +738,8 @@ CK_RV C_DecryptInit(CK_SESSION_HANDLE hSession, // Null mechanism pointer is not good if (!pMechanism) { - TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); - return CKR_MECHANISM_INVALID; + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + return CKR_ARGUMENTS_BAD; } sltp = &(Anchor->SltList[rSession.slotID]); @@ -713,8 +908,8 @@ CK_RV C_DeriveKey(CK_SESSION_HANDLE hSession, //if (!phKey ) return CKR_ARGUMENTS_BAD; if (!pMechanism) { - TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); - return CKR_MECHANISM_INVALID; + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + return CKR_ARGUMENTS_BAD; } // Null template with attribute count is bad // but we will let a template with len 0 pass through @@ -966,8 +1161,8 @@ CK_RV C_DigestInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism) } if (!pMechanism) { - TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); - return CKR_MECHANISM_INVALID; + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + return CKR_ARGUMENTS_BAD; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); @@ -1204,8 +1399,8 @@ CK_RV C_EncryptInit(CK_SESSION_HANDLE hSession, } if (!pMechanism) { - TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); - return CKR_MECHANISM_INVALID; + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + return CKR_ARGUMENTS_BAD; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); @@ -1386,7 +1581,7 @@ CK_RV C_FindObjects(CK_SESSION_HANDLE hSession, return CKR_CRYPTOKI_NOT_INITIALIZED; } - if (!phObject || !pulObjectCount) { + if (!phObject || !pulObjectCount || ulMaxObjectCount == 0) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } @@ -1545,8 +1740,8 @@ CK_RV C_GenerateKey(CK_SESSION_HANDLE hSession, } if (!pMechanism) { - TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); - return CKR_MECHANISM_INVALID; + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + return CKR_ARGUMENTS_BAD; } if (!phKey) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); @@ -1607,8 +1802,8 @@ CK_RV C_GenerateKeyPair(CK_SESSION_HANDLE hSession, } if (!pMechanism) { - TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); - return CKR_MECHANISM_INVALID; + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + return CKR_ARGUMENTS_BAD; } if (!phPublicKey || !phPrivateKey) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); @@ -1728,12 +1923,12 @@ CK_RV C_GetAttributeValue(CK_SESSION_HANDLE hSession, } if (!pTemplate) { - TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); - return CKR_TEMPLATE_INCOMPLETE; + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + return CKR_ARGUMENTS_BAD; } if (ulCount == 0) { - TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); - return CKR_TEMPLATE_INCOMPLETE; + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + return CKR_ARGUMENTS_BAD; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); @@ -1774,84 +1969,13 @@ CK_RV C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList) api_init(); TRACE_INFO("C_GetFunctionList\n"); - FuncList.version.major = VERSION_MAJOR; - FuncList.version.minor = VERSION_MINOR; - FuncList.C_Initialize = C_Initialize; - FuncList.C_Finalize = C_Finalize; - FuncList.C_GetInfo = C_GetInfo; - FuncList.C_GetFunctionList = C_GetFunctionList; - FuncList.C_GetSlotList = C_GetSlotList; - FuncList.C_GetSlotInfo = C_GetSlotInfo; - FuncList.C_GetTokenInfo = C_GetTokenInfo; - FuncList.C_GetMechanismList = C_GetMechanismList; - FuncList.C_GetMechanismInfo = C_GetMechanismInfo; - FuncList.C_InitToken = C_InitToken; - FuncList.C_InitPIN = C_InitPIN; - FuncList.C_SetPIN = C_SetPIN; - FuncList.C_OpenSession = C_OpenSession; - FuncList.C_CloseSession = C_CloseSession; - FuncList.C_CloseAllSessions = C_CloseAllSessions; - FuncList.C_GetSessionInfo = C_GetSessionInfo; - FuncList.C_GetOperationState = C_GetOperationState; - FuncList.C_SetOperationState = C_SetOperationState; - FuncList.C_Login = C_Login; - FuncList.C_Logout = C_Logout; - FuncList.C_CreateObject = C_CreateObject; - FuncList.C_CopyObject = C_CopyObject; - FuncList.C_DestroyObject = C_DestroyObject; - FuncList.C_GetObjectSize = C_GetObjectSize; - FuncList.C_GetAttributeValue = C_GetAttributeValue; - FuncList.C_SetAttributeValue = C_SetAttributeValue; - FuncList.C_FindObjectsInit = C_FindObjectsInit; - FuncList.C_FindObjects = C_FindObjects; - FuncList.C_FindObjectsFinal = C_FindObjectsFinal; - FuncList.C_EncryptInit = C_EncryptInit; - FuncList.C_Encrypt = C_Encrypt; - FuncList.C_EncryptUpdate = C_EncryptUpdate; - FuncList.C_EncryptFinal = C_EncryptFinal; - FuncList.C_DecryptInit = C_DecryptInit; - FuncList.C_Decrypt = C_Decrypt; - FuncList.C_DecryptUpdate = C_DecryptUpdate; - FuncList.C_DecryptFinal = C_DecryptFinal; - FuncList.C_DigestInit = C_DigestInit; - FuncList.C_Digest = C_Digest; - FuncList.C_DigestUpdate = C_DigestUpdate; - FuncList.C_DigestKey = C_DigestKey; - FuncList.C_DigestFinal = C_DigestFinal; - FuncList.C_SignInit = C_SignInit; - FuncList.C_Sign = C_Sign; - FuncList.C_SignUpdate = C_SignUpdate; - FuncList.C_SignFinal = C_SignFinal; - FuncList.C_SignRecoverInit = C_SignRecoverInit; - FuncList.C_SignRecover = C_SignRecover; - FuncList.C_VerifyInit = C_VerifyInit; - FuncList.C_Verify = C_Verify; - FuncList.C_VerifyUpdate = C_VerifyUpdate; - FuncList.C_VerifyFinal = C_VerifyFinal; - FuncList.C_VerifyRecoverInit = C_VerifyRecoverInit; - FuncList.C_VerifyRecover = C_VerifyRecover; - FuncList.C_DigestEncryptUpdate = C_DigestEncryptUpdate; - FuncList.C_DecryptDigestUpdate = C_DecryptDigestUpdate; - FuncList.C_SignEncryptUpdate = C_SignEncryptUpdate; - FuncList.C_DecryptVerifyUpdate = C_DecryptVerifyUpdate; - FuncList.C_GenerateKey = C_GenerateKey; - FuncList.C_GenerateKeyPair = C_GenerateKeyPair; - FuncList.C_WrapKey = C_WrapKey; - FuncList.C_UnwrapKey = C_UnwrapKey; - FuncList.C_DeriveKey = C_DeriveKey; - FuncList.C_SeedRandom = C_SeedRandom; - FuncList.C_GenerateRandom = C_GenerateRandom; - FuncList.C_GetFunctionStatus = C_GetFunctionStatus; - FuncList.C_CancelFunction = C_CancelFunction; - FuncList.C_WaitForSlotEvent = C_WaitForSlotEvent; if (ppFunctionList) { - (*ppFunctionList) = &FuncList; + (*ppFunctionList) = &func_list_pkcs11_2_40; return CKR_OK; } TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); - return CKR_ARGUMENTS_BAD; } @@ -1896,8 +2020,8 @@ CK_RV C_GetInfo(CK_INFO_PTR pInfo) shData = &(Anchor->SocketDataP); if (!pInfo) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - return CKR_FUNCTION_FAILED; + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + return CKR_ARGUMENTS_BAD; } CK_Info_From_Internal(pInfo, &(shData->ck_info)); @@ -2216,23 +2340,23 @@ CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) shData = &(Anchor->SocketDataP); if (!pInfo) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - return CKR_FUNCTION_FAILED; + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + return CKR_ARGUMENTS_BAD; } - sinfp = shData->slot_info; - sinfp += slotID; - if (slotID >= NUMBER_SLOTS_MANAGED) { TRACE_ERROR("%s\n", ock_err(ERR_SLOT_ID_INVALID)); return CKR_SLOT_ID_INVALID; } + + sinfp = &shData->slot_info[slotID]; + // Netscape and others appear to call // this for every slot. If the slot does not have // a registered STDLL, then this is a FUnction Failed case if (sinfp->present == FALSE) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - return CKR_FUNCTION_FAILED; + TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); + return CKR_TOKEN_NOT_PRESENT; } #ifdef __64BIT__ @@ -2261,9 +2385,6 @@ CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { - uint16 count; - uint16 index; - uint16 sindx; Slot_Info_t *sinfp; Slot_Mgr_Socket_t *shData = &(Anchor->SocketDataP); @@ -2274,24 +2395,25 @@ CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) } if (!pInfo) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - return CKR_FUNCTION_FAILED; + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + return CKR_ARGUMENTS_BAD; } - sinfp = shData->slot_info; - sinfp += slotID; count = 0; if (slotID >= NUMBER_SLOTS_MANAGED) { TRACE_ERROR("%s\n", ock_err(ERR_SLOT_ID_INVALID)); return CKR_SLOT_ID_INVALID; } + + sinfp = &shData->slot_info[slotID]; + // Netscape and others appear to call // this for every slot. If the slot does not have // a registered STDLL, then this is a FUnction Failed case if (sinfp->present == FALSE) { - TRACE_ERROR("%s: No STDLL present.\n", ock_err(ERR_FUNCTION_FAILED)); - return CKR_FUNCTION_FAILED; + TRACE_ERROR("%s: No STDLL present.\n", ock_err(ERR_TOKEN_NOT_PRESENT)); + return CKR_TOKEN_NOT_PRESENT; } memcpy(pInfo, (char *) &(sinfp->pk_slot), sizeof(CK_SLOT_INFO)); @@ -2334,8 +2456,8 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, // Null pSlotList is valid to get count for array allocation if (pulCount == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - return CKR_FUNCTION_FAILED; + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + return CKR_ARGUMENTS_BAD; } TRACE_DEVEL(" Present %d Count %lu\n", tokenPresent, *pulCount); @@ -2557,6 +2679,11 @@ CK_RV C_Initialize(CK_VOID_PTR pVoid) // Clear out the load list memset(slot_loaded, 0, sizeof(int) * NUMBER_SLOTS_MANAGED); + // Zero out API_Proc_Struct + // 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)); + TRACE_DEBUG("Anchor allocated at %s\n", (char *) Anchor); // Validation of the parameters passed @@ -2653,12 +2780,10 @@ CK_RV C_Initialize(CK_VOID_PTR pVoid) rc = CKR_FUNCTION_FAILED; goto error; } - //Zero out API_Proc_Struct //Map Shared Memory Region //if ( Shared Memory Mapped not Successful ) // Free allocated Memory // Return CKR_HOST_MEMORY - memset((char *) Anchor, 0, sizeof(API_Proc_Struct_t)); bt_init(&Anchor->sess_btree, free); Anchor->Pid = getpid(); @@ -2875,14 +3000,11 @@ CK_RV C_Login(CK_SESSION_HANDLE hSession, TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } -#if 0 - /* Allow incorrect PIN checks to fall into the SC_Login - * function, since v2.11 requires flags to be set. - KEY - */ + if (!pPin) { - return CKR_PIN_INCORRECT; + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + return CKR_ARGUMENTS_BAD; } -#endif if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); @@ -3157,12 +3279,12 @@ CK_RV C_SetAttributeValue(CK_SESSION_HANDLE hSession, TRACE_INFO("Valid Session handle id: %lu\n", rSession.sessionh); if (!pTemplate) { - TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); - return CKR_TEMPLATE_INCOMPLETE; + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + return CKR_ARGUMENTS_BAD; } if (!ulCount) { - TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); - return CKR_TEMPLATE_INCOMPLETE; + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + return CKR_ARGUMENTS_BAD; } sltp = &(Anchor->SltList[rSession.slotID]); @@ -3268,8 +3390,10 @@ CK_RV C_SetPIN(CK_SESSION_HANDLE hSession, return CKR_CRYPTOKI_NOT_INITIALIZED; } - if (!pOldPin || !pNewPin) - return CKR_PIN_INVALID; + if (!pOldPin || !pNewPin) { + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + return CKR_ARGUMENTS_BAD; + } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); @@ -3492,8 +3616,8 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession, } if (!pMechanism) { - TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); - return CKR_MECHANISM_INVALID; + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + return CKR_ARGUMENTS_BAD; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); @@ -3595,8 +3719,8 @@ CK_RV C_SignRecoverInit(CK_SESSION_HANDLE hSession, } if (!pMechanism) { - TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); - return CKR_MECHANISM_INVALID; + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + return CKR_ARGUMENTS_BAD; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); @@ -3702,8 +3826,8 @@ CK_RV C_UnwrapKey(CK_SESSION_HANDLE hSession, } if (!pMechanism) { - TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); - return CKR_MECHANISM_INVALID; + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + return CKR_ARGUMENTS_BAD; } if (!phKey) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); @@ -3867,8 +3991,8 @@ CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession, } if (!pMechanism) { - TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); - return CKR_MECHANISM_INVALID; + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + return CKR_ARGUMENTS_BAD; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); @@ -3970,8 +4094,8 @@ CK_RV C_VerifyRecoverInit(CK_SESSION_HANDLE hSession, } if (!pMechanism) { - TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); - return CKR_MECHANISM_INVALID; + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + return CKR_ARGUMENTS_BAD; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); @@ -4215,8 +4339,8 @@ CK_RV C_WrapKey(CK_SESSION_HANDLE hSession, } if (!pMechanism) { - TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); - return CKR_MECHANISM_INVALID; + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + return CKR_ARGUMENTS_BAD; } // other pointers??? @@ -4249,6 +4373,712 @@ CK_RV C_WrapKey(CK_SESSION_HANDLE hSession, return rv; } +CK_RV C_GetInterfaceList(CK_INTERFACE_PTR pInterfaceList, + CK_ULONG_PTR pulCount) +{ + CK_ULONG nmemb; + CK_RV rv; + + TRACE_INFO("C_GetInterfaceList\n"); + + if (pulCount == NULL) { + rv = CKR_ARGUMENTS_BAD; + goto ret; + } + + nmemb = sizeof(interface_list) / sizeof(interface_list[0]); + + if (pInterfaceList == NULL) { + *pulCount = nmemb; + rv = CKR_OK; + goto ret; + } + + if (*pulCount < nmemb) { + *pulCount = nmemb; + rv = CKR_BUFFER_TOO_SMALL; + goto ret; + } + + memcpy(pInterfaceList, interface_list, sizeof(interface_list)); + rv = CKR_OK; + +ret: + return rv; +} + +CK_RV C_GetInterface(CK_UTF8CHAR_PTR pInterfaceName, + CK_VERSION_PTR pVersion, + CK_INTERFACE_PTR_PTR ppInterface, + CK_FLAGS flags) +{ + CK_INTERFACE *interf; + CK_RV rv; + size_t i; + + TRACE_INFO("C_GetInterface\n"); + + if (ppInterface == NULL) { + rv = CKR_ARGUMENTS_BAD; + goto ret; + } + + /* + * Returns the interface in interface_list that matches the arguments + * and is at lowest index. If no interface in interface_list matches + * the arguments, *ppInterface == NULL. + */ + *ppInterface = NULL; + for (i = 0; i < sizeof(interface_list) / sizeof(interface_list[0]); i++) { + interf = &interface_list[i]; + + if ((pInterfaceName == NULL + || (pInterfaceName != NULL + && strcmp((char *)pInterfaceName, (char *)interf->pInterfaceName) == 0)) + && (pVersion == NULL + || (pVersion->major == ((CK_VERSION *)interf->pFunctionList)->major + && pVersion->minor + == ((CK_VERSION *)interf->pFunctionList)->minor)) + && (flags == (interf->flags & flags))) { + *ppInterface = interf; + break; + } + } + + if (*ppInterface == NULL) { + rv = CKR_FUNCTION_FAILED; + goto ret; + } + + rv = CKR_OK; +ret: + return rv; +} + +CK_RV C_LoginUser(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, + CK_UTF8CHAR *pPin, CK_ULONG ulPinLen, + CK_UTF8CHAR *pUsername, CK_ULONG ulUsernameLen) +{ + CK_RV rv; + + UNUSED(hSession); + UNUSED(userType); + UNUSED(pPin); + UNUSED(ulPinLen); + UNUSED(pUsername); + UNUSED(ulUsernameLen); + + TRACE_INFO("C_LoginUser\n"); + + if (API_Initialized() == FALSE) { + TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); + rv = CKR_CRYPTOKI_NOT_INITIALIZED; + goto ret; + } + + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + rv = CKR_FUNCTION_NOT_SUPPORTED; +ret: + return rv; +} + +CK_RV C_SessionCancel(CK_SESSION_HANDLE hSession, CK_FLAGS flags) +{ + CK_RV rv; + + UNUSED(hSession); + UNUSED(flags); + + TRACE_INFO("C_SessionCancel\n"); + + if (API_Initialized() == FALSE) { + TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); + rv = CKR_CRYPTOKI_NOT_INITIALIZED; + goto ret; + } + + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + rv = CKR_FUNCTION_NOT_SUPPORTED; +ret: + return rv; +} + +CK_RV C_MessageEncryptInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM *pMechanism, CK_OBJECT_HANDLE hKey) +{ + CK_RV rv; + + UNUSED(hSession); + UNUSED(pMechanism); + UNUSED(hKey); + + TRACE_INFO("C_MessageEncryptInit\n"); + + if (API_Initialized() == FALSE) { + TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); + rv = CKR_CRYPTOKI_NOT_INITIALIZED; + goto ret; + } + + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + rv = CKR_FUNCTION_NOT_SUPPORTED; +ret: + return rv; +} + +CK_RV C_EncryptMessage(CK_SESSION_HANDLE hSession, + void *pParameter, CK_ULONG ulParameterLen, + CK_BYTE *pAssociatedData, CK_ULONG ulAssociatedDataLen, + CK_BYTE *pPlaintext, CK_ULONG ulPlaintextLen, + CK_BYTE *pCiphertext, CK_ULONG *pulCiphertextLen) +{ + CK_RV rv; + + UNUSED(hSession); + UNUSED(pParameter); + UNUSED(ulParameterLen); + UNUSED(pAssociatedData); + UNUSED(ulAssociatedDataLen); + UNUSED(pPlaintext); + UNUSED(ulPlaintextLen); + UNUSED(pCiphertext); + UNUSED(pulCiphertextLen); + + TRACE_INFO("C_EncryptMessage\n"); + + if (API_Initialized() == FALSE) { + TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); + rv = CKR_CRYPTOKI_NOT_INITIALIZED; + goto ret; + } + + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + rv = CKR_FUNCTION_NOT_SUPPORTED; +ret: + return rv; +} + +CK_RV C_EncryptMessageBegin(CK_SESSION_HANDLE hSession, + void *pParameter, CK_ULONG ulParameterLen, + CK_BYTE *pAssociatedData, + CK_ULONG ulAssociatedDataLen) +{ + CK_RV rv; + + UNUSED(hSession); + UNUSED(pParameter); + UNUSED(ulParameterLen); + UNUSED(pAssociatedData); + UNUSED(ulAssociatedDataLen); + + TRACE_INFO("C_EncryptMessageBegin\n"); + + if (API_Initialized() == FALSE) { + TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); + rv = CKR_CRYPTOKI_NOT_INITIALIZED; + goto ret; + } + + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + rv = CKR_FUNCTION_NOT_SUPPORTED; +ret: + return rv; +} + +CK_RV C_EncryptMessageNext(CK_SESSION_HANDLE hSession, + void *pParameter, CK_ULONG ulParameterLen, + CK_BYTE *pPlaintextPart, + CK_ULONG ulPlaintextPartLen, + CK_BYTE *pCiphertextPart, + CK_ULONG *pulCiphertextPartLen, + CK_ULONG flags) +{ + CK_RV rv; + + UNUSED(hSession); + UNUSED(pParameter); + UNUSED(ulParameterLen); + UNUSED(pPlaintextPart); + UNUSED(ulPlaintextPartLen); + UNUSED(pCiphertextPart); + UNUSED(pulCiphertextPartLen); + UNUSED(flags); + + TRACE_INFO("C_EncryptMessageNext\n"); + + if (API_Initialized() == FALSE) { + TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); + rv = CKR_CRYPTOKI_NOT_INITIALIZED; + goto ret; + } + + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + rv = CKR_FUNCTION_NOT_SUPPORTED; +ret: + return rv; +} + +CK_RV C_MessageEncryptFinal(CK_SESSION_HANDLE hSession) +{ + CK_RV rv; + + UNUSED(hSession); + + TRACE_INFO("C_EncryptMessageFinal\n"); + + if (API_Initialized() == FALSE) { + TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); + rv = CKR_CRYPTOKI_NOT_INITIALIZED; + goto ret; + } + + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + rv = CKR_FUNCTION_NOT_SUPPORTED; +ret: + return rv; +} + +CK_RV C_MessageDecryptInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM *pMechanism, CK_OBJECT_HANDLE hKey) +{ + CK_RV rv; + + UNUSED(hSession); + UNUSED(pMechanism); + UNUSED(hKey); + + TRACE_INFO("C_MessageDecryptInit\n"); + + if (API_Initialized() == FALSE) { + TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); + rv = CKR_CRYPTOKI_NOT_INITIALIZED; + goto ret; + } + + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + rv = CKR_FUNCTION_NOT_SUPPORTED; +ret: + return rv; +} + +CK_RV C_DecryptMessage(CK_SESSION_HANDLE hSession, + void *pParameter, CK_ULONG ulParameterLen, + CK_BYTE *pAssociatedData, CK_ULONG ulAssociatedDataLen, + CK_BYTE *pCiphertext, CK_ULONG ulCiphertextLen, + CK_BYTE *pPlaintext, CK_ULONG *pulPlaintextLen) +{ + CK_RV rv; + + UNUSED(hSession); + UNUSED(pParameter); + UNUSED(ulParameterLen); + UNUSED(pAssociatedData); + UNUSED(ulAssociatedDataLen); + UNUSED(pCiphertext); + UNUSED(ulCiphertextLen); + UNUSED(pPlaintext); + UNUSED(pulPlaintextLen); + + TRACE_INFO("C_DecryptMessage\n"); + + if (API_Initialized() == FALSE) { + TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); + rv = CKR_CRYPTOKI_NOT_INITIALIZED; + goto ret; + } + + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + rv = CKR_FUNCTION_NOT_SUPPORTED; +ret: + return rv; +} + +CK_RV C_DecryptMessageBegin(CK_SESSION_HANDLE hSession, + void *pParameter, CK_ULONG ulParameterLen, + CK_BYTE *pAssociatedData, + CK_ULONG ulAssociatedDataLen) +{ + CK_RV rv; + + UNUSED(hSession); + UNUSED(pParameter); + UNUSED(ulParameterLen); + UNUSED(pAssociatedData); + UNUSED(ulAssociatedDataLen); + + TRACE_INFO("C_DecryptMessageBegin\n"); + + if (API_Initialized() == FALSE) { + TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); + rv = CKR_CRYPTOKI_NOT_INITIALIZED; + goto ret; + } + + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + rv = CKR_FUNCTION_NOT_SUPPORTED; +ret: + return rv; +} + +CK_RV C_DecryptMessageNext(CK_SESSION_HANDLE hSession, + void *pParameter, CK_ULONG ulParameterLen, + CK_BYTE *pCiphertextPart, + CK_ULONG ulCiphertextPartLen, + CK_BYTE *pPlaintextPart, + CK_ULONG *pulPlaintextPartLen, + CK_FLAGS flags) +{ + CK_RV rv; + + UNUSED(hSession); + UNUSED(pParameter); + UNUSED(ulParameterLen); + UNUSED(pCiphertextPart); + UNUSED(ulCiphertextPartLen); + UNUSED(pPlaintextPart); + UNUSED(pulPlaintextPartLen); + UNUSED(flags); + + TRACE_INFO("C_DecryptMessageNext\n"); + + if (API_Initialized() == FALSE) { + TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); + rv = CKR_CRYPTOKI_NOT_INITIALIZED; + goto ret; + } + + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + rv = CKR_FUNCTION_NOT_SUPPORTED; +ret: + return rv; +} + +CK_RV C_MessageDecryptFinal(CK_SESSION_HANDLE hSession) +{ + CK_RV rv; + + UNUSED(hSession); + + TRACE_INFO("C_MessageDecryptFinal\n"); + + if (API_Initialized() == FALSE) { + TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); + rv = CKR_CRYPTOKI_NOT_INITIALIZED; + goto ret; + } + + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + rv = CKR_FUNCTION_NOT_SUPPORTED; +ret: + return rv; +} + +CK_RV C_MessageSignInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM *pMechanism, CK_OBJECT_HANDLE hKey) +{ + CK_RV rv; + + UNUSED(hSession); + UNUSED(pMechanism); + UNUSED(hKey); + + TRACE_INFO("C_MessageSignInit\n"); + + if (API_Initialized() == FALSE) { + TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); + rv = CKR_CRYPTOKI_NOT_INITIALIZED; + goto ret; + } + + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + rv = CKR_FUNCTION_NOT_SUPPORTED; +ret: + return rv; +} + +CK_RV C_SignMessage(CK_SESSION_HANDLE hSession, + void *pParameter, CK_ULONG ulParameterLen, + CK_BYTE *pData, CK_ULONG ulDataLen, + CK_BYTE *pSignature, CK_ULONG *pulSignatureLen) +{ + CK_RV rv; + + UNUSED(hSession); + UNUSED(pParameter); + UNUSED(ulParameterLen); + UNUSED(pData); + UNUSED(ulDataLen); + UNUSED(pSignature); + UNUSED(pulSignatureLen); + + TRACE_INFO("C_SignMessage\n"); + + if (API_Initialized() == FALSE) { + TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); + rv = CKR_CRYPTOKI_NOT_INITIALIZED; + goto ret; + } + + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + rv = CKR_FUNCTION_NOT_SUPPORTED; +ret: + return rv; +} + +CK_RV C_SignMessageBegin(CK_SESSION_HANDLE hSession, + void *pParameter, CK_ULONG ulParameterLen) +{ + CK_RV rv; + + UNUSED(hSession); + UNUSED(pParameter); + UNUSED(ulParameterLen); + + TRACE_INFO("C_SignMessageBegin\n"); + + if (API_Initialized() == FALSE) { + TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); + rv = CKR_CRYPTOKI_NOT_INITIALIZED; + goto ret; + } + + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + rv = CKR_FUNCTION_NOT_SUPPORTED; +ret: + return rv; +} + +CK_RV C_SignMessageNext(CK_SESSION_HANDLE hSession, + void *pParameter, CK_ULONG ulParameterLen, + CK_BYTE *pDataPart, CK_ULONG ulDataPartLen, + CK_BYTE *pSignature, CK_ULONG *pulSignatureLen) +{ + CK_RV rv; + + UNUSED(hSession); + UNUSED(pParameter); + UNUSED(ulParameterLen); + UNUSED(pDataPart); + UNUSED(ulDataPartLen); + UNUSED(pSignature); + UNUSED(pulSignatureLen); + + TRACE_INFO("C_SignMessageNext\n"); + + if (API_Initialized() == FALSE) { + TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); + rv = CKR_CRYPTOKI_NOT_INITIALIZED; + goto ret; + } + + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + rv = CKR_FUNCTION_NOT_SUPPORTED; +ret: + return rv; +} + +CK_RV C_MessageSignFinal(CK_SESSION_HANDLE hSession) +{ + CK_RV rv; + + UNUSED(hSession); + + TRACE_INFO("C_MessageSignFinal\n"); + + if (API_Initialized() == FALSE) { + TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); + rv = CKR_CRYPTOKI_NOT_INITIALIZED; + goto ret; + } + + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + rv = CKR_FUNCTION_NOT_SUPPORTED; +ret: + return rv; +} + +CK_RV C_MessageVerifyInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM *pMechanism, CK_OBJECT_HANDLE hKey) +{ + CK_RV rv; + + UNUSED(hSession); + UNUSED(pMechanism); + UNUSED(hKey); + + TRACE_INFO("C_MessageVerifyInit\n"); + + if (API_Initialized() == FALSE) { + TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); + rv = CKR_CRYPTOKI_NOT_INITIALIZED; + goto ret; + } + + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + rv = CKR_FUNCTION_NOT_SUPPORTED; +ret: + return rv; +} + +CK_RV C_VerifyMessage(CK_SESSION_HANDLE hSession, + void *pParameter, CK_ULONG ulParameterLen, + CK_BYTE *pData, CK_ULONG ulDataLen, + CK_BYTE *pSignature, CK_ULONG ulSignatureLen) +{ + CK_RV rv; + + UNUSED(hSession); + UNUSED(pParameter); + UNUSED(ulParameterLen); + UNUSED(pData); + UNUSED(ulDataLen); + UNUSED(pSignature); + UNUSED(ulSignatureLen); + + TRACE_INFO("C_VerifyMessage\n"); + + if (API_Initialized() == FALSE) { + TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); + rv = CKR_CRYPTOKI_NOT_INITIALIZED; + goto ret; + } + + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + rv = CKR_FUNCTION_NOT_SUPPORTED; +ret: + return rv; +} + +CK_RV C_VerifyMessageBegin(CK_SESSION_HANDLE hSession, + void *pParameter, CK_ULONG ulParameterLen) +{ + CK_RV rv; + + + UNUSED(hSession); + UNUSED(pParameter); + UNUSED(ulParameterLen); + + TRACE_INFO("C_VerifyMessageBegin\n"); + + if (API_Initialized() == FALSE) { + TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); + rv = CKR_CRYPTOKI_NOT_INITIALIZED; + goto ret; + } + + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + rv = CKR_FUNCTION_NOT_SUPPORTED; +ret: + return rv; +} + +CK_RV C_VerifyMessageNext(CK_SESSION_HANDLE hSession, + void *pParameter, CK_ULONG ulParameterLen, + CK_BYTE *pDataPart, CK_ULONG ulDataPartLen, + CK_BYTE *pSignature, CK_ULONG ulSignatureLen) +{ + CK_RV rv; + + UNUSED(hSession); + UNUSED(pParameter); + UNUSED(ulParameterLen); + UNUSED(pDataPart); + UNUSED(ulDataPartLen); + UNUSED(pSignature); + UNUSED(ulSignatureLen); + + TRACE_INFO("C_VerifyMessageNext\n"); + + if (API_Initialized() == FALSE) { + TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); + rv = CKR_CRYPTOKI_NOT_INITIALIZED; + goto ret; + } + + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + rv = CKR_FUNCTION_NOT_SUPPORTED; +ret: + return rv; +} + +CK_RV C_MessageVerifyFinal(CK_SESSION_HANDLE hSession) +{ + CK_RV rv; + + UNUSED(hSession); + + TRACE_INFO("C_VerifyMessageFinal\n"); + + if (API_Initialized() == FALSE) { + TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); + rv = CKR_CRYPTOKI_NOT_INITIALIZED; + goto ret; + } + + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + rv = CKR_FUNCTION_NOT_SUPPORTED; +ret: + return rv; +} + +CK_RV C_IBM_ReencryptSingle(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pDecrMech, + CK_OBJECT_HANDLE hDecrKey, + CK_MECHANISM_PTR pEncrMech, + CK_OBJECT_HANDLE hEncrKey, + CK_BYTE_PTR pEncryptedData, + CK_ULONG ulEncryptedDataLen, + CK_BYTE_PTR pReencryptedData, + CK_ULONG_PTR pulReencryptedDataLen) +{ + CK_RV rv; + API_Slot_t *sltp; + STDLL_FcnList_t *fcn; + ST_SESSION_T rSession; + + TRACE_INFO("C_IBM_ReencryptSingle\n"); + if (API_Initialized() == FALSE) { + TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); + return CKR_CRYPTOKI_NOT_INITIALIZED; + } + + if (!pDecrMech || !pDecrMech) { + TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); + return CKR_MECHANISM_INVALID; + } + if (!Valid_Session(hSession, &rSession)) { + TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); + TRACE_ERROR("Session handle id: %lu\n", hSession); + return CKR_SESSION_HANDLE_INVALID; + } + TRACE_INFO("Valid Session handle id: %lu\n", rSession.sessionh); + + sltp = &(Anchor->SltList[rSession.slotID]); + if (sltp->DLLoaded == FALSE) { + TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); + return CKR_TOKEN_NOT_PRESENT; + } + if ((fcn = sltp->FcnList) == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); + return CKR_TOKEN_NOT_PRESENT; + } + if (fcn->ST_IBM_ReencryptSingle) { + // Map the Session to the slot session + rv = fcn->ST_IBM_ReencryptSingle(sltp->TokData, &rSession, pDecrMech, + hDecrKey, pEncrMech, hEncrKey, + pEncryptedData, ulEncryptedDataLen, + pReencryptedData, + pulReencryptedDataLen); + TRACE_DEVEL("fcn->ST_IBM_ReencryptSingle returned: 0x%lx\n", rv); + } else { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); + rv = CKR_FUNCTION_NOT_SUPPORTED; + } + + return rv; +} + #ifdef __sun #pragma init(api_init) #else diff --git a/usr/lib/cca_stdll/cca_func.h b/usr/lib/cca_stdll/cca_func.h index 65fa876..4696302 100644 --- a/usr/lib/cca_stdll/cca_func.h +++ b/usr/lib/cca_stdll/cca_func.h @@ -1276,3 +1276,29 @@ typedef void (*CSNBHMV_t) (long *return_code, long *chaining_vector_length, unsigned char *chaining_vector, long *MAC_length, unsigned char *MAC_text); + +/* Cipher Text Translate 2 */ +typedef void (*CSNBCTT2_t)(long *return_code, + long *reason_code, + long *exit_data_length, + unsigned char *exit_data, + long *rule_array_count, + unsigned char *rule_array, + long *key_identifier_in_length, + unsigned char *key_identifier_in, + long *init_vector_in_length, + unsigned char *init_vector_in, + long *cipher_text_in_length, + unsigned char *cipher_text_in, + long *chaining_vector_length, + unsigned char *chaining_vector, + long *key_identifier_out_length, + unsigned char *key_identifier_out, + long *init_vector_out_length, + unsigned char *init_vector_out, + long *cipher_text_out_length, + unsigned char *cipher_text_out, + long *reserved1_length, + unsigned long *reserved1, + long *reserved2_length, + unsigned char *reserved2); diff --git a/usr/lib/cca_stdll/cca_specific.c b/usr/lib/cca_stdll/cca_specific.c index fbc3a90..4f6767b 100644 --- a/usr/lib/cca_stdll/cca_specific.c +++ b/usr/lib/cca_stdll/cca_specific.c @@ -165,6 +165,7 @@ static CSNDRKX_t dll_CSNDRKX; static CSNBKET_t dll_CSNBKET; static CSNBHMG_t dll_CSNBHMG; static CSNBHMV_t dll_CSNBHMV; +static CSNBCTT2_t dll_CSNBCTT2; /* mechanisms provided by this token */ static const MECH_LIST_ELEMENT cca_mech_list[] = { @@ -172,10 +173,21 @@ static const MECH_LIST_ELEMENT cca_mech_list[] = { {CKM_DES3_KEY_GEN, {24, 24, CKF_HW | CKF_GENERATE}}, {CKM_RSA_PKCS_KEY_PAIR_GEN, {512, 4096, CKF_HW | CKF_GENERATE_KEY_PAIR}}, {CKM_RSA_PKCS, {512, 4096, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_SIGN | - CKF_VERIFY}}, + CKF_VERIFY | CKF_WRAP | CKF_UNWRAP}}, {CKM_MD5_RSA_PKCS, {512, 4096, CKF_HW | CKF_SIGN | CKF_VERIFY}}, {CKM_SHA1_RSA_PKCS, {512, 4096, CKF_HW | CKF_SIGN | CKF_VERIFY}}, + {CKM_SHA224_RSA_PKCS, {512, 4096, CKF_HW | CKF_SIGN | CKF_VERIFY}}, {CKM_SHA256_RSA_PKCS, {512, 4096, CKF_HW | CKF_SIGN | CKF_VERIFY}}, + {CKM_SHA384_RSA_PKCS, {512, 4096, CKF_HW | CKF_SIGN | CKF_VERIFY}}, + {CKM_SHA512_RSA_PKCS, {512, 4096, CKF_HW | CKF_SIGN | CKF_VERIFY}}, + {CKM_RSA_PKCS_PSS, {512, 4096, CKF_HW | CKF_SIGN | CKF_VERIFY}}, + {CKM_SHA1_RSA_PKCS_PSS, {512, 4096, CKF_HW | CKF_SIGN | CKF_VERIFY}}, + {CKM_SHA224_RSA_PKCS_PSS, {512, 4096, CKF_HW | CKF_SIGN | CKF_VERIFY}}, + {CKM_SHA256_RSA_PKCS_PSS, {512, 4096, CKF_HW | CKF_SIGN | CKF_VERIFY}}, + {CKM_SHA384_RSA_PKCS_PSS, {512, 4096, CKF_HW | CKF_SIGN | CKF_VERIFY}}, + {CKM_SHA512_RSA_PKCS_PSS, {512, 4096, CKF_HW | CKF_SIGN | CKF_VERIFY}}, + {CKM_RSA_PKCS_OAEP, {512, 4096, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | + CKF_WRAP | CKF_UNWRAP}}, {CKM_DES_CBC, {8, 8, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT}}, {CKM_DES_CBC_PAD, @@ -212,16 +224,12 @@ static const MECH_LIST_ELEMENT cca_mech_list[] = { CKF_EC_F_P}}, {CKM_ECDSA_SHA1, {160, 521, CKF_HW | CKF_SIGN | CKF_VERIFY | CKF_EC_NAMEDCURVE | CKF_EC_F_P}}, - {CKM_GENERIC_SECRET_KEY_GEN, {80, 2048, CKF_HW | CKF_GENERATE}}, {CKM_ECDSA_SHA224, {160, 521, CKF_HW | CKF_SIGN | CKF_VERIFY | CKF_EC_NAMEDCURVE | CKF_EC_F_P}}, - {CKM_GENERIC_SECRET_KEY_GEN, {80, 2048, CKF_HW | CKF_GENERATE}}, {CKM_ECDSA_SHA256, {160, 521, CKF_HW | CKF_SIGN | CKF_VERIFY | CKF_EC_NAMEDCURVE | CKF_EC_F_P}}, - {CKM_GENERIC_SECRET_KEY_GEN, {80, 2048, CKF_HW | CKF_GENERATE}}, {CKM_ECDSA_SHA384, {160, 521, CKF_HW | CKF_SIGN | CKF_VERIFY | CKF_EC_NAMEDCURVE | CKF_EC_F_P}}, - {CKM_GENERIC_SECRET_KEY_GEN, {80, 2048, CKF_HW | CKF_GENERATE}}, {CKM_ECDSA_SHA512, {160, 521, CKF_HW | CKF_SIGN | CKF_VERIFY | CKF_EC_NAMEDCURVE | CKF_EC_F_P}}, {CKM_GENERIC_SECRET_KEY_GEN, {80, 2048, CKF_HW | CKF_GENERATE}} @@ -368,6 +376,7 @@ static CK_RV cca_resolve_lib_sym(void *hdl) *(void **)(&dll_CSNBKET) = dlsym(hdl, "CSNBKET"); *(void **)(&dll_CSNBHMG) = dlsym(hdl, "CSNBHMG"); *(void **)(&dll_CSNBHMV) = dlsym(hdl, "CSNBHMV"); + *(void **)(&dll_CSNBCTT2) = dlsym(hdl, "CSNBCTT2"); if ((error = dlerror()) != NULL) { OCK_SYSLOG(LOG_ERR, "%s\n", error); @@ -508,22 +517,25 @@ static CK_RV cca_key_gen(enum cca_key_type type, CK_BYTE * key, return CKR_OK; } -CK_RV token_specific_des_key_gen(STDLL_TokData_t * tokdata, CK_BYTE * des_key, - CK_ULONG len, CK_ULONG keysize) +CK_RV token_specific_des_key_gen(STDLL_TokData_t *tokdata, CK_BYTE **des_key, + CK_ULONG *len, CK_ULONG keysize, + CK_BBOOL *is_opaque) { unsigned char key_form[CCA_KEYWORD_SIZE]; unsigned char key_type_1[CCA_KEYWORD_SIZE]; UNUSED(tokdata); - /* make sure key is the right size for the token */ - if (len != CCA_KEY_ID_SIZE) - return CKR_FUNCTION_FAILED; + *des_key = calloc(CCA_KEY_ID_SIZE, 1); + if (*des_key == NULL) + return CKR_HOST_MEMORY; + *len = CCA_KEY_ID_SIZE; + *is_opaque = TRUE; memcpy(key_form, "OP ", (size_t) CCA_KEYWORD_SIZE); memcpy(key_type_1, "DATA ", (size_t) CCA_KEYWORD_SIZE); - return cca_key_gen(CCA_DES_KEY, des_key, key_form, key_type_1, keysize); + return cca_key_gen(CCA_DES_KEY, *des_key, key_form, key_type_1, keysize); } @@ -686,11 +698,9 @@ uint16_t cca_inttok_privkey_get_len(CK_BYTE * tok) /* Given a CCA internal token private key object, get the modulus */ CK_RV cca_inttok_privkey_get_n(CK_BYTE * tok, CK_ULONG * n_len, CK_BYTE * n) { - uint16_t privkey_length, n_length; - uint32_t privkey_n_offset; + uint16_t n_length; - privkey_length = *(uint16_t *) & tok[CCA_RSA_INTTOK_PRIVKEY_LENGTH_OFFSET]; - n_length = *(uint16_t *) & tok[CCA_RSA_INTTOK_PRIVKEY_N_LENGTH_OFFSET]; + n_length = *(uint16_t *) &tok[CCA_RSA_INTTOK_PRIVKEY_N_LENGTH_OFFSET]; if (n_length > (*n_len)) { TRACE_ERROR("Not enough room to return n.(Got %lu, need %hu)\n", @@ -698,9 +708,7 @@ CK_RV cca_inttok_privkey_get_n(CK_BYTE * tok, CK_ULONG * n_len, CK_BYTE * n) return CKR_FUNCTION_FAILED; } - privkey_n_offset = privkey_length - n_length; - - memcpy(n, &tok[privkey_n_offset], (size_t) n_length); + memcpy(n, &tok[CCA_RSA_INTTOK_PRIVKEY_N_OFFSET], (size_t) n_length); *n_len = n_length; return CKR_OK; @@ -898,7 +906,7 @@ CK_RV token_specific_rsa_generate_keypair(STDLL_TokData_t * tokdata, } rule_array_count = 2; - memcpy(rule_array, "RSA-CRT KEY-MGMT", (size_t) (CCA_KEYWORD_SIZE * 2)); + memcpy(rule_array, "RSA-AESCKEY-MGMT", (size_t) (CCA_KEYWORD_SIZE * 2)); private_key_name_length = 0; @@ -1082,6 +1090,231 @@ CK_RV token_specific_rsa_decrypt(STDLL_TokData_t * tokdata, return CKR_OK; } +CK_RV token_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) +{ + CK_RSA_PKCS_OAEP_PARAMS *oaep; + long return_code, reason_code, rule_array_count, data_structure_length; + unsigned char rule_array[CCA_RULE_ARRAY_SIZE] = { 0, }; + CK_ATTRIBUTE *attr; + OBJECT *key_obj = NULL; + CK_RV rc; + + UNUSED(tokdata); + UNUSED(hash); + UNUSED(hlen); + + 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"); + goto done; + } + + /* Find the secure key token */ + if (!template_attribute_find(key_obj->template, CKA_IBM_OPAQUE, &attr)) { + TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); + rc = CKR_TEMPLATE_INCOMPLETE; + goto done; + } + + oaep = (CK_RSA_PKCS_OAEP_PARAMS *)ctx->mech.pParameter; + if (oaep == NULL || + ctx->mech.ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS)) { + TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); + rc = CKR_MECHANISM_PARAM_INVALID; + goto done; + } + + if (oaep->source == CKZ_DATA_SPECIFIED && oaep->ulSourceDataLen > 0) { + TRACE_ERROR("CCA does not support non-empty OAEP source data\n"); + rc = CKR_MECHANISM_PARAM_INVALID; + goto done; + } + + /* The max value allowable by CCA for out_data_len is 512, so cap the + * incoming value if its too large. CCA will throw error 8, 72 otherwise. + */ + if (*out_data_len > 512) + *out_data_len = 512; + + rule_array_count = 2; + switch (oaep->hashAlg) { + case CKM_SHA_1: + if (oaep->mgf != CKG_MGF1_SHA1) { + TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); + rc = CKR_MECHANISM_PARAM_INVALID; + goto done; + } + memcpy(rule_array, "PKCSOAEPSHA-1 ", 2 * CCA_KEYWORD_SIZE); + break; + + case CKM_SHA256: + if (oaep->mgf != CKG_MGF1_SHA256) { + TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); + rc = CKR_MECHANISM_PARAM_INVALID; + goto done; + } + memcpy(rule_array, "PKCSOAEPSHA-256 ", 2 * CCA_KEYWORD_SIZE); + break; + + default: + TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); + rc = CKR_MECHANISM_PARAM_INVALID; + goto done; + } + + data_structure_length = 0; + + dll_CSNDPKE(&return_code, + &reason_code, + NULL, NULL, + &rule_array_count, + rule_array, + (long *)&in_data_len, + in_data, + &data_structure_length, // must be 0 + NULL, // ignored + (long *)&(attr->ulValueLen), + attr->pValue, + (long *)out_data_len, + out_data); + + if (return_code != CCA_SUCCESS) { + TRACE_ERROR("CSNDPKE (RSA ENCRYPT) failed. return:%ld, reason:%ld\n", + return_code, reason_code); + rc = CKR_FUNCTION_FAILED; + goto done; + } else if (reason_code != 0) { + TRACE_WARNING("CSNDPKE (RSA ENCRYPT) succeeded, but" + " returned reason:%ld\n", reason_code); + } + +done: + object_put(tokdata, key_obj, TRUE); + key_obj = NULL; + + return rc; +} + +CK_RV token_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) +{ + CK_RSA_PKCS_OAEP_PARAMS *oaep; + long return_code, reason_code, rule_array_count, data_structure_length; + unsigned char rule_array[CCA_RULE_ARRAY_SIZE] = { 0, }; + CK_ATTRIBUTE *attr; + OBJECT *key_obj = NULL; + CK_RV rc; + + UNUSED(tokdata); + UNUSED(hash); + UNUSED(hlen); + + 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"); + goto done; + } + + /* Find the secure key token */ + if (!template_attribute_find(key_obj->template, CKA_IBM_OPAQUE, &attr)) { + TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); + rc = CKR_TEMPLATE_INCOMPLETE; + goto done; + } + + oaep = (CK_RSA_PKCS_OAEP_PARAMS *)ctx->mech.pParameter; + if (oaep == NULL || + ctx->mech.ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS)) { + TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); + rc = CKR_MECHANISM_PARAM_INVALID; + goto done; + } + + if (oaep->source == CKZ_DATA_SPECIFIED && oaep->ulSourceDataLen > 0) { + TRACE_ERROR("CCA does not support non-empty OAEP source data\n"); + rc = CKR_MECHANISM_PARAM_INVALID; + goto done; + } + + /* The max value allowable by CCA for out_data_len is 512, so cap the + * incoming value if its too large. CCA will throw error 8, 72 otherwise. + */ + if (*out_data_len > 512) + *out_data_len = 512; + + rule_array_count = 2; + switch (oaep->hashAlg) { + case CKM_SHA_1: + if (oaep->mgf != CKG_MGF1_SHA1) { + TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); + rc = CKR_MECHANISM_PARAM_INVALID; + goto done; + } + memcpy(rule_array, "PKCSOAEPSHA-1 ", 2 * CCA_KEYWORD_SIZE); + break; + + case CKM_SHA256: + if (oaep->mgf != CKG_MGF1_SHA256) { + TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); + rc = CKR_MECHANISM_PARAM_INVALID; + goto done; + } + memcpy(rule_array, "PKCSOAEPSHA-256 ", 2 * CCA_KEYWORD_SIZE); + break; + + default: + TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); + rc = CKR_MECHANISM_PARAM_INVALID; + goto done; + } + + data_structure_length = 0; + + dll_CSNDPKD(&return_code, + &reason_code, + NULL, + NULL, + &rule_array_count, + rule_array, + (long *)&in_data_len, + in_data, + &data_structure_length, // must be 0 + NULL, // ignored + (long *) &(attr->ulValueLen), + attr->pValue, + (long *)out_data_len, + out_data); + + if (return_code != CCA_SUCCESS) { + TRACE_ERROR("CSNDPKD (RSA DECRYPT) failed. return:%ld, reason:%ld\n", + return_code, reason_code); + rc = CKR_FUNCTION_FAILED; + goto done; + } else if (reason_code != 0) { + TRACE_WARNING("CSNDPKD (RSA DECRYPT) succeeded, but" + " returned reason:%ld\n", reason_code); + } + +done: + object_put(tokdata, key_obj, TRUE); + key_obj = NULL; + + return rc; +} + CK_RV token_specific_rsa_sign(STDLL_TokData_t * tokdata, SESSION * sess, CK_BYTE * in_data, @@ -1171,15 +1404,287 @@ CK_RV token_specific_rsa_verify(STDLL_TokData_t * tokdata, NULL, &rule_array_count, rule_array, - (long *) &(attr->ulValueLen), + (long *) &(attr->ulValueLen), + attr->pValue, + (long *) &in_data_len, + in_data, (long *) &out_data_len, out_data); + + if (return_code == 4 && reason_code == 429) { + return CKR_SIGNATURE_INVALID; + } else if (return_code != CCA_SUCCESS) { + TRACE_ERROR("CSNDDSV (RSA VERIFY) failed. return:%ld, reason:%ld\n", + return_code, reason_code); + if (return_code == 8 && reason_code == 72) { + /* + * Return CKR_SIGNATURE_INVALID in case of return code 8 and + * reason code 72 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. + */ + return CKR_SIGNATURE_INVALID; + } + return CKR_FUNCTION_FAILED; + } + + if (reason_code != 0) { + TRACE_WARNING("CSNDDSV (RSA VERIFY) succeeded, but" + " returned reason:%ld\n", reason_code); + } + return CKR_OK; +} + +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 *out_data, + CK_ULONG *out_data_len) +{ + CK_RSA_PKCS_PSS_PARAMS *pss; + long return_code, reason_code, rule_array_count; + unsigned char rule_array[CCA_RULE_ARRAY_SIZE] = { 0, }; + long signature_bit_length, message_len; + CK_ATTRIBUTE *attr; + OBJECT *key_obj = NULL; + CK_BYTE *message = NULL; + CK_RV rc; + + UNUSED(tokdata); + UNUSED(sess); + + 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"); + goto done; + } + + /* Find the secure key token */ + if (!template_attribute_find(key_obj->template, CKA_IBM_OPAQUE, &attr)) { + TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); + rc = CKR_TEMPLATE_INCOMPLETE; + goto done; + } + + pss = (CK_RSA_PKCS_PSS_PARAMS *)ctx->mech.pParameter; + if (pss == NULL || + ctx->mech.ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS)) { + TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); + rc = CKR_MECHANISM_PARAM_INVALID; + goto done; + } + + message_len = 4 + in_data_len; + message = malloc(message_len); + if (message == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + rc = CKR_HOST_MEMORY; + goto done; + } + + *((uint32_t *)message) = htonl(pss->sLen); + memcpy(message + 4, in_data, in_data_len); + + /* The max value allowable by CCA for out_data_len is 512, so cap the + * incoming value if its too large. CCA will throw error 8, 72 otherwise. + */ + if (*out_data_len > 512) + *out_data_len = 512; + + rule_array_count = 2; + switch (pss->hashAlg) { + case CKM_SHA_1: + if (pss->mgf != CKG_MGF1_SHA1) { + TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); + rc = CKR_MECHANISM_PARAM_INVALID; + goto done; + } + memcpy(rule_array, "PKCS-PSSSHA-1 ", 2 * CCA_KEYWORD_SIZE); + break; + case CKM_SHA224: + if (pss->mgf != CKG_MGF1_SHA224) { + TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); + rc = CKR_MECHANISM_PARAM_INVALID; + goto done; + } + memcpy(rule_array, "PKCS-PSSSHA-224 ", 2 * CCA_KEYWORD_SIZE); + break; + case CKM_SHA256: + if (pss->mgf != CKG_MGF1_SHA256) { + TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); + rc = CKR_MECHANISM_PARAM_INVALID; + goto done; + } + memcpy(rule_array, "PKCS-PSSSHA-256 ", 2 * CCA_KEYWORD_SIZE); + break; + case CKM_SHA384: + if (pss->mgf != CKG_MGF1_SHA384) { + TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); + rc = CKR_MECHANISM_PARAM_INVALID; + goto done; + } + memcpy(rule_array, "PKCS-PSSSHA-384 ", 2 * CCA_KEYWORD_SIZE); + break; + case CKM_SHA512: + if (pss->mgf != CKG_MGF1_SHA512) { + TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); + rc = CKR_MECHANISM_PARAM_INVALID; + goto done; + } + memcpy(rule_array, "PKCS-PSSSHA-512 ", 2 * CCA_KEYWORD_SIZE); + break; + } + + dll_CSNDDSG(&return_code, + &reason_code, + NULL, + NULL, + &rule_array_count, + rule_array, + (long *)&(attr->ulValueLen), + attr->pValue, + &message_len, + message, + (long *)out_data_len, &signature_bit_length, out_data); + + if (return_code != CCA_SUCCESS) { + TRACE_ERROR("CSNDDSG (RSA PSS SIGN) failed. return :%ld, reason: %ld\n", + return_code, reason_code); + rc = CKR_FUNCTION_FAILED; + goto done; + } else if (reason_code != 0) { + TRACE_WARNING("CSNDDSG (RSA PSS SIGN) succeeded, but " + "returned reason: %ld\n", reason_code); + } + +done: + object_put(tokdata, key_obj, TRUE); + key_obj = NULL; + + if (message != NULL) + free(message); + + 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 *out_data, + CK_ULONG out_data_len) +{ + CK_RSA_PKCS_PSS_PARAMS *pss; + long return_code, reason_code, rule_array_count, message_len; + unsigned char rule_array[CCA_RULE_ARRAY_SIZE] = { 0, }; + CK_ATTRIBUTE *attr; + OBJECT *key_obj = NULL; + CK_BYTE *message = NULL; + CK_RV rc; + + UNUSED(tokdata); + UNUSED(sess); + + 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"); + goto done; + } + + /* Find the secure key token */ + if (!template_attribute_find(key_obj->template, CKA_IBM_OPAQUE, &attr)) { + TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); + rc = CKR_TEMPLATE_INCOMPLETE; + goto done; + } + + pss = (CK_RSA_PKCS_PSS_PARAMS *)ctx->mech.pParameter; + if (pss == NULL || + ctx->mech.ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS)) { + TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); + rc = CKR_MECHANISM_PARAM_INVALID; + goto done; + } + + message_len = 4 + in_data_len; + message = malloc(message_len); + if (message == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + rc = CKR_HOST_MEMORY; + goto done; + } + + *((uint32_t *)message) = pss->sLen; + memcpy(message + 4, in_data, in_data_len); + + /* The max value allowable by CCA for out_data_len is 512, so cap the + * incoming value if its too large. CCA will throw error 8, 72 otherwise. + */ + if (out_data_len > 512) + out_data_len = 512; + + rule_array_count = 2; + switch (pss->hashAlg) { + case CKM_SHA_1: + if (pss->mgf != CKG_MGF1_SHA1) { + TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); + rc = CKR_MECHANISM_PARAM_INVALID; + goto done; + } + memcpy(rule_array, "PKCS-PSSSHA-1 ", 2 * CCA_KEYWORD_SIZE); + break; + case CKM_SHA224: + if (pss->mgf != CKG_MGF1_SHA224) { + TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); + rc = CKR_MECHANISM_PARAM_INVALID; + goto done; + } + memcpy(rule_array, "PKCS-PSSSHA-224 ", 2 * CCA_KEYWORD_SIZE); + break; + case CKM_SHA256: + if (pss->mgf != CKG_MGF1_SHA256) { + TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); + rc = CKR_MECHANISM_PARAM_INVALID; + goto done; + } + memcpy(rule_array, "PKCS-PSSSHA-256 ", 2 * CCA_KEYWORD_SIZE); + break; + case CKM_SHA384: + if (pss->mgf != CKG_MGF1_SHA384) { + TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); + rc = CKR_MECHANISM_PARAM_INVALID; + goto done; + } + memcpy(rule_array, "PKCS-PSSSHA-384 ", 2 * CCA_KEYWORD_SIZE); + break; + case CKM_SHA512: + if (pss->mgf != CKG_MGF1_SHA512) { + TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); + rc = CKR_MECHANISM_PARAM_INVALID; + goto done; + } + memcpy(rule_array, "PKCS-PSSSHA-512 ", 2 * CCA_KEYWORD_SIZE); + break; + } + + dll_CSNDDSV(&return_code, + &reason_code, + NULL, + NULL, + &rule_array_count, + rule_array, + (long *)&(attr->ulValueLen), attr->pValue, - (long *) &in_data_len, - in_data, (long *) &out_data_len, out_data); + &message_len, + message, + (long *)&out_data_len, out_data); if (return_code == 4 && reason_code == 429) { - return CKR_SIGNATURE_INVALID; + rc = CKR_SIGNATURE_INVALID; + goto done; } else if (return_code != CCA_SUCCESS) { - TRACE_ERROR("CSNDDSV (RSA VERIFY) failed. return:%ld, reason:%ld\n", + TRACE_ERROR("CSNDDSV (RSA PSS VERIFY) failed. return:%ld, reason:%ld\n", return_code, reason_code); if (return_code == 8 && reason_code == 72) { /* @@ -1188,22 +1693,33 @@ CK_RV token_specific_rsa_verify(STDLL_TokData_t * tokdata, * and it may have failed due to a tampered signature being * greater or equal to the modulus. */ - return CKR_SIGNATURE_INVALID; + rc = CKR_SIGNATURE_INVALID; + goto done; } - return CKR_FUNCTION_FAILED; + rc = CKR_FUNCTION_FAILED; + goto done; } if (reason_code != 0) { - TRACE_WARNING("CSNDDSV (RSA VERIFY) succeeded, but" + TRACE_WARNING("CSNDDSV (RSA PSS VERIFY) succeeded, but" " returned reason:%ld\n", reason_code); } - return CKR_OK; + +done: + object_put(tokdata, key_obj, TRUE); + key_obj = NULL; + + if (message != NULL) + free(message); + + return rc; } #ifndef NOAES -CK_RV token_specific_aes_key_gen(STDLL_TokData_t * tokdata, CK_BYTE * aes_key, - CK_ULONG len, CK_ULONG key_size) +CK_RV token_specific_aes_key_gen(STDLL_TokData_t *tokdata, CK_BYTE **aes_key, + CK_ULONG *len, CK_ULONG key_size, + CK_BBOOL *is_opaque) { long return_code, reason_code; unsigned char key_token[CCA_KEY_ID_SIZE] = { 0, }; @@ -1218,9 +1734,11 @@ CK_RV token_specific_aes_key_gen(STDLL_TokData_t * tokdata, CK_BYTE * aes_key, UNUSED(tokdata); - /* make sure key is the right size for the token */ - if (len != CCA_KEY_ID_SIZE) - return CKR_FUNCTION_FAILED; + *aes_key = calloc(CCA_KEY_ID_SIZE, 1); + if (*aes_key == NULL) + return CKR_HOST_MEMORY; + *len = CCA_KEY_ID_SIZE; + *is_opaque = TRUE; memcpy(rule_array, "INTERNALAES NO-KEY ", (size_t) (CCA_KEYWORD_SIZE * 3)); @@ -1263,9 +1781,9 @@ CK_RV token_specific_aes_key_gen(STDLL_TokData_t * tokdata, CK_BYTE * aes_key, } memcpy(key_form, "OP ", (size_t) CCA_KEYWORD_SIZE); memcpy(key_type, "AESTOKEN", (size_t) CCA_KEYWORD_SIZE); - memcpy(aes_key, key_token, (size_t) CCA_KEY_ID_SIZE); + memcpy(*aes_key, key_token, (size_t) CCA_KEY_ID_SIZE); - return cca_key_gen(CCA_AES_KEY, aes_key, key_form, key_type, key_size); + return cca_key_gen(CCA_AES_KEY, *aes_key, key_form, key_type, key_size); } CK_RV token_specific_aes_ecb(STDLL_TokData_t * tokdata, @@ -2968,7 +3486,7 @@ static CK_RV rsa_import_privkey_crt(TEMPLATE * priv_tmpl) /* Now build a key token with the imported public key */ rule_array_count = 2; - memcpy(rule_array, "RSA-CRT KEY-MGMT", (size_t) (CCA_KEYWORD_SIZE * 2)); + memcpy(rule_array, "RSA-AESCKEY-MGMT", (size_t) (CCA_KEYWORD_SIZE * 2)); private_key_name_length = 0; @@ -3809,3 +4327,674 @@ CK_RV token_specific_generic_secret_key_gen(STDLL_TokData_t * tokdata, return CKR_OK; } + +static CK_RV ccatok_wrap_key_rsa_pkcs(CK_MECHANISM *mech, CK_BBOOL length_only, + OBJECT *wrapping_key, OBJECT *key, + CK_BYTE *wrapped_key, + CK_ULONG *wrapped_key_len) +{ + long return_code, reason_code, rule_array_count; + unsigned char rule_array[CCA_RULE_ARRAY_SIZE] = { 0 }; + CK_BYTE buffer[900] = { 0, }; + long buffer_len = sizeof(buffer); + CK_ATTRIBUTE *attr, *key_opaque, *wrap_key_opaque; + CK_OBJECT_CLASS key_class; + CK_KEY_TYPE key_type; + CK_RSA_PKCS_OAEP_PARAMS *oaep; + + if (!template_attribute_find(key->template, CKA_CLASS, &attr)) + return CKR_KEY_NOT_WRAPPABLE; + key_class = *(CK_OBJECT_CLASS *)attr->pValue; + + if (key_class != CKO_SECRET_KEY) + return CKR_KEY_NOT_WRAPPABLE; + + if (!template_attribute_find(key->template, CKA_KEY_TYPE, &attr)) + return CKR_KEY_NOT_WRAPPABLE; + key_type = *(CK_KEY_TYPE *) attr->pValue; + + switch (key_type) { + case CKK_DES: + case CKK_DES2: + case CKK_DES3: + switch (mech->mechanism) { + case CKM_RSA_PKCS: + rule_array_count = 2; + memcpy(rule_array, "DES PKCS-1.2", 2 * CCA_KEYWORD_SIZE); + break; + case CKM_RSA_PKCS_OAEP: + rule_array_count = 3; + oaep = (CK_RSA_PKCS_OAEP_PARAMS *)mech->pParameter; + if (oaep == NULL || + mech->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS)) + return CKR_MECHANISM_PARAM_INVALID; + + if (oaep->source == CKZ_DATA_SPECIFIED && + oaep->ulSourceDataLen > 0) { + TRACE_ERROR("CCA doesn't support non-empty OAEP source data\n"); + return CKR_MECHANISM_PARAM_INVALID; + } + + switch (oaep->hashAlg) { + case CKM_SHA_1: + if (oaep->mgf != CKG_MGF1_SHA1) + return CKR_MECHANISM_PARAM_INVALID; + memcpy(rule_array, "DES PKCSOAEPSHA-1 ", + 3 * CCA_KEYWORD_SIZE); + break; + case CKM_SHA256: + if (oaep->mgf != CKG_MGF1_SHA256) + return CKR_MECHANISM_PARAM_INVALID; + memcpy(rule_array, "DES PKCSOAEPSHA-256 ", + 3 * CCA_KEYWORD_SIZE); + break; + default: + return CKR_MECHANISM_PARAM_INVALID; + } + break; + default: + return CKR_MECHANISM_INVALID; + } + break; + case CKK_AES: + switch (mech->mechanism) { + case CKM_RSA_PKCS: + rule_array_count = 2; + memcpy(rule_array, "AES PKCS-1.2", 2 * CCA_KEYWORD_SIZE); + break; + case CKM_RSA_PKCS_OAEP: + rule_array_count = 3; + oaep = (CK_RSA_PKCS_OAEP_PARAMS *)mech->pParameter; + if (oaep == NULL || + mech->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS)) + return CKR_MECHANISM_PARAM_INVALID; + + if (oaep->source == CKZ_DATA_SPECIFIED && + oaep->ulSourceDataLen > 0) { + TRACE_ERROR("CCA does not support non-empty OAEP source " + "data\n"); + return CKR_MECHANISM_PARAM_INVALID; + } + + switch (oaep->hashAlg) { + case CKM_SHA_1: + if (oaep->mgf != CKG_MGF1_SHA1) + return CKR_MECHANISM_PARAM_INVALID; + memcpy(rule_array, "AES PKCSOAEPSHA-1 ", + 3 * CCA_KEYWORD_SIZE); + break; + case CKM_SHA256: + if (oaep->mgf != CKG_MGF1_SHA256) + return CKR_MECHANISM_PARAM_INVALID; + memcpy(rule_array, "AES PKCSOAEPSHA-256 ", + 3 * CCA_KEYWORD_SIZE); + break; + default: + return CKR_MECHANISM_PARAM_INVALID; + } + break; + default: + return CKR_MECHANISM_INVALID; + } + break; + default: + return CKR_KEY_NOT_WRAPPABLE; + } + + if (!template_attribute_find(key->template, CKA_IBM_OPAQUE, &key_opaque)) + return CKR_KEY_NOT_WRAPPABLE; + + if (!template_attribute_find(wrapping_key->template, CKA_IBM_OPAQUE, + &wrap_key_opaque)) + return CKR_KEY_NOT_WRAPPABLE; + + dll_CSNDSYX(&return_code, &reason_code, NULL, NULL, &rule_array_count, + rule_array, (long *)&key_opaque->ulValueLen, + key_opaque->pValue, (long *)&wrap_key_opaque->ulValueLen, + wrap_key_opaque->pValue, &buffer_len, buffer); + + if (return_code != CCA_SUCCESS) { + TRACE_ERROR("CSNDSYX (SYMMETRIC KEY EXPORT) failed." + " return:%ld, reason:%ld\n", return_code, reason_code); + return CKR_FUNCTION_FAILED; + } + + if (length_only) { + *wrapped_key_len = buffer_len; + return CKR_OK; + } + + if ((CK_ULONG)buffer_len > *wrapped_key_len) { + *wrapped_key_len = buffer_len; + return CKR_BUFFER_TOO_SMALL; + } + + memcpy(wrapped_key, buffer, buffer_len); + *wrapped_key_len = buffer_len; + + return CKR_OK; +} + +static CK_RV ccatok_unwrap_key_rsa_pkcs(CK_MECHANISM *mech, + OBJECT *wrapping_key, OBJECT *key, + CK_BYTE *wrapped_key, + CK_ULONG wrapped_key_len) +{ + long return_code, reason_code, rule_array_count; + unsigned char rule_array[CCA_RULE_ARRAY_SIZE] = { 0 }; + CK_BYTE buffer[3500] = { 0, }; + CK_BYTE dummy[AES_KEY_SIZE_256] = { 0, }; + long buffer_len = sizeof(buffer); + CK_ATTRIBUTE *attr, *wrap_key_opaque,*key_opaque = NULL; + CK_ATTRIBUTE *value = NULL, *value_len = NULL; + CK_OBJECT_CLASS key_class; + CK_KEY_TYPE key_type, cca_key_type; + CK_ULONG key_size = 0; + CK_RSA_PKCS_OAEP_PARAMS *oaep; + uint16_t val; + CK_RV rc; + + if (!template_attribute_find(key->template, CKA_CLASS, &attr)) + return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT; + key_class = *(CK_OBJECT_CLASS *)attr->pValue; + + if (key_class != CKO_SECRET_KEY) + return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT; + + if (!template_attribute_find(key->template, CKA_KEY_TYPE, &attr)) + return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT; + key_type = *(CK_KEY_TYPE *) attr->pValue; + + switch (key_type) { + case CKK_DES: + case CKK_DES2: + case CKK_DES3: + switch (mech->mechanism) { + case CKM_RSA_PKCS: + rule_array_count = 2; + memcpy(rule_array, "DES PKCS-1.2", 2 * CCA_KEYWORD_SIZE); + break; + case CKM_RSA_PKCS_OAEP: + rule_array_count = 3; + oaep = (CK_RSA_PKCS_OAEP_PARAMS *)mech->pParameter; + if (oaep == NULL || + mech->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS)) + return CKR_MECHANISM_PARAM_INVALID; + + if (oaep->source == CKZ_DATA_SPECIFIED && + oaep->ulSourceDataLen > 0) { + TRACE_ERROR("CCA does not support non-empty OAEP source " + "data\n"); + return CKR_MECHANISM_PARAM_INVALID; + } + + switch (oaep->hashAlg) { + case CKM_SHA_1: + if (oaep->mgf != CKG_MGF1_SHA1) + return CKR_MECHANISM_PARAM_INVALID; + memcpy(rule_array, "DES PKCSOAEPSHA-1 ", + 3 * CCA_KEYWORD_SIZE); + break; + case CKM_SHA256: + if (oaep->mgf != CKG_MGF1_SHA256) + return CKR_MECHANISM_PARAM_INVALID; + memcpy(rule_array, "DES PKCSOAEPSHA-256 ", + 3 * CCA_KEYWORD_SIZE); + break; + default: + return CKR_MECHANISM_PARAM_INVALID; + } + break; + default: + return CKR_MECHANISM_INVALID; + } + break; + case CKK_AES: + switch (mech->mechanism) { + case CKM_RSA_PKCS: + rule_array_count = 2; + memcpy(rule_array, "AES PKCS-1.2", 2 * CCA_KEYWORD_SIZE); + break; + case CKM_RSA_PKCS_OAEP: + rule_array_count = 3; + oaep = (CK_RSA_PKCS_OAEP_PARAMS *)mech->pParameter; + if (oaep == NULL || + mech->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS)) + return CKR_MECHANISM_PARAM_INVALID; + + if (oaep->source == CKZ_DATA_SPECIFIED && + oaep->ulSourceDataLen > 0) { + TRACE_ERROR("CCA does not support non-empty OAEP source " + "data\n"); + return CKR_MECHANISM_PARAM_INVALID; + } + + switch (oaep->hashAlg) { + case CKM_SHA_1: + if (oaep->mgf != CKG_MGF1_SHA1) + return CKR_MECHANISM_PARAM_INVALID; + memcpy(rule_array, "AES PKCSOAEPSHA-1 ", + 3 * CCA_KEYWORD_SIZE); + break; + case CKM_SHA256: + if (oaep->mgf != CKG_MGF1_SHA256) + return CKR_MECHANISM_PARAM_INVALID; + memcpy(rule_array, "AES PKCSOAEPSHA-256 ", + 3 * CCA_KEYWORD_SIZE); + break; + default: + return CKR_MECHANISM_PARAM_INVALID; + } + break; + default: + return CKR_MECHANISM_INVALID; + } + break; + default: + return CKR_WRAPPED_KEY_INVALID; + } + + if (!template_attribute_find(wrapping_key->template, CKA_IBM_OPAQUE, + &wrap_key_opaque)) + return CKR_TEMPLATE_INCONSISTENT; + + dll_CSNDSYI(&return_code, &reason_code, NULL, NULL, &rule_array_count, + rule_array, (long *)&wrapped_key_len, wrapped_key, + (long *)&wrap_key_opaque->ulValueLen, wrap_key_opaque->pValue, + &buffer_len, buffer); + + if (return_code != CCA_SUCCESS) { + TRACE_ERROR("CSNDSYI (SYMMETRIC KEY IMPORT) failed." + " return:%ld, reason:%ld\n", return_code, reason_code); + return CKR_FUNCTION_FAILED; + } + + if (buffer[0] != 0x01) { /* Internal key token */ + TRACE_DEVEL("key token invalid\n"); + return CKR_FUNCTION_FAILED; + } + + switch (buffer[4]) { + case 0x00: /* DES key token */ + case 0x01: /* DES3 key token */ + switch (buffer[59] & 0x30) { + case 0x00: + cca_key_type = CKK_DES; + key_size = DES_KEY_SIZE; + break; + case 0x10: + cca_key_type = CKK_DES2; + key_size = 2 * DES_KEY_SIZE; + break; + case 0x20: + cca_key_type = CKK_DES3; + key_size = 3 * DES_KEY_SIZE; + break; + default: + TRACE_DEVEL("key token invalid\n"); + return CKR_FUNCTION_FAILED; + } + break; + case 0x04:/* AES key token */ + cca_key_type = CKK_AES; + memcpy(&val, &buffer[56], sizeof(val)); + key_size = ntohs(val) / 8; + break; + default: + TRACE_DEVEL("key token invalid\n"); + return CKR_FUNCTION_FAILED; + } + + if (key_type != cca_key_type) { + TRACE_DEVEL("Wrong key type\n"); + return CKR_FUNCTION_FAILED; + } + + rc = build_attribute(CKA_IBM_OPAQUE, buffer, buffer_len, &key_opaque); + if (rc != CKR_OK) { + TRACE_DEVEL("build_attribute failed\n"); + goto error; + } + + rc = build_attribute(CKA_VALUE, dummy, key_size, &value); + if (rc != CKR_OK) { + TRACE_DEVEL("build_attribute failed\n"); + goto error; + } + switch (key_type) { + case CKK_GENERIC_SECRET: + case CKK_AES: + rc = build_attribute(CKA_VALUE_LEN, (CK_BYTE *)&key_size, + sizeof(CK_ULONG), &value_len); + if (rc != CKR_OK) { + TRACE_DEVEL("build_attribute failed\n"); + goto error; + } + break; + default: + break; + } + + template_update_attribute(key->template, key_opaque); + template_update_attribute(key->template, value); + if (value_len != NULL) + template_update_attribute(key->template, value_len); + + return CKR_OK; + +error: + if (key_opaque) + free(key_opaque); + if (value) + free(value); + if (value_len) + free(value_len); + + return rc; +} + +CK_RV token_specific_key_wrap(STDLL_TokData_t *tokdata, SESSION *session, + CK_MECHANISM *mech, CK_BBOOL length_only, + OBJECT *wrapping_key, OBJECT *key, + CK_BYTE *wrapped_key, CK_ULONG *wrapped_key_len, + CK_BBOOL *not_opaque) +{ + CK_ATTRIBUTE *attr; + CK_OBJECT_CLASS wrap_key_class; + CK_KEY_TYPE wrap_key_type; + + UNUSED(tokdata); + UNUSED(session); + + *not_opaque = FALSE; + + if (!template_attribute_find(wrapping_key->template, CKA_CLASS, &attr)) + return CKR_KEY_NOT_WRAPPABLE; + wrap_key_class = *(CK_OBJECT_CLASS *)attr->pValue; + + if (!template_attribute_find(wrapping_key->template, CKA_KEY_TYPE, &attr)) + return CKR_KEY_NOT_WRAPPABLE; + wrap_key_type = *(CK_KEY_TYPE *) attr->pValue; + + switch (mech->mechanism) { + case CKM_RSA_PKCS: + case CKM_RSA_PKCS_OAEP: + if (wrap_key_class != CKO_PUBLIC_KEY && wrap_key_type != CKK_RSA) + return CKR_WRAPPING_KEY_TYPE_INCONSISTENT; + + return ccatok_wrap_key_rsa_pkcs(mech, length_only, wrapping_key, key, + wrapped_key, wrapped_key_len); + default: + return CKR_MECHANISM_INVALID; + } + } + +CK_RV token_specific_key_unwrap(STDLL_TokData_t *tokdata, SESSION *session, + CK_MECHANISM *mech, + CK_BYTE *wrapped_key, CK_ULONG wrapped_key_len, + OBJECT *unwrapping_key, OBJECT *unwrapped_key, + CK_BBOOL *not_opaque) +{ + CK_ATTRIBUTE *attr; + CK_ATTRIBUTE *local = NULL, *always_sens = NULL, *sensitive = NULL; + CK_ATTRIBUTE *extractable = NULL, *never_extract = NULL; + CK_OBJECT_CLASS unwrap_key_class; + CK_KEY_TYPE unwrap_keytype; + CK_BBOOL true = TRUE; + CK_BBOOL false = FALSE; + CK_RV rc; + + UNUSED(tokdata); + UNUSED(session); + + *not_opaque = FALSE; + + if (!template_attribute_find(unwrapping_key->template, CKA_CLASS, &attr)) + return CKR_KEY_NOT_WRAPPABLE; + unwrap_key_class = *(CK_OBJECT_CLASS *)attr->pValue; + + if (!template_attribute_find(unwrapping_key->template, CKA_KEY_TYPE, &attr)) + return CKR_KEY_NOT_WRAPPABLE; + unwrap_keytype = *(CK_KEY_TYPE *) attr->pValue; + + switch (mech->mechanism) { + case CKM_RSA_PKCS: + case CKM_RSA_PKCS_OAEP: + if (unwrap_key_class != CKO_PRIVATE_KEY && unwrap_keytype != CKK_RSA) + return CKR_WRAPPING_KEY_TYPE_INCONSISTENT; + + rc = ccatok_unwrap_key_rsa_pkcs(mech, unwrapping_key, unwrapped_key, + wrapped_key, wrapped_key_len); + if (rc != CKR_OK) + goto error; + break; + default: + return CKR_MECHANISM_INVALID; + } + + /* + * make sure + * CKA_LOCAL == FALSE + * CKA_ALWAYS_SENSITIVE == FALSE + * CKA_EXTRACTABLE == TRUE + * CKA_NEVER_EXTRACTABLE == FALSE + */ + rc = build_attribute(CKA_LOCAL, &false, 1, &local); + if (rc != CKR_OK) { + TRACE_DEVEL("build attribute failed\n"); + goto error; + } + rc = build_attribute(CKA_ALWAYS_SENSITIVE, &false, 1, &always_sens); + if (rc != CKR_OK) { + TRACE_DEVEL("build attribute failed\n"); + goto error; + } + rc = build_attribute(CKA_SENSITIVE, &false, 1, &sensitive); + if (rc != CKR_OK) { + TRACE_DEVEL("build_attribute failed\n"); + goto error; + } + rc = build_attribute(CKA_EXTRACTABLE, &true, 1, &extractable); + if (rc != CKR_OK) { + TRACE_DEVEL("build_attribute failed\n"); + goto error; + } + rc = build_attribute(CKA_NEVER_EXTRACTABLE, &false, 1, &never_extract); + if (rc != CKR_OK) { + TRACE_DEVEL("build_attribute failed\n"); + goto error; + } + + template_update_attribute(unwrapped_key->template, local); + template_update_attribute(unwrapped_key->template, always_sens); + template_update_attribute(unwrapped_key->template, sensitive); + template_update_attribute(unwrapped_key->template, extractable); + template_update_attribute(unwrapped_key->template, never_extract); + + return CKR_OK; + +error: + if (local) + free(local); + if (extractable) + free(extractable); + if (always_sens) + free(always_sens); + if (never_extract) + free(never_extract); + + return rc; +} + +CK_RV token_specific_reencrypt_single(STDLL_TokData_t *tokdata, + SESSION *session, + ENCR_DECR_CONTEXT *decr_ctx, + CK_MECHANISM *decr_mech, + OBJECT *decr_key_obj, + ENCR_DECR_CONTEXT *encr_ctx, + CK_MECHANISM *encr_mech, + OBJECT *encr_key_obj, + CK_BYTE *in_data, CK_ULONG in_data_len, + CK_BYTE *out_data, CK_ULONG *out_data_len) +{ + CK_ATTRIBUTE *decr_key_opaque, *encr_key_opaque; + long return_code, reason_code, rule_array_count = 0; + unsigned char rule_array[CCA_RULE_ARRAY_SIZE] = { 0 }; + CK_BYTE in_iv[AES_BLOCK_SIZE] = { 0 }; + CK_BYTE out_iv[AES_BLOCK_SIZE] = { 0 }; + long in_iv_len = 0, out_iv_len = 0; + CK_BYTE cv[128] = { 0 }; + long cv_len = 128, zero = 0; + CK_ULONG max_clear_len, req_out_len; + + UNUSED(tokdata); + UNUSED(session); + UNUSED(decr_ctx); + UNUSED(encr_ctx); + + if (!template_attribute_find(decr_key_obj->template, CKA_IBM_OPAQUE, + &decr_key_opaque)) { + TRACE_ERROR("Could not find CKA_IBM_OPAQUE for the decryption key.\n"); + return CKR_FUNCTION_FAILED; + } + + if (!template_attribute_find(encr_key_obj->template, CKA_IBM_OPAQUE, + &encr_key_opaque)) { + TRACE_ERROR("Could not find CKA_IBM_OPAQUE for the encryption key.\n"); + return CKR_FUNCTION_FAILED; + } + + /* CCA only supports AES-ECB/CBC, and 3DES-CBC with CSNBCTT2 */ + switch (decr_mech->mechanism) { + case CKM_AES_ECB: + rule_array_count = 2; + memcpy(rule_array, "IKEY-AESI-ECB ", 2 * CCA_KEYWORD_SIZE); + + max_clear_len = in_data_len; + break; + case CKM_AES_CBC: + rule_array_count = 2; + memcpy(rule_array, "IKEY-AESI-CBC ", 2 * CCA_KEYWORD_SIZE); + + in_iv_len = decr_mech->ulParameterLen; + if (in_iv_len != AES_BLOCK_SIZE) + return CKR_MECHANISM_PARAM_INVALID; + memcpy(in_iv, decr_mech->pParameter, in_iv_len); + + max_clear_len = in_data_len; + break; + case CKM_AES_CBC_PAD: + rule_array_count = 2; + memcpy(rule_array, "IKEY-AESIPKCSPAD", 2 * CCA_KEYWORD_SIZE); + + in_iv_len = decr_mech->ulParameterLen; + if (in_iv_len != AES_BLOCK_SIZE) + return CKR_MECHANISM_PARAM_INVALID; + memcpy(in_iv, decr_mech->pParameter, in_iv_len); + + /* PKCS#7 pads at least 1 byte in any case */ + max_clear_len = in_data_len - 1; + break; + case CKM_DES3_CBC: + rule_array_count = 2; + memcpy(rule_array, "IKEY-DESI-CBC ", 2 * CCA_KEYWORD_SIZE); + + in_iv_len = decr_mech->ulParameterLen; + if (in_iv_len != DES_BLOCK_SIZE) + return CKR_MECHANISM_PARAM_INVALID; + memcpy(in_iv, decr_mech->pParameter, in_iv_len); + + max_clear_len = in_data_len; + break; + default: + TRACE_DEVEL("Decryption method %lu not supported\n", + decr_mech->mechanism); + return CKR_MECHANISM_INVALID; + } + + switch (encr_mech->mechanism) { + case CKM_AES_ECB: + memcpy(rule_array + (rule_array_count * CCA_KEYWORD_SIZE), + "OKEY-AESO-ECB ", 2 * CCA_KEYWORD_SIZE); + rule_array_count += 2; + + /* Round up to the next block size */ + req_out_len = (max_clear_len / AES_BLOCK_SIZE) * AES_BLOCK_SIZE + + (max_clear_len % AES_BLOCK_SIZE ? AES_BLOCK_SIZE : 0); + break; + case CKM_AES_CBC: + memcpy(rule_array + (rule_array_count * CCA_KEYWORD_SIZE), + "OKEY-AESO-CBC ", 2 * CCA_KEYWORD_SIZE); + rule_array_count += 2; + + out_iv_len = encr_mech->ulParameterLen; + if (out_iv_len != AES_BLOCK_SIZE) + return CKR_MECHANISM_PARAM_INVALID; + memcpy(out_iv, encr_mech->pParameter, out_iv_len); + + /* Round up to the next block size */ + req_out_len = (max_clear_len / AES_BLOCK_SIZE) * AES_BLOCK_SIZE + + (max_clear_len % AES_BLOCK_SIZE ? AES_BLOCK_SIZE : 0); + break; + case CKM_AES_CBC_PAD: + memcpy(rule_array + (rule_array_count * CCA_KEYWORD_SIZE), + "OKEY-AESOPKCSPAD", 2 * CCA_KEYWORD_SIZE); + rule_array_count += 2; + + out_iv_len = encr_mech->ulParameterLen; + if (out_iv_len != AES_BLOCK_SIZE) + return CKR_MECHANISM_PARAM_INVALID; + memcpy(out_iv, encr_mech->pParameter, out_iv_len); + + /* PKCS#7 pads a full block, if already a multiple of the block size */ + req_out_len = AES_BLOCK_SIZE * (max_clear_len / AES_BLOCK_SIZE + 1); + break; + case CKM_DES3_CBC: + memcpy(rule_array + (rule_array_count * CCA_KEYWORD_SIZE), + "OKEY-DESO-CBC ", 2 * CCA_KEYWORD_SIZE); + rule_array_count += 2; + + out_iv_len = encr_mech->ulParameterLen; + if (out_iv_len != DES_BLOCK_SIZE) + return CKR_MECHANISM_PARAM_INVALID; + memcpy(out_iv, encr_mech->pParameter, out_iv_len); + + /* Round up to the next block size */ + req_out_len = (max_clear_len / DES_BLOCK_SIZE) * DES_BLOCK_SIZE + + (max_clear_len % DES_BLOCK_SIZE ? DES_BLOCK_SIZE : 0); + break; + default: + TRACE_DEVEL("Encryption method %lu not supported\n", + decr_mech->mechanism); + return CKR_MECHANISM_INVALID; + } + + if (out_data == NULL) { + *out_data_len = req_out_len; + return CKR_OK; + } + + if (*out_data_len < req_out_len) { + *out_data_len = req_out_len; + TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); + return CKR_BUFFER_TOO_SMALL; + } + + dll_CSNBCTT2(&return_code, &reason_code, NULL, NULL, &rule_array_count, + rule_array, (long *)&decr_key_opaque->ulValueLen, + decr_key_opaque->pValue, &in_iv_len, in_iv, + (long *)&in_data_len, in_data, &cv_len, cv, + (long *)&encr_key_opaque->ulValueLen, encr_key_opaque->pValue, + &out_iv_len, out_iv, (long *)out_data_len, out_data, + &zero, NULL, &zero, NULL); + + if (return_code != CCA_SUCCESS) { + TRACE_ERROR("CSNBCTT2 (CIPHER TEXT TRANSLATE) failed." + " return:%ld, reason:%ld\n", return_code, reason_code); + if (return_code == 8 && reason_code == 72) + return CKR_DATA_LEN_RANGE; + return CKR_FUNCTION_FAILED; + } + + return CKR_OK; +} diff --git a/usr/lib/cca_stdll/cca_stdll.h b/usr/lib/cca_stdll/cca_stdll.h index cdc902d..186041c 100644 --- a/usr/lib/cca_stdll/cca_stdll.h +++ b/usr/lib/cca_stdll/cca_stdll.h @@ -68,7 +68,9 @@ #define CCA_RSA_INTTOK_PRIVKEY_LENGTH_OFFSET 2 #define CCA_RSA_INTTOK_PUBKEY_LENGTH_OFFSET 2 /* Offset into an RSA private key area of the length of n, the modulus */ -#define CCA_RSA_INTTOK_PRIVKEY_N_LENGTH_OFFSET 64 +#define CCA_RSA_INTTOK_PRIVKEY_N_LENGTH_OFFSET 62 +/* Offset into an RSA private key area of n, the modulus */ +#define CCA_RSA_INTTOK_PRIVKEY_N_OFFSET 134 /* Offset into an RSA public key area of the length of e, the public exponent */ #define CCA_RSA_INTTOK_PUBKEY_E_LENGTH_OFFSET 6 /* Offset into an RSA public key area of the value of e, the public exponent */ diff --git a/usr/lib/cca_stdll/cca_stdll.mk b/usr/lib/cca_stdll/cca_stdll.mk index 6e46a9d..2d85be5 100644 --- a/usr/lib/cca_stdll/cca_stdll.mk +++ b/usr/lib/cca_stdll/cca_stdll.mk @@ -34,7 +34,9 @@ opencryptoki_stdll_libpkcs11_cca_la_SOURCES = \ 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/cca_stdll/cca_specific.c + usr/lib/common/shared_memory.c usr/lib/common/profile_obj.c \ + usr/lib/cca_stdll/cca_specific.c + if ENABLE_LOCKS opencryptoki_stdll_libpkcs11_cca_la_SOURCES += \ usr/lib/common/lock_btree.c usr/lib/common/lock_sess_mgr.c diff --git a/usr/lib/cca_stdll/tok_struct.h b/usr/lib/cca_stdll/tok_struct.h index 39d19c1..48fe908 100644 --- a/usr/lib/cca_stdll/tok_struct.h +++ b/usr/lib/cca_stdll/tok_struct.h @@ -32,7 +32,7 @@ token_spec_t token_specific = { CCA_CONFIG_PATH, "ccatok", - 64, + TRUE, // Token data info: { FALSE, // Don't use per guest data store @@ -76,10 +76,10 @@ token_spec_t token_specific = { NULL, // rsa_x509_sign NULL, // rsa_x509_verify NULL, // rsa_x509_verify_recover - NULL, // rsa_oaep_decrypt - NULL, // rsa_oaep_encrypt - NULL, // rsa_pss_sign - NULL, // rsa_pss_verify + &token_specific_rsa_oaep_decrypt, + &token_specific_rsa_oaep_encrypt, + &token_specific_rsa_pss_sign, + &token_specific_rsa_pss_verify, &token_specific_rsa_generate_keypair, // Elliptic Curve &token_specific_ec_sign, @@ -128,7 +128,10 @@ token_spec_t token_specific = { NULL, // dsa_verify &token_specific_get_mechanism_list, &token_specific_get_mechanism_info, - &token_specific_object_add + &token_specific_object_add, + &token_specific_key_wrap, + &token_specific_key_unwrap, + &token_specific_reencrypt_single, }; #endif diff --git a/usr/lib/common/asn1.c b/usr/lib/common/asn1.c index 01d600c..ba7f018 100644 --- a/usr/lib/common/asn1.c +++ b/usr/lib/common/asn1.c @@ -1115,15 +1115,12 @@ CK_RV ber_decode_SPKI(CK_BYTE *spki, CK_BYTE **alg_oid, CK_ULONG *alg_oid_len, // version Version -- always '0' for now // modulus INTEGER // publicExponent INTEGER -// if secure key -// opaque OCTET_STRING -// else -// privateExponent INTEGER -// prime1 INTEGER -// prime2 INTEGER -// exponent1 INTEGER -// exponent2 INTEGER -// coefficient INTEGER +// privateExponent INTEGER +// prime1 INTEGER +// prime2 INTEGER +// exponent1 INTEGER +// exponent2 INTEGER +// coefficient INTEGER // } // CK_RV ber_encode_RSAPrivateKey(CK_BBOOL length_only, @@ -1136,7 +1133,7 @@ CK_RV ber_encode_RSAPrivateKey(CK_BBOOL length_only, CK_ATTRIBUTE *prime2, CK_ATTRIBUTE *exponent1, CK_ATTRIBUTE *exponent2, - CK_ATTRIBUTE *coeff, CK_ATTRIBUTE *opaque) + CK_ATTRIBUTE *coeff) { CK_BYTE *buf = NULL; CK_BYTE *buf2 = NULL; @@ -1154,23 +1151,18 @@ CK_RV ber_encode_RSAPrivateKey(CK_BBOOL length_only, offset += len; rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, publ_exp->ulValueLen); offset += len; - if (opaque != NULL) { - rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, opaque->ulValueLen); - offset += len; - } else { - rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, priv_exp->ulValueLen); - offset += len; - rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, prime1->ulValueLen); - offset += len; - rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, prime2->ulValueLen); - offset += len; - rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, exponent1->ulValueLen); - offset += len; - rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, exponent2->ulValueLen); - offset += len; - rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, coeff->ulValueLen); - offset += len; - } + rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, priv_exp->ulValueLen); + offset += len; + rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, prime1->ulValueLen); + offset += len; + rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, prime2->ulValueLen); + offset += len; + rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, exponent1->ulValueLen); + offset += len; + rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, exponent2->ulValueLen); + offset += len; + rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, coeff->ulValueLen); + offset += len; if (rc != CKR_OK) { TRACE_DEVEL("ber_encode_INTEGER failed\n"); @@ -1241,103 +1233,88 @@ CK_RV ber_encode_RSAPrivateKey(CK_BBOOL length_only, buf2 = NULL; } - if (opaque != NULL) { - // the CKA_IBM_OPAQUE attrib - rc = ber_encode_OCTET_STRING(FALSE, &buf2, &len, - (CK_BYTE *) opaque + - sizeof(CK_ATTRIBUTE), opaque->ulValueLen); - if (rc != CKR_OK) { - TRACE_DEVEL("ber_encode_OCTET_STRING failed\n"); - goto error; - } + rc = ber_encode_INTEGER(FALSE, &buf2, &len, + (CK_BYTE *) priv_exp + sizeof(CK_ATTRIBUTE), + priv_exp->ulValueLen); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_encode_INTEGER failed\n"); + goto error; + } + if (buf2 != NULL) { memcpy(buf + offset, buf2, len); offset += len; free(buf2); buf2 = NULL; - } else { - rc = ber_encode_INTEGER(FALSE, &buf2, &len, - (CK_BYTE *) priv_exp + sizeof(CK_ATTRIBUTE), - priv_exp->ulValueLen); - if (rc != CKR_OK) { - TRACE_DEVEL("ber_encode_INTEGER failed\n"); - goto error; - } - if (buf2 != NULL) { - memcpy(buf + offset, buf2, len); - offset += len; - free(buf2); - buf2 = NULL; - } + } - rc = ber_encode_INTEGER(FALSE, &buf2, &len, - (CK_BYTE *) prime1 + sizeof(CK_ATTRIBUTE), - prime1->ulValueLen); - if (rc != CKR_OK) { - TRACE_DEVEL("ber_encode_INTEGER failed\n"); - goto error; - } - if (buf2 != NULL) { - memcpy(buf + offset, buf2, len); - offset += len; - free(buf2); - buf2 = NULL; - } + rc = ber_encode_INTEGER(FALSE, &buf2, &len, + (CK_BYTE *) prime1 + sizeof(CK_ATTRIBUTE), + prime1->ulValueLen); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_encode_INTEGER failed\n"); + goto error; + } + if (buf2 != NULL) { + memcpy(buf + offset, buf2, len); + offset += len; + free(buf2); + buf2 = NULL; + } - rc = ber_encode_INTEGER(FALSE, &buf2, &len, - (CK_BYTE *) prime2 + sizeof(CK_ATTRIBUTE), - prime2->ulValueLen); - if (rc != CKR_OK) { - TRACE_DEVEL("ber_encode_INTEGER failed\n"); - goto error; - } - if (buf2 != NULL) { - memcpy(buf + offset, buf2, len); - offset += len; - free(buf2); - buf2 = NULL; - } + rc = ber_encode_INTEGER(FALSE, &buf2, &len, + (CK_BYTE *) prime2 + sizeof(CK_ATTRIBUTE), + prime2->ulValueLen); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_encode_INTEGER failed\n"); + goto error; + } + if (buf2 != NULL) { + memcpy(buf + offset, buf2, len); + offset += len; + free(buf2); + buf2 = NULL; + } - rc = ber_encode_INTEGER(FALSE, &buf2, &len, - (CK_BYTE *) exponent1 + sizeof(CK_ATTRIBUTE), - exponent1->ulValueLen); - if (rc != CKR_OK) { - TRACE_DEVEL("ber_encode_INTEGER failed\n"); - goto error; - } - if (buf2 != NULL) { - memcpy(buf + offset, buf2, len); - offset += len; - free(buf2); - buf2 = NULL; - } + rc = ber_encode_INTEGER(FALSE, &buf2, &len, + (CK_BYTE *) exponent1 + sizeof(CK_ATTRIBUTE), + exponent1->ulValueLen); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_encode_INTEGER failed\n"); + goto error; + } + if (buf2 != NULL) { + memcpy(buf + offset, buf2, len); + offset += len; + free(buf2); + buf2 = NULL; + } - rc = ber_encode_INTEGER(FALSE, &buf2, &len, - (CK_BYTE *) exponent2 + sizeof(CK_ATTRIBUTE), - exponent2->ulValueLen); - if (rc != CKR_OK) { - TRACE_DEVEL("ber_encode_INTEGER failed\n"); - goto error; - } - if (buf2 != NULL) { - memcpy(buf + offset, buf2, len); - offset += len; - free(buf2); - buf2 = NULL; - } + rc = ber_encode_INTEGER(FALSE, &buf2, &len, + (CK_BYTE *) exponent2 + sizeof(CK_ATTRIBUTE), + exponent2->ulValueLen); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_encode_INTEGER failed\n"); + goto error; + } + if (buf2 != NULL) { + memcpy(buf + offset, buf2, len); + offset += len; + free(buf2); + buf2 = NULL; + } - rc = ber_encode_INTEGER(FALSE, &buf2, &len, - (CK_BYTE *) coeff + sizeof(CK_ATTRIBUTE), - coeff->ulValueLen); - if (rc != CKR_OK) { - TRACE_DEVEL("ber_encode_INTEGER failed\n"); - goto error; - } - if (buf2 != NULL) { - memcpy(buf + offset, buf2, len); - offset += len; - free(buf2); - buf2 = NULL; - } + rc = ber_encode_INTEGER(FALSE, &buf2, &len, + (CK_BYTE *) coeff + sizeof(CK_ATTRIBUTE), + coeff->ulValueLen); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_encode_INTEGER failed\n"); + goto error; + } + if (buf2 != NULL) { + memcpy(buf + offset, buf2, len); + offset += len; + free(buf2); + buf2 = NULL; } rc = ber_encode_SEQUENCE(FALSE, &buf2, &len, buf, offset); @@ -1373,8 +1350,7 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data, CK_ATTRIBUTE **prime2, CK_ATTRIBUTE **exponent1, CK_ATTRIBUTE **exponent2, - CK_ATTRIBUTE **coeff, - CK_ATTRIBUTE **opaque, CK_BBOOL isopaque) + CK_ATTRIBUTE **coeff) { CK_ATTRIBUTE *n_attr = NULL; CK_ATTRIBUTE *e_attr = NULL; @@ -1384,7 +1360,6 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data, CK_ATTRIBUTE *e1_attr = NULL; CK_ATTRIBUTE *e2_attr = NULL; CK_ATTRIBUTE *coeff_attr = NULL; - CK_ATTRIBUTE *o_attr = NULL; CK_BYTE *alg = NULL; CK_BYTE *rsa_priv_key = NULL; @@ -1440,75 +1415,63 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data, } offset += field_len; - if (isopaque) { - // opaque attribute, the CCA key - // - rc = ber_decode_OCTET_STRING(buf + offset, &tmp, &len, &field_len); - if (rc != CKR_OK) { - TRACE_DEVEL("ber_decode_OCTET_STRING failed\n"); - goto cleanup; - } - offset += field_len; - } else { - - // private exponent - // - rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); - if (rc != CKR_OK) { - TRACE_DEVEL("ber_decode_INTEGER failed\n"); - goto cleanup; - } - offset += field_len; + // private exponent + // + rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_INTEGER failed\n"); + goto cleanup; + } + offset += field_len; - // prime #1 - // - rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); - if (rc != CKR_OK) { - TRACE_DEVEL("ber_decode_INTEGER failed\n"); - goto cleanup; - } - offset += field_len; + // prime #1 + // + rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_INTEGER failed\n"); + goto cleanup; + } + offset += field_len; - // prime #2 - // - rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); - if (rc != CKR_OK) { - TRACE_DEVEL("ber_decode_INTEGER failed\n"); - goto cleanup; - } - offset += field_len; + // prime #2 + // + rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_INTEGER failed\n"); + goto cleanup; + } + offset += field_len; - // exponent #1 - // - rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); - if (rc != CKR_OK) { - TRACE_DEVEL("ber_decode_INTEGER failed\n"); - goto cleanup; - } - offset += field_len; + // exponent #1 + // + rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_INTEGER failed\n"); + goto cleanup; + } + offset += field_len; - // exponent #2 - // - rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); - if (rc != CKR_OK) { - TRACE_DEVEL("ber_decode_INTEGER failed\n"); - goto cleanup; - } - offset += field_len; + // exponent #2 + // + rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_INTEGER failed\n"); + goto cleanup; + } + offset += field_len; - // coefficient - // - rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); - if (rc != CKR_OK) { - TRACE_DEVEL("ber_decode_INTEGER failed\n"); - goto cleanup; - } - offset += field_len; + // coefficient + // + rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_INTEGER failed\n"); + goto cleanup; + } + offset += field_len; - if (offset > buf_len) { - TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); - return CKR_FUNCTION_FAILED; - } + if (offset > buf_len) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + return CKR_FUNCTION_FAILED; } // @@ -1556,119 +1519,101 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data, offset += field_len; } - if (isopaque) { - // opaque attribute, the CCA key - // - rc = ber_decode_OCTET_STRING(buf + offset, &tmp, &len, &field_len); - if (rc != CKR_OK) { - TRACE_DEVEL("ber_decode_OCTET_STRING failed\n"); - goto cleanup; - } else { - rc = build_attribute(CKA_IBM_OPAQUE, tmp, len, &o_attr); - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute failed\n"); - goto cleanup; - } - offset += field_len; - } - *opaque = o_attr; + // private exponent + // + rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_INTEGER failed\n"); + goto cleanup; } else { - // private exponent - // - rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); + rc = build_attribute(CKA_PRIVATE_EXPONENT, tmp, len, &d_attr); if (rc != CKR_OK) { - TRACE_DEVEL("ber_decode_INTEGER failed\n"); + TRACE_DEVEL("build_attribute failed\n"); goto cleanup; - } else { - rc = build_attribute(CKA_PRIVATE_EXPONENT, tmp, len, &d_attr); - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute failed\n"); - goto cleanup; - } - offset += field_len; } + offset += field_len; + } - // prime #1 - // - rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); + // prime #1 + // + rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_INTEGER failed\n"); + goto cleanup; + } else { + rc = build_attribute(CKA_PRIME_1, tmp, len, &p_attr); if (rc != CKR_OK) { - TRACE_DEVEL("ber_decode_INTEGER failed\n"); + TRACE_DEVEL("build_attribute failed\n"); goto cleanup; - } else { - rc = build_attribute(CKA_PRIME_1, tmp, len, &p_attr); - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute failed\n"); - goto cleanup; - } - offset += field_len; } + offset += field_len; + } - // prime #2 - // - rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); + // prime #2 + // + rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_INTEGER failed\n"); + goto cleanup; + } else { + rc = build_attribute(CKA_PRIME_2, tmp, len, &q_attr); if (rc != CKR_OK) { - TRACE_DEVEL("ber_decode_INTEGER failed\n"); + TRACE_DEVEL("build_attribute failed\n"); goto cleanup; - } else { - rc = build_attribute(CKA_PRIME_2, tmp, len, &q_attr); - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute failed\n"); - goto cleanup; - } - offset += field_len; } + offset += field_len; + } - // exponent #1 - // - rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); + // exponent #1 + // + rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_INTEGER failed\n"); + goto cleanup; + } else { + rc = build_attribute(CKA_EXPONENT_1, tmp, len, &e1_attr); if (rc != CKR_OK) { - TRACE_DEVEL("ber_decode_INTEGER failed\n"); + TRACE_DEVEL("build_attribute failed\n"); goto cleanup; - } else { - rc = build_attribute(CKA_EXPONENT_1, tmp, len, &e1_attr); - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute failed\n"); - goto cleanup; - } - offset += field_len; } + offset += field_len; + } - // exponent #2 - // - rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); + // exponent #2 + // + rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_INTEGER failed\n"); + goto cleanup; + } else { + rc = build_attribute(CKA_EXPONENT_2, tmp, len, &e2_attr); if (rc != CKR_OK) { - TRACE_DEVEL("ber_decode_INTEGER failed\n"); + TRACE_DEVEL("build_attribute failed\n"); goto cleanup; - } else { - rc = build_attribute(CKA_EXPONENT_2, tmp, len, &e2_attr); - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute failed\n"); - goto cleanup; - } - offset += field_len; } + offset += field_len; + } - // coefficient - // - rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); + // coefficient + // + rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_INTEGER failed\n"); + goto cleanup; + } else { + rc = build_attribute(CKA_COEFFICIENT, tmp, len, &coeff_attr); if (rc != CKR_OK) { - TRACE_DEVEL("ber_decode_INTEGER failed\n"); + TRACE_DEVEL("build_attribute failed\n"); goto cleanup; - } else { - rc = build_attribute(CKA_COEFFICIENT, tmp, len, &coeff_attr); - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute failed\n"); - goto cleanup; - } - offset += len; } - *priv_exp = d_attr; - *prime1 = p_attr; - *prime2 = q_attr; - *exponent1 = e1_attr; - *exponent2 = e2_attr; - *coeff = coeff_attr; + offset += len; } + *priv_exp = d_attr; + *prime1 = p_attr; + *prime2 = q_attr; + *exponent1 = e1_attr; + *exponent2 = e2_attr; + *coeff = coeff_attr; *modulus = n_attr; *publ_exp = e_attr; @@ -1680,23 +1625,18 @@ cleanup: free(n_attr); if (e_attr) free(e_attr); - if (isopaque) { - if (o_attr) - free(o_attr); - } else { - if (d_attr) - free(d_attr); - if (p_attr) - free(p_attr); - if (q_attr) - free(q_attr); - if (e1_attr) - free(e1_attr); - if (e2_attr) - free(e2_attr); - if (coeff_attr) - free(coeff_attr); - } + if (d_attr) + free(d_attr); + if (p_attr) + free(p_attr); + if (q_attr) + free(q_attr); + if (e1_attr) + free(e1_attr); + if (e2_attr) + free(e2_attr); + if (coeff_attr) + free(coeff_attr); return rc; } @@ -2524,7 +2464,7 @@ CK_RV der_encode_ECPrivateKey(CK_BBOOL length_only, CK_ULONG *data_len, CK_ATTRIBUTE *params, CK_ATTRIBUTE *point, - CK_ATTRIBUTE *opaque, CK_ATTRIBUTE *pubkey) + CK_ATTRIBUTE *pubkey) { CK_BYTE *buf = NULL; CK_BYTE *buf2 = NULL; @@ -2548,15 +2488,9 @@ CK_RV der_encode_ECPrivateKey(CK_BBOOL length_only, offset += len; // private key octet - if (opaque != NULL) { - rc |= ber_encode_OCTET_STRING(TRUE, NULL, &len, NULL, - opaque->ulValueLen); - offset += len; - } else { - rc |= ber_encode_OCTET_STRING(TRUE, NULL, &len, NULL, - point->ulValueLen); - offset += len; - } + rc |= ber_encode_OCTET_STRING(TRUE, NULL, &len, NULL, + point->ulValueLen); + offset += len; if (rc != CKR_OK) { TRACE_DEVEL("der encoding failed\n"); return CKR_FUNCTION_FAILED; @@ -2616,33 +2550,18 @@ CK_RV der_encode_ECPrivateKey(CK_BBOOL length_only, buf2 = NULL; } - if (opaque != NULL) { - // the CKA_IBM_OPAQUE attrib - rc = ber_encode_OCTET_STRING(FALSE, &buf2, &len, - (CK_BYTE *) opaque + - sizeof(CK_ATTRIBUTE), opaque->ulValueLen); - if (rc != CKR_OK) { - TRACE_DEVEL("ber_encode_OCTET_STRING failed\n"); - goto error; - } + rc = ber_encode_OCTET_STRING(FALSE, &buf2, &len, + (CK_BYTE *) point + + sizeof(CK_ATTRIBUTE), point->ulValueLen); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_encode_INTEGER failed\n"); + goto error; + } + if (buf2 != NULL) { memcpy(buf + offset, buf2, len); offset += len; free(buf2); buf2 = NULL; - } else { - rc = ber_encode_OCTET_STRING(FALSE, &buf2, &len, - (CK_BYTE *) point + - sizeof(CK_ATTRIBUTE), point->ulValueLen); - if (rc != CKR_OK) { - TRACE_DEVEL("ber_encode_INTEGER failed\n"); - goto error; - } - if (buf2 != NULL) { - memcpy(buf + offset, buf2, len); - offset += len; - free(buf2); - buf2 = NULL; - } } /* generate optional bit-string of public key */ @@ -2709,12 +2628,10 @@ CK_RV der_decode_ECPrivateKey(CK_BYTE *data, CK_ULONG data_len, CK_ATTRIBUTE **params, CK_ATTRIBUTE **pub_key, - CK_ATTRIBUTE **priv_key, - CK_ATTRIBUTE **opaque_key, CK_BBOOL isOpaque) + CK_ATTRIBUTE **priv_key) { CK_ATTRIBUTE *pub_attr = NULL; CK_ATTRIBUTE *priv_attr = NULL; - CK_ATTRIBUTE *opaque_attr = NULL; CK_ATTRIBUTE *parm_attr = NULL; CK_BYTE *alg = NULL; CK_BYTE *buf = NULL; @@ -2731,6 +2648,24 @@ CK_RV der_decode_ECPrivateKey(CK_BYTE *data, CK_ULONG ecpoint_len; CK_RV rc; + /* + * For unwrapping, the data passed to this function may be larger than the + * actual sequence, due to padding. So look at the data only up to the + * length in the first SEQUENCE. + * Since an EC private key may include an optional public key, we need to + * know the actual length to be able to find out of the optional public key + * is present or not. + */ + rc = ber_decode_SEQUENCE(data, &buf, &buf_len, &field_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_SEQUENCE failed\n"); + return rc; + } + if (field_len > data_len) { + TRACE_DEVEL("passed data is too short\n"); + return CKR_FUNCTION_FAILED; + } + data_len = field_len; /* Decode PrivateKeyInfo into alg and eckey */ rc = ber_decode_PrivateKeyInfo(data, data_len, &alg, &alg_len, &eckey); @@ -2834,23 +2769,14 @@ CK_RV der_decode_ECPrivateKey(CK_BYTE *data, } /* Build attr for private key */ - if (isOpaque) { - rc = build_attribute(CKA_IBM_OPAQUE, priv_buf, priv_len, &opaque_attr); - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute for private key failed\n"); - goto cleanup; - } - } else { - rc = build_attribute(CKA_VALUE, priv_buf, priv_len, &priv_attr); - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute for private key failed\n"); - goto cleanup; - } + rc = build_attribute(CKA_VALUE, priv_buf, priv_len, &priv_attr); + if (rc != CKR_OK) { + TRACE_DEVEL("build_attribute for private key failed\n"); + goto cleanup; } *pub_key = pub_attr; // may be NULL if no BIT_STRING available - *priv_key = priv_attr; // may be NULL if key is opaque - *opaque_key = opaque_attr; + *priv_key = priv_attr; *params = parm_attr; if (ecpoint) free(ecpoint); @@ -2862,8 +2788,6 @@ cleanup: free(pub_attr); if (priv_attr) free(priv_attr); - if (opaque_attr) - free(opaque_attr); if (parm_attr) free(parm_attr); if (ecpoint) @@ -3847,8 +3771,7 @@ CK_RV ber_encode_IBM_DilithiumPrivateKey(CK_BBOOL length_only, CK_ATTRIBUTE *s1, CK_ATTRIBUTE *s2, CK_ATTRIBUTE *t0, - CK_ATTRIBUTE *t1, - CK_ATTRIBUTE *opaque) + CK_ATTRIBUTE *t1) { CK_BYTE *buf = NULL, *buf2 = NULL, *buf3 = NULL; CK_ULONG len, len2, offset; @@ -3861,27 +3784,22 @@ CK_RV ber_encode_IBM_DilithiumPrivateKey(CK_BBOOL length_only, rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, sizeof(version)); offset += len; - if (opaque != NULL) { - rc |= ber_encode_OCTET_STRING(TRUE, NULL, &len, NULL, opaque->ulValueLen); - offset += len; - } else { - rc |= ber_encode_BIT_STRING(TRUE, NULL, &len, NULL, rho->ulValueLen, 0); - offset += len; - rc |= ber_encode_BIT_STRING(TRUE, NULL, &len, NULL, seed->ulValueLen, 0); - offset += len; - rc |= ber_encode_BIT_STRING(TRUE, NULL, &len, NULL, tr->ulValueLen, 0); - offset += len; - rc |= ber_encode_BIT_STRING(TRUE, NULL, &len, NULL, s1->ulValueLen, 0); - offset += len; - rc |= ber_encode_BIT_STRING(TRUE, NULL, &len, NULL, s2->ulValueLen, 0); - offset += len; - rc |= ber_encode_BIT_STRING(TRUE, NULL, &len, NULL, t0->ulValueLen, 0); + rc |= ber_encode_BIT_STRING(TRUE, NULL, &len, NULL, rho->ulValueLen, 0); + offset += len; + rc |= ber_encode_BIT_STRING(TRUE, NULL, &len, NULL, seed->ulValueLen, 0); + offset += len; + rc |= ber_encode_BIT_STRING(TRUE, NULL, &len, NULL, tr->ulValueLen, 0); + offset += len; + rc |= ber_encode_BIT_STRING(TRUE, NULL, &len, NULL, s1->ulValueLen, 0); + offset += len; + rc |= ber_encode_BIT_STRING(TRUE, NULL, &len, NULL, s2->ulValueLen, 0); + offset += len; + rc |= ber_encode_BIT_STRING(TRUE, NULL, &len, NULL, t0->ulValueLen, 0); + offset += len; + if (t1) { + rc |= ber_encode_BIT_STRING(TRUE, NULL, &len2, NULL, t1->ulValueLen, 0); + rc |= ber_encode_CHOICE(TRUE, 0, NULL, &len, NULL, len2); offset += len; - if (t1) { - rc |= ber_encode_BIT_STRING(TRUE, NULL, &len2, NULL, t1->ulValueLen, 0); - rc |= ber_encode_CHOICE(TRUE, 0, NULL, &len, NULL, len2); - offset += len; - } } if (rc != CKR_OK) { @@ -3926,105 +3844,90 @@ CK_RV ber_encode_IBM_DilithiumPrivateKey(CK_BBOOL length_only, free(buf2); buf2 = NULL; - /* Check if key given as opaque blob */ - if (opaque != NULL) { - // the CKA_IBM_OPAQUE attrib - rc = ber_encode_OCTET_STRING(FALSE, &buf2, &len, - opaque->pValue, opaque->ulValueLen); - if (rc != CKR_OK) { - TRACE_ERROR("ber_encode_OCTET_STRING failed\n"); - goto error; - } - memcpy(buf + offset, buf2, len); - offset += len; - free(buf2); - buf2 = NULL; - } else { - /* rho */ - rc = ber_encode_BIT_STRING(FALSE, &buf2, &len, - rho->pValue, rho->ulValueLen, 0); - if (rc != CKR_OK) { - TRACE_ERROR("ber_encode_BIT_STRING of rho failed\n"); - goto error; - } - memcpy(buf + offset, buf2, len); - offset += len; - free(buf2); - buf2 = NULL; + /* rho */ + rc = ber_encode_BIT_STRING(FALSE, &buf2, &len, + rho->pValue, rho->ulValueLen, 0); + if (rc != CKR_OK) { + TRACE_ERROR("ber_encode_BIT_STRING of rho failed\n"); + goto error; + } + memcpy(buf + offset, buf2, len); + offset += len; + free(buf2); + buf2 = NULL; - /* seed */ - rc = ber_encode_BIT_STRING(FALSE, &buf2, &len, - seed->pValue, seed->ulValueLen, 0); - if (rc != CKR_OK) { - TRACE_ERROR("ber_encode_BIT_STRING of seed failed\n"); - goto error; - } - memcpy(buf + offset, buf2, len); - offset += len; - free(buf2); - buf2 = NULL; + /* seed */ + rc = ber_encode_BIT_STRING(FALSE, &buf2, &len, + seed->pValue, seed->ulValueLen, 0); + if (rc != CKR_OK) { + TRACE_ERROR("ber_encode_BIT_STRING of seed failed\n"); + goto error; + } + memcpy(buf + offset, buf2, len); + offset += len; + free(buf2); + buf2 = NULL; - /* tr */ - rc = ber_encode_BIT_STRING(FALSE, &buf2, &len, - tr->pValue, tr->ulValueLen, 0); - if (rc != CKR_OK) { - TRACE_ERROR("ber_encode_BIT_STRING of (tr) failed\n"); - goto error; - } - memcpy(buf + offset, buf2, len); - offset += len; - free(buf2); - buf2 = NULL; + /* tr */ + rc = ber_encode_BIT_STRING(FALSE, &buf2, &len, + tr->pValue, tr->ulValueLen, 0); + if (rc != CKR_OK) { + TRACE_ERROR("ber_encode_BIT_STRING of (tr) failed\n"); + goto error; + } + memcpy(buf + offset, buf2, len); + offset += len; + free(buf2); + buf2 = NULL; - /* s1 */ - rc = ber_encode_BIT_STRING(FALSE, &buf2, &len, - s1->pValue, s1->ulValueLen, 0); - if (rc != CKR_OK) { - TRACE_ERROR("ber_encode_BIT_STRING of (s1) failed\n"); - goto error; - } - memcpy(buf + offset, buf2, len); - offset += len; - free(buf2); - buf2 = NULL; + /* s1 */ + rc = ber_encode_BIT_STRING(FALSE, &buf2, &len, + s1->pValue, s1->ulValueLen, 0); + if (rc != CKR_OK) { + TRACE_ERROR("ber_encode_BIT_STRING of (s1) failed\n"); + goto error; + } + memcpy(buf + offset, buf2, len); + offset += len; + free(buf2); + buf2 = NULL; - /* s2 */ - rc = ber_encode_BIT_STRING(FALSE, &buf2, &len, - s2->pValue, s2->ulValueLen, 0); - if (rc != CKR_OK) { - TRACE_ERROR("ber_encode_BIT_STRING of (s2) failed\n"); - goto error; - } - memcpy(buf + offset, buf2, len); - offset += len; - free(buf2); - buf2 = NULL; + /* s2 */ + rc = ber_encode_BIT_STRING(FALSE, &buf2, &len, + s2->pValue, s2->ulValueLen, 0); + if (rc != CKR_OK) { + TRACE_ERROR("ber_encode_BIT_STRING of (s2) failed\n"); + goto error; + } + memcpy(buf + offset, buf2, len); + offset += len; + free(buf2); + buf2 = NULL; + + /* t0 */ + rc = ber_encode_BIT_STRING(FALSE, &buf2, &len, + t0->pValue, t0->ulValueLen, 0); + if (rc != CKR_OK) { + TRACE_ERROR("ber_encode_BIT_STRING of (t0) failed\n"); + goto error; + } + memcpy(buf + offset, buf2, len); + offset += len; + free(buf2); + buf2 = NULL; - /* t0 */ - rc = ber_encode_BIT_STRING(FALSE, &buf2, &len, - t0->pValue, t0->ulValueLen, 0); + /* (t1) Optional bit-string of public key */ + if (t1 && t1->pValue) { + rc = ber_encode_BIT_STRING(FALSE, &buf3, &len2, t1->pValue, t1->ulValueLen, 0); + rc |= ber_encode_CHOICE(FALSE, 0, &buf2, &len, buf3, len2); if (rc != CKR_OK) { - TRACE_ERROR("ber_encode_BIT_STRING of (t0) failed\n"); + TRACE_ERROR("encoding of t1 value failed\n"); goto error; } memcpy(buf + offset, buf2, len); offset += len; free(buf2); buf2 = NULL; - - /* (t1) Optional bit-string of public key */ - if (t1 && t1->pValue) { - rc = ber_encode_BIT_STRING(FALSE, &buf3, &len2, t1->pValue, t1->ulValueLen, 0); - rc |= ber_encode_CHOICE(FALSE, 0, &buf2, &len, buf3, len2); - if (rc != CKR_OK) { - TRACE_ERROR("encoding of t1 value failed\n"); - goto error; - } - memcpy(buf + offset, buf2, len); - offset += len; - free(buf2); - buf2 = NULL; - } } /* Encode sequence */ @@ -4076,14 +3979,11 @@ CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data, CK_ATTRIBUTE **s1, CK_ATTRIBUTE **s2, CK_ATTRIBUTE **t0, - CK_ATTRIBUTE **t1, - CK_ATTRIBUTE **opaque, - CK_BBOOL isopaque) + CK_ATTRIBUTE **t1) { CK_ATTRIBUTE *rho_attr = NULL, *seed_attr = NULL; CK_ATTRIBUTE *tr_attr = NULL, *s1_attr = NULL, *s2_attr = NULL; CK_ATTRIBUTE *t0_attr = NULL, *t1_attr = NULL; - CK_ATTRIBUTE *o_attr = NULL; CK_BYTE *alg = NULL; CK_BYTE *dilithium_priv_key = NULL; CK_BYTE *buf = NULL; @@ -4121,123 +4021,102 @@ CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data, } offset += field_len; - /* Check if key given as opaque blob */ - if (isopaque) { - - /* Key is opaque */ - rc = ber_decode_OCTET_STRING(buf + offset, &tmp, &len, &field_len); - if (rc != CKR_OK) { - TRACE_DEVEL("ber_decode_OCTET_STRING failed\n"); - goto cleanup; - } else { - rc = build_attribute(CKA_IBM_OPAQUE, tmp, len, &o_attr); - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute failed\n"); - goto cleanup; - } - offset += field_len; - } - *opaque = o_attr; - + /* rho */ + rc = ber_decode_BIT_STRING(buf + offset, &tmp, &len, &field_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_BIT_STRING of (rho) failed\n"); + goto cleanup; } else { - - /* rho */ - rc = ber_decode_BIT_STRING(buf + offset, &tmp, &len, &field_len); + rc = build_attribute(CKA_IBM_DILITHIUM_RHO, tmp, len, &rho_attr); if (rc != CKR_OK) { - TRACE_DEVEL("ber_decode_BIT_STRING of (rho) failed\n"); + TRACE_DEVEL("build_attribute for (rho) failed\n"); goto cleanup; - } else { - rc = build_attribute(CKA_IBM_DILITHIUM_RHO, tmp, len, &rho_attr); - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute for (rho) failed\n"); - goto cleanup; - } - offset += field_len; } + offset += field_len; + } - /* seed */ - rc = ber_decode_BIT_STRING(buf + offset, &tmp, &len, &field_len); + /* seed */ + rc = ber_decode_BIT_STRING(buf + offset, &tmp, &len, &field_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_BIT_STRING of (seed) failed\n"); + goto cleanup; + } else { + rc = build_attribute(CKA_IBM_DILITHIUM_SEED, tmp, len, &seed_attr); if (rc != CKR_OK) { - TRACE_DEVEL("ber_decode_BIT_STRING of (seed) failed\n"); + TRACE_DEVEL("build_attribute for (seed) failed\n"); goto cleanup; - } else { - rc = build_attribute(CKA_IBM_DILITHIUM_SEED, tmp, len, &seed_attr); - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute for (seed) failed\n"); - goto cleanup; - } - offset += field_len; } + offset += field_len; + } - /* tr */ - rc = ber_decode_BIT_STRING(buf + offset, &tmp, &len, &field_len); + /* tr */ + rc = ber_decode_BIT_STRING(buf + offset, &tmp, &len, &field_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_BIT_STRING of (tr) failed\n"); + goto cleanup; + } else { + rc = build_attribute(CKA_IBM_DILITHIUM_TR, tmp, len, &tr_attr); if (rc != CKR_OK) { - TRACE_DEVEL("ber_decode_BIT_STRING of (tr) failed\n"); + TRACE_DEVEL("build_attribute for (tr) failed\n"); goto cleanup; - } else { - rc = build_attribute(CKA_IBM_DILITHIUM_TR, tmp, len, &tr_attr); - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute for (tr) failed\n"); - goto cleanup; - } - offset += field_len; } + offset += field_len; + } - /* s1 */ - rc = ber_decode_BIT_STRING(buf + offset, &tmp, &len, &field_len); + /* s1 */ + rc = ber_decode_BIT_STRING(buf + offset, &tmp, &len, &field_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_BIT_STRING of (s1) failed\n"); + goto cleanup; + } else { + rc = build_attribute(CKA_IBM_DILITHIUM_S1, tmp, len, &s1_attr); if (rc != CKR_OK) { - TRACE_DEVEL("ber_decode_BIT_STRING of (s1) failed\n"); + TRACE_DEVEL("build_attribute for (s1) failed\n"); goto cleanup; - } else { - rc = build_attribute(CKA_IBM_DILITHIUM_S1, tmp, len, &s1_attr); - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute for (s1) failed\n"); - goto cleanup; - } - offset += field_len; } + offset += field_len; + } - /* s2 */ - rc = ber_decode_BIT_STRING(buf + offset, &tmp, &len, &field_len); + /* s2 */ + rc = ber_decode_BIT_STRING(buf + offset, &tmp, &len, &field_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_BIT_STRING of (s2) failed\n"); + goto cleanup; + } else { + rc = build_attribute(CKA_IBM_DILITHIUM_S2, tmp, len, &s2_attr); if (rc != CKR_OK) { - TRACE_DEVEL("ber_decode_BIT_STRING of (s2) failed\n"); + TRACE_DEVEL("build_attribute for (s2) failed\n"); goto cleanup; - } else { - rc = build_attribute(CKA_IBM_DILITHIUM_S2, tmp, len, &s2_attr); - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute for (s2) failed\n"); - goto cleanup; - } - offset += field_len; } + offset += field_len; + } - /* t0 */ - rc = ber_decode_BIT_STRING(buf + offset, &tmp, &len, &field_len); + /* t0 */ + rc = ber_decode_BIT_STRING(buf + offset, &tmp, &len, &field_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_BIT_STRING of (t0) failed\n"); + goto cleanup; + } else { + rc = build_attribute(CKA_IBM_DILITHIUM_T0, tmp, len, &t0_attr); if (rc != CKR_OK) { - TRACE_DEVEL("ber_decode_BIT_STRING of (t0) failed\n"); + TRACE_DEVEL("build_attribute for (t0) failed\n"); goto cleanup; - } else { - rc = build_attribute(CKA_IBM_DILITHIUM_T0, tmp, len, &t0_attr); - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute for (t0) failed\n"); - goto cleanup; - } - offset += field_len; } + offset += field_len; + } - /* t1 */ - rc = ber_decode_BIT_STRING(buf + offset, &tmp, &len, &field_len); + /* t1 */ + rc = ber_decode_BIT_STRING(buf + offset, &tmp, &len, &field_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_BIT_STRING of (t1) failed\n"); + goto cleanup; + } else { + rc = build_attribute(CKA_IBM_DILITHIUM_T1, tmp, len, &t1_attr); if (rc != CKR_OK) { - TRACE_DEVEL("ber_decode_BIT_STRING of (t1) failed\n"); + TRACE_DEVEL("build_attribute for (t1) failed\n"); goto cleanup; - } else { - rc = build_attribute(CKA_IBM_DILITHIUM_T1, tmp, len, &t1_attr); - if (rc != CKR_OK) { - TRACE_DEVEL("build_attribute for (t1) failed\n"); - goto cleanup; - } - offset += field_len; } + offset += field_len; } /* Check if buffer big enough */ @@ -4263,23 +4142,18 @@ cleanup: free(seed_attr); if (t1_attr) free(t1_attr); - if (isopaque) { - if (o_attr) - free(o_attr); - } else { - if (rho_attr) - free(rho_attr); - if (seed_attr) - free(seed_attr); - if (tr_attr) - free(tr_attr); - if (s1_attr) - free(s1_attr); - if (s2_attr) - free(s2_attr); - if (t0_attr) - free(t0_attr); - } + if (rho_attr) + free(rho_attr); + if (seed_attr) + free(seed_attr); + if (tr_attr) + free(tr_attr); + if (s1_attr) + free(s1_attr); + if (s2_attr) + free(s2_attr); + if (t0_attr) + free(t0_attr); return rc; } diff --git a/usr/lib/common/configparser.h b/usr/lib/common/configparser.h new file mode 100644 index 0000000..13ca648 --- /dev/null +++ b/usr/lib/common/configparser.h @@ -0,0 +1,76 @@ +/* + * 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 --git a/usr/lib/common/decr_mgr.c b/usr/lib/common/decr_mgr.c index d0a7816..c2f24b2 100644 --- a/usr/lib/common/decr_mgr.c +++ b/usr/lib/common/decr_mgr.c @@ -586,16 +586,7 @@ CK_RV decr_mgr_init(STDLL_TokData_t *tokdata, goto done; } - if ((mech->ulParameterLen > 0) || (mech->mechanism == CKM_AES_CTR) || - (mech->mechanism == CKM_AES_GCM)) { - ptr = (CK_BYTE *) malloc(mech->ulParameterLen); - if (!ptr) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - memcpy(ptr, mech->pParameter, mech->ulParameterLen); - } else if (mech->ulParameterLen > 0) { + if (mech->ulParameterLen > 0 && mech->pParameter != NULL) { ptr = (CK_BYTE *) malloc(mech->ulParameterLen); if (!ptr) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); diff --git a/usr/lib/common/defs.h b/usr/lib/common/defs.h index 7b5d15d..22d75d2 100644 --- a/usr/lib/common/defs.h +++ b/usr/lib/common/defs.h @@ -81,7 +81,6 @@ enum { #define MAX_RSA_KEYLEN 1920 -#define MAX_AES_KEY_SIZE 64 /* encompasses CCA key size */ #define AES_KEY_SIZE_256 32 #define AES_KEY_SIZE_192 24 #define AES_KEY_SIZE_128 16 @@ -89,7 +88,6 @@ enum { #define AES_INIT_VECTOR_SIZE AES_BLOCK_SIZE #define AES_COUNTER_SIZE 16 -#define MAX_DES_KEY_SIZE 64 /* encompasses CCA key size */ #define DES_KEY_SIZE 8 #define DES_BLOCK_SIZE 8 diff --git a/usr/lib/common/dig_mgr.c b/usr/lib/common/dig_mgr.c index bd6c0ac..b4d9ac6 100644 --- a/usr/lib/common/dig_mgr.c +++ b/usr/lib/common/dig_mgr.c @@ -100,7 +100,7 @@ CK_RV digest_mgr_init(STDLL_TokData_t *tokdata, return CKR_MECHANISM_INVALID; } - if (mech->ulParameterLen > 0) { + if (mech->ulParameterLen > 0 && mech->pParameter != NULL) { ptr = (CK_BYTE *) malloc(mech->ulParameterLen); if (!ptr) { digest_mgr_cleanup(ctx); // to de-initialize context above @@ -330,7 +330,7 @@ CK_RV digest_mgr_digest_key(STDLL_TokData_t *tokdata, /* * Secure keys can not be digested by digesting the CKA_VALUE attribute. */ - if (is_secure_key_token()) { + if (token_specific.secure_key_token) { TRACE_ERROR("%s because its a secure key token\n", ock_err(CKR_KEY_INDIGESTIBLE)); rc = CKR_KEY_INDIGESTIBLE; diff --git a/usr/lib/common/dp_obj.c b/usr/lib/common/dp_obj.c index e23148e..e1f8061 100644 --- a/usr/lib/common/dp_obj.c +++ b/usr/lib/common/dp_obj.c @@ -189,7 +189,8 @@ CK_RV dp_object_validate_attribute(TEMPLATE *tmpl, CK_ATTRIBUTE *attr, return CKR_ATTRIBUTE_READ_ONLY; case CKA_LOCAL: if (mode == MODE_CREATE || mode == MODE_KEYGEN) { - TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_TYPE_INVALID)); + TRACE_ERROR("%s: %lx\n", ock_err(ERR_ATTRIBUTE_TYPE_INVALID), + attr->type); return CKR_ATTRIBUTE_TYPE_INVALID; } return CKR_OK; diff --git a/usr/lib/common/ec_defs.h b/usr/lib/common/ec_defs.h index 0b13f03..1f48794 100644 --- a/usr/lib/common/ec_defs.h +++ b/usr/lib/common/ec_defs.h @@ -11,8 +11,16 @@ #ifndef _EC_DEFS #define _EC_DEFS +#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 diff --git a/usr/lib/common/encr_mgr.c b/usr/lib/common/encr_mgr.c index 6cd8d4c..621b339 100644 --- a/usr/lib/common/encr_mgr.c +++ b/usr/lib/common/encr_mgr.c @@ -24,6 +24,7 @@ #include "tok_spec_struct.h" #include "trace.h" +#include // // @@ -581,16 +582,7 @@ CK_RV encr_mgr_init(STDLL_TokData_t *tokdata, goto done; } - if ((mech->ulParameterLen > 0) || (mech->mechanism == CKM_AES_CTR) || - (mech->mechanism == CKM_AES_GCM)) { - ptr = (CK_BYTE *) malloc(mech->ulParameterLen); - if (!ptr) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - rc = CKR_HOST_MEMORY; - goto done; - } - memcpy(ptr, mech->pParameter, mech->ulParameterLen); - } else if (mech->ulParameterLen > 0) { + if (mech->ulParameterLen > 0 && mech->pParameter != NULL) { ptr = (CK_BYTE *) malloc(mech->ulParameterLen); if (!ptr) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); @@ -1056,3 +1048,145 @@ encr_mgr_encrypt_final(STDLL_TokData_t *tokdata, return CKR_FUNCTION_FAILED; } + +CK_RV encr_mgr_reencrypt_single(STDLL_TokData_t *tokdata, SESSION *sess, + ENCR_DECR_CONTEXT *decr_ctx, + CK_MECHANISM *decr_mech, + CK_OBJECT_HANDLE decr_key, + ENCR_DECR_CONTEXT *encr_ctx, + CK_MECHANISM *encr_mech, + CK_OBJECT_HANDLE encr_key, + CK_BYTE *in_data, CK_ULONG in_data_len, + CK_BYTE *out_data, CK_ULONG *out_data_len) +{ + OBJECT *decr_key_obj = NULL; + OBJECT *encr_key_obj = NULL; + CK_ATTRIBUTE *attr = NULL; + CK_ULONG decr_data_len = 0; + CK_BYTE *decr_data = NULL; + CK_BBOOL flag; + CK_RV rc; + + if (!sess || !decr_ctx || !encr_ctx || !decr_mech || !encr_mech) { + TRACE_ERROR("Invalid function arguments.\n"); + return CKR_FUNCTION_FAILED; + } + + if (decr_ctx->active != FALSE || encr_ctx->active != FALSE) { + TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); + return CKR_OPERATION_ACTIVE; + } + + if (token_specific.t_reencrypt_single != NULL) { + rc = object_mgr_find_in_map1(tokdata, decr_key, &decr_key_obj, + READ_LOCK); + if (rc != CKR_OK) { + TRACE_ERROR("Failed to acquire decr-key from specified handle.\n"); + if (rc == CKR_OBJECT_HANDLE_INVALID) + return CKR_KEY_HANDLE_INVALID; + else + return rc; + } + + rc = object_mgr_find_in_map1(tokdata, encr_key, &encr_key_obj, + READ_LOCK); + if (rc != CKR_OK) { + TRACE_ERROR("Failed to acquire encr-key from specified handle.\n"); + if (rc == CKR_OBJECT_HANDLE_INVALID) + return CKR_KEY_HANDLE_INVALID; + else + return rc; + } + + rc = template_attribute_find(decr_key_obj->template, CKA_DECRYPT, + &attr); + if (rc == FALSE) { + TRACE_ERROR("Could not find CKA_DECRYPT for the decr-key.\n"); + rc = CKR_KEY_FUNCTION_NOT_PERMITTED; + goto done; + } else { + flag = *(CK_BBOOL *)attr->pValue; + if (flag != TRUE) { + TRACE_ERROR("%s\n", ock_err(ERR_KEY_FUNCTION_NOT_PERMITTED)); + rc = CKR_KEY_FUNCTION_NOT_PERMITTED; + goto done; + } + } + + rc = template_attribute_find(encr_key_obj->template, CKA_ENCRYPT, + &attr); + if (rc == FALSE) { + TRACE_ERROR("Could not find CKA_ENCRYPT for the encr-key.\n"); + rc = CKR_KEY_FUNCTION_NOT_PERMITTED; + goto done; + } else { + flag = *(CK_BBOOL *)attr->pValue; + if (flag != TRUE) { + TRACE_ERROR("%s\n", ock_err(ERR_KEY_FUNCTION_NOT_PERMITTED)); + rc = CKR_KEY_FUNCTION_NOT_PERMITTED; + goto done; + } + } + + rc = token_specific.t_reencrypt_single(tokdata, sess, decr_ctx, + decr_mech, decr_key_obj, + encr_ctx, encr_mech, + encr_key_obj, in_data, + in_data_len, out_data, + out_data_len); + if (rc != CKR_OK) + TRACE_DEVEL("Token specific reencrypt single failed.\n"); + + goto done; + } + + /* No token specific reencrypt_single function, perform it manually */ + + rc = decr_mgr_init(tokdata, sess, decr_ctx, OP_DECRYPT_INIT, decr_mech, + decr_key); + if (rc != CKR_OK) + goto done; + + rc = encr_mgr_init(tokdata, sess, encr_ctx, OP_ENCRYPT_INIT, encr_mech, + encr_key); + if (rc != CKR_OK) + goto done; + + rc = decr_mgr_decrypt(tokdata, sess, TRUE, decr_ctx, in_data, in_data_len, + NULL, &decr_data_len); + if (rc != CKR_OK) + goto done; + + decr_data = malloc(decr_data_len); + if (decr_data == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + rc = CKR_HOST_MEMORY; + goto done; + } + + rc = decr_mgr_decrypt(tokdata, sess, FALSE, decr_ctx, in_data, in_data_len, + decr_data, &decr_data_len); + if (rc != CKR_OK) + goto done; + + rc = encr_mgr_encrypt(tokdata, sess, out_data == NULL, encr_ctx, decr_data, + decr_data_len, out_data, out_data_len); + if (rc != CKR_OK) + goto done; + +done: + object_put(tokdata, decr_key_obj, TRUE); + decr_key_obj = NULL; + object_put(tokdata, encr_key_obj, TRUE); + encr_key_obj = NULL; + + if (decr_data != NULL) { + OPENSSL_cleanse(decr_data, decr_data_len); + free(decr_data); + } + + decr_mgr_cleanup(decr_ctx); + encr_mgr_cleanup(encr_ctx); + + return rc; +} diff --git a/usr/lib/common/h_extern.h b/usr/lib/common/h_extern.h index 2d65994..a011a16 100644 --- a/usr/lib/common/h_extern.h +++ b/usr/lib/common/h_extern.h @@ -57,6 +57,8 @@ extern const CK_BYTE ber_idDH[]; extern const CK_ULONG ber_idDHLen; extern const CK_BYTE ber_idEC[]; extern const CK_ULONG ber_idECLen; +extern const CK_BYTE ber_idDilithium[]; +extern const CK_ULONG ber_idDilithiumLen; extern const CK_BYTE ber_md2WithRSAEncryption[]; extern const CK_ULONG ber_md2WithRSAEncryptionLen; @@ -428,7 +430,7 @@ CK_RV restore_private_token_object(STDLL_TokData_t *tokdata, CK_RV delete_token_object(STDLL_TokData_t *tokdata, OBJECT *ptr); CK_RV delete_token_data(STDLL_TokData_t *tokdata); -char *get_pk_dir(STDLL_TokData_t *tokdata, char *); +char *get_pk_dir(STDLL_TokData_t *tokdata, char *, size_t); CK_RV init_token_data(STDLL_TokData_t *, CK_SLOT_ID); CK_RV load_token_data(STDLL_TokData_t *, CK_SLOT_ID); @@ -441,8 +443,8 @@ CK_RV save_masterkey_user(STDLL_TokData_t *tokdata); CK_RV generate_master_key(STDLL_TokData_t *tokdata, CK_BYTE *key); -void init_data_store(STDLL_TokData_t *tokdata, char *directory, - char *data_store); +CK_RV init_data_store(STDLL_TokData_t *tokdata, char *directory, + char *data_store, size_t len); void final_data_store(STDLL_TokData_t * tokdata); void copy_token_contents_sensibly(CK_TOKEN_INFO_PTR pInfo, @@ -457,6 +459,8 @@ CK_RV compute_sha(STDLL_TokData_t *tokdata, CK_BYTE *data, CK_ULONG len, CK_RV get_sha_size(CK_ULONG mech, CK_ULONG *hsize); CK_RV get_sha_block_size(CK_ULONG mech, CK_ULONG *bsize); +CK_RV get_hmac_digest(CK_ULONG mech, CK_ULONG *digest_mech, CK_BBOOL *general); + CK_RV mgf1(STDLL_TokData_t *tokdata, CK_BYTE *seed, CK_ULONG seedlen, CK_BYTE *mask, CK_ULONG maskLen, CK_RSA_PKCS_MGF_TYPE mgf); @@ -1569,69 +1573,19 @@ CK_RV hmac_verify_final(STDLL_TokData_t *tokdata, SESSION *sess, CK_RV hmac_verify_init(STDLL_TokData_t *tokdata, SESSION *sess, CK_MECHANISM *mech, CK_OBJECT_HANDLE key); -CK_RV sha1_hmac_sign(STDLL_TokData_t *tokdata, - SESSION *sess, CK_BBOOL length_only, - SIGN_VERIFY_CONTEXT *ctx, - CK_BYTE *in_data, - CK_ULONG in_data_len, - CK_BYTE *out_data, CK_ULONG *out_data_len); - -CK_RV sha1_hmac_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 sha224_hmac_sign(STDLL_TokData_t *tokdata, - SESSION *sess, CK_BBOOL length_only, - SIGN_VERIFY_CONTEXT *ctx, - CK_BYTE *in_data, - CK_ULONG in_data_len, - CK_BYTE *out_data, CK_ULONG *out_data_len); - -CK_RV sha224_hmac_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 sha256_hmac_sign(STDLL_TokData_t *tokdata, - SESSION *sess, CK_BBOOL length_only, - SIGN_VERIFY_CONTEXT *ctx, - CK_BYTE *in_data, - CK_ULONG in_data_len, - CK_BYTE *out_data, CK_ULONG *out_data_len); - -CK_RV sha256_hmac_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 sha384_hmac_sign(STDLL_TokData_t *tokdata, - SESSION *sess, CK_BBOOL length_only, - SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, - CK_ULONG in_data_len, CK_BYTE *out_data, - CK_ULONG *out_data_len); - -CK_RV sha384_hmac_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 sha512_hmac_sign(STDLL_TokData_t *tokdata, - SESSION *sess, CK_BBOOL length_only, - SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, - CK_ULONG in_data_len, CK_BYTE *out_data, - CK_ULONG *out_data_len); +CK_RV sha_hmac_sign(STDLL_TokData_t *tokdata, + SESSION *sess, CK_BBOOL length_only, + SIGN_VERIFY_CONTEXT *ctx, + CK_BYTE *in_data, + CK_ULONG in_data_len, + CK_BYTE *out_data, CK_ULONG *out_data_len); -CK_RV sha512_hmac_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 sha_hmac_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); //adding the hmac secret key generation here CK_RV ckm_generic_secret_key_gen(STDLL_TokData_t *tokdata, TEMPLATE *tmpl); @@ -1848,6 +1802,16 @@ CK_RV encr_mgr_encrypt_update(STDLL_TokData_t *tokdata, SESSION *sess, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len); +CK_RV encr_mgr_reencrypt_single(STDLL_TokData_t *tokdata, SESSION *sess, + ENCR_DECR_CONTEXT *decr_ctx, + CK_MECHANISM *decr_mech, + CK_OBJECT_HANDLE decr_key, + ENCR_DECR_CONTEXT *encr_ctx, + CK_MECHANISM *encr_mech, + CK_OBJECT_HANDLE encr_key, + CK_BYTE *in_data, CK_ULONG in_data_len, + CK_BYTE *out_data, CK_ULONG *out_data_len); + // decryption manager routines // CK_RV decr_mgr_init(STDLL_TokData_t *tokdata, @@ -2341,6 +2305,12 @@ CK_RV data_object_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode); CK_RV data_object_validate_attribute(TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode); +// PROFILE OBJECT ROUTINES +CK_RV profile_object_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode); +CK_RV profile_object_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode); +CK_RV profile_object_validate_attribute(TEMPLATE *tmpl, CK_ATTRIBUTE *attr, + CK_ULONG mode); + // CERTIFICATE ROUTINES // CK_RV cert_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode); @@ -2373,7 +2343,7 @@ CK_RV publ_key_validate_attribute(STDLL_TokData_t *tokdata, CK_RV priv_key_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode); CK_RV priv_key_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode); CK_RV priv_key_unwrap(TEMPLATE *tmpl, CK_ULONG keytype, CK_BYTE *data, - CK_ULONG data_len, CK_BBOOL isopaque); + CK_ULONG data_len); CK_RV priv_key_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode); @@ -2382,7 +2352,7 @@ CK_RV secret_key_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode); CK_RV secret_key_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode); CK_RV secret_key_unwrap(STDLL_TokData_t *tokdata, TEMPLATE *tmpl, CK_ULONG keytype, CK_BYTE *data, CK_ULONG data_len, - CK_BBOOL fromend, CK_BBOOL isopaque); + CK_BBOOL fromend); CK_RV secret_key_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode); @@ -2400,8 +2370,7 @@ CK_RV rsa_priv_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode); CK_RV rsa_priv_wrap_get_data(TEMPLATE *tmpl, CK_BBOOL length_only, CK_BYTE **data, CK_ULONG *data_len); -CK_RV rsa_priv_unwrap(TEMPLATE *tmpl, CK_BYTE *data, CK_ULONG data_len, - CK_BBOOL isopaque); +CK_RV rsa_priv_unwrap(TEMPLATE *tmpl, CK_BYTE *data, CK_ULONG data_len); CK_RV rsa_priv_unwrap_get_data(TEMPLATE *tmpl, CK_BYTE *data, CK_ULONG total_length); @@ -2437,8 +2406,7 @@ CK_RV ecdsa_priv_wrap_get_data(TEMPLATE *tmpl, CK_BBOOL length_only, CK_BYTE **data, CK_ULONG *data_len); CK_RV ecdsa_priv_unwrap_get_data(TEMPLATE *tmpl, CK_BYTE *data, CK_ULONG data_len); -CK_RV ec_priv_unwrap(TEMPLATE *tmpl, - CK_BYTE *data, CK_ULONG data_len, CK_BBOOL isOpaque); +CK_RV ec_priv_unwrap(TEMPLATE *tmpl, CK_BYTE *data, CK_ULONG data_len); // Dilithium routines // @@ -2453,7 +2421,7 @@ CK_RV ibm_dilithium_priv_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE * CK_RV ibm_dilithium_priv_wrap_get_data(TEMPLATE *tmpl, CK_BBOOL length_only, CK_BYTE **data, CK_ULONG *data_len); CK_RV ibm_dilithium_priv_unwrap(TEMPLATE *tmpl, CK_BYTE *data, - CK_ULONG total_length, CK_BBOOL isOpaque); + CK_ULONG total_length); CK_RV ibm_dilithium_priv_unwrap_get_data(TEMPLATE *tmpl, CK_BYTE *data, CK_ULONG total_length); @@ -2497,7 +2465,7 @@ CK_RV generic_secret_validate_attribute(STDLL_TokData_t *tokdata, CK_RV generic_secret_wrap_get_data(TEMPLATE *tmpl, CK_BBOOL length_only, CK_BYTE **data, CK_ULONG *data_len); CK_RV generic_secret_unwrap(TEMPLATE *tmpl, CK_BYTE *data, CK_ULONG data_len, - CK_BBOOL fromend, CK_BBOOL isopaque); + CK_BBOOL fromend); // RC2 routines CK_RV rc2_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode); @@ -2522,7 +2490,7 @@ CK_RV des_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode); CK_BBOOL des_check_weak_key(CK_BYTE *key); CK_RV des_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode); CK_RV des_unwrap(STDLL_TokData_t *tokdata, TEMPLATE *tmpl, CK_BYTE *data, - CK_ULONG data_len, CK_BBOOL fromend, CK_BBOOL isopaque); + CK_ULONG data_len, CK_BBOOL fromend); CK_RV des_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode); CK_RV des_wrap_get_data(TEMPLATE *tmpl, CK_BBOOL length_only, CK_BYTE **data, @@ -2538,7 +2506,7 @@ CK_RV des2_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl, CK_RV des3_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode); CK_RV des3_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode); CK_RV des3_unwrap(STDLL_TokData_t *tokdata, TEMPLATE *tmpl, CK_BYTE *data, - CK_ULONG data_len, CK_BBOOL fromend, CK_BBOOL isopaque); + CK_ULONG data_len, CK_BBOOL fromend); CK_RV des3_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode); CK_RV des3_wrap_get_data(TEMPLATE *tmpl, CK_BBOOL length_only, CK_BYTE **data, @@ -2548,7 +2516,7 @@ CK_RV des3_wrap_get_data(TEMPLATE *tmpl, CK_BBOOL length_only, CK_BYTE **data, CK_RV aes_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode); CK_RV aes_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode); CK_RV aes_unwrap(STDLL_TokData_t *tokdata, TEMPLATE *tmpl, CK_BYTE *data, - CK_ULONG data_len, CK_BBOOL fromend, CK_BBOOL isopaque); + CK_ULONG data_len, CK_BBOOL fromend); CK_RV aes_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode); CK_RV aes_wrap_get_data(TEMPLATE *tmpl, CK_BBOOL length_only, CK_BYTE **data, @@ -2676,7 +2644,7 @@ CK_RV ber_encode_RSAPrivateKey(CK_BBOOL length_only, CK_ATTRIBUTE *prime2, CK_ATTRIBUTE *exponent1, CK_ATTRIBUTE *exponent2, - CK_ATTRIBUTE *coeff, CK_ATTRIBUTE *opaque); + CK_ATTRIBUTE *coeff); CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data, CK_ULONG data_len, @@ -2687,8 +2655,7 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data, CK_ATTRIBUTE **prime2, CK_ATTRIBUTE **exponent1, CK_ATTRIBUTE **exponent2, - CK_ATTRIBUTE **coeff, - CK_ATTRIBUTE **opaque, CK_BBOOL isopaque); + CK_ATTRIBUTE **coeff); CK_RV ber_encode_RSAPublicKey(CK_BBOOL length_only, CK_BYTE **data, CK_ULONG *data_len, CK_ATTRIBUTE *modulus, @@ -2704,14 +2671,13 @@ CK_RV der_encode_ECPrivateKey(CK_BBOOL length_only, CK_ULONG *data_len, CK_ATTRIBUTE *params, CK_ATTRIBUTE *point, - CK_ATTRIBUTE *opaque, CK_ATTRIBUTE *pubkey); + CK_ATTRIBUTE *pubkey); CK_RV der_decode_ECPrivateKey(CK_BYTE *data, CK_ULONG data_len, CK_ATTRIBUTE **params, CK_ATTRIBUTE **pub_key, - CK_ATTRIBUTE **priv_key, - CK_ATTRIBUTE **opaque_key, CK_BBOOL isOpaque); + CK_ATTRIBUTE **priv_key); CK_RV ber_encode_ECPublicKey(CK_BBOOL length_only, CK_BYTE **data, CK_ULONG *data_len, CK_ATTRIBUTE *params, @@ -2791,8 +2757,7 @@ CK_RV ber_encode_IBM_DilithiumPrivateKey(CK_BBOOL length_only, CK_ATTRIBUTE *s1, CK_ATTRIBUTE *s2, CK_ATTRIBUTE *t0, - CK_ATTRIBUTE *t1, - CK_ATTRIBUTE *opaque); + CK_ATTRIBUTE *t1); CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data, CK_ULONG data_len, @@ -2802,15 +2767,11 @@ CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data, CK_ATTRIBUTE **s1, CK_ATTRIBUTE **s2, CK_ATTRIBUTE **t0, - CK_ATTRIBUTE **t1, - CK_ATTRIBUTE **opaque, - CK_BBOOL isopaque); + CK_ATTRIBUTE **t1); #include "tok_spec_struct.h" extern token_spec_t token_specific; -CK_BBOOL is_secure_key_token(); - /* CKA_HIDDEN will be used to filter return results on a C_FindObjects call. * Used for objects internal to a token for management of that token */ diff --git a/usr/lib/common/hwf_obj.c b/usr/lib/common/hwf_obj.c index 176a39d..83b97f9 100644 --- a/usr/lib/common/hwf_obj.c +++ b/usr/lib/common/hwf_obj.c @@ -136,7 +136,7 @@ CK_RV hwf_validate_attribute(TEMPLATE *tmpl, CK_ATTRIBUTE *attr, return template_validate_base_attribute(tmpl, attr, mode); } - TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_TYPE_INVALID)); + TRACE_ERROR("%s: %lx\n", ock_err(ERR_ATTRIBUTE_TYPE_INVALID), attr->type); return CKR_ATTRIBUTE_TYPE_INVALID; } diff --git a/usr/lib/common/key.c b/usr/lib/common/key.c index 36da163..e643729 100644 --- a/usr/lib/common/key.c +++ b/usr/lib/common/key.c @@ -263,7 +263,7 @@ CK_RV key_object_validate_attribute(TEMPLATE *tmpl, CK_ATTRIBUTE *attr, return template_validate_base_attribute(tmpl, attr, mode); } - TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_TYPE_INVALID)); + TRACE_ERROR("%s: %lx\n", ock_err(ERR_ATTRIBUTE_TYPE_INVALID), attr->type); return CKR_ATTRIBUTE_TYPE_INVALID; } @@ -400,7 +400,7 @@ CK_RV publ_key_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl, return key_object_validate_attribute(tmpl, attr, mode); } - TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_TYPE_INVALID)); + TRACE_ERROR("%s: %lx\n", ock_err(ERR_ATTRIBUTE_TYPE_INVALID), attr->type); return CKR_ATTRIBUTE_TYPE_INVALID; } @@ -579,7 +579,7 @@ CK_RV priv_key_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode) // CK_RV priv_key_unwrap(TEMPLATE *tmpl, CK_ULONG keytype, - CK_BYTE *data, CK_ULONG data_len, CK_BBOOL isopaque) + CK_BYTE *data, CK_ULONG data_len) { CK_ATTRIBUTE *extractable = NULL; CK_ATTRIBUTE *always_sens = NULL; @@ -592,7 +592,7 @@ CK_RV priv_key_unwrap(TEMPLATE *tmpl, switch (keytype) { case CKK_RSA: - rc = rsa_priv_unwrap(tmpl, data, data_len, isopaque); + rc = rsa_priv_unwrap(tmpl, data, data_len); break; case CKK_DSA: rc = dsa_priv_unwrap(tmpl, data, data_len); @@ -601,10 +601,10 @@ CK_RV priv_key_unwrap(TEMPLATE *tmpl, rc = dh_priv_unwrap(tmpl, data, data_len); break; case CKK_EC: - rc = ec_priv_unwrap(tmpl, data, data_len, isopaque); + rc = ec_priv_unwrap(tmpl, data, data_len); break; case CKK_IBM_PQC_DILITHIUM: - rc = ibm_dilithium_priv_unwrap(tmpl, data, data_len, isopaque); + rc = ibm_dilithium_priv_unwrap(tmpl, data, data_len); break; default: TRACE_ERROR("%s\n", ock_err(ERR_WRAPPED_KEY_INVALID)); @@ -750,7 +750,7 @@ CK_RV priv_key_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl, return key_object_validate_attribute(tmpl, attr, mode); } - TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_TYPE_INVALID)); + TRACE_ERROR("%s: %lx\n", ock_err(ERR_ATTRIBUTE_TYPE_INVALID), attr->type); return CKR_ATTRIBUTE_TYPE_INVALID; } @@ -931,7 +931,7 @@ CK_RV secret_key_unwrap(STDLL_TokData_t *tokdata, TEMPLATE *tmpl, CK_ULONG keytype, CK_BYTE *data, - CK_ULONG data_len, CK_BBOOL fromend, CK_BBOOL isopaque) + CK_ULONG data_len, CK_BBOOL fromend) { CK_ATTRIBUTE *local = NULL; CK_ATTRIBUTE *always_sens = NULL; @@ -945,13 +945,13 @@ CK_RV secret_key_unwrap(STDLL_TokData_t *tokdata, switch (keytype) { case CKK_CDMF: case CKK_DES: - rc = des_unwrap(tokdata, tmpl, data, data_len, fromend, isopaque); + rc = des_unwrap(tokdata, tmpl, data, data_len, fromend); break; case CKK_DES3: - rc = des3_unwrap(tokdata, tmpl, data, data_len, fromend, isopaque); + rc = des3_unwrap(tokdata, tmpl, data, data_len, fromend); break; case CKK_AES: - rc = aes_unwrap(tokdata, tmpl, data, data_len, fromend, isopaque); + rc = aes_unwrap(tokdata, tmpl, data, data_len, fromend); break; case CKK_GENERIC_SECRET: case CKK_RC2: @@ -960,7 +960,7 @@ CK_RV secret_key_unwrap(STDLL_TokData_t *tokdata, case CKK_CAST: case CKK_CAST3: case CKK_CAST5: - rc = generic_secret_unwrap(tmpl, data, data_len, fromend, isopaque); + rc = generic_secret_unwrap(tmpl, data, data_len, fromend); break; default: TRACE_ERROR("%s\n", ock_err(ERR_WRAPPED_KEY_INVALID)); @@ -1099,7 +1099,7 @@ CK_RV secret_key_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl, return key_object_validate_attribute(tmpl, attr, mode); } - TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_TYPE_INVALID)); + TRACE_ERROR("%s: %lx\n", ock_err(ERR_ATTRIBUTE_TYPE_INVALID), attr->type); return CKR_ATTRIBUTE_TYPE_INVALID; } @@ -1520,7 +1520,6 @@ CK_RV rsa_priv_wrap_get_data(TEMPLATE *tmpl, CK_ATTRIBUTE *prime1 = NULL, *prime2 = NULL; CK_ATTRIBUTE *exponent1 = NULL, *exponent2 = NULL; CK_ATTRIBUTE *coeff = NULL; - CK_ATTRIBUTE *opaque = NULL; CK_RV rc; @@ -1534,40 +1533,35 @@ CK_RV rsa_priv_wrap_get_data(TEMPLATE *tmpl, TRACE_ERROR("Could not find CKA_PUBLIC_EXPONENT for the key.\n"); return CKR_FUNCTION_FAILED; } - // CKA_IBM_OPAQUE is used for secure key, if it is not available, then - // assume using clear key and get rest of attributes required for clear key. - - if (template_attribute_find(tmpl, CKA_IBM_OPAQUE, &opaque) == FALSE) { - if (template_attribute_find(tmpl, CKA_PRIVATE_EXPONENT, &priv_exp) == - FALSE) { - TRACE_ERROR("Could not find private exponent for the key.\n"); - return CKR_FUNCTION_FAILED; - } - if (template_attribute_find(tmpl, CKA_PRIME_1, &prime1) == FALSE) { - TRACE_ERROR("Could not find CKA_PRIME_1 for the key.\n"); - return CKR_FUNCTION_FAILED; - } - if (template_attribute_find(tmpl, CKA_PRIME_2, &prime2) == FALSE) { - TRACE_ERROR("Could not find CKA_PRIME_2 for the key.\n"); - return CKR_FUNCTION_FAILED; - } - if (template_attribute_find(tmpl, CKA_EXPONENT_1, &exponent1) == FALSE) { - TRACE_ERROR("Could not find CKA_EXPONENT_1 for the key.\n"); - return CKR_FUNCTION_FAILED; - } - if (template_attribute_find(tmpl, CKA_EXPONENT_2, &exponent2) == FALSE) { - TRACE_ERROR("Could not find CKA_EXPONENT_2 for the key.\n"); - return CKR_FUNCTION_FAILED; - } - if (template_attribute_find(tmpl, CKA_COEFFICIENT, &coeff) == FALSE) { - TRACE_ERROR("Could not find CKA_COEFFICIENT for the key.\n"); - return CKR_FUNCTION_FAILED; - } + if (template_attribute_find(tmpl, CKA_PRIVATE_EXPONENT, &priv_exp) == + FALSE) { + TRACE_ERROR("Could not find private exponent for the key.\n"); + return CKR_FUNCTION_FAILED; + } + if (template_attribute_find(tmpl, CKA_PRIME_1, &prime1) == FALSE) { + TRACE_ERROR("Could not find CKA_PRIME_1 for the key.\n"); + return CKR_FUNCTION_FAILED; + } + if (template_attribute_find(tmpl, CKA_PRIME_2, &prime2) == FALSE) { + TRACE_ERROR("Could not find CKA_PRIME_2 for the key.\n"); + return CKR_FUNCTION_FAILED; + } + if (template_attribute_find(tmpl, CKA_EXPONENT_1, &exponent1) == FALSE) { + TRACE_ERROR("Could not find CKA_EXPONENT_1 for the key.\n"); + return CKR_FUNCTION_FAILED; + } + if (template_attribute_find(tmpl, CKA_EXPONENT_2, &exponent2) == FALSE) { + TRACE_ERROR("Could not find CKA_EXPONENT_2 for the key.\n"); + return CKR_FUNCTION_FAILED; + } + if (template_attribute_find(tmpl, CKA_COEFFICIENT, &coeff) == FALSE) { + TRACE_ERROR("Could not find CKA_COEFFICIENT for the key.\n"); + return CKR_FUNCTION_FAILED; } rc = ber_encode_RSAPrivateKey(length_only, data, data_len, modulus, publ_exp, priv_exp, prime1, prime2, - exponent1, exponent2, coeff, opaque); + exponent1, exponent2, coeff); if (rc != CKR_OK) { TRACE_DEVEL("ber_encode_RSAPrivateKey failed\n"); } @@ -1578,8 +1572,7 @@ CK_RV rsa_priv_wrap_get_data(TEMPLATE *tmpl, // // -CK_RV rsa_priv_unwrap(TEMPLATE *tmpl, - CK_BYTE *data, CK_ULONG total_length, CK_BBOOL isopaque) +CK_RV rsa_priv_unwrap(TEMPLATE *tmpl, CK_BYTE *data, CK_ULONG total_length) { CK_ATTRIBUTE *modulus = NULL; CK_ATTRIBUTE *publ_exp = NULL; @@ -1589,7 +1582,6 @@ CK_RV rsa_priv_unwrap(TEMPLATE *tmpl, CK_ATTRIBUTE *exponent1 = NULL; CK_ATTRIBUTE *exponent2 = NULL; CK_ATTRIBUTE *coeff = NULL; - CK_ATTRIBUTE *opaque = NULL; CK_RV rc; rc = ber_decode_RSAPrivateKey(data, @@ -1600,7 +1592,7 @@ CK_RV rsa_priv_unwrap(TEMPLATE *tmpl, &prime1, &prime2, &exponent1, - &exponent2, &coeff, &opaque, isopaque); + &exponent2, &coeff); if (rc != CKR_OK) { TRACE_DEVEL("ber_decode_RSAPrivateKey failed\n"); @@ -1608,29 +1600,21 @@ CK_RV rsa_priv_unwrap(TEMPLATE *tmpl, } p11_attribute_trim(modulus); p11_attribute_trim(publ_exp); - if (isopaque) { - p11_attribute_trim(opaque); - } else { - p11_attribute_trim(priv_exp); - p11_attribute_trim(prime1); - p11_attribute_trim(prime2); - p11_attribute_trim(exponent1); - p11_attribute_trim(exponent2); - p11_attribute_trim(coeff); - } + p11_attribute_trim(priv_exp); + p11_attribute_trim(prime1); + p11_attribute_trim(prime2); + p11_attribute_trim(exponent1); + p11_attribute_trim(exponent2); + p11_attribute_trim(coeff); template_update_attribute(tmpl, modulus); template_update_attribute(tmpl, publ_exp); - if (isopaque) { - template_update_attribute(tmpl, opaque); - } else { - template_update_attribute(tmpl, priv_exp); - template_update_attribute(tmpl, prime1); - template_update_attribute(tmpl, prime2); - template_update_attribute(tmpl, exponent1); - template_update_attribute(tmpl, exponent2); - template_update_attribute(tmpl, coeff); - } + template_update_attribute(tmpl, priv_exp); + template_update_attribute(tmpl, prime1); + template_update_attribute(tmpl, prime2); + template_update_attribute(tmpl, exponent1); + template_update_attribute(tmpl, exponent2); + template_update_attribute(tmpl, coeff); return CKR_OK; } @@ -1670,7 +1654,6 @@ CK_RV ibm_dilithium_priv_wrap_get_data(TEMPLATE *tmpl, CK_ATTRIBUTE *keyform, *rho = NULL, *seed = NULL; CK_ATTRIBUTE *tr = NULL, *s1 = NULL, *s2 = NULL; CK_ATTRIBUTE *t0 = NULL, *t1 = NULL; - CK_ATTRIBUTE *opaque = NULL; CK_RV rc; /* A private Dilithium key must have a keyform value */ @@ -1686,48 +1669,43 @@ CK_RV ibm_dilithium_priv_wrap_get_data(TEMPLATE *tmpl, return CKR_TEMPLATE_INCONSISTENT; } - /* Check if key given as opaque blob */ - if (template_attribute_find(tmpl, CKA_IBM_OPAQUE, &opaque) == FALSE) { - - if (template_attribute_find(tmpl, CKA_IBM_DILITHIUM_RHO, &rho) == FALSE) { - TRACE_ERROR("Could not find CKA_IBM_DILITHIUM_RHO for the key.\n"); - return CKR_TEMPLATE_INCONSISTENT; - } + if (template_attribute_find(tmpl, CKA_IBM_DILITHIUM_RHO, &rho) == FALSE) { + TRACE_ERROR("Could not find CKA_IBM_DILITHIUM_RHO for the key.\n"); + return CKR_TEMPLATE_INCONSISTENT; + } - if (template_attribute_find(tmpl, CKA_IBM_DILITHIUM_SEED, &seed) == FALSE) { - TRACE_ERROR("Could not find CKA_IBM_DILITHIUM_SEED for the key.\n"); - return CKR_TEMPLATE_INCONSISTENT; - } + if (template_attribute_find(tmpl, CKA_IBM_DILITHIUM_SEED, &seed) == FALSE) { + TRACE_ERROR("Could not find CKA_IBM_DILITHIUM_SEED for the key.\n"); + return CKR_TEMPLATE_INCONSISTENT; + } - if (template_attribute_find(tmpl, CKA_IBM_DILITHIUM_TR, &tr) == FALSE) { - TRACE_ERROR("Could not find CKA_IBM_DILITHIUM_TR for the key.\n"); - return CKR_TEMPLATE_INCONSISTENT; - } + if (template_attribute_find(tmpl, CKA_IBM_DILITHIUM_TR, &tr) == FALSE) { + TRACE_ERROR("Could not find CKA_IBM_DILITHIUM_TR for the key.\n"); + return CKR_TEMPLATE_INCONSISTENT; + } - if (template_attribute_find(tmpl, CKA_IBM_DILITHIUM_S1, &s1) == FALSE) { - TRACE_ERROR("Could not find CKA_IBM_DILITHIUM_S1 for the key.\n"); - return CKR_TEMPLATE_INCONSISTENT; - } + if (template_attribute_find(tmpl, CKA_IBM_DILITHIUM_S1, &s1) == FALSE) { + TRACE_ERROR("Could not find CKA_IBM_DILITHIUM_S1 for the key.\n"); + return CKR_TEMPLATE_INCONSISTENT; + } - if (template_attribute_find(tmpl, CKA_IBM_DILITHIUM_S2, &s2) == FALSE) { - TRACE_ERROR("Could not find CKA_IBM_DILITHIUM_S2 for the key.\n"); - return CKR_TEMPLATE_INCONSISTENT; - } + if (template_attribute_find(tmpl, CKA_IBM_DILITHIUM_S2, &s2) == FALSE) { + TRACE_ERROR("Could not find CKA_IBM_DILITHIUM_S2 for the key.\n"); + return CKR_TEMPLATE_INCONSISTENT; + } - if (template_attribute_find(tmpl, CKA_IBM_DILITHIUM_T0, &t0) == FALSE) { - TRACE_ERROR("Could not find CKA_IBM_DILITHIUM_T0 for the key.\n"); - return CKR_TEMPLATE_INCONSISTENT; - } + if (template_attribute_find(tmpl, CKA_IBM_DILITHIUM_T0, &t0) == FALSE) { + TRACE_ERROR("Could not find CKA_IBM_DILITHIUM_T0 for the key.\n"); + return CKR_TEMPLATE_INCONSISTENT; + } - if (template_attribute_find(tmpl, CKA_IBM_DILITHIUM_T1, &t1) == FALSE) { - TRACE_ERROR("Could not find CKA_IBM_DILITHIUM_T1 for the key.\n"); - return CKR_TEMPLATE_INCONSISTENT; - } + if (template_attribute_find(tmpl, CKA_IBM_DILITHIUM_T1, &t1) == FALSE) { + TRACE_ERROR("Could not find CKA_IBM_DILITHIUM_T1 for the key.\n"); + return CKR_TEMPLATE_INCONSISTENT; } rc = ber_encode_IBM_DilithiumPrivateKey(length_only, data, data_len, - rho, seed, tr, s1, s2, t0, t1, - opaque); + rho, seed, tr, s1, s2, t0, t1); if (rc != CKR_OK) { TRACE_DEVEL("ber_encode_IBM_DilithiumPrivateKey failed\n"); } @@ -1765,25 +1743,20 @@ CK_RV ibm_dilithium_priv_unwrap_get_data(TEMPLATE *tmpl, CK_BYTE *data, // // CK_RV ibm_dilithium_priv_unwrap(TEMPLATE *tmpl, CK_BYTE *data, - CK_ULONG total_length, CK_BBOOL isOpaque) + CK_ULONG total_length) { CK_ATTRIBUTE *rho = NULL, *seed = NULL, *tr = NULL; CK_ATTRIBUTE *s1 = NULL, *s2 = NULL, *t0 = NULL, *t1 = NULL; - CK_ATTRIBUTE *opaque = NULL; CK_RV rc; rc = ber_decode_IBM_DilithiumPrivateKey(data, total_length, - &rho, &seed, &tr, &s1, &s2, &t0, &t1, - &opaque, isOpaque); + &rho, &seed, &tr, &s1, &s2, &t0, &t1); if (rc != CKR_OK) { TRACE_ERROR("der_decode_IBM_DilithiumPrivateKey failed\n"); return rc; } - if (isOpaque) - rc |= template_update_attribute(tmpl, opaque); - - rc |= template_update_attribute(tmpl, rho); + rc = template_update_attribute(tmpl, rho); rc |= template_update_attribute(tmpl, seed); rc |= template_update_attribute(tmpl, tr); rc |= template_update_attribute(tmpl, s1); @@ -2535,7 +2508,6 @@ CK_RV ecdsa_priv_wrap_get_data(TEMPLATE *tmpl, { CK_ATTRIBUTE *params = NULL; CK_ATTRIBUTE *point = NULL; - CK_ATTRIBUTE *opaque = NULL; CK_ATTRIBUTE *pubkey = NULL; CK_RV rc; @@ -2550,21 +2522,16 @@ CK_RV ecdsa_priv_wrap_get_data(TEMPLATE *tmpl, TRACE_ERROR("Could not find CKA_EC_POINT for the key.\n"); return CKR_FUNCTION_FAILED; } - // CKA_IBM_OPAQUE is used for secure key, if it is not available, then - // assume using clear key and get rest of attributes required for clear key. - - if (template_attribute_find(tmpl, CKA_IBM_OPAQUE, &opaque) == FALSE) { - if (template_attribute_find(tmpl, CKA_VALUE, &point) == FALSE) { - TRACE_ERROR("Could not find EC Point for the key.\n"); - return CKR_FUNCTION_FAILED; - } + if (template_attribute_find(tmpl, CKA_VALUE, &point) == FALSE) { + TRACE_ERROR("Could not find EC Point for the key.\n"); + return CKR_FUNCTION_FAILED; } /* check if optional public-key part was defined */ template_attribute_find(tmpl, CKA_EC_POINT, &pubkey); rc = der_encode_ECPrivateKey(length_only, data, data_len, params, - point, opaque, pubkey); + point, pubkey); if (rc != CKR_OK) { TRACE_DEVEL("der_encode_ECPrivateKey failed\n"); } @@ -2601,17 +2568,15 @@ CK_RV ecdsa_priv_unwrap_get_data(TEMPLATE *tmpl, // // -CK_RV ec_priv_unwrap(TEMPLATE *tmpl, - CK_BYTE *data, CK_ULONG total_length, CK_BBOOL isOpaque) +CK_RV ec_priv_unwrap(TEMPLATE *tmpl, CK_BYTE *data, CK_ULONG total_length) { CK_ATTRIBUTE *pubkey = NULL; CK_ATTRIBUTE *privkey = NULL; - CK_ATTRIBUTE *opaque = NULL; CK_ATTRIBUTE *ecparam = NULL; CK_RV rc; rc = der_decode_ECPrivateKey(data, total_length, &ecparam, - &pubkey, &privkey, &opaque, isOpaque); + &pubkey, &privkey); if (rc != CKR_OK) { TRACE_DEVEL("der_decode_ECPrivateKey failed\n"); @@ -2620,8 +2585,6 @@ CK_RV ec_priv_unwrap(TEMPLATE *tmpl, p11_attribute_trim(pubkey); p11_attribute_trim(privkey); - if (isOpaque) - template_update_attribute(tmpl, opaque); if (pubkey) template_update_attribute(tmpl, pubkey); if (privkey) @@ -3972,13 +3935,10 @@ CK_RV generic_secret_wrap_get_data(TEMPLATE *tmpl, return CKR_FUNCTION_FAILED; } - rc = template_attribute_find(tmpl, CKA_IBM_OPAQUE, &attr); + rc = template_attribute_find(tmpl, CKA_VALUE, &attr); if (rc == FALSE) { - rc = template_attribute_find(tmpl, CKA_VALUE, &attr); - if (rc == FALSE) { - TRACE_ERROR("%s\n", ock_err(ERR_KEY_NOT_WRAPPABLE)); - return CKR_KEY_NOT_WRAPPABLE; - } + TRACE_ERROR("%s\n", ock_err(ERR_KEY_NOT_WRAPPABLE)); + return CKR_KEY_NOT_WRAPPABLE; } *data_len = attr->ulValueLen; @@ -4002,7 +3962,7 @@ CK_RV generic_secret_wrap_get_data(TEMPLATE *tmpl, CK_RV generic_secret_unwrap(TEMPLATE *tmpl, CK_BYTE *data, CK_ULONG data_len, - CK_BBOOL fromend, CK_BBOOL isopaque) + CK_BBOOL fromend) { CK_ATTRIBUTE *attr = NULL; CK_ATTRIBUTE *value_attr = NULL; @@ -4035,10 +3995,7 @@ CK_RV generic_secret_unwrap(TEMPLATE *tmpl, if (fromend == TRUE) ptr -= data_len; - if (isopaque) - rc = build_attribute(CKA_IBM_OPAQUE, ptr, data_len, &value_attr); - else - rc = build_attribute(CKA_VALUE, ptr, data_len, &value_attr); + rc = build_attribute(CKA_VALUE, ptr, data_len, &value_attr); if (rc != CKR_OK) { TRACE_DEVEL("build_attribute failed\n"); @@ -4512,7 +4469,7 @@ CK_RV des_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode) CK_RV des_unwrap(STDLL_TokData_t *tokdata, TEMPLATE *tmpl, CK_BYTE *data, - CK_ULONG data_len, CK_BBOOL fromend, CK_BBOOL isopaque) + CK_ULONG data_len, CK_BBOOL fromend) { CK_ATTRIBUTE *value_attr = NULL; CK_BYTE *ptr = NULL; @@ -4523,46 +4480,30 @@ CK_RV des_unwrap(STDLL_TokData_t *tokdata, TRACE_ERROR("%s\n", ock_err(ERR_WRAPPED_KEY_INVALID)); return CKR_WRAPPED_KEY_INVALID; } - if (fromend == TRUE) { - if (isopaque) - ptr = data + data_len; - else - ptr = data + data_len - DES_BLOCK_SIZE; - } else { + if (fromend == TRUE) + ptr = data + data_len - DES_BLOCK_SIZE; + else ptr = data; - } - if (isopaque) { - value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + data_len); - } else { - if (tokdata->nv_token_data->tweak_vector.check_des_parity == TRUE) { - for (i = 0; i < DES_KEY_SIZE; i++) { - if (parity_is_odd(ptr[i]) == FALSE) { - TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); - return CKR_ATTRIBUTE_VALUE_INVALID; - } + if (tokdata->nv_token_data->tweak_vector.check_des_parity == TRUE) { + for (i = 0; i < DES_KEY_SIZE; i++) { + if (parity_is_odd(ptr[i]) == FALSE) { + TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); + return CKR_ATTRIBUTE_VALUE_INVALID; } } - value_attr = - (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + DES_BLOCK_SIZE); } - + value_attr = + (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + DES_BLOCK_SIZE); if (!value_attr) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } - if (isopaque) { - value_attr->type = CKA_IBM_OPAQUE; - value_attr->ulValueLen = data_len; - value_attr->pValue = (CK_BYTE *) value_attr + sizeof(CK_ATTRIBUTE); - memcpy(value_attr->pValue, ptr, data_len); - } else { - value_attr->type = CKA_VALUE; - value_attr->ulValueLen = DES_BLOCK_SIZE; - value_attr->pValue = (CK_BYTE *) value_attr + sizeof(CK_ATTRIBUTE); - memcpy(value_attr->pValue, ptr, DES_BLOCK_SIZE); - } + value_attr->type = CKA_VALUE; + value_attr->ulValueLen = DES_BLOCK_SIZE; + value_attr->pValue = (CK_BYTE *) value_attr + sizeof(CK_ATTRIBUTE); + memcpy(value_attr->pValue, ptr, DES_BLOCK_SIZE); template_update_attribute(tmpl, value_attr); @@ -4641,13 +4582,10 @@ CK_RV des_wrap_get_data(TEMPLATE *tmpl, return CKR_FUNCTION_FAILED; } - rc = template_attribute_find(tmpl, CKA_IBM_OPAQUE, &attr); + rc = template_attribute_find(tmpl, CKA_VALUE, &attr); if (rc == FALSE) { - rc = template_attribute_find(tmpl, CKA_VALUE, &attr); - if (rc == FALSE) { - TRACE_ERROR("%s\n", ock_err(ERR_KEY_NOT_WRAPPABLE)); - return CKR_KEY_NOT_WRAPPABLE; - } + TRACE_ERROR("%s\n", ock_err(ERR_KEY_NOT_WRAPPABLE)); + return CKR_KEY_NOT_WRAPPABLE; } *data_len = attr->ulValueLen; @@ -4848,7 +4786,7 @@ CK_RV des3_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode) CK_RV des3_unwrap(STDLL_TokData_t *tokdata, TEMPLATE *tmpl, CK_BYTE *data, - CK_ULONG data_len, CK_BBOOL fromend, CK_BBOOL isopaque) + CK_ULONG data_len, CK_BBOOL fromend) { CK_ATTRIBUTE *value_attr = NULL; CK_BYTE *ptr = NULL; @@ -4859,47 +4797,31 @@ CK_RV des3_unwrap(STDLL_TokData_t *tokdata, TRACE_ERROR("%s\n", ock_err(ERR_WRAPPED_KEY_INVALID)); return CKR_WRAPPED_KEY_INVALID; } - if (fromend == TRUE) { - if (isopaque) - ptr = data + data_len; - else - ptr = data + data_len - (3 * DES_BLOCK_SIZE); - } else { + if (fromend == TRUE) + ptr = data + data_len - (3 * DES_BLOCK_SIZE); + else ptr = data; - } - if (isopaque) { - value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + data_len); - } else { - if (tokdata->nv_token_data->tweak_vector.check_des_parity == TRUE) { - for (i = 0; i < 3 * DES_KEY_SIZE; i++) { - if (parity_is_odd(ptr[i]) == FALSE) { - TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); - return CKR_ATTRIBUTE_VALUE_INVALID; - } + if (tokdata->nv_token_data->tweak_vector.check_des_parity == TRUE) { + for (i = 0; i < 3 * DES_KEY_SIZE; i++) { + if (parity_is_odd(ptr[i]) == FALSE) { + TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); + return CKR_ATTRIBUTE_VALUE_INVALID; } } - value_attr = - (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + - (3 * DES_BLOCK_SIZE)); } + value_attr = + (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + (3 * DES_BLOCK_SIZE)); if (!value_attr) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } - if (isopaque) { - value_attr->type = CKA_IBM_OPAQUE; - value_attr->ulValueLen = data_len; - value_attr->pValue = (CK_BYTE *) value_attr + sizeof(CK_ATTRIBUTE); - memcpy(value_attr->pValue, ptr, data_len); - } else { - value_attr->type = CKA_VALUE; - value_attr->ulValueLen = 3 * DES_BLOCK_SIZE; - value_attr->pValue = (CK_BYTE *) value_attr + sizeof(CK_ATTRIBUTE); - memcpy(value_attr->pValue, ptr, 3 * DES_BLOCK_SIZE); - } + value_attr->type = CKA_VALUE; + value_attr->ulValueLen = 3 * DES_BLOCK_SIZE; + value_attr->pValue = (CK_BYTE *) value_attr + sizeof(CK_ATTRIBUTE); + memcpy(value_attr->pValue, ptr, 3 * DES_BLOCK_SIZE); template_update_attribute(tmpl, value_attr); @@ -4972,14 +4894,11 @@ CK_RV des3_wrap_get_data(TEMPLATE *tmpl, TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } - // try secure key first, if not found then try clear key... - rc = template_attribute_find(tmpl, CKA_IBM_OPAQUE, &attr); + + rc = template_attribute_find(tmpl, CKA_VALUE, &attr); if (rc == FALSE) { - rc = template_attribute_find(tmpl, CKA_VALUE, &attr); - if (rc == FALSE) { - TRACE_ERROR("%s\n", ock_err(ERR_KEY_NOT_WRAPPABLE)); - return CKR_KEY_NOT_WRAPPABLE; - } + TRACE_ERROR("%s\n", ock_err(ERR_KEY_NOT_WRAPPABLE)); + return CKR_KEY_NOT_WRAPPABLE; } *data_len = attr->ulValueLen; @@ -5918,13 +5837,10 @@ CK_RV aes_wrap_get_data(TEMPLATE *tmpl, return CKR_FUNCTION_FAILED; } - rc = template_attribute_find(tmpl, CKA_IBM_OPAQUE, &attr); + rc = template_attribute_find(tmpl, CKA_VALUE, &attr); if (rc == FALSE) { - rc = template_attribute_find(tmpl, CKA_VALUE, &attr); - if (rc == FALSE) { - TRACE_ERROR("%s\n", ock_err(ERR_KEY_NOT_WRAPPABLE)); - return CKR_KEY_NOT_WRAPPABLE; - } + TRACE_ERROR("%s\n", ock_err(ERR_KEY_NOT_WRAPPABLE)); + return CKR_KEY_NOT_WRAPPABLE; } *data_len = attr->ulValueLen; @@ -5947,7 +5863,7 @@ CK_RV aes_wrap_get_data(TEMPLATE *tmpl, CK_RV aes_unwrap(STDLL_TokData_t *tokdata, TEMPLATE *tmpl, CK_BYTE *data, - CK_ULONG data_len, CK_BBOOL fromend, CK_BBOOL isopaque) + CK_ULONG data_len, CK_BBOOL fromend) { CK_ATTRIBUTE *value_attr = NULL; CK_ATTRIBUTE *val_len_attr = NULL; @@ -5961,27 +5877,15 @@ CK_RV aes_unwrap(STDLL_TokData_t *tokdata, * unwrapping an AES key, but we need it for several reasons: * - because some mechanisms may have added padding * - AES keys come in several sizes - * - secure key size depends on token specifics - * If not a secure key, try datalen and see if matches an aes key size. + * If not a available, try datalen and see if matches an aes key size. * Otherwise, fail because we need to return CKA_VALUE_LEN and we cannot - * unless user tells us what it is for secure key. - * - * Note: since cca token has secure key size of 64, which is a multiple of - * aes blocksize, can assume datalen will always be 64. - * However, a better solution is to create a token specific wrap and - * unwrap and do this kind of stuff in the token. + * unless user tells us what it is. */ found = template_attribute_find(tmpl, CKA_VALUE_LEN, &val_len_attr); - if (found) { + if (found) key_size = *(CK_ULONG *) val_len_attr->pValue; - } else { - if (isopaque) { - TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); - return CKR_TEMPLATE_INCOMPLETE; - } else { - key_size = data_len; - } - } + else + key_size = data_len; /* key_size should be one of AES's possible sizes */ if (key_size != AES_KEY_SIZE_128 && @@ -5990,19 +5894,10 @@ CK_RV aes_unwrap(STDLL_TokData_t *tokdata, return CKR_WRAPPED_KEY_LEN_RANGE; } - if (fromend == TRUE) { - if (isopaque) - ptr = data + data_len; - else - ptr = data + data_len - key_size; - } else { + if (fromend == TRUE) + ptr = data + data_len - key_size; + else ptr = data; - } - - /* reset key_size for secure key, assuming datalen is the token's secure key - * size */ - if (isopaque) - key_size = data_len; value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + key_size); @@ -6011,11 +5906,7 @@ CK_RV aes_unwrap(STDLL_TokData_t *tokdata, return CKR_HOST_MEMORY; } - if (isopaque) - value_attr->type = CKA_IBM_OPAQUE; - else - value_attr->type = CKA_VALUE; - + value_attr->type = CKA_VALUE; value_attr->ulValueLen = key_size; value_attr->pValue = (CK_BYTE *) value_attr + sizeof(CK_ATTRIBUTE); memcpy(value_attr->pValue, ptr, key_size); diff --git a/usr/lib/common/key_mgr.c b/usr/lib/common/key_mgr.c index 9ed6bcb..ce0a350 100644 --- a/usr/lib/common/key_mgr.c +++ b/usr/lib/common/key_mgr.c @@ -535,14 +535,14 @@ CK_RV key_mgr_wrap_key(STDLL_TokData_t *tokdata, CK_BYTE *wrapped_key, CK_ULONG *wrapped_key_len) { ENCR_DECR_CONTEXT *ctx = NULL; - OBJECT *key1_obj = NULL; - OBJECT *key2_obj = NULL; + OBJECT *wrapping_key_obj = NULL; + OBJECT *key_obj = NULL; CK_ATTRIBUTE *attr = NULL; CK_BYTE *data = NULL; CK_ULONG data_len; CK_OBJECT_CLASS class; CK_KEY_TYPE keytype; - CK_BBOOL flag; + CK_BBOOL flag, not_opaque = FALSE; CK_RV rc; @@ -551,29 +551,25 @@ CK_RV key_mgr_wrap_key(STDLL_TokData_t *tokdata, return CKR_FUNCTION_FAILED; } - rc = object_mgr_find_in_map1(tokdata, h_wrapping_key, &key1_obj, READ_LOCK); + rc = object_mgr_find_in_map1(tokdata, h_wrapping_key, &wrapping_key_obj, + READ_LOCK); if (rc != CKR_OK) { TRACE_ERROR("%s\n", ock_err(ERR_WRAPPING_KEY_HANDLE_INVALID)); if (rc == CKR_OBJECT_HANDLE_INVALID) - return CKR_WRAPPING_KEY_HANDLE_INVALID; - - return rc; + rc = CKR_WRAPPING_KEY_HANDLE_INVALID; + goto done; } - object_put(tokdata, key1_obj, TRUE); - key1_obj = NULL; - - rc = object_mgr_find_in_map1(tokdata, h_key, &key2_obj, READ_LOCK); + rc = object_mgr_find_in_map1(tokdata, h_key, &key_obj, READ_LOCK); if (rc != CKR_OK) { TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) - return CKR_KEY_HANDLE_INVALID; - - return rc; + rc = CKR_KEY_HANDLE_INVALID; + goto done; } // is the key-to-be-wrapped EXTRACTABLE? // - rc = template_attribute_find(key2_obj->template, CKA_EXTRACTABLE, &attr); + rc = template_attribute_find(key_obj->template, CKA_EXTRACTABLE, &attr); if (rc == FALSE) { TRACE_ERROR("Failed to find CKA_EXTRACTABLE in key template.\n"); // could happen if user tries to wrap a public key @@ -591,7 +587,7 @@ CK_RV key_mgr_wrap_key(STDLL_TokData_t *tokdata, // what kind of key are we trying to wrap? make sure the mechanism is // allowed to wrap this kind of key // - rc = template_attribute_find(key2_obj->template, CKA_CLASS, &attr); + rc = template_attribute_find(key_obj->template, CKA_CLASS, &attr); if (rc == FALSE) { TRACE_DEVEL("CKA_CLASS is missing for key to be wrapped.\n"); rc = CKR_KEY_NOT_WRAPPABLE; @@ -655,10 +651,28 @@ CK_RV key_mgr_wrap_key(STDLL_TokData_t *tokdata, goto done; } + if (token_specific.t_key_wrap == NULL && token_specific.secure_key_token) { + TRACE_ERROR("Need a token specific wrap for a secure key token\n"); + rc = CKR_FUNCTION_NOT_SUPPORTED; + goto done; + } + + if (token_specific.t_key_wrap != NULL) { + rc = token_specific.t_key_wrap(tokdata, sess, mech, length_only, + wrapping_key_obj, key_obj, + wrapped_key, wrapped_key_len, + ¬_opaque); + if (rc != CKR_OK) { + TRACE_ERROR("token specific wrap function failed\n"); + goto done; + } + if (rc == CKR_OK && not_opaque == FALSE) + goto done; + } // extract the secret data to be wrapped // - rc = template_attribute_find(key2_obj->template, CKA_KEY_TYPE, &attr); + rc = template_attribute_find(key_obj->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { TRACE_ERROR("Failed to find CKA_KEY_TYPE in key template.\n"); rc = CKR_KEY_NOT_WRAPPABLE; @@ -672,7 +686,7 @@ CK_RV key_mgr_wrap_key(STDLL_TokData_t *tokdata, case CKK_CDMF: #endif case CKK_DES: - rc = des_wrap_get_data(key2_obj->template, length_only, &data, + rc = des_wrap_get_data(key_obj->template, length_only, &data, &data_len); if (rc != CKR_OK) { TRACE_DEVEL("des_wrap_get_data failed.\n"); @@ -680,7 +694,7 @@ CK_RV key_mgr_wrap_key(STDLL_TokData_t *tokdata, } break; case CKK_DES3: - rc = des3_wrap_get_data(key2_obj->template, length_only, &data, + rc = des3_wrap_get_data(key_obj->template, length_only, &data, &data_len); if (rc != CKR_OK) { TRACE_DEVEL("des3_wrap_get_data failed.\n"); @@ -688,7 +702,7 @@ CK_RV key_mgr_wrap_key(STDLL_TokData_t *tokdata, } break; case CKK_RSA: - rc = rsa_priv_wrap_get_data(key2_obj->template, length_only, &data, + rc = rsa_priv_wrap_get_data(key_obj->template, length_only, &data, &data_len); if (rc != CKR_OK) { TRACE_DEVEL("rsa_priv_wrap_get_data failed.\n"); @@ -697,7 +711,7 @@ CK_RV key_mgr_wrap_key(STDLL_TokData_t *tokdata, break; #if !(NODSA) case CKK_DSA: - rc = dsa_priv_wrap_get_data(key2_obj->template, length_only, &data, + rc = dsa_priv_wrap_get_data(key_obj->template, length_only, &data, &data_len); if (rc != CKR_OK) { TRACE_DEVEL("dsa_priv_wrap_get_data failed.\n"); @@ -706,7 +720,7 @@ CK_RV key_mgr_wrap_key(STDLL_TokData_t *tokdata, break; #endif case CKK_GENERIC_SECRET: - rc = generic_secret_wrap_get_data(key2_obj->template, length_only, + rc = generic_secret_wrap_get_data(key_obj->template, length_only, &data, &data_len); if (rc != CKR_OK) { TRACE_DEVEL("generic_secret_wrap_get_data failed.\n"); @@ -715,7 +729,7 @@ CK_RV key_mgr_wrap_key(STDLL_TokData_t *tokdata, break; #ifndef NOAES case CKK_AES: - rc = aes_wrap_get_data(key2_obj->template, length_only, &data, + rc = aes_wrap_get_data(key_obj->template, length_only, &data, &data_len); if (rc != CKR_OK) { TRACE_DEVEL("aes_wrap_get_data failed.\n"); @@ -724,7 +738,7 @@ CK_RV key_mgr_wrap_key(STDLL_TokData_t *tokdata, break; #endif case CKK_EC: - rc = ecdsa_priv_wrap_get_data(key2_obj->template, length_only, &data, + rc = ecdsa_priv_wrap_get_data(key_obj->template, length_only, &data, &data_len); if (rc != CKR_OK) { TRACE_DEVEL("ecdsa_priv_wrap_get_data failed with rc=%s.\n", @@ -839,8 +853,14 @@ CK_RV key_mgr_wrap_key(STDLL_TokData_t *tokdata, free(ctx); done: - object_put(tokdata, key2_obj, TRUE); - key2_obj = NULL; + if (wrapping_key_obj != NULL) { + object_put(tokdata, wrapping_key_obj, TRUE); + wrapping_key_obj = NULL; + } + if (key_obj != NULL) { + object_put(tokdata, key_obj, TRUE); + key_obj = NULL; + } return rc; } @@ -859,38 +879,28 @@ CK_RV key_mgr_unwrap_key(STDLL_TokData_t *tokdata, CK_OBJECT_HANDLE *h_unwrapped_key) { ENCR_DECR_CONTEXT *ctx = NULL; - OBJECT *key_obj = NULL, *tmp_obj = NULL; + OBJECT *key_obj = NULL, *unwrapping_key_obj = NULL; CK_BYTE *data = NULL; CK_ULONG data_len; - CK_ULONG keyclass = 0, keytype = 0; + CK_ULONG keyclass = 0, keytype = 0, priv_keytype = 0; CK_ULONG i; - CK_BBOOL found_class, found_type, fromend, isopaque = FALSE; + CK_BBOOL found_class, found_type, fromend, not_opaque = FALSE; CK_RV rc; - CK_ATTRIBUTE *attr = NULL; - if (!sess || !wrapped_key || !h_unwrapped_key) { TRACE_ERROR("%s received bad argument(s)\n", __func__); return CKR_FUNCTION_FAILED; } - rc = object_mgr_find_in_map1(tokdata, h_unwrapping_key, &tmp_obj, READ_LOCK); + rc = object_mgr_find_in_map1(tokdata, h_unwrapping_key, &unwrapping_key_obj, + READ_LOCK); if (rc != CKR_OK) { TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) - return CKR_WRAPPING_KEY_HANDLE_INVALID; - else - return rc; - } - - if (template_attribute_find(tmp_obj->template, CKA_IBM_OPAQUE, &attr) == - TRUE) { - isopaque = TRUE; + rc = CKR_UNWRAPPING_KEY_HANDLE_INVALID; + goto done; } - object_put(tokdata, tmp_obj, TRUE); - tmp_obj = NULL; - found_class = FALSE; found_type = FALSE; @@ -924,10 +934,10 @@ CK_RV key_mgr_unwrap_key(STDLL_TokData_t *tokdata, // we can be a bit lenient for private key since can extract key type // from BER-encoded information. - if (found_class == FALSE || - (found_type == FALSE && keyclass != CKO_PRIVATE_KEY)) { + if (found_class == FALSE || found_type == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); - return CKR_TEMPLATE_INCOMPLETE; + rc = CKR_TEMPLATE_INCOMPLETE; + goto done; } switch (mech->mechanism) { @@ -940,7 +950,8 @@ CK_RV key_mgr_unwrap_key(STDLL_TokData_t *tokdata, case CKM_RSA_X_509: if (keyclass != CKO_SECRET_KEY) { TRACE_ERROR("The specified mechanism unwraps secret keys only.\n"); - return CKR_ARGUMENTS_BAD; + rc = CKR_ARGUMENTS_BAD; + goto done; } break; #if !(NOCMF) @@ -960,38 +971,70 @@ CK_RV key_mgr_unwrap_key(STDLL_TokData_t *tokdata, case CKM_AES_CBC_PAD: if ((keyclass != CKO_SECRET_KEY) && (keyclass != CKO_PRIVATE_KEY)) { TRACE_ERROR("Specified mech unwraps secret & private keys only.\n"); - return CKR_ARGUMENTS_BAD; + rc = CKR_ARGUMENTS_BAD; + goto done; } break; default: TRACE_ERROR("The specified mechanism cannot unwrap keys.\n"); - return CKR_MECHANISM_INVALID; + rc = CKR_MECHANISM_INVALID; + goto done; + } + + rc = object_mgr_create_skel(tokdata, sess, attributes, attrib_count, + MODE_UNWRAP, keyclass, keytype, &key_obj); + if (rc != CKR_OK) { + TRACE_DEVEL("object_mgr_create_skel failed.\n"); + goto done; + } + + if (token_specific.t_key_unwrap == NULL && + token_specific.secure_key_token) { + TRACE_ERROR("Need a token specific unwrap for a secure key token\n"); + rc = CKR_FUNCTION_NOT_SUPPORTED; + goto done; + } + + if (token_specific.t_key_unwrap != NULL) { + rc = token_specific.t_key_unwrap(tokdata, sess, mech, + wrapped_key, wrapped_key_len, + unwrapping_key_obj, key_obj, + ¬_opaque); + if (rc != CKR_OK) { + TRACE_ERROR("token specific unwrap function failed\n"); + goto done; + } + if (rc == CKR_OK && not_opaque == FALSE) + goto final; } // looks okay... do the decryption ctx = (ENCR_DECR_CONTEXT *) malloc(sizeof(ENCR_DECR_CONTEXT)); if (!ctx) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - return CKR_HOST_MEMORY; + rc = CKR_HOST_MEMORY; + goto done; } memset(ctx, 0x0, sizeof(ENCR_DECR_CONTEXT)); rc = decr_mgr_init(tokdata, sess, ctx, OP_UNWRAP, mech, h_unwrapping_key); if (rc != CKR_OK) - return rc; + goto done; rc = decr_mgr_decrypt(tokdata, sess, TRUE, ctx, wrapped_key, wrapped_key_len, data, &data_len); if (rc != CKR_OK) { + if (rc == CKR_ENCRYPTED_DATA_LEN_RANGE) + rc = CKR_WRAPPED_KEY_LEN_RANGE; TRACE_DEVEL("decr_mgr_decrypt failed.\n"); - goto error; + goto done; } data = (CK_BYTE *) malloc(data_len); if (!data) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; - goto error; + goto done; } rc = decr_mgr_decrypt(tokdata, sess, @@ -1002,8 +1045,10 @@ CK_RV key_mgr_unwrap_key(STDLL_TokData_t *tokdata, free(ctx); if (rc != CKR_OK) { + if (rc == CKR_ENCRYPTED_DATA_LEN_RANGE) + rc = CKR_WRAPPED_KEY_LEN_RANGE; TRACE_DEVEL("decr_mgr_decrypt failed.\n"); - goto error; + goto done; } // if we use X.509, the data will be padded from the front with zeros. // PKCS #11 specifies that for this mechanism, CK_VALUE is to be read @@ -1017,26 +1062,21 @@ CK_RV key_mgr_unwrap_key(STDLL_TokData_t *tokdata, fromend = FALSE; // extract the key type from the PrivateKeyInfo::AlgorithmIndicator - // if (keyclass == CKO_PRIVATE_KEY) { - rc = key_mgr_get_private_key_type(data, data_len, &keytype); + rc = key_mgr_get_private_key_type(data, data_len, &priv_keytype); if (rc != CKR_OK) { TRACE_DEVEL("key_mgr_get_private_key_type failed.\n"); - goto error; + goto done; } - } - // we have decrypted the wrapped key data. we also - // know what type of key it is. now we need to construct a new key - // object... - // - rc = object_mgr_create_skel(tokdata, sess, - attributes, attrib_count, - MODE_UNWRAP, keyclass, keytype, &key_obj); - if (rc != CKR_OK) { - TRACE_DEVEL("object_mgr_create_skel failed.\n"); - goto error; + if (priv_keytype != keytype) { + rc = CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT; + TRACE_DEVEL("keytype in template (%lu) does not match the unwrapped" + " key (%lu).\n", keytype, priv_keytype); + goto done; + } } + // at this point, 'key_obj' should contain a skeleton key. depending on // the key type. we're now ready to plug in the decrypted key data. // in some cases, the data will be BER-encoded so we'll need to decode it. @@ -1047,11 +1087,10 @@ CK_RV key_mgr_unwrap_key(STDLL_TokData_t *tokdata, switch (keyclass) { case CKO_SECRET_KEY: rc = secret_key_unwrap(tokdata, key_obj->template, keytype, data, - data_len, fromend, isopaque); + data_len, fromend); break; case CKO_PRIVATE_KEY: - rc = priv_key_unwrap(key_obj->template, keytype, data, data_len, - isopaque); + rc = priv_key_unwrap(key_obj->template, keytype, data, data_len); break; default: rc = CKR_WRAPPED_KEY_INVALID; @@ -1060,26 +1099,26 @@ CK_RV key_mgr_unwrap_key(STDLL_TokData_t *tokdata, if (rc != CKR_OK) { TRACE_DEVEL("key_unwrap failed.\n"); - goto error; + goto done; } + +final: // at this point, the key should be fully constructed...assign // an object handle and store the key // rc = object_mgr_create_final(tokdata, sess, key_obj, h_unwrapped_key); if (rc != CKR_OK) { TRACE_DEVEL("object_mgr_create_final failed.\n"); - goto error; - } - if (data) { - OPENSSL_cleanse(data, data_len); - free(data); + goto done; } - return rc; - -error: - if (key_obj) +done: + if (rc != CKR_OK && key_obj) object_free(key_obj); + if (unwrapping_key_obj != NULL) { + object_put(tokdata, unwrapping_key_obj, TRUE); + unwrapping_key_obj = NULL; + } if (data) { OPENSSL_cleanse(data, data_len); free(data); @@ -1126,6 +1165,22 @@ CK_RV key_mgr_get_private_key_type(CK_BYTE *keydata, return CKR_OK; } } + // Check only the OBJECT IDENTIFIER for DH + // + if (alg_len >= ber_idDHLen) { + if (memcmp(alg, ber_idDH, ber_idDHLen) == 0) { + *keytype = CKK_DH; + return CKR_OK; + } + } + // Check only the OBJECT IDENTIFIER for DILITHIUM + // + if (alg_len >= ber_idDilithiumLen) { + if (memcmp(alg, ber_idDilithium, ber_idDilithiumLen) == 0) { + *keytype = CKK_IBM_PQC_DILITHIUM; + return CKR_OK; + } + } TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; diff --git a/usr/lib/common/lexer.l b/usr/lib/common/lexer.l new file mode 100644 index 0000000..b35a0b7 --- /dev/null +++ b/usr/lib/common/lexer.l @@ -0,0 +1,86 @@ +/* + * 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 --git a/usr/lib/common/loadsave.c b/usr/lib/common/loadsave.c index c30dd1a..1711f1b 100644 --- a/usr/lib/common/loadsave.c +++ b/usr/lib/common/loadsave.c @@ -41,6 +41,7 @@ #include "sw_crypt.h" #include "trace.h" #include "ock_syslog.h" +#include "slotmgr.h" // for ock_snprintf extern void set_perm(int); @@ -50,16 +51,71 @@ CK_RV reload_token_object_old(STDLL_TokData_t *tokdata, OBJECT *obj); CK_RV save_public_token_object_old(STDLL_TokData_t *tokdata, OBJECT *obj); CK_RV load_public_token_objects_old(STDLL_TokData_t *tokdata); -char *get_pk_dir(STDLL_TokData_t *tokdata, char *fname) +static int get_token_object_path(char *buf, size_t buflen, + STDLL_TokData_t *tokdata, char *path) { + if (ock_snprintf(buf, buflen, "%s/" PK_LITE_OBJ_DIR "/%s", + tokdata->data_store, path) != 0) { + TRACE_ERROR("buffer overflow for object path %s", path); + return -1; + } + return 0; +} + +static FILE *open_token_object_path(char *buf, size_t buflen, + STDLL_TokData_t *tokdata, char *path, + char *mode) +{ + if (get_token_object_path(buf, buflen, tokdata, path) < 0) + return NULL; + return fopen(buf, mode); +} + +static int get_token_data_store_path(char *buf, size_t buflen, + STDLL_TokData_t *tokdata, char *path) +{ + if (ock_snprintf(buf, buflen, "%s/%s", tokdata->data_store, path)) { + TRACE_ERROR("buffer overflow for path %s", path); + return -1; + } + return 0; +} + +static FILE *open_token_data_store_path(char *buf, size_t buflen, + STDLL_TokData_t *tokdata, char *path, + char *mode) +{ + if (get_token_data_store_path(buf, buflen, tokdata, path) < 0) + return NULL; + return fopen(buf, mode); +} + +static FILE *open_token_object_index(char *buf, size_t buflen, + STDLL_TokData_t *tokdata, char *mode) +{ + return open_token_object_path(buf, buflen, tokdata, PK_LITE_OBJ_IDX, mode); +} + +static FILE *open_token_nvdat(char *buf, size_t buflen, + STDLL_TokData_t *tokdata, char *mode) +{ + if (ock_snprintf(buf, buflen, "%s/" PK_LITE_NV, tokdata->data_store)) { + TRACE_ERROR("NVDAT.TOK file name buffer overflow\n"); + return NULL; + } + return fopen(buf, mode); +} + +char *get_pk_dir(STDLL_TokData_t *tokdata, char *fname, size_t len) +{ + int snres; struct passwd *pw = NULL; if (token_specific.data_store.per_user && (pw = getpwuid(getuid())) != NULL) - sprintf(fname, "%s/%s", tokdata->pk_dir, pw->pw_name); + snres = ock_snprintf(fname, len, "%s/%s", tokdata->pk_dir, pw->pw_name); else - sprintf(fname, "%s", tokdata->pk_dir); - - return fname; + snres = ock_snprintf(fname, len, "%s", tokdata->pk_dir); + return snres != 0 ? NULL : fname; } void set_perm(int file) @@ -112,9 +168,7 @@ CK_RV save_token_object(STDLL_TokData_t *tokdata, OBJECT *obj) return rc; // update the index file if it exists - sprintf(fname, "%s/%s/%s", tokdata->data_store, PK_LITE_OBJ_DIR, - PK_LITE_OBJ_IDX); - fp = fopen(fname, "r"); + fp = open_token_object_index(fname, sizeof(fname), tokdata, "r"); if (fp) { set_perm(fileno(fp)); while (fgets(line, 50, fp)) { @@ -151,11 +205,6 @@ CK_RV delete_token_object(STDLL_TokData_t *tokdata, OBJECT *obj) FILE *fp1, *fp2; char objidx[PATH_MAX], idxtmp[PATH_MAX], fname[PATH_MAX], line[256]; - sprintf(objidx, "%s/%s/%s", tokdata->data_store, - PK_LITE_OBJ_DIR, PK_LITE_OBJ_IDX); - sprintf(idxtmp, "%s/%s/%s", tokdata->data_store, - PK_LITE_OBJ_DIR, "IDX.TMP"); - // FIXME: on UNIX, we need to make sure these guys aren't symlinks // before we blindly write to these files... // @@ -163,8 +212,9 @@ CK_RV delete_token_object(STDLL_TokData_t *tokdata, OBJECT *obj) // remove the object from the index file // - fp1 = fopen(objidx, "r"); - fp2 = fopen(idxtmp, "w"); + fp1 = open_token_object_index(objidx, sizeof(objidx), tokdata, "r"); + fp2 = open_token_object_path(idxtmp, sizeof(idxtmp), + tokdata, "IDX.TMP", "w"); if (!fp1 || !fp2) { if (fp1) fclose(fp1); @@ -206,9 +256,11 @@ CK_RV delete_token_object(STDLL_TokData_t *tokdata, OBJECT *obj) fclose(fp1); fclose(fp2); - sprintf(fname, "%s/%s/%s", tokdata->data_store, - PK_LITE_OBJ_DIR, (char *) obj->name); - unlink(fname); + if (get_token_object_path(fname, sizeof(fname), tokdata, + (char *) obj->name) < 0) + TRACE_DEVEL("file name buffer overflow in obj unlink\n"); + else + unlink(fname); return CKR_OK; } @@ -239,36 +291,43 @@ done: return rc; } -void init_data_store(STDLL_TokData_t *tokdata, char *directory, - char *data_store) +CK_RV init_data_store(STDLL_TokData_t *tokdata, char *directory, + char *data_store, size_t len) { char *pkdir; + int pklen; if (tokdata->pk_dir != NULL) { free(tokdata->pk_dir); tokdata->pk_dir = NULL; } - if ((pkdir = getenv("PKCS_APP_STORE")) != NULL) { - tokdata->pk_dir = (char *) malloc(strlen(pkdir) + 1024); - memset(tokdata->pk_dir, 0, strlen(pkdir) + 1024); - sprintf(tokdata->pk_dir, "%s/%s", pkdir, SUB_DIR); - get_pk_dir(tokdata, data_store); - return; + if ((pkdir = secure_getenv("PKCS_APP_STORE")) != NULL) { + pklen = strlen(pkdir) + 1024; + tokdata->pk_dir = (char *) calloc(pklen, 1); + if (!(tokdata->pk_dir)) + return CKR_HOST_MEMORY; + if (ock_snprintf(tokdata->pk_dir, pklen, "%s/%s", pkdir, SUB_DIR) != 0) + return CKR_FUNCTION_FAILED; + return get_pk_dir(tokdata, data_store, len) ? CKR_OK : CKR_FUNCTION_FAILED; } if (directory) { - tokdata->pk_dir = (char *) malloc(strlen(directory) + 25); - memset(tokdata->pk_dir, 0, strlen(directory) + 25); - sprintf(tokdata->pk_dir, "%s", directory); + pklen = strlen(directory) + 1; + tokdata->pk_dir = (char *) calloc(pklen, 1); + if (!(tokdata->pk_dir)) + return CKR_HOST_MEMORY; + if (ock_snprintf(tokdata->pk_dir, pklen, "%s", directory) != 0) + return CKR_FUNCTION_FAILED; } else { - tokdata->pk_dir = (char *) malloc(strlen(PK_DIR) + 25); - memset(tokdata->pk_dir, 0, strlen(PK_DIR) + 25); - sprintf(tokdata->pk_dir, "%s", PK_DIR); - } - get_pk_dir(tokdata, data_store); - - return; + pklen = strlen(PK_DIR) + 1; + tokdata->pk_dir = (char *) calloc(pklen, 1); + if (!(tokdata->pk_dir)) + return CKR_HOST_MEMORY; + if (ock_snprintf(tokdata->pk_dir, pklen, "%s", PK_DIR) != 0) + return CKR_FUNCTION_FAILED; + } + return get_pk_dir(tokdata, data_store, len) ? CKR_OK : CKR_FUNCTION_FAILED; } void final_data_store(STDLL_TokData_t * tokdata) @@ -283,8 +342,7 @@ void final_data_store(STDLL_TokData_t * tokdata) * tokversion < 3.12 object store */ -static CK_RV get_encryption_info_for_clear_key(CK_ULONG *p_key_len, - CK_ULONG *p_block_size) +static CK_RV get_encryption_info(CK_ULONG *p_key_len, CK_ULONG *p_block_size) { CK_ULONG key_len = 0L; CK_ULONG block_size = 0L; @@ -311,25 +369,6 @@ static CK_RV get_encryption_info_for_clear_key(CK_ULONG *p_key_len, return CKR_OK; } -static CK_RV get_encryption_info(CK_ULONG *p_key_len, CK_ULONG *p_block_size) -{ - CK_RV rc; - - rc = get_encryption_info_for_clear_key(p_key_len, p_block_size); - if (rc != CKR_OK) - return rc; - - /* Tokens that use a secure key have a different size for key because - * it's just an indentifier not a real key. - */ - if (is_secure_key_token()) { - if (p_key_len) - *p_key_len = token_specific.token_keysize; - } - - return CKR_OK; -} - static CK_BYTE *duplicate_initial_vector(const CK_BYTE *iv) { CK_ULONG block_size = 0L; @@ -430,7 +469,7 @@ static CK_RV encrypt_data_with_clear_key(STDLL_TokData_t *tokdata, CK_RV rc = CKR_OK; CK_BYTE *initial_vector = NULL; - if (!is_secure_key_token() && + 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); @@ -546,7 +585,7 @@ static CK_RV decrypt_data_with_clear_key(STDLL_TokData_t *tokdata, CK_RV rc = CKR_OK; CK_BYTE *initial_vector = NULL; - if (!is_secure_key_token() && + 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); @@ -600,8 +639,7 @@ CK_RV load_token_data_old(STDLL_TokData_t *tokdata, CK_SLOT_ID slot_id) goto out_nolock; } - sprintf(fname, "%s/%s", tokdata->data_store, PK_LITE_NV); - fp = fopen(fname, "r"); + fp = open_token_nvdat(fname, sizeof(fname), tokdata, "r"); if (!fp) { /* Better error checking added */ if (errno == ENOENT) { @@ -674,8 +712,7 @@ CK_RV save_token_data_old(STDLL_TokData_t *tokdata, CK_SLOT_ID slot_id) goto out_nolock; } - sprintf(fname, "%s/%s", tokdata->data_store, PK_LITE_NV); - fp = fopen(fname, "w"); + fp = open_token_nvdat(fname, sizeof(fname), tokdata, "w"); if (!fp) { TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno)); rc = CKR_FUNCTION_FAILED; @@ -804,8 +841,12 @@ static CK_RV save_private_token_object_old(STDLL_TokData_t *tokdata, OBJECT *obj goto error; } - sprintf(fname, "%s/%s/", tokdata->data_store, PK_LITE_OBJ_DIR); - strncat(fname, (char *) obj->name, 8); + if (ock_snprintf(fname, PATH_MAX, "%s/%s/%.8s", tokdata->data_store, + PK_LITE_OBJ_DIR, (char *)obj->name) != 0) { + TRACE_ERROR("private token object old name buffer overflow\n"); + rc = CKR_FUNCTION_FAILED; + goto error; + } fp = fopen(fname, "w"); if (!fp) { TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno)); @@ -864,20 +905,14 @@ CK_RV load_private_token_objects_old(STDLL_TokData_t *tokdata) CK_RV rc; size_t read_size; - sprintf(iname, "%s/%s/%s", tokdata->data_store, PK_LITE_OBJ_DIR, - PK_LITE_OBJ_IDX); - - fp1 = fopen(iname, "r"); + fp1 = open_token_object_index(iname, sizeof(iname), tokdata, "r"); if (!fp1) return CKR_OK; // no token objects while (fgets(tmp, 50, fp1)) { tmp[strlen(tmp) - 1] = 0; - sprintf(fname, "%s/%s/", tokdata->data_store, PK_LITE_OBJ_DIR); - strcat(fname, tmp); - - fp2 = fopen(fname, "r"); + fp2 = open_token_object_path(fname, sizeof(fname), tokdata, tmp, "r"); if (!fp2) continue; @@ -954,20 +989,44 @@ CK_RV load_masterkey_so_old(STDLL_TokData_t *tokdata) CK_ULONG key_len = 0L; CK_ULONG master_key_len = 0L; CK_ULONG block_size = 0L; + struct stat sb; - if ((rc = get_encryption_info_for_clear_key(&key_len, - &block_size)) != CKR_OK) - goto done; - - if ((rc = get_encryption_info(&master_key_len, NULL)) != CKR_OK) + if ((rc = get_encryption_info(&key_len, &block_size)) != CKR_OK) goto done; + master_key_len = key_len; memset(tokdata->master_key, 0x0, master_key_len); data_len = master_key_len + SHA1_HASH_SIZE; clear_len = cipher_len = (data_len + block_size - 1) & ~(block_size - 1); + sprintf(fname, "%s/MK_SO", tokdata->data_store); + if (stat(fname, &sb) != 0) { + TRACE_ERROR("stat(%s): %s\n", fname, strerror(errno)); + rc = CKR_FUNCTION_FAILED; + goto done; + } + + if ((CK_ULONG)sb.st_size > cipher_len && + token_specific.secure_key_token && + strcmp(token_specific.token_subdir, "ccatok") == 0) { + /* + * The CCA token used to have a secure master key length of 64, although + * it uses clear keys for the master key in the meantime. The master key + * length has an influence on the file size of the MK_SO and MK_USER + * files when using the old pin encryption format. Use special handling + * for such larger MK_SO files, and accept the larger length. Newly + * written MK_SO files will use the clear key master key length, but we + * need to be able to read larger files for backwards compatibility. + */ + master_key_len = 64; + + data_len = master_key_len + SHA1_HASH_SIZE; + clear_len = cipher_len = (data_len + block_size - 1) + & ~(block_size - 1); + } + key = malloc(key_len); cipher = malloc(cipher_len); clear = malloc(clear_len); @@ -978,10 +1037,8 @@ CK_RV load_masterkey_so_old(STDLL_TokData_t *tokdata) // this file gets created on C_InitToken so we can assume that it always // exists // - sprintf(fname, "%s/MK_SO", tokdata->data_store); - fp = fopen(fname, "r"); + fp = open_token_data_store_path(fname, sizeof(fname), tokdata, "MK_SO", "r"); if (!fp) { - TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno)); rc = CKR_FUNCTION_FAILED; goto done; } @@ -1057,20 +1114,44 @@ CK_RV load_masterkey_user_old(STDLL_TokData_t *tokdata) CK_ULONG key_len = 0L; CK_ULONG master_key_len = 0L; CK_ULONG block_size = 0L; + struct stat sb; - if ((rc = - get_encryption_info_for_clear_key(&key_len, &block_size)) != CKR_OK) - goto done; - - if ((rc = get_encryption_info(&master_key_len, NULL)) != CKR_OK) + if ((rc = get_encryption_info(&key_len, &block_size)) != CKR_OK) goto done; + master_key_len = key_len; memset(tokdata->master_key, 0x0, master_key_len); data_len = master_key_len + SHA1_HASH_SIZE; clear_len = cipher_len = (data_len + block_size - 1) & ~(block_size - 1); + sprintf(fname, "%s/MK_USER", tokdata->data_store); + if (stat(fname, &sb) != 0) { + TRACE_ERROR("stat(%s): %s\n", fname, strerror(errno)); + rc = CKR_FUNCTION_FAILED; + goto done; + } + + if ((CK_ULONG)sb.st_size > cipher_len && + token_specific.secure_key_token && + strcmp(token_specific.token_subdir, "ccatok") == 0) { + /* + * The CCA token used to have a secure master key length of 64, although + * it uses clear keys for the master key in the meantime. The master key + * length has an influence on the file size of the MK_SO and MK_USER + * files when using the old pin encryption format. Use special handling + * for such larger MK_USER files, and accept the larger length. Newly + * written MK_USER files will use the clear key master key length, but + * we need to be able to read larger files for backwards compatibility. + */ + master_key_len = 64; + + data_len = master_key_len + SHA1_HASH_SIZE; + clear_len = cipher_len = (data_len + block_size - 1) + & ~(block_size - 1); + } + key = malloc(key_len); cipher = malloc(cipher_len); clear = malloc(clear_len); @@ -1081,10 +1162,8 @@ CK_RV load_masterkey_user_old(STDLL_TokData_t *tokdata) // this file gets created on C_InitToken so we can assume that it always // exists // - sprintf(fname, "%s/MK_USER", tokdata->data_store); - fp = fopen(fname, "r"); + fp = open_token_data_store_path(fname, sizeof(fname), tokdata, "MK_USER", "r"); if (!fp) { - TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno)); rc = CKR_FUNCTION_FAILED; goto done; } @@ -1155,7 +1234,6 @@ CK_RV save_masterkey_so_old(STDLL_TokData_t *tokdata) CK_ULONG cipher_len = 0L; CK_BYTE *key = NULL; CK_ULONG key_len = 0L; - CK_ULONG master_key_len = 0L; CK_ULONG block_size = 0L; CK_ULONG data_len = 0L; char fname[PATH_MAX]; @@ -1165,14 +1243,10 @@ CK_RV save_masterkey_so_old(STDLL_TokData_t *tokdata) if (!token_specific.data_store.use_master_key) return CKR_OK; - if ((rc = get_encryption_info_for_clear_key(&key_len, - &block_size)) != CKR_OK) - goto done; - - if ((rc = get_encryption_info(&master_key_len, NULL)) != CKR_OK) + if ((rc = get_encryption_info(&key_len, &block_size)) != CKR_OK) goto done; - data_len = master_key_len + SHA1_HASH_SIZE; + data_len = key_len + SHA1_HASH_SIZE; cipher_len = clear_len = block_size * (data_len / block_size + 1); key = malloc(key_len); @@ -1184,9 +1258,9 @@ CK_RV save_masterkey_so_old(STDLL_TokData_t *tokdata) goto done; } // Copy data to buffer (key+hash) - memcpy(clear, tokdata->master_key, master_key_len); + memcpy(clear, tokdata->master_key, key_len); if ((rc = compute_sha1(tokdata, tokdata->master_key, - master_key_len, clear + master_key_len)) != CKR_OK) + key_len, clear + key_len)) != CKR_OK) goto done; add_pkcs_padding(clear + data_len, block_size, data_len, clear_len); @@ -1205,10 +1279,8 @@ CK_RV save_masterkey_so_old(STDLL_TokData_t *tokdata) // // probably ought to ensure the permissions are correct // - sprintf(fname, "%s/MK_SO", tokdata->data_store); - fp = fopen(fname, "w"); + fp = open_token_data_store_path(fname, sizeof(fname), tokdata, "MK_SO", "w"); if (!fp) { - TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno)); rc = CKR_FUNCTION_FAILED; goto done; } @@ -1247,20 +1319,15 @@ CK_RV save_masterkey_user_old(STDLL_TokData_t *tokdata) CK_ULONG cipher_len = 0L; CK_BYTE *key = NULL; CK_ULONG key_len = 0L; - CK_ULONG master_key_len = 0L; CK_ULONG block_size = 0L; CK_ULONG data_len = 0L; char fname[PATH_MAX]; CK_RV rc; - if ((rc = get_encryption_info_for_clear_key(&key_len, - &block_size)) != CKR_OK) - goto done; - - if ((rc = get_encryption_info(&master_key_len, NULL)) != CKR_OK) + if ((rc = get_encryption_info(&key_len, &block_size)) != CKR_OK) goto done; - data_len = master_key_len + SHA1_HASH_SIZE; + data_len = key_len + SHA1_HASH_SIZE; cipher_len = clear_len = block_size * (data_len / block_size + 1); key = malloc(key_len); @@ -1272,9 +1339,9 @@ CK_RV save_masterkey_user_old(STDLL_TokData_t *tokdata) goto done; } // Copy data to buffer (key+hash) - memcpy(clear, tokdata->master_key, master_key_len); + memcpy(clear, tokdata->master_key, key_len); if ((rc = compute_sha1(tokdata, tokdata->master_key, - master_key_len, clear + master_key_len)) != CKR_OK) + key_len, clear + key_len)) != CKR_OK) goto done; add_pkcs_padding(clear + data_len, block_size, data_len, clear_len); @@ -1293,10 +1360,8 @@ CK_RV save_masterkey_user_old(STDLL_TokData_t *tokdata) // // probably ought to ensure the permissions are correct // - sprintf(fname, "%s/MK_USER", tokdata->data_store); - fp = fopen(fname, "w"); + fp = open_token_data_store_path(fname, sizeof(fname), tokdata, "MK_USER", "w"); if (!fp) { - TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno)); rc = CKR_FUNCTION_FAILED; goto done; } @@ -1328,20 +1393,21 @@ CK_RV generate_master_key_old(STDLL_TokData_t *tokdata, CK_BYTE *key) { CK_RV rc = CKR_OK; CK_ULONG key_len = 0L; - CK_ULONG master_key_len = 0L; + CK_ULONG master_key_len; + CK_BYTE *master_key = NULL; + CK_BBOOL is_opaque = FALSE; /* Skip it if master key is not needed. */ if (!token_specific.data_store.use_master_key) return CKR_OK; - if ((rc = get_encryption_info_for_clear_key(&key_len, NULL)) != CKR_OK || - (rc = get_encryption_info(&master_key_len, NULL)) != CKR_OK) - return ERR_FUNCTION_FAILED; + if ((rc = 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 (is_secure_key_token()) + if (token_specific.secure_key_token) return rng_generate(tokdata, key, key_len); /* For clear key tokens, let token generate masterkey @@ -1349,14 +1415,32 @@ CK_RV generate_master_key_old(STDLL_TokData_t *tokdata, CK_BYTE *key) */ switch (token_specific.data_store.encryption_algorithm) { case CKM_DES3_CBC: - return token_specific.t_des_key_gen(tokdata, key, - master_key_len, key_len); + rc = token_specific.t_des_key_gen(tokdata, &master_key, + &master_key_len, key_len, + &is_opaque); + break; case CKM_AES_CBC: - return token_specific.t_aes_key_gen(tokdata, key, - master_key_len, key_len); + rc = token_specific.t_aes_key_gen(tokdata, &master_key, + &master_key_len, key_len, + &is_opaque); + break; + default: + return CKR_MECHANISM_INVALID; + } + + if (rc != CKR_OK) + return rc; + + if (master_key_len != key_len) { + TRACE_ERROR("Invalid master key size: %lu\n", master_key_len); + free(master_key); + return CKR_FUNCTION_FAILED; } - return ERR_MECHANISM_INVALID; + memcpy(key, master_key, master_key_len); + free(master_key); + + return CKR_OK; } CK_RV restore_private_token_object_old(STDLL_TokData_t *tokdata, CK_BYTE *data, @@ -1479,12 +1563,12 @@ CK_RV reload_token_object_old(STDLL_TokData_t *tokdata, OBJECT *obj) CK_RV rc; size_t read_size; - memset(fname, 0x0, sizeof(fname)); - - sprintf(fname, "%s/%s/", tokdata->data_store, PK_LITE_OBJ_DIR); - - strncat(fname, (char *) obj->name, 8); - + if (ock_snprintf(fname, PATH_MAX, "%s/%s/%.8s", tokdata->data_store, + PK_LITE_OBJ_DIR, (char *)obj->name) != 0) { + TRACE_ERROR("token object file name buffer overflow\n"); + rc = CKR_FUNCTION_FAILED; + goto done; + } fp = fopen(fname, "r"); if (!fp) { TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno)); @@ -1554,13 +1638,18 @@ CK_RV save_public_token_object_old(STDLL_TokData_t *tokdata, OBJECT * obj) CK_BBOOL flag = FALSE; CK_RV rc; CK_ULONG_32 total_len; + rc = object_flatten(obj, &clear, &clear_len); if (rc != CKR_OK) { goto error; } - sprintf(fname, "%s/%s/", tokdata->data_store, PK_LITE_OBJ_DIR); - strncat(fname, (char *) obj->name, 8); + if (ock_snprintf(fname, PATH_MAX, "%s/%s/%.8s", tokdata->data_store, + PK_LITE_OBJ_DIR, (char *)obj->name) != 0) { + TRACE_ERROR("public token object file name buffer overflow\n"); + rc = CKR_FUNCTION_FAILED; + goto error; + } fp = fopen(fname, "w"); if (!fp) { TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno)); @@ -1604,20 +1693,14 @@ CK_RV load_public_token_objects_old(STDLL_TokData_t *tokdata) CK_ULONG_32 size; size_t read_size; - sprintf(iname, "%s/%s/%s", tokdata->data_store, PK_LITE_OBJ_DIR, - PK_LITE_OBJ_IDX); - - fp1 = fopen(iname, "r"); + fp1 = open_token_object_index(iname, sizeof(iname), tokdata, "r"); if (!fp1) return CKR_OK; // no token objects while (fgets(tmp, 50, fp1)) { tmp[strlen(tmp) - 1] = 0; - sprintf(fname, "%s/%s/", tokdata->data_store, PK_LITE_OBJ_DIR); - strcat(fname, tmp); - - fp2 = fopen(fname, "r"); + fp2 = open_token_object_path(fname, sizeof(fname), tokdata, tmp, "r"); if (!fp2) continue; @@ -1701,7 +1784,7 @@ static CK_RV aes_256_gcm_seal(unsigned char *out, || EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) != 1 || EVP_CipherUpdate(ctx, NULL, &outlen, aad, aadlen) != 1 || EVP_CipherUpdate(ctx, out, &outlen, in, inlen) != 1 - || EVP_CipherFinal_ex(ctx, out, &outlen) != 1 + || EVP_CipherFinal_ex(ctx, out + outlen, &outlen) != 1 || EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag) != 1) { TRACE_ERROR("%s\n", ock_err(ERR_GENERAL_ERROR)); rc = ERR_GENERAL_ERROR; @@ -1741,7 +1824,7 @@ static CK_RV aes_256_gcm_unseal(unsigned char *out, || EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 0) != 1 || EVP_CipherUpdate(ctx, NULL, &outlen, aad, aadlen) != 1 || EVP_CipherUpdate(ctx, out, &outlen, in, inlen) != 1 - || EVP_CipherFinal_ex(ctx, out, &outlen) != 1) { + || EVP_CipherFinal_ex(ctx, out + outlen, &outlen) != 1) { TRACE_ERROR("%s\n", ock_err(ERR_GENERAL_ERROR)); rc = ERR_GENERAL_ERROR; goto done; @@ -1759,6 +1842,7 @@ static CK_RV aes_256_wrap(unsigned char out[40], { CK_RV rc; int outlen; + unsigned char buffer[40 + EVP_MAX_BLOCK_LENGTH]; EVP_CIPHER_CTX *ctx = NULL; @@ -1772,13 +1856,14 @@ static CK_RV aes_256_wrap(unsigned char out[40], EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW); if (EVP_CipherInit_ex(ctx, EVP_aes_256_wrap(), NULL, kek, NULL, 1) != 1 - || EVP_CipherUpdate(ctx, out, &outlen, in, 32) != 1 - || EVP_CipherFinal_ex(ctx, out, &outlen) != 1) { + || EVP_CipherUpdate(ctx, buffer, &outlen, in, 32) != 1 + || EVP_CipherFinal_ex(ctx, buffer + outlen, &outlen) != 1) { TRACE_ERROR("%s\n", ock_err(ERR_GENERAL_ERROR)); rc = ERR_GENERAL_ERROR; goto done; } + memcpy(out, buffer, 40); rc = CKR_OK; done: EVP_CIPHER_CTX_free(ctx); @@ -1791,6 +1876,7 @@ static CK_RV aes_256_unwrap(unsigned char key[32], { CK_RV rc; int outlen; + unsigned char buffer[32 + EVP_MAX_BLOCK_LENGTH]; EVP_CIPHER_CTX *ctx = NULL; @@ -1804,13 +1890,14 @@ static CK_RV aes_256_unwrap(unsigned char key[32], EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW); if (EVP_CipherInit_ex(ctx, EVP_aes_256_wrap(), NULL, kek, NULL, 0) != 1 - || EVP_CipherUpdate(ctx, key, &outlen, in, 40) != 1 - || EVP_CipherFinal_ex(ctx, key, &outlen) != 1) { + || EVP_CipherUpdate(ctx, buffer, &outlen, in, 40) != 1 + || EVP_CipherFinal_ex(ctx, buffer + outlen, &outlen) != 1) { TRACE_ERROR("%s\n", ock_err(ERR_GENERAL_ERROR)); rc = ERR_GENERAL_ERROR; goto done; } + memcpy(key, buffer, 32); rc = CKR_OK; done: EVP_CIPHER_CTX_free(ctx); @@ -1854,10 +1941,9 @@ CK_RV save_masterkey_so(STDLL_TokData_t *tokdata) // // probably ought to ensure the permissions are correct // - sprintf(fname, "%s/MK_SO", tokdata->data_store); - fp = fopen(fname, "w"); + fp = open_token_data_store_path(fname, sizeof(fname), tokdata, "MK_SO", + "w"); if (!fp) { - TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno)); rc = CKR_FUNCTION_FAILED; goto done; } @@ -1892,10 +1978,9 @@ CK_RV load_masterkey_so(STDLL_TokData_t *tokdata) // this file gets created on C_InitToken so we can assume that it always // exists // - sprintf(fname, "%s/MK_SO", tokdata->data_store); - fp = fopen(fname, "r"); + fp = open_token_data_store_path(fname, sizeof(fname), tokdata, "MK_SO", + "r"); if (!fp) { - TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno)); rc = CKR_FUNCTION_FAILED; goto done; } @@ -1944,10 +2029,9 @@ CK_RV save_masterkey_user(STDLL_TokData_t *tokdata) // // probably ought to ensure the permissions are correct // - sprintf(fname, "%s/MK_USER", tokdata->data_store); - fp = fopen(fname, "w"); + fp = open_token_data_store_path(fname, sizeof(fname), tokdata, "MK_USER", + "w"); if (!fp) { - TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno)); rc = CKR_FUNCTION_FAILED; goto done; } @@ -1983,10 +2067,9 @@ CK_RV load_masterkey_user(STDLL_TokData_t *tokdata) // this file gets created on C_InitToken so we can assume that it always // exists // - sprintf(fname, "%s/MK_USER", tokdata->data_store); - fp = fopen(fname, "r"); + fp = open_token_data_store_path(fname, sizeof(fname), tokdata, "MK_USER", + "r"); if (!fp) { - TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno)); rc = CKR_FUNCTION_FAILED; goto done; } @@ -2028,8 +2111,7 @@ CK_RV save_token_data(STDLL_TokData_t *tokdata, CK_SLOT_ID slot_id) goto out_nolock; } - sprintf(fname, "%s/%s", tokdata->data_store, PK_LITE_NV); - fp = fopen(fname, "w"); + fp = open_token_nvdat(fname, sizeof(fname), tokdata, "w"); if (!fp) { TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno)); rc = CKR_FUNCTION_FAILED; @@ -2116,8 +2198,7 @@ CK_RV load_token_data(STDLL_TokData_t *tokdata, CK_SLOT_ID slot_id) goto out_nolock; } - sprintf(fname, "%s/%s", tokdata->data_store, PK_LITE_NV); - fp = fopen(fname, "r"); + fp = open_token_nvdat(fname, sizeof(fname), tokdata, "r"); if (!fp) { /* Better error checking added */ if (errno == ENOENT) { @@ -2242,8 +2323,8 @@ static inline int inc32(unsigned char ctr[4]) * u8 tag[16] | 16-byte footer * ---------------- <--+ */ -#define HEADER_LEN 64 -#define FOOTER_LEN 16 +#define HEADER_LEN 64 +#define FOOTER_LEN 16 // // Note: The token lock (XProcLock) must be held when calling this function. @@ -2411,20 +2492,14 @@ CK_RV load_private_token_objects(STDLL_TokData_t *tokdata) if (tokdata->version < TOK_NEW_DATA_STORE) return load_private_token_objects_old(tokdata); - sprintf(iname, "%s/%s/%s", tokdata->data_store, PK_LITE_OBJ_DIR, - PK_LITE_OBJ_IDX); - - fp1 = fopen(iname, "r"); + fp1 = open_token_object_index(iname, sizeof(iname), tokdata, "r"); if (!fp1) return CKR_OK; // no token objects while (fgets(tmp, 50, fp1)) { tmp[strlen(tmp) - 1] = 0; - sprintf(fname, "%s/%s/", tokdata->data_store, PK_LITE_OBJ_DIR); - strcat(fname, tmp); - - fp2 = fopen(fname, "r"); + fp2 = open_token_object_path(fname, sizeof(fname), tokdata, tmp,"r"); if (!fp2) continue; @@ -2553,6 +2628,7 @@ CK_RV reload_token_object(STDLL_TokData_t *tokdata, OBJECT *obj) CK_ULONG size_64; CK_RV rc; uint32_t len; + uint32_t ver; if (tokdata->version < TOK_NEW_DATA_STORE) return reload_token_object_old(tokdata, obj); @@ -2576,9 +2652,18 @@ CK_RV reload_token_object(STDLL_TokData_t *tokdata, OBJECT *obj) goto done; } + memcpy(&ver, header, 4); memcpy(&priv, header + 4, 1); memcpy(&len, header + 60, 4); - size = be32toh(len); + + /* + * In OCK 3.12 - 3.14 the version and size was not stored in BE. So if + * version field is in platform endianness, keep size as is also. + */ + if (ver == TOK_NEW_DATA_STORE) + size = len; + else + size = be32toh(len); buf = (CK_BYTE *) malloc(size); if (buf == NULL) { @@ -2630,7 +2715,7 @@ done: * u8 object[object_len] | body * ---------------- <--+ */ -#define PUB_HEADER_LEN 16 +#define PUB_HEADER_LEN 16 // // Note: The token lock (XProcLock) must be held when calling this function. @@ -2643,8 +2728,9 @@ CK_RV save_public_token_object(STDLL_TokData_t *tokdata, OBJECT *obj) CK_ULONG clear_len; CK_BBOOL flag = FALSE; CK_RV rc; - CK_ULONG_32 len; + CK_ULONG_32 len, be_len; unsigned char reserved[7] = {0}; + uint32_t tmp; if (tokdata->version < TOK_NEW_DATA_STORE) return save_public_token_object_old(tokdata, obj); @@ -2665,11 +2751,14 @@ CK_RV save_public_token_object(STDLL_TokData_t *tokdata, OBJECT *obj) goto done; } + tmp = htobe32(tokdata->version); + be_len = htobe32(len); + set_perm(fileno(fp)); - if (fwrite(&tokdata->version, 4, 1, fp) != 1 + if (fwrite(&tmp, 4, 1, fp) != 1 || fwrite(&flag, 1, 1, fp) != 1 || fwrite(reserved, 7, 1, fp) != 1 - || fwrite(&len, 4, 1, fp) != 1 + || fwrite(&be_len, 4, 1, fp) != 1 || fwrite(clear, len, 1, fp) != 1) { rc = CKR_FUNCTION_FAILED; goto done; @@ -2700,14 +2789,12 @@ CK_RV load_public_token_objects(STDLL_TokData_t *tokdata) CK_BBOOL priv; CK_ULONG_32 size; unsigned char header[PUB_HEADER_LEN]; + uint32_t ver; if (tokdata->version < TOK_NEW_DATA_STORE) return load_public_token_objects_old(tokdata); - sprintf(iname, "%s/%s/%s", tokdata->data_store, PK_LITE_OBJ_DIR, - PK_LITE_OBJ_IDX); - - fp1 = fopen(iname, "r"); + fp1 = open_token_object_index(iname, sizeof(iname), tokdata, "r"); if (!fp1) return CKR_OK; // no token objects @@ -2727,9 +2814,16 @@ CK_RV load_public_token_objects(STDLL_TokData_t *tokdata) continue; } + memcpy(&ver, header, 4); memcpy(&priv, header + 4, 1); memcpy(&size, header + 12, 4); - size = be32toh(size); + + /* + * In OCK 3.12 - 3.14 the version and size was not stored in BE. So if + * version field is in platform endianness, keep size as is also + */ + if (ver != TOK_NEW_DATA_STORE) + size = be32toh(size); if (priv == TRUE) { fclose(fp2); diff --git a/usr/lib/common/mech_aes.c b/usr/lib/common/mech_aes.c index 7448587..c30caf5 100644 --- a/usr/lib/common/mech_aes.c +++ b/usr/lib/common/mech_aes.c @@ -290,7 +290,8 @@ CK_RV aes_cbc_pad_encrypt(STDLL_TokData_t *tokdata, rc = CKR_HOST_MEMORY; goto done; } - memcpy(clear, in_data, in_data_len); + if (in_data != NULL && in_data_len > 0) + memcpy(clear, in_data, in_data_len); add_pkcs_padding(clear + in_data_len, AES_BLOCK_SIZE, in_data_len, padded_len); @@ -867,7 +868,7 @@ CK_RV aes_cbc_pad_encrypt_update(STDLL_TokData_t *tokdata, // note, this is subtly different from the other encrypt update routines // if (total <= AES_BLOCK_SIZE) { - if (length_only == FALSE) { + if (length_only == FALSE && in_data_len) { memcpy(context->data + context->len, in_data, in_data_len); context->len += in_data_len; } @@ -876,7 +877,7 @@ CK_RV aes_cbc_pad_encrypt_update(STDLL_TokData_t *tokdata, return CKR_OK; } else { remain = (total % AES_BLOCK_SIZE); - out_len = total - remain; // out_len is a multiple of DES_BLOCK_SIZE + out_len = total - remain; // out_len is a multiple of AES_BLOCK_SIZE if (remain == 0) { remain = AES_BLOCK_SIZE; @@ -968,7 +969,7 @@ CK_RV aes_cbc_pad_decrypt_update(STDLL_TokData_t *tokdata, // note, this is subtly different from the other decrypt update routines // if (total <= AES_BLOCK_SIZE) { - if (length_only == FALSE) { + if (length_only == FALSE && in_data_len) { memcpy(context->data + context->len, in_data, in_data_len); context->len += in_data_len; } @@ -2383,7 +2384,8 @@ CK_RV aes_mac_sign_update(STDLL_TokData_t *tokdata, total = (context->len + in_data_len); if (total < AES_BLOCK_SIZE) { - memcpy(context->data + context->len, in_data, in_data_len); + if (in_data_len > 0) + memcpy(context->data + context->len, in_data, in_data_len); context->len += in_data_len; return CKR_OK; } else { @@ -2581,7 +2583,8 @@ CK_RV aes_mac_verify_update(STDLL_TokData_t *tokdata, total = (context->len + in_data_len); if (total < AES_BLOCK_SIZE) { - memcpy(context->data + context->len, in_data, in_data_len); + if (in_data_len > 0) + memcpy(context->data + context->len, in_data, in_data_len); context->len += in_data_len; return CKR_OK; } else { @@ -2768,7 +2771,8 @@ CK_RV aes_cmac_sign_update(STDLL_TokData_t *tokdata, total = (context->len + in_data_len); if (total <= AES_BLOCK_SIZE) { - memcpy(context->data + context->len, in_data, in_data_len); + if (in_data_len > 0) + memcpy(context->data + context->len, in_data, in_data_len); context->len += in_data_len; return CKR_OK; } else { @@ -2955,7 +2959,8 @@ CK_RV aes_cmac_verify_update(STDLL_TokData_t *tokdata, total = (context->len + in_data_len); if (total <= AES_BLOCK_SIZE) { - memcpy(context->data + context->len, in_data, in_data_len); + if (in_data_len > 0) + memcpy(context->data + context->len, in_data, in_data_len); context->len += in_data_len; return CKR_OK; } else { @@ -3360,12 +3365,11 @@ CK_RV ckm_aes_key_gen(STDLL_TokData_t *tokdata, TEMPLATE *tmpl) CK_ATTRIBUTE *local_attr = NULL; CK_ATTRIBUTE *val_len_attr = NULL; CK_BYTE *aes_key = NULL; - CK_BYTE dummy_key[AES_KEY_SIZE_256] = { 0, }; CK_ULONG rc; CK_ULONG key_size; CK_ULONG token_keysize; CK_BBOOL found = FALSE; - + CK_BBOOL is_opaque = FALSE; found = template_attribute_find(tmpl, CKA_VALUE_LEN, &val_len_attr); if (found == FALSE) @@ -3382,26 +3386,14 @@ CK_RV ckm_aes_key_gen(STDLL_TokData_t *tokdata, TEMPLATE *tmpl) return CKR_MECHANISM_INVALID; } - if (is_secure_key_token()) - token_keysize = token_specific.token_keysize; - else - token_keysize = key_size; - - if ((aes_key = (CK_BYTE *) calloc(1, token_keysize)) == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - return CKR_HOST_MEMORY; - } - - rc = token_specific.t_aes_key_gen(tokdata, aes_key, token_keysize, - key_size); + rc = token_specific.t_aes_key_gen(tokdata, &aes_key, &token_keysize, + key_size, &is_opaque); if (rc != CKR_OK) goto err; - /* For secure-key keys put in CKA_IBM_OPAQUE - * and put dummy_key in CKA_VALUE. - */ - if (is_secure_key_token()) { + /* For opaque keys put in CKA_IBM_OPAQUE and put dummy_key in CKA_VALUE. */ + if (is_opaque) { opaque_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + token_keysize); if (!opaque_attr) { @@ -3414,6 +3406,12 @@ CK_RV ckm_aes_key_gen(STDLL_TokData_t *tokdata, TEMPLATE *tmpl) opaque_attr->pValue = (CK_BYTE *) opaque_attr + sizeof(CK_ATTRIBUTE); memcpy(opaque_attr->pValue, aes_key, token_keysize); template_update_attribute(tmpl, opaque_attr); + } else { + if (token_keysize != key_size) { + TRACE_ERROR("Invalid key size: %lu\n", token_keysize); + rc = CKR_FUNCTION_FAILED; + goto err; + } } value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + key_size); @@ -3442,8 +3440,8 @@ CK_RV ckm_aes_key_gen(STDLL_TokData_t *tokdata, TEMPLATE *tmpl) value_attr->type = CKA_VALUE; value_attr->ulValueLen = key_size; value_attr->pValue = (CK_BYTE *) value_attr + sizeof(CK_ATTRIBUTE); - if (is_secure_key_token()) - memcpy(value_attr->pValue, dummy_key, key_size); + if (is_opaque) + memset(value_attr->pValue, 0, key_size); else memcpy(value_attr->pValue, aes_key, key_size); free(aes_key); diff --git a/usr/lib/common/mech_des.c b/usr/lib/common/mech_des.c index 6e5bef9..e4e10ea 100644 --- a/usr/lib/common/mech_des.c +++ b/usr/lib/common/mech_des.c @@ -294,7 +294,8 @@ CK_RV des_cbc_pad_encrypt(STDLL_TokData_t *tokdata, rc = CKR_HOST_MEMORY; goto done; } - memcpy(clear, in_data, in_data_len); + if (in_data != NULL && in_data_len > 0) + memcpy(clear, in_data, in_data_len); add_pkcs_padding(clear + in_data_len, DES_BLOCK_SIZE, in_data_len, padded_len); @@ -757,7 +758,7 @@ CK_RV des_cbc_pad_encrypt_update(STDLL_TokData_t *tokdata, // note, this is subtly different from the other encrypt update routines // if (total <= DES_BLOCK_SIZE) { - if (length_only == FALSE) { + if (length_only == FALSE && in_data_len) { memcpy(context->data + context->len, in_data, in_data_len); context->len += in_data_len; } @@ -858,7 +859,7 @@ CK_RV des_cbc_pad_decrypt_update(STDLL_TokData_t *tokdata, // note, this is subtly different from the other decrypt update routines // if (total <= DES_BLOCK_SIZE) { - if (length_only == FALSE) { + if (length_only == FALSE && in_data_len) { memcpy(context->data + context->len, in_data, in_data_len); context->len += in_data_len; } @@ -1225,33 +1226,22 @@ CK_RV ckm_des_key_gen(STDLL_TokData_t *tokdata, TEMPLATE *tmpl) CK_ATTRIBUTE *class_attr = NULL; CK_ATTRIBUTE *local_attr = NULL; CK_BYTE *des_key = NULL; - CK_BYTE dummy_key[DES_KEY_SIZE] = { 0, }; CK_ULONG rc; - CK_ULONG keysize; + CK_ULONG keysize = 0; + CK_BBOOL is_opaque = FALSE; if (token_specific.t_des_key_gen == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } - if (is_secure_key_token()) - keysize = token_specific.token_keysize; - else - keysize = DES_KEY_SIZE; - - if ((des_key = (CK_BYTE *) calloc(1, keysize)) == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - return CKR_HOST_MEMORY; - } - - rc = token_specific.t_des_key_gen(tokdata, des_key, keysize, DES_KEY_SIZE); + rc = token_specific.t_des_key_gen(tokdata, &des_key, &keysize, + DES_KEY_SIZE, &is_opaque); if (rc != CKR_OK) goto err; - /* For secure-key keys put in CKA_IBM_OPAQUE - * and put dummy_key in CKA_VALUE. - */ - if (is_secure_key_token()) { + /* For opaque keys put in CKA_IBM_OPAQUE and put dummy_key in CKA_VALUE. */ + if (is_opaque) { opaque_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + keysize); if (!opaque_attr) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); @@ -1263,6 +1253,12 @@ CK_RV ckm_des_key_gen(STDLL_TokData_t *tokdata, TEMPLATE *tmpl) opaque_attr->pValue = (CK_BYTE *) opaque_attr + sizeof(CK_ATTRIBUTE); memcpy(opaque_attr->pValue, des_key, keysize); template_update_attribute(tmpl, opaque_attr); + } else { + if (keysize != DES_KEY_SIZE) { + TRACE_ERROR("Invalid key size: %lu\n", keysize); + rc = CKR_FUNCTION_FAILED; + goto err; + } } value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + DES_KEY_SIZE); @@ -1291,8 +1287,8 @@ CK_RV ckm_des_key_gen(STDLL_TokData_t *tokdata, TEMPLATE *tmpl) value_attr->type = CKA_VALUE; value_attr->ulValueLen = DES_KEY_SIZE; value_attr->pValue = (CK_BYTE *) value_attr + sizeof(CK_ATTRIBUTE); - if (is_secure_key_token()) - memcpy(value_attr->pValue, dummy_key, DES_KEY_SIZE); + if (is_opaque) + memset(value_attr->pValue, 0, DES_KEY_SIZE); else memcpy(value_attr->pValue, des_key, DES_KEY_SIZE); free(des_key); diff --git a/usr/lib/common/mech_des3.c b/usr/lib/common/mech_des3.c index 8a588f7..cf98423 100644 --- a/usr/lib/common/mech_des3.c +++ b/usr/lib/common/mech_des3.c @@ -294,7 +294,8 @@ CK_RV des3_cbc_pad_encrypt(STDLL_TokData_t *tokdata, rc = CKR_HOST_MEMORY; goto done; } - memcpy(clear, in_data, in_data_len); + if (in_data != NULL && in_data_len > 0) + memcpy(clear, in_data, in_data_len); add_pkcs_padding(clear + in_data_len, DES_BLOCK_SIZE, in_data_len, padded_len); @@ -578,7 +579,7 @@ CK_RV des3_cbc_encrypt_update(STDLL_TokData_t *tokdata, total = (context->len + in_data_len); if (total < DES_BLOCK_SIZE) { - if (length_only == FALSE) { + if (length_only == FALSE && in_data_len) { memcpy(context->data + context->len, in_data, in_data_len); context->len += in_data_len; } @@ -669,7 +670,7 @@ CK_RV des3_cbc_decrypt_update(STDLL_TokData_t *tokdata, total = context->len + in_data_len; if (total < DES_BLOCK_SIZE) { - if (length_only == FALSE) { + if (length_only == FALSE && in_data_len) { memcpy(context->data + context->len, in_data, in_data_len); context->len += in_data_len; } @@ -764,7 +765,7 @@ CK_RV des3_cbc_pad_encrypt_update(STDLL_TokData_t *tokdata, // note, this is subtly different from the other encrypt update routines // if (total <= DES_BLOCK_SIZE) { - if (length_only == FALSE) { + if (length_only == FALSE && in_data_len) { memcpy(context->data + context->len, in_data, in_data_len); context->len += in_data_len; } @@ -864,7 +865,7 @@ CK_RV des3_cbc_pad_decrypt_update(STDLL_TokData_t *tokdata, // note, this is subtly different from the other decrypt update routines // if (total <= DES_BLOCK_SIZE) { - if (length_only == FALSE) { + if (length_only == FALSE && in_data_len) { memcpy(context->data + context->len, in_data, in_data_len); context->len += in_data_len; } @@ -2030,7 +2031,8 @@ CK_RV des3_mac_sign_update(STDLL_TokData_t *tokdata, total = (context->len + in_data_len); if (total < DES_BLOCK_SIZE) { - memcpy(context->data + context->len, in_data, in_data_len); + if (in_data_len > 0) + memcpy(context->data + context->len, in_data, in_data_len); context->len += in_data_len; return CKR_OK; } else { @@ -2223,7 +2225,8 @@ CK_RV des3_mac_verify_update(STDLL_TokData_t *tokdata, total = (context->len + in_data_len); if (total < DES_BLOCK_SIZE) { - memcpy(context->data + context->len, in_data, in_data_len); + if (in_data_len > 0) + memcpy(context->data + context->len, in_data, in_data_len); context->len += in_data_len; return CKR_OK; } else { @@ -2408,7 +2411,8 @@ CK_RV des3_cmac_sign_update(STDLL_TokData_t *tokdata, total = (context->len + in_data_len); if (total <= DES_BLOCK_SIZE) { - memcpy(context->data + context->len, in_data, in_data_len); + if (in_data_len > 0) + memcpy(context->data + context->len, in_data, in_data_len); context->len += in_data_len; return CKR_OK; } else { @@ -2589,7 +2593,8 @@ CK_RV des3_cmac_verify_update(STDLL_TokData_t *tokdata, total = (context->len + in_data_len); if (total <= DES_BLOCK_SIZE) { - memcpy(context->data + context->len, in_data, in_data_len); + if (in_data_len > 0) + memcpy(context->data + context->len, in_data, in_data_len); context->len += in_data_len; return CKR_OK; } else { @@ -2708,34 +2713,22 @@ CK_RV ckm_des3_key_gen(STDLL_TokData_t *tokdata, TEMPLATE *tmpl) CK_ATTRIBUTE *class_attr = NULL; CK_ATTRIBUTE *local_attr = NULL; CK_BYTE *des_key = NULL; - CK_BYTE dummy_key[3 * DES_KEY_SIZE] = { 0, }; CK_ULONG rc; - CK_ULONG keysize; + CK_ULONG keysize = 0; + CK_BBOOL is_opaque = FALSE; if (token_specific.t_des_key_gen == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } - if (is_secure_key_token()) - keysize = token_specific.token_keysize; - else - keysize = (3 * DES_KEY_SIZE); - - if ((des_key = (CK_BYTE *) calloc(1, keysize)) == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - return CKR_HOST_MEMORY; - } - - rc = token_specific.t_des_key_gen(tokdata, des_key, keysize, - 3 * DES_KEY_SIZE); + rc = token_specific.t_des_key_gen(tokdata, &des_key, &keysize, + 3 * DES_KEY_SIZE, &is_opaque); if (rc != CKR_OK) goto err; - /* For secure-key keys put in CKA_IBM_OPAQUE - * and put dummy_key in CKA_VALUE. - */ - if (is_secure_key_token()) { + /* For opaque keys put in CKA_IBM_OPAQUE and put dummy_key in CKA_VALUE. */ + if (is_opaque) { opaque_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + keysize); if (!opaque_attr) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); @@ -2747,6 +2740,12 @@ CK_RV ckm_des3_key_gen(STDLL_TokData_t *tokdata, TEMPLATE *tmpl) opaque_attr->pValue = (CK_BYTE *) opaque_attr + sizeof(CK_ATTRIBUTE); memcpy(opaque_attr->pValue, des_key, keysize); template_update_attribute(tmpl, opaque_attr); + } else { + if (keysize != 3 * DES_KEY_SIZE) { + TRACE_ERROR("Invalid key size: %lu\n", keysize); + rc = CKR_FUNCTION_FAILED; + goto err; + } } value_attr = @@ -2776,8 +2775,8 @@ CK_RV ckm_des3_key_gen(STDLL_TokData_t *tokdata, TEMPLATE *tmpl) value_attr->type = CKA_VALUE; value_attr->ulValueLen = 3 * DES_KEY_SIZE; value_attr->pValue = (CK_BYTE *) value_attr + sizeof(CK_ATTRIBUTE); - if (is_secure_key_token()) - memcpy(value_attr->pValue, dummy_key, 3 * DES_KEY_SIZE); + if (is_opaque) + memset(value_attr->pValue, 0, 3 * DES_KEY_SIZE); else memcpy(value_attr->pValue, des_key, 3 * DES_KEY_SIZE); free(des_key); diff --git a/usr/lib/common/mech_dh.c b/usr/lib/common/mech_dh.c index 6733075..7fc4ec8 100644 --- a/usr/lib/common/mech_dh.c +++ b/usr/lib/common/mech_dh.c @@ -62,11 +62,7 @@ CK_RV dh_pkcs_derive(STDLL_TokData_t *tokdata, // Perform DH checking of parameters // Check the existance of the public-value in mechanism - if ((!mech->pParameter) || - ((mech->ulParameterLen != 64) && - (mech->ulParameterLen != 96) && - (mech->ulParameterLen != 128) && - (mech->ulParameterLen != 192) && (mech->ulParameterLen != 256))) { + if (mech->pParameter == NULL || mech->ulParameterLen == 0) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return (CKR_MECHANISM_PARAM_INVALID); } diff --git a/usr/lib/common/mech_ec.c b/usr/lib/common/mech_ec.c index 29705a2..6aa9015 100644 --- a/usr/lib/common/mech_ec.c +++ b/usr/lib/common/mech_ec.c @@ -13,6 +13,8 @@ * Mechanisms for Elliptic Curve (EC) */ +#define _GNU_SOURCE +#include #include #include #include @@ -854,7 +856,7 @@ CK_RV ckm_kdf_X9_63(STDLL_TokData_t *tokdata, SESSION *sess, CK_ULONG kdf, CK_BYTE hash[MAX_SUPPORTED_HASH_LENGTH]; CK_ULONG h_len; CK_RV rc; - unsigned int i, counter; + unsigned int i, counter, counter_en; /* Check max keylen according to ANSI X9.63 */ /* digest_len * 2^32 */ @@ -884,7 +886,8 @@ CK_RV ckm_kdf_X9_63(STDLL_TokData_t *tokdata, SESSION *sess, CK_ULONG kdf, /* Provide key bytes according to ANSI X9.63 */ counter = 1; for (i = 0; i < key_len / kdf_digest_len; i++) { - memcpy(ctx + z_len, &counter, sizeof(int)); + counter_en = htobe32(counter); + memcpy(ctx + z_len, &counter_en, counter_length); rc = ckm_kdf(tokdata, sess, kdf, ctx, ctx_len, hash, &h_len); if (rc != 0) { free(ctx); @@ -1104,7 +1107,7 @@ CK_RV ecdh_pkcs_derive(STDLL_TokData_t *tokdata, SESSION *sess, rc = pkcs_get_keytype(pTemplate, ulCount, mech, &keytype, &class); if (rc != CKR_OK) { TRACE_ERROR("get_keytype failed with rc=0x%lx\n", rc); - return rc; + return CKR_TEMPLATE_INCOMPLETE; } /* Determine derived key length */ @@ -1338,8 +1341,8 @@ CK_RV ec_uncompress_public_key(CK_BYTE *curve, CK_ULONG curve_len, bn_y = BN_new(); ctx = BN_CTX_new(); - if (!EC_POINT_set_compressed_coordinates_GFp(group, - point, bn_x, y_bit, ctx)) { + if (!EC_POINT_set_compressed_coordinates(group, + point, bn_x, y_bit, ctx)) { rc = CKR_FUNCTION_FAILED; goto end; } @@ -1349,7 +1352,7 @@ CK_RV ec_uncompress_public_key(CK_BYTE *curve, CK_ULONG curve_len, goto end; } - if (!EC_POINT_get_affine_coordinates_GFp(group, point, bn_x, bn_y, ctx)) { + if (!EC_POINT_get_affine_coordinates(group, point, bn_x, bn_y, ctx)) { rc = CKR_FUNCTION_FAILED; goto end; } diff --git a/usr/lib/common/mech_rsa.c b/usr/lib/common/mech_rsa.c index f5c2d06..adc9470 100644 --- a/usr/lib/common/mech_rsa.c +++ b/usr/lib/common/mech_rsa.c @@ -2633,7 +2633,8 @@ CK_RV emsa_pss_encode(STDLL_TokData_t *tokdata, } /* pkcs1v2.2, Step 5: set M' */ - memcpy(buf + 8, in_data, in_data_len); + if (in_data_len > 0) + memcpy(buf + 8, in_data, in_data_len); /* pkcs1v2.2, Step 6: Compute Hash(M') */ rc = compute_sha(tokdata, buf, 8 + hlen + pssParms->sLen, H, @@ -2747,7 +2748,8 @@ CK_RV emsa_pss_verify(STDLL_TokData_t *tokdata, /* pkcs1v2.2, Step 12: Set M'. Note: Use end of buf. */ M = buf + (i + pssParms->sLen); memset(M, 0, 8); - memcpy(M + 8, in_data, in_data_len); // in_data is mHash. + if (in_data_len > 0) + memcpy(M + 8, in_data, in_data_len); // in_data is mHash. memcpy(M + (8 + in_data_len), salt, pssParms->sLen); /* pkcs1v2.2, Step 13: Compute Hash(M'). */ diff --git a/usr/lib/common/mech_sha.c b/usr/lib/common/mech_sha.c index 8a60bb1..fdf83d5 100644 --- a/usr/lib/common/mech_sha.c +++ b/usr/lib/common/mech_sha.c @@ -299,772 +299,41 @@ CK_RV sha_hash_final(STDLL_TokData_t *tokdata, SESSION *sess, } } -// this routine gets called for two mechanisms actually: -// CKM_SHA_1_HMAC -// CKM_SHA_1_HMAC_GENERAL +// this routine gets called for these mechanisms actually: +// CKM_SHA_1_HMAC +// CKM_SHA_1_HMAC_GENERAL +// CKM_SHA224_HMAC +// CKM_SHA224_HMAC_GENERAL +// CKM_SHA256_HMAC +// CKM_SHA256_HMAC_GENERAL +// CKM_SHA384_HMAC +// CKM_SHA384_HMAC_GENERAL +// CKM_SHA512_HMAC +// CKM_SHA512_HMAC_GENERAL +// CKM_SHA512_224_HMAC +// CKM_SHA512_224_HMAC_GENERAL +// CKM_SHA512_256_HMAC +// CKM_SHA512_256_HMAC_GENERAL +// CKM_IBM_SHA3_224_HMAC +// CKM_IBM_SHA3_256_HMAC +// CKM_IBM_SHA3_384_HMAC +// CKM_IBM_SHA3_512_HMAC // -CK_RV sha1_hmac_sign(STDLL_TokData_t *tokdata, - SESSION *sess, CK_BBOOL length_only, - SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, - CK_ULONG in_data_len, CK_BYTE *out_data, - CK_ULONG *out_data_len) -{ - OBJECT *key_obj = NULL; - CK_ATTRIBUTE *attr = NULL; - CK_BYTE hash[SHA1_HASH_SIZE]; - DIGEST_CONTEXT digest_ctx; - CK_MECHANISM digest_mech; - CK_BYTE k_ipad[SHA1_BLOCK_SIZE]; - CK_BYTE k_opad[SHA1_BLOCK_SIZE]; - CK_ULONG key_bytes, hash_len, hmac_len; - CK_ULONG i; - CK_RV rc; - - if (!sess || !ctx || !out_data_len) { - TRACE_ERROR("%s received bad argument(s)\n", __func__); - return CKR_FUNCTION_FAILED; - } - - if (ctx->mech.mechanism == CKM_SHA_1_HMAC_GENERAL) { - hmac_len = *(CK_ULONG *) ctx->mech.pParameter; - - if (hmac_len == 0) { - *out_data_len = 0; - return CKR_OK; - } - } else { - hmac_len = SHA1_HASH_SIZE; - } - - if (length_only == TRUE) { - *out_data_len = hmac_len; - return CKR_OK; - } - - if (token_specific.t_hmac_sign != NULL) - return token_specific.t_hmac_sign(tokdata, sess, in_data, - in_data_len, out_data, out_data_len); - - /* Do manual hmac if token doesn't have an hmac crypto call. - * Secure tokens should not do manual hmac. - */ - - memset(&digest_ctx, 0x0, sizeof(DIGEST_CONTEXT)); - - rc = object_mgr_find_in_map1(tokdata, ctx->key, &key_obj, READ_LOCK); - if (rc != CKR_OK) { - TRACE_ERROR("Failed to acquire key from specified handle"); - if (rc == CKR_OBJECT_HANDLE_INVALID) - return CKR_KEY_HANDLE_INVALID; - else - return rc; - } - - rc = template_attribute_find(key_obj->template, CKA_VALUE, &attr); - if (rc == FALSE) { - TRACE_ERROR("Could not find CKA_VALUE in the template\n"); - rc = CKR_FUNCTION_FAILED; - goto done; - } - - key_bytes = attr->ulValueLen; - - - // build (K XOR ipad), (K XOR opad) - // - if (key_bytes > SHA1_BLOCK_SIZE) { - digest_mech.mechanism = CKM_SHA_1; - digest_mech.ulParameterLen = 0; - digest_mech.pParameter = NULL; - - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Init failed.\n"); - goto done; - } - - hash_len = sizeof(hash); - rc = digest_mgr_digest(tokdata, sess, FALSE, &digest_ctx, - attr->pValue, attr->ulValueLen, hash, &hash_len); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Digest failed.\n"); - goto done; - } - - memset(&digest_ctx, 0x0, sizeof(DIGEST_CONTEXT)); - - for (i = 0; i < hash_len; i++) { - k_ipad[i] = hash[i] ^ 0x36; - k_opad[i] = hash[i] ^ 0x5C; - } - - memset(&k_ipad[i], 0x36, SHA1_BLOCK_SIZE - i); - memset(&k_opad[i], 0x5C, SHA1_BLOCK_SIZE - i); - } else { - CK_BYTE *key = attr->pValue; - - for (i = 0; i < key_bytes; i++) { - k_ipad[i] = key[i] ^ 0x36; - k_opad[i] = key[i] ^ 0x5C; - } - - memset(&k_ipad[i], 0x36, SHA1_BLOCK_SIZE - key_bytes); - memset(&k_opad[i], 0x5C, SHA1_BLOCK_SIZE - key_bytes); - } - - digest_mech.mechanism = CKM_SHA_1; - digest_mech.ulParameterLen = 0; - digest_mech.pParameter = NULL; - - // inner hash - // - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Init failed.\n"); - goto done; - } - - rc = digest_mgr_digest_update(tokdata, sess, &digest_ctx, k_ipad, - SHA1_BLOCK_SIZE); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Update failed.\n"); - goto done; - } - - rc = digest_mgr_digest_update(tokdata, sess, &digest_ctx, in_data, - in_data_len); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Update failed.\n"); - goto done; - } - - hash_len = sizeof(hash); - rc = digest_mgr_digest_final(tokdata, sess, FALSE, &digest_ctx, hash, - &hash_len); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Final failed.\n"); - goto done; - } - - memset(&digest_ctx, 0x0, sizeof(DIGEST_CONTEXT)); - - // outer hash - // - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Init failed.\n"); - goto done; - } - - rc = digest_mgr_digest_update(tokdata, sess, &digest_ctx, k_opad, - SHA1_BLOCK_SIZE); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Update failed.\n"); - goto done; - } - - rc = digest_mgr_digest_update(tokdata, sess, &digest_ctx, hash, hash_len); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Update failed.\n"); - goto done; - } - - hash_len = sizeof(hash); - rc = digest_mgr_digest_final(tokdata, sess, FALSE, &digest_ctx, hash, - &hash_len); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Final failed.\n"); - goto done; - } - - memcpy(out_data, hash, hmac_len); - *out_data_len = hmac_len; - -done: - object_put(tokdata, key_obj, TRUE); - key_obj = NULL; - - return rc; -} - -/** This routine gets called for two mechanisms actually: - * CKM_SHA224_HMAC - * CKM_SHA224_HMAC_GENERAL - */ -CK_RV sha224_hmac_sign(STDLL_TokData_t *tokdata, - SESSION *sess, CK_BBOOL length_only, - SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, - CK_ULONG in_data_len, CK_BYTE *out_data, - CK_ULONG *out_data_len) -{ - OBJECT *key_obj = NULL; - CK_ATTRIBUTE *attr = NULL; - CK_BYTE hash[SHA224_HASH_SIZE]; - DIGEST_CONTEXT digest_ctx; - CK_MECHANISM digest_mech; - CK_BYTE k_ipad[SHA224_BLOCK_SIZE]; - CK_BYTE k_opad[SHA224_BLOCK_SIZE]; - CK_ULONG key_bytes, hash_len, hmac_len; - CK_ULONG i; - CK_RV rc; - - if (!sess || !ctx || !out_data_len) { - TRACE_ERROR("%s received bad argument(s)\n", __func__); - return CKR_FUNCTION_FAILED; - } - - if (ctx->mech.mechanism == CKM_SHA224_HMAC_GENERAL) { - hmac_len = *(CK_ULONG *) ctx->mech.pParameter; - - if (hmac_len == 0) { - *out_data_len = 0; - return CKR_OK; - } - } else { - hmac_len = SHA224_HASH_SIZE; - } - - if (length_only == TRUE) { - *out_data_len = hmac_len; - return CKR_OK; - } - - if (token_specific.t_hmac_sign != NULL) - return token_specific.t_hmac_sign(tokdata, sess, in_data, - in_data_len, out_data, out_data_len); - - /* Do manual hmac if token doesn't have an hmac crypto call. - * Secure tokens should not do manual hmac. - */ - memset(&digest_ctx, 0x0, sizeof(DIGEST_CONTEXT)); - - rc = object_mgr_find_in_map1(tokdata, ctx->key, &key_obj, READ_LOCK); - if (rc != CKR_OK) { - TRACE_ERROR("Failed to acquire key from specified handle"); - if (rc == CKR_OBJECT_HANDLE_INVALID) - return CKR_KEY_HANDLE_INVALID; - else - return rc; - } - rc = template_attribute_find(key_obj->template, CKA_VALUE, &attr); - if (rc == FALSE) { - TRACE_ERROR("Could not find CKA_VALUE in the template\n"); - rc = CKR_FUNCTION_FAILED; - goto done; - } - - key_bytes = attr->ulValueLen; - - // build (K XOR ipad), (K XOR opad) - // - if (key_bytes > SHA224_BLOCK_SIZE) { - digest_mech.mechanism = CKM_SHA224; - digest_mech.ulParameterLen = 0; - digest_mech.pParameter = NULL; - - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Init failed.\n"); - goto done; - } - - hash_len = sizeof(hash); - rc = digest_mgr_digest(tokdata, sess, FALSE, &digest_ctx, - attr->pValue, attr->ulValueLen, hash, &hash_len); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Digest failed.\n"); - goto done; - } - - memset(&digest_ctx, 0x0, sizeof(DIGEST_CONTEXT)); - - for (i = 0; i < hash_len; i++) { - k_ipad[i] = hash[i] ^ 0x36; - k_opad[i] = hash[i] ^ 0x5C; - } - - memset(&k_ipad[i], 0x36, SHA224_BLOCK_SIZE - i); - memset(&k_opad[i], 0x5C, SHA224_BLOCK_SIZE - i); - } else { - CK_BYTE *key = attr->pValue; - - for (i = 0; i < key_bytes; i++) { - k_ipad[i] = key[i] ^ 0x36; - k_opad[i] = key[i] ^ 0x5C; - } - - memset(&k_ipad[i], 0x36, SHA224_BLOCK_SIZE - key_bytes); - memset(&k_opad[i], 0x5C, SHA224_BLOCK_SIZE - key_bytes); - } - - digest_mech.mechanism = CKM_SHA224; - digest_mech.ulParameterLen = 0; - digest_mech.pParameter = NULL; - - // inner hash - // - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Init failed.\n"); - goto done; - } - - rc = digest_mgr_digest_update(tokdata, sess, &digest_ctx, k_ipad, - SHA224_BLOCK_SIZE); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Update failed.\n"); - goto done; - } - - rc = digest_mgr_digest_update(tokdata, sess, &digest_ctx, in_data, - in_data_len); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Update failed.\n"); - goto done; - } - - hash_len = sizeof(hash); - rc = digest_mgr_digest_final(tokdata, sess, FALSE, &digest_ctx, hash, - &hash_len); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Final failed.\n"); - goto done; - } - - memset(&digest_ctx, 0x0, sizeof(DIGEST_CONTEXT)); - - // outer hash - // - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Init failed.\n"); - goto done; - } - - rc = digest_mgr_digest_update(tokdata, sess, &digest_ctx, k_opad, - SHA224_BLOCK_SIZE); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Update failed.\n"); - goto done; - } - - rc = digest_mgr_digest_update(tokdata, sess, &digest_ctx, hash, hash_len); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Update failed.\n"); - goto done; - } - - hash_len = sizeof(hash); - rc = digest_mgr_digest_final(tokdata, sess, FALSE, &digest_ctx, hash, - &hash_len); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Final failed.\n"); - goto done; - } - - memcpy(out_data, hash, hmac_len); - *out_data_len = hmac_len; - -done: - object_put(tokdata, key_obj, TRUE); - key_obj = NULL; - - return rc; -} - -/** This routine gets called for two mechanisms actually: - * CKM_SHA256_HMAC - * CKM_SHA256_HMAC_GENERAL - */ -CK_RV sha256_hmac_sign(STDLL_TokData_t *tokdata, - SESSION *sess, CK_BBOOL length_only, - SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, - CK_ULONG in_data_len, CK_BYTE *out_data, - CK_ULONG *out_data_len) -{ - OBJECT *key_obj = NULL; - CK_ATTRIBUTE *attr = NULL; - CK_BYTE hash[SHA256_HASH_SIZE]; - DIGEST_CONTEXT digest_ctx; - CK_MECHANISM digest_mech; - CK_BYTE k_ipad[SHA256_BLOCK_SIZE]; - CK_BYTE k_opad[SHA256_BLOCK_SIZE]; - CK_ULONG key_bytes, hash_len, hmac_len; - CK_ULONG i; - CK_RV rc; - - if (!sess || !ctx || !out_data_len) { - TRACE_ERROR("%s received bad argument(s)\n", __func__); - return CKR_FUNCTION_FAILED; - } - - if (ctx->mech.mechanism == CKM_SHA256_HMAC_GENERAL) { - hmac_len = *(CK_ULONG *) ctx->mech.pParameter; - - if (hmac_len == 0) { - *out_data_len = 0; - return CKR_OK; - } - } else { - hmac_len = SHA256_HASH_SIZE; - } - - if (length_only == TRUE) { - *out_data_len = hmac_len; - return CKR_OK; - } - - if (token_specific.t_hmac_sign != NULL) - return token_specific.t_hmac_sign(tokdata, sess, in_data, - in_data_len, out_data, out_data_len); - - /* Do manual hmac if token doesn't have an hmac crypto call. - * Secure tokens should not do manual hmac. - */ - memset(&digest_ctx, 0x0, sizeof(DIGEST_CONTEXT)); - - rc = object_mgr_find_in_map1(tokdata, ctx->key, &key_obj, READ_LOCK); - if (rc != CKR_OK) { - TRACE_ERROR("Failed to acquire key from specified handle"); - if (rc == CKR_OBJECT_HANDLE_INVALID) - return CKR_KEY_HANDLE_INVALID; - else - return rc; - } - rc = template_attribute_find(key_obj->template, CKA_VALUE, &attr); - if (rc == FALSE) { - TRACE_ERROR("Could not find CKA_VALUE in the template\n"); - rc = CKR_FUNCTION_FAILED; - goto done; - } - - key_bytes = attr->ulValueLen; - - // build (K XOR ipad), (K XOR opad) - // - if (key_bytes > SHA256_BLOCK_SIZE) { - digest_mech.mechanism = CKM_SHA256; - digest_mech.ulParameterLen = 0; - digest_mech.pParameter = NULL; - - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Init failed.\n"); - goto done; - } - - hash_len = sizeof(hash); - rc = digest_mgr_digest(tokdata, sess, FALSE, &digest_ctx, - attr->pValue, attr->ulValueLen, hash, &hash_len); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Digest failed.\n"); - goto done; - } - - memset(&digest_ctx, 0x0, sizeof(DIGEST_CONTEXT)); - - for (i = 0; i < hash_len; i++) { - k_ipad[i] = hash[i] ^ 0x36; - k_opad[i] = hash[i] ^ 0x5C; - } - - memset(&k_ipad[i], 0x36, SHA256_BLOCK_SIZE - i); - memset(&k_opad[i], 0x5C, SHA256_BLOCK_SIZE - i); - } else { - CK_BYTE *key = attr->pValue; - - for (i = 0; i < key_bytes; i++) { - k_ipad[i] = key[i] ^ 0x36; - k_opad[i] = key[i] ^ 0x5C; - } - - memset(&k_ipad[i], 0x36, SHA256_BLOCK_SIZE - key_bytes); - memset(&k_opad[i], 0x5C, SHA256_BLOCK_SIZE - key_bytes); - } - - digest_mech.mechanism = CKM_SHA256; - digest_mech.ulParameterLen = 0; - digest_mech.pParameter = NULL; - - // inner hash - // - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Init failed.\n"); - goto done; - } - - rc = digest_mgr_digest_update(tokdata, sess, &digest_ctx, k_ipad, - SHA256_BLOCK_SIZE); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Update failed.\n"); - goto done; - } - - rc = digest_mgr_digest_update(tokdata, sess, &digest_ctx, in_data, - in_data_len); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Update failed.\n"); - goto done; - } - - hash_len = sizeof(hash); - rc = digest_mgr_digest_final(tokdata, sess, FALSE, &digest_ctx, hash, - &hash_len); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Final failed.\n"); - goto done; - } - - memset(&digest_ctx, 0x0, sizeof(DIGEST_CONTEXT)); - - // outer hash - // - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Init failed.\n"); - goto done; - } - - rc = digest_mgr_digest_update(tokdata, sess, &digest_ctx, k_opad, - SHA256_BLOCK_SIZE); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Update failed.\n"); - goto done; - } - - rc = digest_mgr_digest_update(tokdata, sess, &digest_ctx, hash, hash_len); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Update failed.\n"); - goto done; - } - - hash_len = sizeof(hash); - rc = digest_mgr_digest_final(tokdata, sess, FALSE, &digest_ctx, hash, - &hash_len); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Final failed.\n"); - goto done; - } - - memcpy(out_data, hash, hmac_len); - *out_data_len = hmac_len; - -done: - object_put(tokdata, key_obj, TRUE); - key_obj = NULL; - - return rc; -} - -/** This routine gets called for two mechanisms actually: - * CKM_SHA384_HMAC - * CKM_SHA384_HMAC_GENERAL - */ -CK_RV sha384_hmac_sign(STDLL_TokData_t *tokdata, - SESSION *sess, CK_BBOOL length_only, - SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, - CK_ULONG in_data_len, CK_BYTE *out_data, - CK_ULONG *out_data_len) -{ - OBJECT *key_obj = NULL; - CK_ATTRIBUTE *attr = NULL; - CK_BYTE hash[SHA384_HASH_SIZE]; - DIGEST_CONTEXT digest_ctx; - CK_MECHANISM digest_mech; - CK_BYTE k_ipad[SHA384_BLOCK_SIZE]; - CK_BYTE k_opad[SHA384_BLOCK_SIZE]; - CK_ULONG key_bytes, hash_len, hmac_len; - CK_ULONG i; - CK_RV rc; - - if (!sess || !ctx || !out_data_len) { - TRACE_ERROR("%s received bad argument(s)\n", __func__); - return CKR_FUNCTION_FAILED; - } - - if (ctx->mech.mechanism == CKM_SHA384_HMAC_GENERAL) { - hmac_len = *(CK_ULONG *) ctx->mech.pParameter; - - if (hmac_len == 0) { - *out_data_len = 0; - return CKR_OK; - } - } else { - hmac_len = SHA384_HASH_SIZE; - } - - if (length_only == TRUE) { - *out_data_len = hmac_len; - return CKR_OK; - } - - if (token_specific.t_hmac_sign != NULL) - return token_specific.t_hmac_sign(tokdata, sess, in_data, - in_data_len, out_data, out_data_len); - - /* Do manual hmac if token doesn't have an hmac crypto call. - * Secure tokens should not do manual hmac. - */ - - memset(&digest_ctx, 0x0, sizeof(DIGEST_CONTEXT)); - - rc = object_mgr_find_in_map1(tokdata, ctx->key, &key_obj, READ_LOCK); - if (rc != CKR_OK) { - TRACE_ERROR("Failed to acquire key from specified handle"); - if (rc == CKR_OBJECT_HANDLE_INVALID) - return CKR_KEY_HANDLE_INVALID; - else - return rc; - } - rc = template_attribute_find(key_obj->template, CKA_VALUE, &attr); - if (rc == FALSE) { - TRACE_ERROR("Could not find CKA_VALUE in the template\n"); - rc = CKR_FUNCTION_FAILED; - goto done; - } - - key_bytes = attr->ulValueLen; - - // build (K XOR ipad), (K XOR opad) - // - if (key_bytes > SHA384_BLOCK_SIZE) { - digest_mech.mechanism = CKM_SHA384; - digest_mech.ulParameterLen = 0; - digest_mech.pParameter = NULL; - - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Init failed.\n"); - goto done; - } - - hash_len = sizeof(hash); - rc = digest_mgr_digest(tokdata, sess, FALSE, &digest_ctx, - attr->pValue, attr->ulValueLen, hash, &hash_len); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Digest failed.\n"); - goto done; - } - - memset(&digest_ctx, 0x0, sizeof(DIGEST_CONTEXT)); - - for (i = 0; i < hash_len; i++) { - k_ipad[i] = hash[i] ^ 0x36; - k_opad[i] = hash[i] ^ 0x5C; - } - - memset(&k_ipad[i], 0x36, SHA384_BLOCK_SIZE - i); - memset(&k_opad[i], 0x5C, SHA384_BLOCK_SIZE - i); - } else { - CK_BYTE *key = attr->pValue; - - for (i = 0; i < key_bytes; i++) { - k_ipad[i] = key[i] ^ 0x36; - k_opad[i] = key[i] ^ 0x5C; - } - - memset(&k_ipad[i], 0x36, SHA384_BLOCK_SIZE - key_bytes); - memset(&k_opad[i], 0x5C, SHA384_BLOCK_SIZE - key_bytes); - } - - digest_mech.mechanism = CKM_SHA384; - digest_mech.ulParameterLen = 0; - digest_mech.pParameter = NULL; - - // inner hash - // - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Init failed.\n"); - goto done; - } - - rc = digest_mgr_digest_update(tokdata, sess, &digest_ctx, k_ipad, - SHA384_BLOCK_SIZE); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Update failed.\n"); - goto done; - } - - rc = digest_mgr_digest_update(tokdata, sess, &digest_ctx, in_data, - in_data_len); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Update failed.\n"); - goto done; - } - - hash_len = sizeof(hash); - rc = digest_mgr_digest_final(tokdata, sess, FALSE, &digest_ctx, hash, - &hash_len); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Final failed.\n"); - goto done; - } - - memset(&digest_ctx, 0x0, sizeof(DIGEST_CONTEXT)); - - // outer hash - // - rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Init failed.\n"); - goto done; - } - - rc = digest_mgr_digest_update(tokdata, sess, &digest_ctx, k_opad, - SHA384_BLOCK_SIZE); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Update failed.\n"); - goto done; - } - - rc = digest_mgr_digest_update(tokdata, sess, &digest_ctx, hash, hash_len); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Update failed.\n"); - goto done; - } - - hash_len = sizeof(hash); - rc = digest_mgr_digest_final(tokdata, sess, FALSE, &digest_ctx, hash, - &hash_len); - if (rc != CKR_OK) { - TRACE_DEVEL("Digest Mgr Final failed.\n"); - goto done; - } - - memcpy(out_data, hash, hmac_len); - *out_data_len = hmac_len; - -done: - object_put(tokdata, key_obj, TRUE); - key_obj = NULL; - - return rc; -} - -/** This routine gets called for 6 mechanisms actually: - * CKM_SHA512_HMAC - * CKM_SHA512_HMAC_GENERAL - * CKM_SHA512_224_HMAC - * CKM_SHA512_224_HMAC_GENERAL - * CKM_SHA512_256_HMAC - * CKM_SHA512_256_HMAC_GENERAL - */ -CK_RV sha512_hmac_sign(STDLL_TokData_t *tokdata, - SESSION *sess, CK_BBOOL length_only, - SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, - CK_ULONG in_data_len, CK_BYTE *out_data, - CK_ULONG *out_data_len) +CK_RV sha_hmac_sign(STDLL_TokData_t *tokdata, + SESSION *sess, CK_BBOOL length_only, + SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, + CK_ULONG in_data_len, CK_BYTE *out_data, + CK_ULONG *out_data_len) { OBJECT *key_obj = NULL; CK_ATTRIBUTE *attr = NULL; - CK_BYTE hash[SHA512_HASH_SIZE]; + CK_BYTE hash[MAX_SHA_HASH_SIZE]; DIGEST_CONTEXT digest_ctx; CK_MECHANISM digest_mech; - CK_BYTE k_ipad[SHA512_BLOCK_SIZE]; - CK_BYTE k_opad[SHA512_BLOCK_SIZE]; - CK_ULONG key_bytes, hash_len, hmac_len; + CK_BYTE k_ipad[MAX_SHA_BLOCK_SIZE]; + CK_BYTE k_opad[MAX_SHA_BLOCK_SIZE]; + CK_ULONG key_bytes, hash_len, hmac_len, digest_hash_len, digest_block_size; + CK_BBOOL general = FALSE; CK_ULONG i; CK_RV rc; @@ -1073,21 +342,37 @@ CK_RV sha512_hmac_sign(STDLL_TokData_t *tokdata, return CKR_FUNCTION_FAILED; } - if (ctx->mech.mechanism == CKM_SHA512_HMAC_GENERAL || - ctx->mech.mechanism == CKM_SHA512_224_HMAC_GENERAL || - ctx->mech.mechanism == CKM_SHA512_256_HMAC_GENERAL) { - hmac_len = *(CK_ULONG *) ctx->mech.pParameter; + digest_mech.ulParameterLen = 0; + digest_mech.pParameter = NULL; + rc = get_hmac_digest(ctx->mech.mechanism, &digest_mech.mechanism, &general); + if (rc != 0) { + TRACE_ERROR("get_hmac_digest failed"); + return rc; + } + + rc = get_sha_block_size(digest_mech.mechanism, &digest_block_size); + if (rc != 0) { + TRACE_ERROR("get_sha_block_size failed"); + return rc; + } + + rc = get_sha_size(digest_mech.mechanism, &digest_hash_len); + if (rc != 0) { + TRACE_ERROR("get_sha_size failed"); + return rc; + } + + if (general == FALSE) { + hmac_len = digest_hash_len; + } else { + hmac_len = *(CK_ULONG *)ctx->mech.pParameter; + if (hmac_len > digest_hash_len) + return CKR_MECHANISM_PARAM_INVALID; if (hmac_len == 0) { *out_data_len = 0; return CKR_OK; } - } else if (ctx->mech.mechanism == CKM_SHA512_224_HMAC) { - hmac_len = SHA224_HASH_SIZE; - } else if (ctx->mech.mechanism == CKM_SHA512_224_HMAC) { - hmac_len = SHA256_HASH_SIZE; - } else { - hmac_len = SHA512_HASH_SIZE; } if (length_only == TRUE) { @@ -1102,6 +387,7 @@ CK_RV sha512_hmac_sign(STDLL_TokData_t *tokdata, /* Do manual hmac if token doesn't have an hmac crypto call. * Secure tokens should not do manual hmac. */ + memset(&digest_ctx, 0x0, sizeof(DIGEST_CONTEXT)); rc = object_mgr_find_in_map1(tokdata, ctx->key, &key_obj, READ_LOCK); @@ -1112,6 +398,7 @@ CK_RV sha512_hmac_sign(STDLL_TokData_t *tokdata, else return rc; } + rc = template_attribute_find(key_obj->template, CKA_VALUE, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_VALUE in the template\n"); @@ -1123,18 +410,14 @@ CK_RV sha512_hmac_sign(STDLL_TokData_t *tokdata, // build (K XOR ipad), (K XOR opad) // - if (key_bytes > SHA512_BLOCK_SIZE) { - digest_mech.mechanism = CKM_SHA512; - digest_mech.ulParameterLen = 0; - digest_mech.pParameter = NULL; - + if (key_bytes > digest_block_size) { rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); goto done; } - hash_len = sizeof(hash); + hash_len = digest_hash_len; rc = digest_mgr_digest(tokdata, sess, FALSE, &digest_ctx, attr->pValue, attr->ulValueLen, hash, &hash_len); if (rc != CKR_OK) { @@ -1149,8 +432,8 @@ CK_RV sha512_hmac_sign(STDLL_TokData_t *tokdata, k_opad[i] = hash[i] ^ 0x5C; } - memset(&k_ipad[i], 0x36, SHA512_BLOCK_SIZE - i); - memset(&k_opad[i], 0x5C, SHA512_BLOCK_SIZE - i); + memset(&k_ipad[i], 0x36, digest_block_size - i); + memset(&k_opad[i], 0x5C, digest_block_size - i); } else { CK_BYTE *key = attr->pValue; @@ -1159,14 +442,10 @@ CK_RV sha512_hmac_sign(STDLL_TokData_t *tokdata, k_opad[i] = key[i] ^ 0x5C; } - memset(&k_ipad[i], 0x36, SHA512_BLOCK_SIZE - key_bytes); - memset(&k_opad[i], 0x5C, SHA512_BLOCK_SIZE - key_bytes); + memset(&k_ipad[i], 0x36, digest_block_size - key_bytes); + memset(&k_opad[i], 0x5C, digest_block_size - key_bytes); } - digest_mech.mechanism = CKM_SHA512; - digest_mech.ulParameterLen = 0; - digest_mech.pParameter = NULL; - // inner hash // rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech); @@ -1176,7 +455,7 @@ CK_RV sha512_hmac_sign(STDLL_TokData_t *tokdata, } rc = digest_mgr_digest_update(tokdata, sess, &digest_ctx, k_ipad, - SHA512_BLOCK_SIZE); + digest_block_size); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Update failed.\n"); goto done; @@ -1189,17 +468,14 @@ CK_RV sha512_hmac_sign(STDLL_TokData_t *tokdata, goto done; } - hash_len = sizeof(hash); + hash_len = digest_hash_len; rc = digest_mgr_digest_final(tokdata, sess, FALSE, &digest_ctx, hash, &hash_len); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Final failed.\n"); - return rc; + goto done; } - /* Do manual hmac if token doesn't have an hmac crypto call. - * Secure tokens should not do manual hmac. - */ memset(&digest_ctx, 0x0, sizeof(DIGEST_CONTEXT)); // outer hash @@ -1211,7 +487,7 @@ CK_RV sha512_hmac_sign(STDLL_TokData_t *tokdata, } rc = digest_mgr_digest_update(tokdata, sess, &digest_ctx, k_opad, - SHA512_BLOCK_SIZE); + digest_block_size); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Update failed.\n"); goto done; @@ -1223,7 +499,7 @@ CK_RV sha512_hmac_sign(STDLL_TokData_t *tokdata, goto done; } - hash_len = sizeof(hash); + hash_len = digest_hash_len; rc = digest_mgr_digest_final(tokdata, sess, FALSE, &digest_ctx, hash, &hash_len); if (rc != CKR_OK) { @@ -1241,71 +517,35 @@ done: return rc; } -CK_RV sha1_hmac_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_BYTE hmac[SHA1_HASH_SIZE]; - SIGN_VERIFY_CONTEXT hmac_ctx; - CK_ULONG hmac_len, len; - CK_RV rc; - - if (!sess || !ctx || !in_data || !signature) { - TRACE_ERROR("%s received bad argument(s)\n", __func__); - return CKR_FUNCTION_FAILED; - } - - if (token_specific.t_hmac_verify != NULL) - return token_specific.t_hmac_verify(tokdata, sess, in_data, - in_data_len, signature, sig_len); - - /* Do manual hmac verify if token doesn't have an hmac crypto call. - * Secure tokens should not do manual hmac. - */ - if (ctx->mech.mechanism == CKM_SHA_1_HMAC_GENERAL) - hmac_len = *(CK_ULONG *) ctx->mech.pParameter; - else - hmac_len = SHA1_HASH_SIZE; - - memset(&hmac_ctx, 0, sizeof(SIGN_VERIFY_CONTEXT)); - - rc = sign_mgr_init(tokdata, sess, &hmac_ctx, &ctx->mech, FALSE, ctx->key); - if (rc != CKR_OK) { - TRACE_DEVEL("Sign Mgr Init failed.\n"); - goto done; - } - len = sizeof(hmac); - rc = sign_mgr_sign(tokdata, sess, FALSE, &hmac_ctx, in_data, in_data_len, - hmac, &len); - if (rc != CKR_OK) { - TRACE_DEVEL("Sign Mgr Sign failed.\n"); - goto done; - } - if ((len != hmac_len) || (len != sig_len)) { - TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_LEN_RANGE)); - rc = CKR_SIGNATURE_LEN_RANGE; - goto done; - } - - if (CRYPTO_memcmp(hmac, signature, hmac_len) != 0) { - TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); - rc = CKR_SIGNATURE_INVALID; - } - -done: - sign_mgr_cleanup(&hmac_ctx); - return rc; -} - -CK_RV sha224_hmac_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) +// this routine gets called for these mechanisms actually: +// CKM_SHA_1_HMAC +// CKM_SHA_1_HMAC_GENERAL +// CKM_SHA224_HMAC +// CKM_SHA224_HMAC_GENERAL +// CKM_SHA256_HMAC +// CKM_SHA256_HMAC_GENERAL +// CKM_SHA384_HMAC +// CKM_SHA384_HMAC_GENERAL +// CKM_SHA512_HMAC +// CKM_SHA512_HMAC_GENERAL +// CKM_SHA512_224_HMAC +// CKM_SHA512_224_HMAC_GENERAL +// CKM_SHA512_256_HMAC +// CKM_SHA512_256_HMAC_GENERAL +// CKM_IBM_SHA3_224_HMAC +// CKM_IBM_SHA3_256_HMAC +// CKM_IBM_SHA3_384_HMAC +// CKM_IBM_SHA3_512_HMAC +// +CK_RV sha_hmac_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_BYTE hmac[SHA224_HASH_SIZE]; + CK_BYTE hmac[MAX_SHA_HASH_SIZE]; SIGN_VERIFY_CONTEXT hmac_ctx; - CK_ULONG hmac_len, len; + CK_ULONG hmac_len, len, digest_mech, digest_hash_len; + CK_BBOOL general = FALSE; CK_RV rc; if (!sess || !ctx || !in_data || !signature) { @@ -1320,70 +560,27 @@ CK_RV sha224_hmac_verify(STDLL_TokData_t *tokdata, /* Do manual hmac verify if token doesn't have an hmac crypto call. * Secure tokens should not do manual hmac. */ - if (ctx->mech.mechanism == CKM_SHA224_HMAC_GENERAL) - hmac_len = *(CK_ULONG *) ctx->mech.pParameter; - else - hmac_len = SHA224_HASH_SIZE; - - memset(&hmac_ctx, 0, sizeof(SIGN_VERIFY_CONTEXT)); - - rc = sign_mgr_init(tokdata, sess, &hmac_ctx, &ctx->mech, FALSE, ctx->key); - if (rc != CKR_OK) { - TRACE_DEVEL("Sign Mgr Init failed.\n"); - goto done; - } - len = sizeof(hmac); - rc = sign_mgr_sign(tokdata, sess, FALSE, &hmac_ctx, in_data, in_data_len, - hmac, &len); - if (rc != CKR_OK) { - TRACE_DEVEL("Sign Mgr Sign failed.\n"); - goto done; - } - - if ((len != hmac_len) || (len != sig_len)) { - TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_LEN_RANGE)); - rc = CKR_SIGNATURE_LEN_RANGE; - goto done; + rc = get_hmac_digest(ctx->mech.mechanism, &digest_mech, &general); + if (rc != 0) { + TRACE_ERROR("get_hmac_digest failed"); + return rc; } - if (CRYPTO_memcmp(hmac, signature, hmac_len) != 0) { - TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); - rc = CKR_SIGNATURE_INVALID; + rc = get_sha_size(digest_mech, &digest_hash_len); + if (rc != 0) { + TRACE_ERROR("get_sha_size failed"); + return rc; } -done: - sign_mgr_cleanup(&hmac_ctx); - return rc; -} - -CK_RV sha256_hmac_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_BYTE hmac[SHA256_HASH_SIZE]; - SIGN_VERIFY_CONTEXT hmac_ctx; - CK_ULONG hmac_len, len; - CK_RV rc; - - if (!sess || !ctx || !in_data || !signature) { - TRACE_ERROR("%s received bad argument(s)\n", __func__); - return CKR_FUNCTION_FAILED; + if (general == FALSE) { + hmac_len = digest_hash_len; + } else { + hmac_len = *(CK_ULONG *)ctx->mech.pParameter; + if (hmac_len > digest_hash_len) + return CKR_MECHANISM_PARAM_INVALID; } - if (token_specific.t_hmac_verify != NULL) - return token_specific.t_hmac_verify(tokdata, sess, in_data, - in_data_len, signature, sig_len); - - /* Do manual hmac verify if token doesn't have an hmac crypto call. - * Secure tokens should not do manual hmac. - */ - if (ctx->mech.mechanism == CKM_SHA256_HMAC_GENERAL) - hmac_len = *(CK_ULONG *) ctx->mech.pParameter; - else - hmac_len = SHA256_HASH_SIZE; - memset(&hmac_ctx, 0, sizeof(SIGN_VERIFY_CONTEXT)); rc = sign_mgr_init(tokdata, sess, &hmac_ctx, &ctx->mech, FALSE, ctx->key); @@ -1391,15 +588,13 @@ CK_RV sha256_hmac_verify(STDLL_TokData_t *tokdata, TRACE_DEVEL("Sign Mgr Init failed.\n"); goto done; } - - len = sizeof(hmac); + len = hmac_len; rc = sign_mgr_sign(tokdata, sess, FALSE, &hmac_ctx, in_data, in_data_len, hmac, &len); if (rc != CKR_OK) { TRACE_DEVEL("Sign Mgr Sign failed.\n"); goto done; } - if ((len != hmac_len) || (len != sig_len)) { TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_LEN_RANGE)); rc = CKR_SIGNATURE_LEN_RANGE; @@ -1413,125 +608,10 @@ CK_RV sha256_hmac_verify(STDLL_TokData_t *tokdata, done: sign_mgr_cleanup(&hmac_ctx); - - return rc; -} - -CK_RV sha384_hmac_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_BYTE hmac[SHA384_HASH_SIZE]; - SIGN_VERIFY_CONTEXT hmac_ctx; - CK_ULONG hmac_len, len; - CK_RV rc; - - if (!sess || !ctx || !in_data || !signature) { - TRACE_ERROR("%s received bad argument(s)\n", __func__); - return CKR_FUNCTION_FAILED; - } - if (token_specific.t_hmac_verify != NULL) - return token_specific.t_hmac_verify(tokdata, sess, in_data, - in_data_len, signature, sig_len); - - /* Do manual hmac verify if token doesn't have an hmac crypto call. - * Secure tokens should not do manual hmac. - */ - if (ctx->mech.mechanism == CKM_SHA384_HMAC_GENERAL) - hmac_len = *(CK_ULONG *) ctx->mech.pParameter; - else - hmac_len = SHA384_HASH_SIZE; - - memset(&hmac_ctx, 0, sizeof(SIGN_VERIFY_CONTEXT)); - - rc = sign_mgr_init(tokdata, sess, &hmac_ctx, &ctx->mech, FALSE, ctx->key); - if (rc != CKR_OK) { - TRACE_DEVEL("Sign Mgr Init failed.\n"); - goto done; - } - len = sizeof(hmac); - rc = sign_mgr_sign(tokdata, sess, FALSE, &hmac_ctx, in_data, in_data_len, - hmac, &len); - if (rc != CKR_OK) { - TRACE_DEVEL("Sign Mgr Sign failed.\n"); - goto done; - } - if ((len != hmac_len) || (len != sig_len)) { - TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_LEN_RANGE)); - rc = CKR_SIGNATURE_LEN_RANGE; - goto done; - } - - if (CRYPTO_memcmp(hmac, signature, hmac_len) != 0) { - TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); - rc = CKR_SIGNATURE_INVALID; - } -done: - sign_mgr_cleanup(&hmac_ctx); - return rc; } -CK_RV sha512_hmac_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_BYTE hmac[SHA512_HASH_SIZE]; - SIGN_VERIFY_CONTEXT hmac_ctx; - CK_ULONG hmac_len, len; - CK_RV rc; - - if (!sess || !ctx || !in_data || !signature) { - TRACE_ERROR("%s received bad argument(s)\n", __func__); - return CKR_FUNCTION_FAILED; - } - if (token_specific.t_hmac_verify != NULL) - return token_specific.t_hmac_verify(tokdata, sess, in_data, - in_data_len, signature, sig_len); - - /* Do manual hmac verify if token doesn't have an hmac crypto call. - * Secure tokens should not do manual hmac. - */ - if (ctx->mech.mechanism == CKM_SHA512_HMAC_GENERAL) - hmac_len = *(CK_ULONG *) ctx->mech.pParameter; - else if (ctx->mech.mechanism == CKM_SHA512_224_HMAC) - hmac_len = SHA224_HASH_SIZE; - else if (ctx->mech.mechanism == CKM_SHA512_256_HMAC) - hmac_len = SHA256_HASH_SIZE; - else - hmac_len = SHA512_HASH_SIZE; - - memset(&hmac_ctx, 0, sizeof(SIGN_VERIFY_CONTEXT)); - - rc = sign_mgr_init(tokdata, sess, &hmac_ctx, &ctx->mech, FALSE, ctx->key); - if (rc != CKR_OK) { - TRACE_DEVEL("Sign Mgr Init failed.\n"); - goto done; - } - len = sizeof(hmac); - rc = sign_mgr_sign(tokdata, sess, FALSE, &hmac_ctx, in_data, in_data_len, - hmac, &len); - if (rc != CKR_OK) { - TRACE_DEVEL("Sign Mgr Sign failed.\n"); - goto done; - } - if ((len != hmac_len) || (len != sig_len)) { - TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_LEN_RANGE)); - rc = CKR_SIGNATURE_LEN_RANGE; - goto done; - } - - if (CRYPTO_memcmp(hmac, signature, hmac_len) != 0) { - TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); - rc = CKR_SIGNATURE_INVALID; - } -done: - sign_mgr_cleanup(&hmac_ctx); - return rc; -} CK_RV hmac_sign_init(STDLL_TokData_t *tokdata, SESSION *sess, CK_MECHANISM *mech, CK_OBJECT_HANDLE hkey) diff --git a/usr/lib/common/new_host.c b/usr/lib/common/new_host.c index 93ada56..118a6da 100644 --- a/usr/lib/common/new_host.c +++ b/usr/lib/common/new_host.c @@ -115,13 +115,24 @@ CK_RV ST_Initialize(API_Slot_t *sltp, CK_SLOT_ID SlotNumber, bt_init(&sltp->TokData->publ_token_obj_btree, call_object_free); if (strlen(sinfp->tokname)) { - sprintf(abs_tokdir_name, "%s/%s", CONFIG_PATH, sinfp->tokname); + if (ock_snprintf(abs_tokdir_name, PATH_MAX, "%s/%s", + CONFIG_PATH, sinfp->tokname) != 0) { + TRACE_ERROR("token directory path buffer overflow\n"); + rc = CKR_FUNCTION_FAILED; + goto done; + } TRACE_DEVEL("Token directory: %s\n", abs_tokdir_name); - init_data_store(sltp->TokData, (char *) abs_tokdir_name, - sltp->TokData->data_store); + rc = init_data_store(sltp->TokData, (char *) abs_tokdir_name, + sltp->TokData->data_store, + sizeof(sltp->TokData->data_store)); } else { - init_data_store(sltp->TokData, (char *) PK_DIR, - sltp->TokData->data_store); + rc = init_data_store(sltp->TokData, (char *) PK_DIR, + sltp->TokData->data_store, + sizeof(sltp->TokData->data_store)); + } + if (rc != CKR_OK) { + TRACE_ERROR("init_data_store failed with buffer error.\n"); + goto done; } sltp->TokData->version = sinfp->version; @@ -488,6 +499,9 @@ CK_RV SC_InitToken(STDLL_TokData_t *tokdata, CK_SLOT_ID sid, CK_CHAR_PTR pPin, memcpy(dat->so_login_key, login_key, 32); } tokdata->nv_token_data->token_info.flags |= CKF_TOKEN_INITIALIZED; + tokdata->nv_token_data->token_info.flags &= ~(CKF_USER_PIN_INITIALIZED | + CKF_USER_PIN_LOCKED | CKF_USER_PIN_FINAL_TRY | + CKF_USER_PIN_COUNT_LOW); memcpy(tokdata->nv_token_data->token_info.label, pLabel, 32); rc = save_token_data(tokdata, sid); @@ -988,7 +1002,7 @@ CK_RV SC_SetPIN(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession, } done: - TRACE_INFO("C_SetPin: rc = 0x%08lx, session = %lu\n", + TRACE_INFO("C_SetPIN: rc = 0x%08lx, session = %lu\n", rc, sSession->sessionh); pthread_mutex_unlock(&tokdata->login_mutex); @@ -1297,6 +1311,12 @@ CK_RV SC_Login(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession, goto done; } + if (!(*flags & CKF_USER_PIN_INITIALIZED)) { + TRACE_ERROR("%s\n", ock_err(ERR_USER_PIN_NOT_INITIALIZED)); + rc = CKR_USER_PIN_NOT_INITIALIZED; + goto done; + } + /* Check if token has a specific handler for this, otherwise * fall back to default behaviour. */ @@ -2792,8 +2812,10 @@ CK_RV SC_Sign(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession, TRACE_DEVEL("sign_mgr_sign() failed.\n"); done: - if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) - sign_mgr_cleanup(&sess->sign_ctx); + if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) { + if (sess != NULL) + sign_mgr_cleanup(&sess->sign_ctx); + } TRACE_INFO("C_Sign: rc = 0x%08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulDataLen); @@ -2841,7 +2863,7 @@ CK_RV SC_SignUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession, TRACE_DEVEL("sign_mgr_sign_update() failed.\n"); done: - if (rc != CKR_OK) + if (rc != CKR_OK && sess != NULL) sign_mgr_cleanup(&sess->sign_ctx); TRACE_INFO("C_SignUpdate: rc = 0x%08lx, sess = %ld, datalen = %lu\n", @@ -2895,8 +2917,10 @@ CK_RV SC_SignFinal(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession, TRACE_ERROR("sign_mgr_sign_final() failed.\n"); done: - if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) - sign_mgr_cleanup(&sess->sign_ctx); + if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) { + if (sess != NULL) + sign_mgr_cleanup(&sess->sign_ctx); + } TRACE_INFO("C_SignFinal: rc = 0x%08lx, sess = %ld\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle); @@ -3008,8 +3032,10 @@ CK_RV SC_SignRecover(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession, TRACE_DEVEL("sign_mgr_sign_recover() failed.\n"); done: - if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) - sign_mgr_cleanup(&sess->sign_ctx); + if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) { + if (sess != NULL) + sign_mgr_cleanup(&sess->sign_ctx); + } TRACE_INFO("C_SignRecover: rc = 0x%08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulDataLen); @@ -3117,7 +3143,8 @@ CK_RV SC_Verify(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession, TRACE_DEVEL("verify_mgr_verify() failed.\n"); done: - verify_mgr_cleanup(&sess->verify_ctx); + if (sess != NULL) + verify_mgr_cleanup(&sess->verify_ctx); TRACE_INFO("C_Verify: rc = 0x%08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulDataLen); @@ -3166,7 +3193,7 @@ CK_RV SC_VerifyUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession, TRACE_DEVEL("verify_mgr_verify_update() failed.\n"); done: - if (rc != CKR_OK) + if (rc != CKR_OK && sess != NULL) verify_mgr_cleanup(&sess->verify_ctx); TRACE_INFO("C_VerifyUpdate: rc = 0x%08lx, sess = %ld, datalen = %lu\n", @@ -3216,7 +3243,8 @@ CK_RV SC_VerifyFinal(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession, TRACE_DEVEL("verify_mgr_verify_final() failed.\n"); done: - verify_mgr_cleanup(&sess->verify_ctx); + if (sess != NULL) + verify_mgr_cleanup(&sess->verify_ctx); TRACE_INFO("C_VerifyFinal: rc = 0x%08lx, sess = %ld\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle); @@ -3331,8 +3359,10 @@ CK_RV SC_VerifyRecover(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession, TRACE_DEVEL("verify_mgr_verify_recover() failed.\n"); done: - if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) - verify_mgr_cleanup(&sess->verify_ctx); + if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) { + if (sess != NULL) + verify_mgr_cleanup(&sess->verify_ctx); + } TRACE_INFO("C_VerifyRecover: rc = 0x%08lx, sess = %ld, recover len = %lu, " "length_only = %d\n", rc, @@ -3946,6 +3976,77 @@ CK_RV SC_CancelFunction(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession) return CKR_FUNCTION_NOT_PARALLEL; } +CK_RV SC_IBM_ReencryptSingle(STDLL_TokData_t *tokdata, ST_SESSION_T *sSession, + CK_MECHANISM_PTR pDecrMech, + CK_OBJECT_HANDLE hDecrKey, + CK_MECHANISM_PTR pEncrMech, + CK_OBJECT_HANDLE hEncrKey, + CK_BYTE_PTR pEncryptedData, + CK_ULONG ulEncryptedDataLen, + CK_BYTE_PTR pReencryptedData, + CK_ULONG_PTR pulReencryptedDataLen) +{ + SESSION *sess = NULL; + CK_RV rc = CKR_OK; + + if (tokdata->initialized == FALSE) { + TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); + rc = CKR_CRYPTOKI_NOT_INITIALIZED; + goto done; + } + + if (!pDecrMech || !pEncrMech) { + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + rc = CKR_ARGUMENTS_BAD; + goto done; + } + + sess = session_mgr_find(tokdata, sSession->sessionh); + if (!sess) { + TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); + rc = CKR_SESSION_HANDLE_INVALID; + goto done; + } + + rc = valid_mech(tokdata, pDecrMech, CKF_DECRYPT); + if (rc != CKR_OK) + goto done; + rc = valid_mech(tokdata, pEncrMech, CKF_ENCRYPT); + if (rc != CKR_OK) + goto done; + + if (pin_expired(&sess->session_info, + tokdata->nv_token_data->token_info.flags) == TRUE) { + TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); + rc = CKR_PIN_EXPIRED; + goto done; + } + + if (sess->decr_ctx.active == TRUE || sess->encr_ctx.active == TRUE) { + rc = CKR_OPERATION_ACTIVE; + TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); + goto done; + } + + rc = encr_mgr_reencrypt_single(tokdata, sess, &sess->decr_ctx, pDecrMech, + hDecrKey, &sess->encr_ctx, pEncrMech, + hEncrKey, pEncryptedData, ulEncryptedDataLen, + pReencryptedData, pulReencryptedDataLen); + if (rc != CKR_OK) + TRACE_DEVEL("encr_mgr_reencrypt_single() failed.\n"); + +done: + TRACE_INFO("SC_IBM_ReencryptSingle: rc = 0x%08lx, sess = %ld, " + "decrmech = 0x%lx, encrmech = 0x%lx\n", + rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, + (pDecrMech ? pDecrMech->mechanism : (CK_ULONG)-1), + (pEncrMech ? pEncrMech->mechanism : (CK_ULONG)-1)); + + if (sess != NULL) + session_mgr_put(tokdata, sess); + + return rc; +} void SC_SetFunctionList(void) { @@ -4010,4 +4111,6 @@ void SC_SetFunctionList(void) function_list.ST_GenerateRandom = SC_GenerateRandom; function_list.ST_GetFunctionStatus = NULL; // SC_GetFunctionStatus; function_list.ST_CancelFunction = NULL; // SC_CancelFunction; + + function_list.ST_IBM_ReencryptSingle = SC_IBM_ReencryptSingle; } diff --git a/usr/lib/common/obj_mgr.c b/usr/lib/common/obj_mgr.c index 3e4ba3b..68e7be6 100644 --- a/usr/lib/common/obj_mgr.c +++ b/usr/lib/common/obj_mgr.c @@ -28,35 +28,9 @@ #include "../api/apiproto.h" -CK_RV object_mgr_add(STDLL_TokData_t *tokdata, - SESSION *sess, - CK_ATTRIBUTE *pTemplate, - CK_ULONG ulCount, CK_OBJECT_HANDLE *handle) +static CK_RV object_mgr_check_session(SESSION *sess, CK_BBOOL priv_obj, + CK_BBOOL sess_obj) { - OBJECT *o = NULL; - CK_BBOOL priv_obj, sess_obj, added = FALSE, locked = FALSE; - CK_RV rc; - unsigned long obj_handle; - - if (!sess || !pTemplate || !handle) { - TRACE_ERROR("Invalid function arguments.\n"); - return CKR_ARGUMENTS_BAD; - } - - rc = object_create(tokdata, pTemplate, ulCount, &o); - if (rc != CKR_OK) { - TRACE_DEVEL("Object Create failed.\n"); - goto done; - } - - if (token_specific.t_object_add != NULL) { - rc = token_specific.t_object_add(tokdata, sess, o); - if (rc != CKR_OK) { - TRACE_DEVEL("Token specific object add failed.\n"); - goto done; - } - } - // check whether session has permissions to create the object, etc // // Object R/O R/W R/O R/W R/W @@ -67,46 +41,78 @@ CK_RV object_mgr_add(STDLL_TokData_t *tokdata, // Public token R/O R/W R/O R/W R/W // Private token R/O R/W // - sess_obj = object_is_session_object(o); - priv_obj = object_is_private(o); - if (sess->session_info.state == CKS_RO_PUBLIC_SESSION) { if (priv_obj) { TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); - rc = CKR_USER_NOT_LOGGED_IN; - goto done; + return CKR_USER_NOT_LOGGED_IN; } if (!sess_obj) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_READ_ONLY)); - rc = CKR_SESSION_READ_ONLY; - goto done; + return CKR_SESSION_READ_ONLY; } } if (sess->session_info.state == CKS_RO_USER_FUNCTIONS) { if (!sess_obj) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_READ_ONLY)); - rc = CKR_SESSION_READ_ONLY; - goto done; + return CKR_SESSION_READ_ONLY; } } if (sess->session_info.state == CKS_RW_PUBLIC_SESSION) { if (priv_obj) { TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); - rc = CKR_USER_NOT_LOGGED_IN; - goto done; + return CKR_USER_NOT_LOGGED_IN; } } if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) { if (priv_obj) { TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); - rc = CKR_USER_NOT_LOGGED_IN; + return CKR_USER_NOT_LOGGED_IN; + } + } + + return CKR_OK; +} + +CK_RV object_mgr_add(STDLL_TokData_t *tokdata, + SESSION *sess, + CK_ATTRIBUTE *pTemplate, + CK_ULONG ulCount, CK_OBJECT_HANDLE *handle) +{ + OBJECT *o = NULL; + CK_BBOOL priv_obj, sess_obj, added = FALSE, locked = FALSE; + CK_RV rc; + unsigned long obj_handle; + + if (!sess || !pTemplate || !handle) { + TRACE_ERROR("Invalid function arguments.\n"); + return CKR_ARGUMENTS_BAD; + } + + rc = object_create(tokdata, pTemplate, ulCount, &o); + if (rc != CKR_OK) { + TRACE_DEVEL("Object Create failed.\n"); + goto done; + } + + if (token_specific.t_object_add != NULL) { + rc = token_specific.t_object_add(tokdata, sess, o); + if (rc != CKR_OK) { + TRACE_DEVEL("Token specific object add failed.\n"); goto done; } } + + sess_obj = object_is_session_object(o); + priv_obj = object_is_private(o); + + rc = object_mgr_check_session(sess, priv_obj, sess_obj); + if (rc != CKR_OK) + goto done; + // okay, object is created and the session permissions look okay. // add the object to the appropriate list and assign an object handle // @@ -346,56 +352,13 @@ CK_RV object_mgr_copy(STDLL_TokData_t *tokdata, goto done; } - // check whether session has permissions to create the object, etc - // - // Object R/O R/W R/O R/W R/W - // Type Public Public User User SO - // ------------------------------------------------------------- - // Public session R/W R/W R/W R/W R/W - // Private session R/W R/W - // Public token R/O R/W R/O R/W R/W - // Private token R/O R/W - // sess_obj = object_is_session_object(new_obj); priv_obj = object_is_private(new_obj); - if (sess->session_info.state == CKS_RO_PUBLIC_SESSION) { - if (priv_obj) { - TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); - rc = CKR_USER_NOT_LOGGED_IN; - goto done; - } - - if (!sess_obj) { - TRACE_ERROR("%s\n", ock_err(ERR_SESSION_READ_ONLY)); - rc = CKR_SESSION_READ_ONLY; - goto done; - } - } - - if (sess->session_info.state == CKS_RO_USER_FUNCTIONS) { - if (!sess_obj) { - TRACE_ERROR("%s\n", ock_err(ERR_SESSION_READ_ONLY)); - rc = CKR_SESSION_READ_ONLY; - goto done; - } - } - - if (sess->session_info.state == CKS_RW_PUBLIC_SESSION) { - if (priv_obj) { - TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); - rc = CKR_USER_NOT_LOGGED_IN; - goto done; - } - } + rc = object_mgr_check_session(sess, priv_obj, sess_obj); + if (rc != CKR_OK) + goto done; - if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) { - if (priv_obj) { - TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); - rc = CKR_USER_NOT_LOGGED_IN; - goto done; - } - } // okay, object is created and the session permissions look okay. // add the object to the appropriate list and assign an object handle // @@ -758,9 +721,26 @@ CK_RV object_mgr_destroy_object(STDLL_TokData_t *tokdata, OBJECT_MAP *map; OBJECT *o = NULL; CK_BBOOL locked = FALSE; + CK_BBOOL priv_obj; + CK_BBOOL sess_obj; UNUSED(sess); + rc = object_mgr_find_in_map1(tokdata, handle, &o, READ_LOCK); + if (rc != CKR_OK || o == NULL) { + TRACE_DEVEL("object_mgr_find_in_map1 failed.\n"); + return CKR_OBJECT_HANDLE_INVALID; + } + + sess_obj = object_is_session_object(o); + priv_obj = object_is_private(o); + + rc = object_mgr_check_session(sess, priv_obj, sess_obj); + object_put(tokdata, o, TRUE); + o = NULL; + if (rc != CKR_OK) + return rc; + /* Don't use a delete callback, the map will be freed below */ map = bt_node_free(&tokdata->object_map_btree, handle, FALSE); if (map == NULL) { @@ -1683,43 +1663,10 @@ CK_RV object_mgr_set_attribute_values(STDLL_TokData_t *tokdata, rc = CKR_ATTRIBUTE_READ_ONLY; goto done; } - if (sess->session_info.state == CKS_RO_PUBLIC_SESSION) { - if (priv_obj) { - TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); - rc = CKR_USER_NOT_LOGGED_IN; - goto done; - } - if (!sess_obj) { - TRACE_ERROR("%s\n", ock_err(ERR_SESSION_READ_ONLY)); - rc = CKR_SESSION_READ_ONLY; - goto done; - } - } - - if (sess->session_info.state == CKS_RO_USER_FUNCTIONS) { - if (!sess_obj) { - TRACE_ERROR("%s\n", ock_err(ERR_SESSION_READ_ONLY)); - rc = CKR_SESSION_READ_ONLY; - goto done; - } - } - - if (sess->session_info.state == CKS_RW_PUBLIC_SESSION) { - if (priv_obj) { - TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); - rc = CKR_USER_NOT_LOGGED_IN; - goto done; - } - } - - if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) { - if (priv_obj) { - TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); - rc = CKR_USER_NOT_LOGGED_IN; - goto done; - } - } + rc = object_mgr_check_session(sess, priv_obj, sess_obj); + if (rc != CKR_OK) + goto done; rc = object_set_attribute_values(tokdata, obj, pTemplate, ulCount); if (rc != CKR_OK) { @@ -1751,6 +1698,12 @@ CK_RV object_mgr_set_attribute_values(STDLL_TokData_t *tokdata, save_token_object(tokdata, obj); if (priv_obj) { + if (tokdata->global_shm->num_priv_tok_obj == 0) { + TRACE_DEVEL("%s\n", ock_err(ERR_OBJECT_HANDLE_INVALID)); + rc = CKR_OBJECT_HANDLE_INVALID; + XProcUnLock(tokdata); + goto done; + } rc = object_mgr_search_shm_for_obj(tokdata->global_shm-> priv_tok_objs, 0, tokdata->global_shm-> @@ -1765,6 +1718,12 @@ CK_RV object_mgr_set_attribute_values(STDLL_TokData_t *tokdata, entry = &tokdata->global_shm->priv_tok_objs[index]; } else { + if (tokdata->global_shm->num_publ_tok_obj == 0) { + TRACE_DEVEL("%s\n", ock_err(ERR_OBJECT_HANDLE_INVALID)); + rc = CKR_OBJECT_HANDLE_INVALID; + XProcUnLock(tokdata); + goto done; + } rc = object_mgr_search_shm_for_obj(tokdata->global_shm-> publ_tok_objs, 0, tokdata->global_shm-> @@ -1846,6 +1805,10 @@ CK_RV object_mgr_del_from_shm(OBJECT *obj, LW_SHM_TYPE *global_shm) priv = object_is_private(obj); if (priv) { + if (global_shm->num_priv_tok_obj == 0) { + TRACE_DEVEL("%s\n", ock_err(ERR_OBJECT_HANDLE_INVALID)); + return CKR_OBJECT_HANDLE_INVALID; + } rc = object_mgr_search_shm_for_obj(global_shm->priv_tok_objs, 0, global_shm->num_priv_tok_obj - 1, obj, &index); @@ -1886,6 +1849,10 @@ CK_RV object_mgr_del_from_shm(OBJECT *obj, LW_SHM_TYPE *global_shm) sizeof(TOK_OBJ_ENTRY)); } } else { + if (global_shm->num_publ_tok_obj == 0) { + TRACE_DEVEL("%s\n", ock_err(ERR_OBJECT_HANDLE_INVALID)); + return CKR_OBJECT_HANDLE_INVALID; + } rc = object_mgr_search_shm_for_obj(global_shm->publ_tok_objs, 0, global_shm->num_publ_tok_obj - 1, obj, &index); diff --git a/usr/lib/common/object.c b/usr/lib/common/object.c index 367670a..a6d7411 100644 --- a/usr/lib/common/object.c +++ b/usr/lib/common/object.c @@ -99,7 +99,8 @@ CK_RV object_create(STDLL_TokData_t * tokdata, return CKR_ATTRIBUTE_TYPE_INVALID; } - if (class != CKO_DATA && subclass_given != TRUE) { + if (subclass_given != TRUE + && class != CKO_DATA && class != CKO_PROFILE) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } @@ -461,7 +462,8 @@ CK_RV object_get_attribute_values(OBJECT * obj, for (i = 0; i < ulCount; i++) { flag = template_check_exportability(obj_tmpl, pTemplate[i].type); if (flag == FALSE) { - TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_SENSITIVE)); + TRACE_ERROR("%s: %lx\n", ock_err(ERR_ATTRIBUTE_SENSITIVE), + pTemplate[i].type); rc = CKR_ATTRIBUTE_SENSITIVE; pTemplate[i].ulValueLen = (CK_ULONG) - 1; continue; @@ -469,7 +471,8 @@ CK_RV object_get_attribute_values(OBJECT * obj, flag = template_attribute_find(obj_tmpl, pTemplate[i].type, &attr); if (flag == FALSE) { - TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_TYPE_INVALID)); + TRACE_ERROR("%s: %lx\n", ock_err(ERR_ATTRIBUTE_TYPE_INVALID), + pTemplate[i].type); rc = CKR_ATTRIBUTE_TYPE_INVALID; pTemplate[i].ulValueLen = (CK_ULONG) - 1; continue; @@ -478,7 +481,8 @@ CK_RV object_get_attribute_values(OBJECT * obj, if (pTemplate[i].pValue == NULL) { pTemplate[i].ulValueLen = attr->ulValueLen; } else if (pTemplate[i].ulValueLen >= attr->ulValueLen) { - memcpy(pTemplate[i].pValue, attr->pValue, attr->ulValueLen); + if (attr->pValue != NULL) + memcpy(pTemplate[i].pValue, attr->pValue, attr->ulValueLen); pTemplate[i].ulValueLen = attr->ulValueLen; } else { TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); diff --git a/usr/lib/common/p11util.c b/usr/lib/common/p11util.c index 84b63ce..3787ab5 100644 --- a/usr/lib/common/p11util.c +++ b/usr/lib/common/p11util.c @@ -167,6 +167,8 @@ CK_BBOOL is_attribute_defined(CK_ATTRIBUTE_TYPE type) case CKA_ALWAYS_SENSITIVE: case CKA_ALWAYS_AUTHENTICATE: case CKA_MODIFIABLE: + case CKA_UNIQUE_ID: + case CKA_PROFILE_ID: case CKA_ECDSA_PARAMS: case CKA_EC_POINT: case CKA_HW_FEATURE_TYPE: @@ -425,7 +427,7 @@ char *p11_get_ckm(CK_ULONG mechanism) _sym2str(CKM_IBM_SHA3_384_HMAC); _sym2str(CKM_IBM_SHA3_512_HMAC); _sym2str(CKM_IBM_EC_C25519); - _sym2str(CKM_IBM_EDDSA_SHA512); + _sym2str(CKM_IBM_ED25519_SHA512); _sym2str(CKM_IBM_EC_C448); _sym2str(CKM_IBM_ED448_SHA3); _sym2str(CKM_IBM_DILITHIUM); @@ -445,7 +447,7 @@ char *p11_ahex_dump(char **dst, CK_BYTE_PTR ptr, CK_ULONG len) return NULL; } - *dst = (char *) calloc(2 * len + 1, sizeof(char)); + *dst = (char *) malloc(2 * len + 1); if (*dst == NULL) { return NULL; } diff --git a/usr/lib/common/parser.y b/usr/lib/common/parser.y new file mode 100644 index 0000000..86806fc --- /dev/null +++ b/usr/lib/common/parser.y @@ -0,0 +1,304 @@ +/* + * 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 --git a/usr/lib/common/pkcs_utils.c b/usr/lib/common/pkcs_utils.c new file mode 100644 index 0000000..d3074d5 --- /dev/null +++ b/usr/lib/common/pkcs_utils.c @@ -0,0 +1,477 @@ +/* + * 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 + */ + +/* + * Some routines that are shared between the pkcs utilities in usr/sbin. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "defs.h" +#include "host_defs.h" + +#define OCK_TOOL +#include "pkcs_utils.h" + +extern pkcs_trace_level_t trace_level; + +void pkcs_trace(pkcs_trace_level_t level, const char *file, int line, + const char *fmt, ...) +{ + va_list ap; + const char *fmt_pre; + char buf[1024]; + char *pbuf; + int buflen, len; + + if (level > trace_level) + return; + + pbuf = buf; + buflen = sizeof(buf); + + /* add file line */ + switch (level) { + case TRACE_LEVEL_NONE: + fmt_pre = ""; + break; + case TRACE_LEVEL_ERROR: + fmt_pre = "[%s:%d] ERROR: "; + break; + case TRACE_LEVEL_WARNING: + fmt_pre = "[%s:%d] WARN: "; + break; + case TRACE_LEVEL_INFO: + fmt_pre = "[%s:%d] INFO: "; + break; + case TRACE_LEVEL_DEVEL: + fmt_pre = "[%s:%d] DEVEL: "; + break; + case TRACE_LEVEL_DEBUG: + fmt_pre = "[%s:%d] DEBUG: "; + break; + default: + return; + } + snprintf(pbuf, buflen, fmt_pre, file, line); + + len = strlen(buf); + pbuf = buf + len; + buflen = sizeof(buf) - len; + + va_start(ap, fmt); + vsnprintf(pbuf, buflen, fmt, ap); + va_end(ap); + + printf("%s", buf); +} + +int compute_hash(int hash_type, int buf_size, char *buf, char *digest) +{ + EVP_MD_CTX *md_ctx = NULL; + unsigned int result_size; + int rc; + + md_ctx = EVP_MD_CTX_create(); + + switch (hash_type) { + case HASH_SHA1: + rc = EVP_DigestInit(md_ctx, EVP_sha1()); + break; + case HASH_MD5: + rc = EVP_DigestInit(md_ctx, EVP_md5()); + break; + default: + rc = -1; + goto done; + } + + if (rc != 1) { + TRACE_ERROR("EVP_DigestInit() failed: rc = %d\n", rc); + rc = -1; + goto done; + } + + rc = EVP_DigestUpdate(md_ctx, buf, buf_size); + if (rc != 1) { + TRACE_ERROR("EVP_DigestUpdate() failed: rc = %d\n", rc); + rc = -1; + goto done; + } + + result_size = EVP_MD_CTX_size(md_ctx); + rc = EVP_DigestFinal(md_ctx, (unsigned char *) digest, &result_size); + if (rc != 1) { + TRACE_ERROR("EVP_DigestFinal() failed: rc = %d\n", rc); + rc = -1; + goto done; + } + + rc = 0; + +done: + + EVP_MD_CTX_destroy(md_ctx); + + return rc; +} + +CK_RV local_rng(CK_BYTE *output, CK_ULONG bytes) +{ + int ranfd; + int rlen; + unsigned int totallen = 0; + + ranfd = open("/dev/prandom", 0); + if (ranfd < 0) + ranfd = open("/dev/urandom", 0); + if (ranfd >= 0) { + do { + rlen = read(ranfd, output + totallen, bytes - totallen); + totallen += rlen; + } while (totallen < bytes); + close(ranfd); + return CKR_OK; + } + + return CKR_FUNCTION_FAILED; +} + +CK_RV aes_256_wrap(unsigned char out[40], const unsigned char in[32], + const unsigned char kek[32]) +{ + CK_RV rc; + int outlen; + unsigned char buffer[40 + EVP_MAX_BLOCK_LENGTH]; + + EVP_CIPHER_CTX *ctx = NULL; + + ctx = EVP_CIPHER_CTX_new(); + if (ctx == NULL) { + TRACE_ERROR("EVP_CIPHER_CTX_new failed.\n"); + rc = CKR_HOST_MEMORY; + goto done; + } + + EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW); + + if (EVP_CipherInit_ex(ctx, EVP_aes_256_wrap(), NULL, kek, NULL, 1) != 1 + || EVP_CipherUpdate(ctx, buffer, &outlen, in, 32) != 1 + || EVP_CipherFinal_ex(ctx, buffer + outlen, &outlen) != 1) { + TRACE_ERROR("EVP_Cipher funcs failed\n"); + rc = CKR_FUNCTION_FAILED; + goto done; + } + + memcpy(out, buffer, 40); + rc = CKR_OK; +done: + EVP_CIPHER_CTX_free(ctx); + return rc; +} + +CK_RV aes_256_unwrap(unsigned char key[32], const unsigned char in[40], + const unsigned char kek[32]) +{ + CK_RV rc; + int outlen; + unsigned char buffer[32 + EVP_MAX_BLOCK_LENGTH]; + + EVP_CIPHER_CTX *ctx = NULL; + + ctx = EVP_CIPHER_CTX_new(); + if (ctx == NULL) { + TRACE_ERROR("EVP_CIPHER_CTX_new failed\n"); + rc = CKR_HOST_MEMORY; + goto done; + } + + EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW); + + if (EVP_CipherInit_ex(ctx, EVP_aes_256_wrap(), NULL, kek, NULL, 0) != 1 + || EVP_CipherUpdate(ctx, buffer, &outlen, in, 40) != 1 + || EVP_CipherFinal_ex(ctx, buffer + outlen, &outlen) != 1) { + rc = CKR_FUNCTION_FAILED; + goto done; + } + + memcpy(key, buffer, 32); + rc = CKR_OK; +done: + EVP_CIPHER_CTX_free(ctx); + return rc; +} + +CK_RV aes_256_gcm_seal(unsigned char *out, unsigned char tag[16], + const unsigned char *aad, size_t aadlen, + const unsigned char *in, size_t inlen, + const unsigned char key[32], + const unsigned char iv[12]) +{ + CK_RV rc; + int outlen; + + EVP_CIPHER_CTX *ctx = NULL; + + ctx = EVP_CIPHER_CTX_new(); + if (ctx == NULL) { + TRACE_ERROR("EVP_CIPHER_CTX_new failed\n"); + rc = CKR_HOST_MEMORY; + goto done; + } + + if (EVP_CipherInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL, -1) != 1 + || EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL) != 1 + || EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) != 1 + || EVP_CipherUpdate(ctx, NULL, &outlen, aad, aadlen) != 1 + || EVP_CipherUpdate(ctx, out, &outlen, in, inlen) != 1 + || EVP_CipherFinal_ex(ctx, out + outlen, &outlen) != 1 + || EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag) != 1) { + TRACE_ERROR("EVP_Cipher funcs failed\n"); + rc = CKR_FUNCTION_FAILED; + goto done; + } + + rc = CKR_OK; +done: + EVP_CIPHER_CTX_free(ctx); + return rc; +} + +int get_pin(char **pin, size_t *pinlen) +{ + struct termios old, new; + int nread; + char *buff = NULL; + size_t buflen; + int rc = 0; + + /* turn echoing off */ + if (tcgetattr(fileno(stdin), &old) != 0) + return -1; + + new = old; + new.c_lflag &= ~ECHO; + if (tcsetattr(fileno(stdin), TCSAFLUSH, &new) != 0) + return -1; + + /* read the pin + * Note: getline will allocate memory for buff. free it when done. + */ + nread = getline(&buff, &buflen, stdin); + if (nread == -1) { + rc = -1; + goto done; + } + + /* Restore terminal */ + (void) tcsetattr(fileno(stdin), TCSAFLUSH, &old); + + /* start a newline */ + 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. */ + buff[nread - 1] = '\0'; + memcpy(*pin, buff, nread); + /* don't include the terminating null in the pinlen */ + *pinlen = nread - 1; + +done: + if (buff) + free(buff); + + return rc; +} + +/** + * Verify that SO PIN and user PIN are correct by comparing their SHA-1 + * values with the stored hashes in NVTOK.DAT. + */ +int verify_pins(char *data_store, char *sopin, unsigned long sopinlen, + char *userpin, unsigned long userpinlen) +{ + TOKEN_DATA td; + char fname[PATH_MAX]; + char pin_sha[SHA1_HASH_SIZE]; + FILE *fp = NULL; + int ret; + int tdnew; + struct stat stbuf; + size_t tdlen; + int fd; + + /* read the NVTOK.DAT */ + snprintf(fname, PATH_MAX, "%s/NVTOK.DAT", data_store); + fp = fopen((char *) fname, "r"); + if (!fp) { + TRACE_ERROR("Cannot not open %s: %s\n", fname, strerror(errno)); + return -1; + } + + fd = fileno(fp); + if ((fstat(fd, &stbuf) != 0) || (!S_ISREG(stbuf.st_mode))) { + ret = -1; + goto done; + } + + if (stbuf.st_size == sizeof(TOKEN_DATA_OLD)) { + /* old data store/pin format */ + tdnew = 0; + tdlen = sizeof(TOKEN_DATA_OLD); + } else if (stbuf.st_size == sizeof(TOKEN_DATA)) { + /* new data store/pin format */ + tdnew = 1; + tdlen = sizeof(TOKEN_DATA); + } else { + TRACE_ERROR("%s has an invalid size of %ld bytes. Neither old nor new token format.\n", + fname, stbuf.st_size); + ret = -1; + goto done; + } + + ret = fread(&td, tdlen, 1, fp); + if (ret != 1) { + TRACE_ERROR("Could not read %s: %s\n", fname, strerror(errno)); + ret = -1; + goto done; + } + + if (tdnew == 0) { + /* Now compute the SHAs for the SO and USER pins entered. + * Compare with the SHAs for SO and USER PINs saved in + * NVTOK.DAT to verify. + */ + + if (sopin != NULL) { + ret = compute_sha1(sopin, sopinlen, pin_sha); + if (ret) { + TRACE_ERROR("Failed to compute sha for SO.\n"); + goto done; + } + + if (memcmp(td.so_pin_sha, pin_sha, SHA1_HASH_SIZE) != 0) { + TRACE_ERROR("SO PIN is incorrect.\n"); + ret = -1; + goto done; + } + } + + if (userpin != NULL) { + ret = compute_sha1(userpin, userpinlen, pin_sha); + if (ret) { + TRACE_ERROR("Failed to compute sha for USER.\n"); + goto done; + } + + if (memcmp(td.user_pin_sha, pin_sha, SHA1_HASH_SIZE) != 0) { + TRACE_ERROR("USER PIN is incorrect.\n"); + ret = -1; + goto done; + } + } + } else if (tdnew == 1) { + if (sopin != NULL) { + unsigned char so_login_key[32]; + + ret = PKCS5_PBKDF2_HMAC(sopin, sopinlen, + td.dat.so_login_salt, 64, + td.dat.so_login_it, EVP_sha512(), + 256 / 8, so_login_key); + if (ret != 1) { + TRACE_ERROR("PBKDF2 failed.\n"); + goto done; + } + + if (CRYPTO_memcmp(td.dat.so_login_key, so_login_key, 32) != 0) { + TRACE_ERROR("USER PIN is incorrect.\n"); + ret = -1; + goto done; + } + } + if (userpin != NULL) { + unsigned char user_login_key[32]; + + ret = PKCS5_PBKDF2_HMAC(userpin, userpinlen, + td.dat.user_login_salt, 64, + td.dat.user_login_it, EVP_sha512(), + 256 / 8, user_login_key); + if (ret != 1) { + TRACE_ERROR("PBKDF2 failed.\n"); + goto done; + } + + if (CRYPTO_memcmp(td.dat.user_login_key, user_login_key, 32) != 0) { + TRACE_ERROR("USER PIN is incorrect.\n"); + ret = -1; + goto done; + } + } + } else { + TRACE_ERROR("Unknown token format.\n"); + ret = -1; + goto done; + } + ret = 0; + +done: + /* clear out the hash */ + memset(pin_sha, 0, SHA1_HASH_SIZE); + if (fp) + fclose(fp); + + return ret; +} + +void set_perm(int file) +{ + struct group *grp; + + // Set absolute permissions or rw-rw---- + fchmod(file, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + + grp = getgrnam("pkcs11"); // Obtain the group id + if (grp) { + // set ownership to root, and pkcs11 group + if (fchown(file, getuid(), grp->gr_gid) != 0) { + goto error; + } + } else { + goto error; + } + + return; + +error: + TRACE_DEVEL("Unable to set permissions on file.\n"); +} diff --git a/usr/lib/common/pkcs_utils.h b/usr/lib/common/pkcs_utils.h new file mode 100644 index 0000000..248559c --- /dev/null +++ b/usr/lib/common/pkcs_utils.h @@ -0,0 +1,81 @@ +/* + * 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 PKCS_UTILS_H +#define PKCS_UTILS_H + +#include "pkcs11types.h" + +#define MASTER_KEY_SIZE 24 +#define MASTER_KEY_SIZE_CCA 64 +#define MAX_MASTER_KEY_SIZE MASTER_KEY_SIZE_CCA + +#define MK_FILE_SIZE_00 48 +#define MK_FILE_SIZE_00_CCA 88 + +#define HASH_SHA1 1 +#define HASH_MD5 2 + +#define compute_sha1(a,b,c) compute_hash((HASH_SHA1),(b),(a),(c)) +#define compute_md5(a,b,c) compute_hash(HASH_MD5,(b),(a),(c)) + +int compute_hash(int hash_type, int buf_size, char *buf, char *digest); + +CK_RV local_rng(CK_BYTE *output, CK_ULONG bytes); + +CK_RV aes_256_wrap(unsigned char out[40], const unsigned char in[32], + const unsigned char kek[32]); + +CK_RV aes_256_unwrap(unsigned char key[32], const unsigned char in[40], + const unsigned char kek[32]); + +CK_RV aes_256_gcm_seal(unsigned char *out, unsigned char tag[16], + const unsigned char *aad, size_t aadlen, + const unsigned char *in, size_t inlen, + const unsigned char key[32], + const unsigned char iv[12]); + +int get_pin(char **pin, size_t *pinlen); + +int verify_pins(char *data_store, char *sopin, unsigned long sopinlen, + char *userpin, unsigned long userpinlen); + +void set_perm(int file); + +#ifdef OCK_TOOL +/* Log levels */ +typedef enum { + TRACE_LEVEL_NONE = 0, + TRACE_LEVEL_ERROR, + TRACE_LEVEL_WARNING, + TRACE_LEVEL_INFO, + TRACE_LEVEL_DEVEL, + TRACE_LEVEL_DEBUG +} pkcs_trace_level_t; + +void pkcs_trace(pkcs_trace_level_t level, const char * file, int line, + const char *fmt, ...) + __attribute__ ((format(printf, 4, 5))); + +#define TRACE_NONE(...) \ + pkcs_trace(TRACE_LEVEL_NONE, __FILE__, __LINE__, __VA_ARGS__) +#define TRACE_ERROR(...) \ + pkcs_trace(TRACE_LEVEL_ERROR, __FILE__, __LINE__, __VA_ARGS__) +#define TRACE_WARN(...) \ + pkcs_trace(TRACE_LEVEL_WARNING, __FILE__, __LINE__, __VA_ARGS__) +#define TRACE_INFO(...) \ + pkcs_trace(TRACE_LEVEL_INFO, __FILE__, __LINE__, __VA_ARGS__) +#define TRACE_DEVEL(...) \ + pkcs_trace(TRACE_LEVEL_DEVEL, __FILE__, __LINE__, __VA_ARGS__) +#define TRACE_DEBUG(...) \ + pkcs_trace(TRACE_LEVEL_DEBUG, __FILE__, __LINE__, __VA_ARGS__) +#endif /* OCK_TOOL */ + +#endif diff --git a/usr/lib/common/profile_obj.c b/usr/lib/common/profile_obj.c new file mode 100644 index 0000000..9e30a08 --- /dev/null +++ b/usr/lib/common/profile_obj.c @@ -0,0 +1,78 @@ +/* + * 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 + */ + +#include +#include +#include + +#include "pkcs11types.h" +#include "defs.h" +#include "host_defs.h" +#include "h_extern.h" +#include "trace.h" + +CK_RV profile_object_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode) +{ + /* CKO_PROFILE has no required attributes */ + return template_check_required_base_attributes(tmpl, mode); +} + +CK_RV profile_object_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode) +{ + CK_ATTRIBUTE *class_attr = NULL; + CK_ATTRIBUTE *profile_id_attr = NULL; + + UNUSED(mode); + + class_attr = + (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_OBJECT_CLASS)); + profile_id_attr = + (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_PROFILE_ID)); + + if (!class_attr || !profile_id_attr) { + if (class_attr) + free(class_attr); + if (profile_id_attr) + free(profile_id_attr); + + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + return CKR_HOST_MEMORY; + } + + class_attr->type = CKA_CLASS; + class_attr->ulValueLen = sizeof(CK_OBJECT_CLASS); + class_attr->pValue = (CK_BYTE *)class_attr + sizeof(CK_ATTRIBUTE); + *(CK_OBJECT_CLASS *)class_attr->pValue = CKO_PROFILE; + + profile_id_attr->type = CKA_PROFILE_ID; + profile_id_attr->ulValueLen = sizeof(CK_PROFILE_ID); + profile_id_attr->pValue = (CK_BYTE *)profile_id_attr + sizeof(CK_ATTRIBUTE); + *(CK_PROFILE_ID *)profile_id_attr->pValue = CKP_INVALID_ID; + + template_update_attribute(tmpl, class_attr); + template_update_attribute(tmpl, profile_id_attr); + return CKR_OK; +} + +CK_RV profile_object_validate_attribute(TEMPLATE *tmpl, CK_ATTRIBUTE *attr, + CK_ULONG mode) +{ + if (!attr) { + TRACE_ERROR("Invalid function arguments.\n"); + return CKR_FUNCTION_FAILED; + } + + switch (attr->type) { + case CKA_PROFILE_ID: + return CKR_OK; + default: + return template_validate_base_attribute(tmpl, attr, mode); + } +} diff --git a/usr/lib/common/shared_memory.c b/usr/lib/common/shared_memory.c index d5a65fc..cddef04 100644 --- a/usr/lib/common/shared_memory.c +++ b/usr/lib/common/shared_memory.c @@ -326,7 +326,7 @@ int sm_close(void *addr, int destroy, int ignore_ref_count) { int rc; int ref; - char name[SM_NAME_LEN + 1] = { 0, }; + char name[SM_NAME_LEN + 2] = { 0, }; struct shm_context *ctx = get_shm_context(addr); if (ctx->ref <= 0) { @@ -341,7 +341,7 @@ int sm_close(void *addr, int destroy, int ignore_ref_count) TRACE_DEVEL("close: ref = %d\n", ref); if (ref == 0 && destroy) { - strncpy(name, ctx->name, SM_NAME_LEN + 1); + strncpy(name, ctx->name, SM_NAME_LEN + 2); name[SM_NAME_LEN] = '\0'; } diff --git a/usr/lib/common/sign_mgr.c b/usr/lib/common/sign_mgr.c index d537cea..705223f 100644 --- a/usr/lib/common/sign_mgr.c +++ b/usr/lib/common/sign_mgr.c @@ -405,6 +405,10 @@ CK_RV sign_mgr_init(STDLL_TokData_t *tokdata, case CKM_SHA512_HMAC: case CKM_SHA512_224_HMAC: case CKM_SHA512_256_HMAC: + case CKM_IBM_SHA3_224_HMAC: + case CKM_IBM_SHA3_256_HMAC: + case CKM_IBM_SHA3_384_HMAC: + case CKM_IBM_SHA3_512_HMAC: if (mech->ulParameterLen != 0) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; @@ -915,28 +919,24 @@ CK_RV sign_mgr_sign(STDLL_TokData_t *tokdata, in_data, in_data_len, out_data, out_data_len); case CKM_SHA_1_HMAC: case CKM_SHA_1_HMAC_GENERAL: - return sha1_hmac_sign(tokdata, sess, length_only, ctx, - in_data, in_data_len, out_data, out_data_len); case CKM_SHA224_HMAC: case CKM_SHA224_HMAC_GENERAL: - return sha224_hmac_sign(tokdata, sess, length_only, ctx, - in_data, in_data_len, out_data, out_data_len); case CKM_SHA256_HMAC: case CKM_SHA256_HMAC_GENERAL: - return sha256_hmac_sign(tokdata, sess, length_only, ctx, - in_data, in_data_len, out_data, out_data_len); case CKM_SHA384_HMAC: case CKM_SHA384_HMAC_GENERAL: - return sha384_hmac_sign(tokdata, sess, length_only, ctx, - in_data, in_data_len, out_data, out_data_len); case CKM_SHA512_HMAC: case CKM_SHA512_HMAC_GENERAL: case CKM_SHA512_224_HMAC: case CKM_SHA512_224_HMAC_GENERAL: case CKM_SHA512_256_HMAC: case CKM_SHA512_256_HMAC_GENERAL: - return sha512_hmac_sign(tokdata, sess, length_only, ctx, - in_data, in_data_len, out_data, out_data_len); + case CKM_IBM_SHA3_224_HMAC: + case CKM_IBM_SHA3_256_HMAC: + case CKM_IBM_SHA3_384_HMAC: + case CKM_IBM_SHA3_512_HMAC: + return sha_hmac_sign(tokdata, sess, length_only, ctx, + in_data, in_data_len, out_data, out_data_len); case CKM_SSL3_MD5_MAC: case CKM_SSL3_SHA1_MAC: return ssl3_mac_sign(tokdata, sess, length_only, ctx, @@ -1060,6 +1060,10 @@ CK_RV sign_mgr_sign_update(STDLL_TokData_t *tokdata, case CKM_SHA512_HMAC_GENERAL: case CKM_SHA512_224_HMAC_GENERAL: case CKM_SHA512_256_HMAC_GENERAL: + case CKM_IBM_SHA3_224_HMAC: + case CKM_IBM_SHA3_256_HMAC: + case CKM_IBM_SHA3_384_HMAC: + case CKM_IBM_SHA3_512_HMAC: return hmac_sign_update(tokdata, sess, in_data, in_data_len); default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); @@ -1161,6 +1165,10 @@ CK_RV sign_mgr_sign_final(STDLL_TokData_t *tokdata, case CKM_SHA512_HMAC_GENERAL: case CKM_SHA512_224_HMAC_GENERAL: case CKM_SHA512_256_HMAC_GENERAL: + case CKM_IBM_SHA3_224_HMAC: + case CKM_IBM_SHA3_256_HMAC: + case CKM_IBM_SHA3_384_HMAC: + case CKM_IBM_SHA3_512_HMAC: return hmac_sign_final(tokdata, sess, signature, sig_len); default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); diff --git a/usr/lib/common/sw_crypt.c b/usr/lib/common/sw_crypt.c index 2de14be..82c0b83 100644 --- a/usr/lib/common/sw_crypt.c +++ b/usr/lib/common/sw_crypt.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include "pkcs11types.h" #include "p11util.h" @@ -31,6 +32,7 @@ CK_RV sw_des3_cbc(CK_BYTE *in_data, 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; @@ -74,6 +76,40 @@ CK_RV sw_des3_cbc(CK_BYTE *in_data, } return CKR_OK; +#else + CK_RV rc; + int outlen; + const EVP_CIPHER *cipher = EVP_des_ede3_cbc(); + EVP_CIPHER_CTX *ctx = NULL; + + 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 = ERR_HOST_MEMORY; + goto done; + } + + if (EVP_CipherInit_ex(ctx, cipher, + NULL, key_value, 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 = ERR_GENERAL_ERROR; + goto done; + } + + *out_data_len = in_data_len; + rc = CKR_OK; +done: + EVP_CIPHER_CTX_free(ctx); + return rc; +#endif } CK_RV sw_aes_cbc(CK_BYTE *in_data, @@ -83,6 +119,7 @@ CK_RV sw_aes_cbc(CK_BYTE *in_data, 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 ? @@ -108,4 +145,47 @@ CK_RV sw_aes_cbc(CK_BYTE *in_data, } return CKR_OK; +#else + CK_RV rc; + int outlen; + const EVP_CIPHER *cipher = NULL; + EVP_CIPHER_CTX *ctx = NULL; + + UNUSED(out_data_len); + + 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(); + + 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 = ERR_HOST_MEMORY; + goto done; + } + + if (EVP_CipherInit_ex(ctx, cipher, + NULL, key_value, 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 = ERR_GENERAL_ERROR; + goto done; + } + + rc = CKR_OK; +done: + EVP_CIPHER_CTX_free(ctx); + return rc; +#endif } diff --git a/usr/lib/common/template.c b/usr/lib/common/template.c index 2e7dd5e..6c93f97 100644 --- a/usr/lib/common/template.c +++ b/usr/lib/common/template.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "pkcs11types.h" #include "defs.h" @@ -41,6 +42,23 @@ #include "p11util.h" #include "trace.h" +/* Random 32 byte string is unique with overwhelming probability. */ +#define UNIQUE_ID_LEN 32 + +static CK_RV get_unique_id_str(char unique_id_str[2 * UNIQUE_ID_LEN + 1]) +{ + unsigned char buf[UNIQUE_ID_LEN]; + size_t i; + + if (RAND_bytes(buf, sizeof(buf)) != 1) + return CKR_FUNCTION_FAILED; + + for (i = 0; i < sizeof(buf); i++) + sprintf(&unique_id_str[i * 2], "%02x", buf[i]); + + return CKR_OK; +} + /* template_add_attributes() * * blindly add the given attributes to the template. do no sanity checking @@ -55,7 +73,8 @@ CK_RV template_add_attributes(TEMPLATE *tmpl, CK_ATTRIBUTE *pTemplate, for (i = 0; i < ulCount; i++) { if (!is_attribute_defined(pTemplate[i].type)) { - TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_TYPE_INVALID)); + TRACE_ERROR("%s: %lx\n", ock_err(ERR_ATTRIBUTE_TYPE_INVALID), + pTemplate[i].type); return CKR_ATTRIBUTE_TYPE_INVALID; } attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + @@ -127,7 +146,8 @@ CK_RV template_add_default_attributes(TEMPLATE *tmpl, TEMPLATE *basetmpl, case CKK_IBM_PQC_DILITHIUM: return ibm_dilithium_publ_set_default_attributes(tmpl, mode); default: - TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); + TRACE_ERROR("%s: %lx\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID), + subclass); return CKR_ATTRIBUTE_VALUE_INVALID; // unknown key type } case CKO_PRIVATE_KEY: @@ -145,7 +165,8 @@ CK_RV template_add_default_attributes(TEMPLATE *tmpl, TEMPLATE *basetmpl, case CKK_IBM_PQC_DILITHIUM: return ibm_dilithium_priv_set_default_attributes(tmpl, mode); default: - TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); + TRACE_ERROR("%s: %lx\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID), + subclass); return CKR_ATTRIBUTE_VALUE_INVALID; // unknown key type } case CKO_SECRET_KEY: @@ -185,7 +206,8 @@ CK_RV template_add_default_attributes(TEMPLATE *tmpl, TEMPLATE *basetmpl, case CKK_AES: return aes_set_default_attributes(tmpl, mode); default: - TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); + TRACE_ERROR("%s: %lx\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID), + subclass); return CKR_ATTRIBUTE_VALUE_INVALID; // unknown key type } case CKO_HW_FEATURE: @@ -197,7 +219,8 @@ CK_RV template_add_default_attributes(TEMPLATE *tmpl, TEMPLATE *basetmpl, case CKH_MONOTONIC_COUNTER: return counter_set_default_attributes(tmpl, mode); default: - TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); + TRACE_ERROR("%s: %lx\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID), + subclass); return CKR_ATTRIBUTE_VALUE_INVALID; } case CKO_DOMAIN_PARAMETERS: @@ -209,11 +232,14 @@ CK_RV template_add_default_attributes(TEMPLATE *tmpl, TEMPLATE *basetmpl, case CKK_X9_42_DH: return dp_x9dh_set_default_attributes(tmpl, mode); default: - TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); + TRACE_ERROR("%s: %lx\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID), + subclass); return CKR_ATTRIBUTE_VALUE_INVALID; } + case CKO_PROFILE: + return profile_object_set_default_attributes(tmpl, mode); default: - TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); + TRACE_ERROR("%s: %lx\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID), class); return CKR_ATTRIBUTE_VALUE_INVALID; } } @@ -297,7 +323,8 @@ CK_RV template_check_required_attributes(TEMPLATE *tmpl, CK_ULONG class, case CKK_IBM_PQC_DILITHIUM: return ibm_dilithium_publ_check_required_attributes(tmpl, mode); default: - TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); + TRACE_ERROR("%s: %lx\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID), + subclass); return CKR_ATTRIBUTE_VALUE_INVALID; // unknown keytype } } else if (class == CKO_PRIVATE_KEY) { @@ -315,7 +342,8 @@ CK_RV template_check_required_attributes(TEMPLATE *tmpl, CK_ULONG class, case CKK_IBM_PQC_DILITHIUM: return ibm_dilithium_priv_check_required_attributes(tmpl, mode); default: - TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); + TRACE_ERROR("%s: %lx\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID), + subclass); return CKR_ATTRIBUTE_VALUE_INVALID; // unknown key type } } else if (class == CKO_SECRET_KEY) { @@ -355,7 +383,8 @@ CK_RV template_check_required_attributes(TEMPLATE *tmpl, CK_ULONG class, case CKK_AES: return aes_check_required_attributes(tmpl, mode); default: - TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); + TRACE_ERROR("%s: %lx\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID), + subclass); return CKR_ATTRIBUTE_VALUE_INVALID; // unknown key type } } else if (class == CKO_HW_FEATURE) { @@ -367,7 +396,8 @@ CK_RV template_check_required_attributes(TEMPLATE *tmpl, CK_ULONG class, case CKH_MONOTONIC_COUNTER: return counter_check_required_attributes(tmpl, mode); default: - TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); + TRACE_ERROR("%s: %lx\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID), + subclass); return CKR_ATTRIBUTE_VALUE_INVALID; } } else if (class == CKO_DOMAIN_PARAMETERS) { @@ -379,12 +409,16 @@ CK_RV template_check_required_attributes(TEMPLATE *tmpl, CK_ULONG class, case CKK_X9_42_DH: return dp_x9dh_check_required_attributes(tmpl, mode); default: - TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); + TRACE_ERROR("%s: %lx\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID), + subclass); return CKR_ATTRIBUTE_VALUE_INVALID; } + } else if (class == CKO_PROFILE) { + return profile_object_check_required_attributes(tmpl, mode); } - TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); + TRACE_ERROR("%s: %lx\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID), + class); return CKR_ATTRIBUTE_VALUE_INVALID; // default fallthru } @@ -450,6 +484,7 @@ CK_BBOOL template_compare(CK_ATTRIBUTE *t1, CK_ULONG ulCount, TEMPLATE *t2) */ CK_RV template_copy(TEMPLATE *dest, TEMPLATE *src) { + char unique_id_str[2 * UNIQUE_ID_LEN + 1]; DL_NODE *node; if (!dest || !src) { @@ -470,10 +505,25 @@ CK_RV template_copy(TEMPLATE *dest, TEMPLATE *src) TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } - memcpy(new_attr, attr, len); + memcpy(new_attr, attr, len); new_attr->pValue = (CK_BYTE *) new_attr + sizeof(CK_ATTRIBUTE); + if (attr->type == CKA_UNIQUE_ID) { + if (attr->ulValueLen < 2 * UNIQUE_ID_LEN) { + free(new_attr); + TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); + return CKR_ATTRIBUTE_VALUE_INVALID; + } + if (get_unique_id_str(unique_id_str) != CKR_OK) { + free(new_attr); + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + return CKR_FUNCTION_FAILED; + } + memcpy(new_attr->pValue, unique_id_str, 2 * UNIQUE_ID_LEN); + new_attr->ulValueLen = 2 * UNIQUE_ID_LEN; + } + dest->attribute_list = dlist_add_as_first(dest->attribute_list, new_attr); node = node->next; @@ -574,10 +624,9 @@ CK_RV template_unflatten_withSize(TEMPLATE **new_tmpl, CK_BYTE *buf, CK_ULONG_32 attr_ulong_32; CK_ULONG attr_ulong; CK_ATTRIBUTE *a1_64 = NULL; - CK_ATTRIBUTE_32 *a1 = NULL; + CK_ATTRIBUTE_32 a1; - - if (!new_tmpl || !buf) { + if (!new_tmpl) { TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } @@ -619,17 +668,16 @@ CK_RV template_unflatten_withSize(TEMPLATE **new_tmpl, CK_BYTE *buf, } memcpy(a2, a1_64, len); } else { - a1 = (CK_ATTRIBUTE_32 *) ptr; - - if ((a1->type == CKA_CLASS || a1->type == CKA_KEY_TYPE - || a1->type == CKA_MODULUS_BITS - || a1->type == CKA_VALUE_BITS - || a1->type == CKA_CERTIFICATE_TYPE - || a1->type == CKA_VALUE_LEN) - && a1->ulValueLen != 0) { + memcpy(&a1, ptr, sizeof(a1)); + if ((a1.type == CKA_CLASS || a1.type == CKA_KEY_TYPE + || a1.type == CKA_MODULUS_BITS + || a1.type == CKA_VALUE_BITS + || a1.type == CKA_CERTIFICATE_TYPE + || a1.type == CKA_VALUE_LEN) + && a1.ulValueLen != 0) { len = sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG); } else { - len = sizeof(CK_ATTRIBUTE) + a1->ulValueLen; + len = sizeof(CK_ATTRIBUTE) + a1.ulValueLen; } a2 = (CK_ATTRIBUTE *) malloc(len); @@ -638,25 +686,25 @@ CK_RV template_unflatten_withSize(TEMPLATE **new_tmpl, CK_BYTE *buf, TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } - a2->type = a1->type; + a2->type = a1.type; - if ((a1->type == CKA_CLASS || a1->type == CKA_KEY_TYPE - || a1->type == CKA_MODULUS_BITS - || a1->type == CKA_VALUE_BITS - || a1->type == CKA_CERTIFICATE_TYPE - || a1->type == CKA_VALUE_LEN) - && a1->ulValueLen != 0) { + if ((a1.type == CKA_CLASS || a1.type == CKA_KEY_TYPE + || a1.type == CKA_MODULUS_BITS + || a1.type == CKA_VALUE_BITS + || a1.type == CKA_CERTIFICATE_TYPE + || a1.type == CKA_VALUE_LEN) + && a1.ulValueLen != 0) { a2->ulValueLen = sizeof(CK_ULONG); { - CK_ULONG_32 *p32; + CK_ULONG_32 u32; CK_BYTE *pb2; - pb2 = (CK_BYTE *) a1; + pb2 = (CK_BYTE *) ptr; pb2 += sizeof(CK_ATTRIBUTE_32); - p32 = (CK_ULONG_32 *) pb2; - attr_ulong_32 = *p32; + memcpy(&u32, pb2, sizeof(u32)); + attr_ulong_32 = u32; } attr_ulong = attr_ulong_32; @@ -670,20 +718,20 @@ CK_RV template_unflatten_withSize(TEMPLATE **new_tmpl, CK_BYTE *buf, } else { CK_BYTE *pb2, *pb; - a2->ulValueLen = a1->ulValueLen; + a2->ulValueLen = a1.ulValueLen; pb2 = (CK_BYTE *) a2; pb2 += sizeof(CK_ATTRIBUTE); - pb = (CK_BYTE *) a1; + pb = (CK_BYTE *) ptr; pb += sizeof(CK_ATTRIBUTE_32); /* if a buffer size is given, make sure it * doesn't get overrun */ - if (buf_size >= 0 && (pb + a1->ulValueLen) > (buf + buf_size)) { + if (buf_size >= 0 && (pb + a1.ulValueLen) > (buf + buf_size)) { free(a2); template_free(tmpl); return CKR_FUNCTION_FAILED; } - memcpy(pb2, pb, a1->ulValueLen); + memcpy(pb2, pb, a1.ulValueLen); } } @@ -701,7 +749,7 @@ CK_RV template_unflatten_withSize(TEMPLATE **new_tmpl, CK_BYTE *buf, if (long_len == 4) ptr += len; else - ptr += sizeof(CK_ATTRIBUTE_32) + a1->ulValueLen; + ptr += sizeof(CK_ATTRIBUTE_32) + a1.ulValueLen; } *new_tmpl = tmpl; @@ -895,14 +943,16 @@ CK_BBOOL template_check_exportability(TEMPLATE *tmpl, CK_ATTRIBUTE_TYPE type) case CKK_KEA: return kea_priv_check_exportability(type); default: - TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); + TRACE_ERROR("%s: %lx\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID), + subclass); return TRUE; } } else if (class == CKO_SECRET_KEY) { return secret_key_check_exportability(type); } - TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); + TRACE_ERROR("%s: %lx\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID), + class); return TRUE; } @@ -954,10 +1004,15 @@ CK_RV template_merge(TEMPLATE *dest, TEMPLATE **src) */ CK_RV template_set_default_common_attributes(TEMPLATE *tmpl) { + char unique_id_str[2 * UNIQUE_ID_LEN + 1]; CK_ATTRIBUTE *token_attr; CK_ATTRIBUTE *priv_attr; CK_ATTRIBUTE *mod_attr; CK_ATTRIBUTE *label_attr; + CK_ATTRIBUTE *unique_id_attr; + + if (get_unique_id_str(unique_id_str) != CKR_OK) + return CKR_FUNCTION_FAILED; /* add the default common attributes */ token_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) @@ -967,8 +1022,9 @@ CK_RV template_set_default_common_attributes(TEMPLATE *tmpl) mod_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL)); label_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + 0); + unique_id_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + UNIQUE_ID_LEN * 2); - if (!token_attr || !priv_attr || !mod_attr || !label_attr) { + if (!token_attr || !priv_attr || !mod_attr || !label_attr || !unique_id_attr) { if (token_attr) free(token_attr); if (priv_attr) @@ -977,6 +1033,8 @@ CK_RV template_set_default_common_attributes(TEMPLATE *tmpl) free(mod_attr); if (label_attr) free(label_attr); + if (unique_id_attr) + free(unique_id_attr); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; @@ -1001,10 +1059,16 @@ CK_RV template_set_default_common_attributes(TEMPLATE *tmpl) label_attr->ulValueLen = 0; // empty string label_attr->pValue = NULL; + unique_id_attr->type = CKA_UNIQUE_ID; + unique_id_attr->ulValueLen = UNIQUE_ID_LEN * 2; + unique_id_attr->pValue = (CK_BYTE *) unique_id_attr + sizeof(CK_ATTRIBUTE); + memcpy(unique_id_attr->pValue, unique_id_str, UNIQUE_ID_LEN * 2); + template_update_attribute(tmpl, token_attr); template_update_attribute(tmpl, priv_attr); template_update_attribute(tmpl, mod_attr); template_update_attribute(tmpl, label_attr); + template_update_attribute(tmpl, unique_id_attr); /* the TEMPLATE 'owns' the attributes now. * it is responsible for freeing them upon deletion... @@ -1170,6 +1234,8 @@ CK_RV template_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl, TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } + } else if (class == CKO_PROFILE) { + return profile_object_validate_attribute(tmpl, attr, mode); } TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); @@ -1250,8 +1316,15 @@ CK_RV template_validate_base_attribute(TEMPLATE *tmpl, CK_ATTRIBUTE *attr, MODE_UNWRAP)) != 0) return CKR_OK; break; + case CKA_UNIQUE_ID: + if ((mode & (MODE_CREATE | MODE_COPY | MODE_DERIVE | MODE_KEYGEN | + MODE_UNWRAP)) != 0) + TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); + return CKR_ATTRIBUTE_READ_ONLY; + break; default: - TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT)); + TRACE_ERROR("%s: %lx\n", ock_err(ERR_TEMPLATE_INCONSISTENT), + attr->type); return CKR_TEMPLATE_INCONSISTENT; } diff --git a/usr/lib/common/tok_spec_struct.h b/usr/lib/common/tok_spec_struct.h index 8765c87..1f19c09 100644 --- a/usr/lib/common/tok_spec_struct.h +++ b/usr/lib/common/tok_spec_struct.h @@ -30,8 +30,8 @@ struct token_specific_struct { // Subdirectory char token_subdir[PATH_MAX]; - // Set to keysize for secure key tokens - int token_keysize; + // Specifies if the token is using secure keys + CK_BBOOL secure_key_token; // Information about how token's data should be stored. struct { @@ -82,7 +82,8 @@ struct token_specific_struct { CK_RV(*t_set_pin) (STDLL_TokData_t *, SESSION *, CK_CHAR_PTR, CK_ULONG, CK_CHAR_PTR, CK_ULONG); - CK_RV(*t_des_key_gen) (STDLL_TokData_t *, CK_BYTE *, CK_ULONG, CK_ULONG); + CK_RV(*t_des_key_gen) (STDLL_TokData_t *, CK_BYTE **, CK_ULONG *, CK_ULONG, + CK_BBOOL *); CK_RV(*t_des_ecb) (STDLL_TokData_t *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *, CK_BYTE); CK_RV(*t_des_cbc) (STDLL_TokData_t *, CK_BYTE *, CK_ULONG, @@ -208,7 +209,8 @@ struct token_specific_struct { CK_RV(*t_generic_secret_key_gen) (STDLL_TokData_t *, TEMPLATE *); // Token Specific AES functions - CK_RV(*t_aes_key_gen) (STDLL_TokData_t *, CK_BYTE *, CK_ULONG, CK_ULONG); + CK_RV(*t_aes_key_gen) (STDLL_TokData_t *, CK_BYTE **, CK_ULONG *, CK_ULONG, + CK_BBOOL *); CK_RV(*t_aes_ecb) (STDLL_TokData_t *tokdata, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *, CK_BYTE); @@ -261,6 +263,16 @@ struct token_specific_struct { CK_RV(*t_object_add) (STDLL_TokData_t *, SESSION *, OBJECT *); + CK_RV(*t_key_wrap) (STDLL_TokData_t *, SESSION *, CK_MECHANISM *, CK_BBOOL, + OBJECT *, OBJECT *, CK_BYTE *, CK_ULONG *, CK_BBOOL *); + + CK_RV(*t_key_unwrap) (STDLL_TokData_t *, SESSION *, CK_MECHANISM *, + CK_BYTE *, CK_ULONG, OBJECT *, OBJECT *, CK_BBOOL *); + + CK_RV(*t_reencrypt_single) (STDLL_TokData_t *, SESSION *, + ENCR_DECR_CONTEXT *, CK_MECHANISM *, OBJECT *, + ENCR_DECR_CONTEXT *, CK_MECHANISM *, OBJECT *, + CK_BYTE *, CK_ULONG , CK_BYTE *, CK_ULONG *); }; typedef struct token_specific_struct token_spec_t; diff --git a/usr/lib/common/tok_specific.h b/usr/lib/common/tok_specific.h index 19f6b47..44721fa 100644 --- a/usr/lib/common/tok_specific.h +++ b/usr/lib/common/tok_specific.h @@ -49,8 +49,8 @@ CK_RV token_specific_init_pin(STDLL_TokData_t *, SESSION *, CK_CHAR_PTR, CK_RV token_specific_set_pin(STDLL_TokData_t *, SESSION *, CK_CHAR_PTR, CK_ULONG, CK_CHAR_PTR, CK_ULONG); -CK_RV token_specific_des_key_gen(STDLL_TokData_t *, CK_BYTE *, CK_ULONG, - CK_ULONG); +CK_RV token_specific_des_key_gen(STDLL_TokData_t *, CK_BYTE **, CK_ULONG *, + CK_ULONG, CK_BBOOL *); CK_RV token_specific_des_ecb(STDLL_TokData_t *, CK_BYTE *, @@ -234,7 +234,7 @@ CK_RV token_specific_generic_secret_key_gen(STDLL_TokData_t *, #ifndef NOAES CK_RV token_specific_aes_key_gen(STDLL_TokData_t *, - CK_BYTE *, CK_ULONG, CK_ULONG); + CK_BYTE **, CK_ULONG *, CK_ULONG, CK_BBOOL *); CK_RV token_specific_aes_ecb(STDLL_TokData_t *, CK_BYTE *, @@ -305,4 +305,18 @@ CK_RV token_specific_get_mechanism_info(STDLL_TokData_t *, CK_RV token_specific_object_add(STDLL_TokData_t *, SESSION *, OBJECT *); +CK_RV token_specific_key_wrap(STDLL_TokData_t *, SESSION *, CK_MECHANISM *, + CK_BBOOL, OBJECT *, OBJECT *, CK_BYTE *, + CK_ULONG *, CK_BBOOL *); + +CK_RV token_specific_key_unwrap(STDLL_TokData_t *, SESSION *, CK_MECHANISM *, + CK_BYTE *, CK_ULONG, OBJECT *, OBJECT *, + CK_BBOOL *); + +CK_RV token_specific_reencrypt_single(STDLL_TokData_t *, SESSION *, + ENCR_DECR_CONTEXT *, CK_MECHANISM *, + OBJECT *, ENCR_DECR_CONTEXT *, + CK_MECHANISM *, OBJECT *, CK_BYTE *, + CK_ULONG , CK_BYTE *, CK_ULONG *); + #endif diff --git a/usr/lib/common/trace.c b/usr/lib/common/trace.c index f470548..83433d6 100644 --- a/usr/lib/common/trace.c +++ b/usr/lib/common/trace.c @@ -203,6 +203,11 @@ CK_RV trace_initialize(void) goto error; } +#ifdef PACKAGE_VERSION + TRACE_INFO("**** OCK Trace level %d activated for OCK version %s ****\n", + trace.level, PACKAGE_VERSION); +#endif + return (CKR_OK); error: diff --git a/usr/lib/common/utility.c b/usr/lib/common/utility.c index cbc0023..8b886df 100644 --- a/usr/lib/common/utility.c +++ b/usr/lib/common/utility.c @@ -33,6 +33,7 @@ #include "shared_memory.h" #include "trace.h" #include "ock_syslog.h" +#include "slotmgr.h" // for ock_snprintf #include #include @@ -236,12 +237,13 @@ DL_NODE *dlist_remove_node(DL_NODE *list, DL_NODE *node) CK_RV CreateXProcLock(char *tokname, STDLL_TokData_t *tokdata) { - char lockfile[2 * PATH_MAX + sizeof(LOCKDIR_PATH) + 6]; - char lockdir[PATH_MAX + sizeof(LOCKDIR_PATH)]; + char lockfile[PATH_MAX]; + char lockdir[PATH_MAX]; struct group *grp; struct stat statbuf; mode_t mode = (S_IRUSR | S_IRGRP); int ret = -1; + char *toklockname; if (tokdata->spinxplfd == -1) { @@ -253,12 +255,17 @@ CK_RV CreateXProcLock(char *tokname, STDLL_TokData_t *tokdata) return CKR_FUNCTION_FAILED; } + toklockname = (strlen(tokname) > 0) ? tokname : SUB_DIR; + + /** create lock subdir for each token if it doesn't exist. * The root directory should be created in slotmgr daemon **/ - if (strlen(tokname) > 0) - sprintf(lockdir, "%s/%s", LOCKDIR_PATH, tokname); - else - sprintf(lockdir, "%s/%s", LOCKDIR_PATH, SUB_DIR); + if (ock_snprintf(lockdir, PATH_MAX, "%s/%s", + LOCKDIR_PATH, toklockname) != 0) { + OCK_SYSLOG(LOG_ERR, "lock directory path too long\n"); + TRACE_ERROR("lock directory path too long\n"); + goto err; + } ret = stat(lockdir, &statbuf); if (ret != 0 && errno == ENOENT) { @@ -291,10 +298,12 @@ CK_RV CreateXProcLock(char *tokname, STDLL_TokData_t *tokdata) } /* create user lock file */ - if (strlen(tokname) > 0) - sprintf(lockfile, "%s/%s/LCK..%s", LOCKDIR_PATH, tokname, tokname); - else - sprintf(lockfile, "%s/%s/LCK..%s", LOCKDIR_PATH, SUB_DIR, SUB_DIR); + if (ock_snprintf(lockfile, sizeof(lockfile), "%s/%s/LCK..%s", + LOCKDIR_PATH, toklockname, toklockname) != 0) { + OCK_SYSLOG(LOG_ERR, "lock file path too long\n"); + TRACE_ERROR("lock file path too long\n"); + goto err; + } if (stat(lockfile, &statbuf) == 0) { tokdata->spinxplfd = open(lockfile, O_RDONLY, mode); @@ -831,7 +840,12 @@ CK_RV attach_shm(STDLL_TokData_t *tokdata, CK_SLOT_ID slot_id) * exists. When it's created (ret=0) the region is initialized with * zeros. */ - ret = sm_open(get_pk_dir(tokdata, buf), 0666, (void **) shm, sizeof(**shm), 0); + if (get_pk_dir(tokdata, buf, PATH_MAX) == NULL) { + TRACE_ERROR("pk_dir buffer overflow"); + rc = CKR_FUNCTION_FAILED; + goto err; + } + ret = sm_open(buf, 0666, (void **) shm, sizeof(**shm), 0); if (ret < 0) { TRACE_DEVEL("sm_open failed.\n"); rc = CKR_FUNCTION_FAILED; @@ -942,6 +956,81 @@ CK_RV get_sha_block_size(CK_ULONG mech, CK_ULONG *bsize) 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) @@ -1128,10 +1217,3 @@ void copy_token_contents_sensibly(CK_TOKEN_INFO_PTR pInfo, pInfo->ulRwSessionCount = CK_UNAVAILABLE_INFORMATION; } -CK_BBOOL is_secure_key_token() -{ - /* - * If token has a specific key size that means that it uses secure keys. - */ - return token_specific.token_keysize > 0 ? TRUE : FALSE; -} diff --git a/usr/lib/common/verify_mgr.c b/usr/lib/common/verify_mgr.c index 646d673..b1512ee 100644 --- a/usr/lib/common/verify_mgr.c +++ b/usr/lib/common/verify_mgr.c @@ -393,6 +393,10 @@ CK_RV verify_mgr_init(STDLL_TokData_t *tokdata, case CKM_SHA512_HMAC: case CKM_SHA512_224_HMAC: case CKM_SHA512_256_HMAC: + case CKM_IBM_SHA3_224_HMAC: + case CKM_IBM_SHA3_256_HMAC: + case CKM_IBM_SHA3_384_HMAC: + case CKM_IBM_SHA3_512_HMAC: if (mech->ulParameterLen != 0) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; @@ -910,28 +914,24 @@ CK_RV verify_mgr_verify(STDLL_TokData_t *tokdata, in_data, in_data_len, signature, sig_len); case CKM_SHA_1_HMAC: case CKM_SHA_1_HMAC_GENERAL: - return sha1_hmac_verify(tokdata, sess, ctx, - in_data, in_data_len, signature, sig_len); case CKM_SHA224_HMAC: case CKM_SHA224_HMAC_GENERAL: - return sha224_hmac_verify(tokdata, sess, ctx, - in_data, in_data_len, signature, sig_len); case CKM_SHA256_HMAC: case CKM_SHA256_HMAC_GENERAL: - return sha256_hmac_verify(tokdata, sess, ctx, - in_data, in_data_len, signature, sig_len); case CKM_SHA384_HMAC: case CKM_SHA384_HMAC_GENERAL: - return sha384_hmac_verify(tokdata, sess, ctx, - in_data, in_data_len, signature, sig_len); case CKM_SHA512_HMAC: case CKM_SHA512_HMAC_GENERAL: case CKM_SHA512_224_HMAC: case CKM_SHA512_224_HMAC_GENERAL: case CKM_SHA512_256_HMAC: case CKM_SHA512_256_HMAC_GENERAL: - return sha512_hmac_verify(tokdata, sess, ctx, - in_data, in_data_len, signature, sig_len); + case CKM_IBM_SHA3_224_HMAC: + case CKM_IBM_SHA3_256_HMAC: + case CKM_IBM_SHA3_384_HMAC: + case CKM_IBM_SHA3_512_HMAC: + return sha_hmac_verify(tokdata, sess, ctx, + in_data, in_data_len, signature, sig_len); case CKM_SSL3_MD5_MAC: case CKM_SSL3_SHA1_MAC: return ssl3_mac_verify(tokdata, sess, ctx, @@ -1053,6 +1053,10 @@ CK_RV verify_mgr_verify_update(STDLL_TokData_t *tokdata, case CKM_SHA512_HMAC_GENERAL: case CKM_SHA512_224_HMAC_GENERAL: case CKM_SHA512_256_HMAC_GENERAL: + case CKM_IBM_SHA3_224_HMAC: + case CKM_IBM_SHA3_256_HMAC: + case CKM_IBM_SHA3_384_HMAC: + case CKM_IBM_SHA3_512_HMAC: return hmac_verify_update(tokdata, sess, in_data, in_data_len); default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); @@ -1144,6 +1148,10 @@ CK_RV verify_mgr_verify_final(STDLL_TokData_t *tokdata, case CKM_SHA512_HMAC_GENERAL: case CKM_SHA512_224_HMAC_GENERAL: case CKM_SHA512_256_HMAC_GENERAL: + case CKM_IBM_SHA3_224_HMAC: + case CKM_IBM_SHA3_256_HMAC: + case CKM_IBM_SHA3_384_HMAC: + case CKM_IBM_SHA3_512_HMAC: return hmac_verify_final(tokdata, sess, signature, sig_len); default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); diff --git a/usr/lib/ep11_stdll/ep11_specific.c b/usr/lib/ep11_stdll/ep11_specific.c index b641aad..12c9884 100644 --- a/usr/lib/ep11_stdll/ep11_specific.c +++ b/usr/lib/ep11_stdll/ep11_specific.c @@ -13,6 +13,8 @@ ========== ****************************************************************************/ +/* Declaration of secure_getenv requires _GNU_SOURCE */ +#define _GNU_SOURCE #include #include #include @@ -336,6 +338,20 @@ static const version_req_t ibm_dilithium_req_versions[] = { }; #define NUM_DILITHIUM_REQ (sizeof(ibm_dilithium_req_versions) / sizeof(version_req_t)) +static const CK_VERSION ibm_cex6p_reencrypt_single_support = + { .major = 6, .minor = 15 }; +static const CK_VERSION ibm_cex7p_reencrypt_single_support = + { .major = 7, .minor = 21 }; + +static const version_req_t reencrypt_single_req_versions[] = { + { .card_type = 6, .min_firmware_version = + &ibm_cex6p_reencrypt_single_support }, + { .card_type = 7, .min_firmware_version = + &ibm_cex7p_reencrypt_single_support } +}; +#define NUM_REENCRYPT_SINGLE_REQ (sizeof(reencrypt_single_req_versions) / \ + sizeof(version_req_t)) + /* Definitions for loading libica dynamically */ typedef unsigned int (*ica_sha1_t)(unsigned int message_part, @@ -514,7 +530,9 @@ typedef struct const_info { #define CKM_IBM_SHA512_224_HMAC CKM_VENDOR_DEFINED + 0x00010015 #define CKM_IBM_SHA512_256_KEY_DERIVATION CKM_VENDOR_DEFINED + 0x00010016 #define CKM_IBM_SHA512_224_KEY_DERIVATION CKM_VENDOR_DEFINED + 0x00010017 +#define CKM_IBM_EC_X25519 CKM_VENDOR_DEFINED + 0x0001001B #define CKM_IBM_EDDSA_PH_SHA512 CKM_VENDOR_DEFINED + 0x0001001D +#define CKM_IBM_EC_X448 CKM_VENDOR_DEFINED + 0x0001001E #define CKM_IBM_SIPHASH CKM_VENDOR_DEFINED + 0x00010021 #define CKM_IBM_DILITHIUM CKM_VENDOR_DEFINED + 0x00010023 #define CKM_IBM_CLEARKEY_TRANSPORT CKM_VENDOR_DEFINED + 0x00020001 @@ -544,7 +562,7 @@ static CK_RV check_key_attributes(STDLL_TokData_t * tokdata, CK_KEY_TYPE kt, CK_OBJECT_CLASS kc, CK_ATTRIBUTE_PTR attrs, CK_ULONG attrs_len, CK_ATTRIBUTE_PTR * p_attrs, - CK_ULONG * p_attrs_len) + CK_ULONG * p_attrs_len, int curve_type) { CK_RV rc; @@ -596,6 +614,8 @@ static CK_RV check_key_attributes(STDLL_TokData_t * tokdata, if ((kt == CKK_EC) || (kt == CKK_ECDSA) || (kt == CKK_DSA)) { check_types = &check_types_pub[0]; attr_cnt = 1; /* only CKA_VERIFY */ + if (kt == CKK_EC && curve_type == MONTGOMERY_CURVE) + attr_cnt = 0; } else if (kt == CKK_RSA) { check_types = &check_types_pub[0]; attr_cnt = sizeof(check_types_pub) / sizeof(CK_ULONG); @@ -607,6 +627,8 @@ static CK_RV check_key_attributes(STDLL_TokData_t * tokdata, if ((kt == CKK_EC) || (kt == CKK_ECDSA) || (kt == CKK_DSA)) { check_types = &check_types_priv[0]; attr_cnt = 1; /* only CKA_SIGN */ + if (kt == CKK_EC && curve_type == MONTGOMERY_CURVE) + attr_cnt = 0; } else if (kt == CKK_RSA) { check_types = &check_types_priv[0]; attr_cnt = sizeof(check_types_priv) / sizeof(CK_ULONG); @@ -738,6 +760,9 @@ static CK_RV ep11_get_keytype(CK_ATTRIBUTE * attrs, CK_ULONG attrs_len, case CKM_DES_KEY_GEN: *type = CKK_DES; break; + case CKM_DES2_KEY_GEN: + *type = CKK_DES2; + break; case CKM_DES3_KEY_GEN: *type = CKK_DES3; break; @@ -1007,6 +1032,7 @@ static const_info_t ep11_mechanisms[] = { CONSTINFO(CKM_IBM_SHA512_256_KEY_DERIVATION), CONSTINFO(CKM_IBM_SHA512_224_KEY_DERIVATION), CONSTINFO(CKM_IBM_EC_C25519), + CONSTINFO(CKM_IBM_ED25519_SHA512), CONSTINFO(CKM_IBM_EDDSA_SHA512), CONSTINFO(CKM_IBM_EDDSA_PH_SHA512), CONSTINFO(CKM_IBM_EC_C448), @@ -1223,7 +1249,7 @@ static CK_RV rawkey_2_blob(STDLL_TokData_t * tokdata, SESSION * sess, __func__, ksize, clen, rc); rc = check_key_attributes(tokdata, ktype, CKO_SECRET_KEY, p_attrs, - attrs_len, &new_p_attrs, &new_attrs_len); + attrs_len, &new_p_attrs, &new_attrs_len, -1); if (rc != CKR_OK) { TRACE_ERROR("%s RSA/EC check private key attributes failed with " "rc=0x%lx\n", __func__, rc); @@ -1266,10 +1292,11 @@ CK_RV token_specific_rng(STDLL_TokData_t * tokdata, CK_BYTE * output, ep11_private_data_t *ep11_data = tokdata->private_data; CK_RV rc = dll_m_GenerateRandom(output, bytes, ep11_data->target); - if (rc != CKR_OK) + 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); + } return rc; } @@ -1323,7 +1350,7 @@ static void *ep11_load_host_lib() char *ep11_lib_name; char *errstr; - ep11_lib_name = getenv(EP11SHAREDLIB_NAME); + ep11_lib_name = secure_getenv(EP11SHAREDLIB_NAME); if (ep11_lib_name != NULL) { lib_ep11 = dlopen(ep11_lib_name, DLOPEN_FLAGS); @@ -1914,7 +1941,7 @@ static CK_RV import_RSA_key(STDLL_TokData_t * tokdata, SESSION * sess, } rc = check_key_attributes(tokdata, CKK_RSA, CKO_PRIVATE_KEY, p_attrs, - attrs_len, &new_p_attrs, &new_attrs_len); + attrs_len, &new_p_attrs, &new_attrs_len, -1); if (rc != CKR_OK) { TRACE_ERROR("%s RSA/EC check private key attributes failed with " "rc=0x%lx\n", __func__, rc); @@ -2126,6 +2153,24 @@ static CK_RV import_EC_key(STDLL_TokData_t * tokdata, SESSION * sess, /* imported private EC key goes here */ + CK_ATTRIBUTE *ec_params; + int i, curve_type = -1; + + if (!template_attribute_find(ec_key_obj->template, + CKA_EC_PARAMS, &ec_params)) { + rc = CKR_TEMPLATE_INCOMPLETE; + goto import_EC_key_end; + } + + 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) { + curve_type = der_ec_supported[i].curve_type; + break; + } + } + /* extract the secret data to be wrapped * since this is AES_CBC_PAD, padding is done in mechanism. */ @@ -2155,7 +2200,8 @@ static CK_RV import_EC_key(STDLL_TokData_t * tokdata, SESSION * sess, } rc = check_key_attributes(tokdata, CKK_EC, CKO_PRIVATE_KEY, p_attrs, - attrs_len, &new_p_attrs, &new_attrs_len); + attrs_len, &new_p_attrs, &new_attrs_len, + curve_type); if (rc != CKR_OK) { TRACE_ERROR("%s EC check private key attributes failed with " "rc=0x%lx\n", __func__, rc); @@ -2361,7 +2407,7 @@ static CK_RV import_DSA_key(STDLL_TokData_t * tokdata, SESSION * sess, } rc = check_key_attributes(tokdata, CKK_DSA, CKO_PRIVATE_KEY, p_attrs, - attrs_len, &new_p_attrs, &new_attrs_len); + attrs_len, &new_p_attrs, &new_attrs_len, -1); if (rc != CKR_OK) { TRACE_ERROR("%s DSA check private key attributes failed with " "rc=0x%lx\n", __func__, rc); @@ -2555,7 +2601,7 @@ static CK_RV import_DH_key(STDLL_TokData_t * tokdata, SESSION * sess, } rc = check_key_attributes(tokdata, CKK_DH, CKO_PRIVATE_KEY, p_attrs, - attrs_len, &new_p_attrs, &new_attrs_len); + attrs_len, &new_p_attrs, &new_attrs_len, -1); if (rc != CKR_OK) { TRACE_ERROR("%s DH check private key attributes failed with " "rc=0x%lx\n", __func__, rc); @@ -2758,7 +2804,7 @@ static CK_RV import_IBM_Dilithium_key(STDLL_TokData_t * tokdata, SESSION * sess, rc = check_key_attributes(tokdata, CKK_IBM_PQC_DILITHIUM, CKO_PRIVATE_KEY, p_attrs, attrs_len, - &new_p_attrs, &new_attrs_len); + &new_p_attrs, &new_attrs_len, -1); if (rc != CKR_OK) { TRACE_ERROR("%s EC check private key attributes failed with " "rc=0x%lx\n", __func__, rc); @@ -2961,7 +3007,7 @@ CK_RV ep11tok_generate_key(STDLL_TokData_t * tokdata, SESSION * session, } rc = check_key_attributes(tokdata, ktype, CKO_SECRET_KEY, attrs, attrs_len, - &new_attrs, &new_attrs_len); + &new_attrs, &new_attrs_len, -1); if (rc != CKR_OK) { TRACE_ERROR("%s check secret key attributes failed: rc=0x%lx\n", __func__, rc); @@ -3699,6 +3745,61 @@ CK_RV token_specific_ec_verify(STDLL_TokData_t *tokdata, SESSION *session, return rc; } +CK_RV token_specific_reencrypt_single(STDLL_TokData_t *tokdata, + SESSION *session, + ENCR_DECR_CONTEXT *decr_ctx, + CK_MECHANISM *decr_mech, + OBJECT *decr_key_obj, + ENCR_DECR_CONTEXT *encr_ctx, + CK_MECHANISM *encr_mech, + OBJECT *encr_key_obj, + 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; + int status; + + UNUSED(decr_ctx); + UNUSED(encr_ctx); + + if (dll_m_ReencryptSingle == NULL) + return CKR_FUNCTION_NOT_SUPPORTED; + + status = check_required_versions(tokdata, reencrypt_single_req_versions, + NUM_REENCRYPT_SINGLE_REQ); + if (status != 1) + return CKR_FUNCTION_NOT_SUPPORTED; + + rc = obj_opaque_2_blob(tokdata, decr_key_obj, &decr_key, &decr_key_len); + if (rc != CKR_OK) { + TRACE_ERROR("%s no decr-blob rc=0x%lx\n", __func__, rc); + return rc; + } + + rc = obj_opaque_2_blob(tokdata, encr_key_obj, &encr_key, &encr_key_len); + if (rc != CKR_OK) { + TRACE_ERROR("%s no encrr-blob rc=0x%lx\n", __func__, rc); + return rc; + } + + RETRY_START + 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); + RETRY_END(rc, tokdata, session) + if (rc != CKR_OK) { + rc = ep11_error_to_pkcs11_error(rc, session); + TRACE_ERROR("%s rc=0x%lx\n", __func__, rc); + } else { + TRACE_INFO("%s rc=0x%lx\n", __func__, rc); + } + + return rc; +} + CK_RV ep11tok_derive_key(STDLL_TokData_t * tokdata, SESSION * session, CK_MECHANISM_PTR mech, CK_OBJECT_HANDLE hBaseKey, CK_OBJECT_HANDLE_PTR handle, CK_ATTRIBUTE_PTR attrs, @@ -3822,7 +3923,7 @@ CK_RV ep11tok_derive_key(STDLL_TokData_t * tokdata, SESSION * session, } rc = check_key_attributes(tokdata, ktype, class, attrs, attrs_len, - &new_attrs, &new_attrs_len); + &new_attrs, &new_attrs_len, -1); if (rc != CKR_OK) { TRACE_ERROR("%s Check key attributes for derived key failed with " "rc=0x%lx\n", __func__, rc); @@ -4047,7 +4148,7 @@ static CK_RV dh_generate_keypair(STDLL_TokData_t * tokdata, rc = check_key_attributes(tokdata, CKK_DH, CKO_PUBLIC_KEY, pPublicKeyTemplate_new, new_public_attr + 1, &dh_pPublicKeyTemplate, - &dh_ulPublicKeyAttributeCount); + &dh_ulPublicKeyAttributeCount, -1); if (rc != CKR_OK) { TRACE_ERROR("%s DH check public key attributes failed with " "rc=0x%lx\n", __func__, rc); @@ -4057,7 +4158,7 @@ static CK_RV dh_generate_keypair(STDLL_TokData_t * tokdata, rc = check_key_attributes(tokdata, CKK_DH, CKO_PRIVATE_KEY, pPrivateKeyTemplate, ulPrivateKeyAttributeCount, &dh_pPrivateKeyTemplate, - &dh_ulPrivateKeyAttributeCount); + &dh_ulPrivateKeyAttributeCount, -1); if (rc != CKR_OK) { TRACE_ERROR("%s DH check private key attributes failed with " "rc=0x%lx\n", __func__, rc); @@ -4366,7 +4467,7 @@ static CK_RV dsa_generate_keypair(STDLL_TokData_t * tokdata, rc = check_key_attributes(tokdata, CKK_DSA, CKO_PUBLIC_KEY, pPublicKeyTemplate_new, new_public_attr + 1, &dsa_pPublicKeyTemplate, - &dsa_ulPublicKeyAttributeCount); + &dsa_ulPublicKeyAttributeCount, -1); if (rc != CKR_OK) { TRACE_ERROR("%s RSA/EC check public key attributes failed with " "rc=0x%lx\n", __func__, rc); @@ -4376,7 +4477,7 @@ static CK_RV dsa_generate_keypair(STDLL_TokData_t * tokdata, rc = check_key_attributes(tokdata, CKK_DSA, CKO_PRIVATE_KEY, pPrivateKeyTemplate, ulPrivateKeyAttributeCount, &dsa_pPrivateKeyTemplate, - &dsa_ulPrivateKeyAttributeCount); + &dsa_ulPrivateKeyAttributeCount, -1); if (rc != CKR_OK) { TRACE_ERROR("%s RSA/EC check private key attributes failed with " "rc=0x%lx\n", __func__, rc); @@ -4533,6 +4634,7 @@ static CK_RV rsa_ec_generate_keypair(STDLL_TokData_t * tokdata, unsigned char *ep11_pin_blob = NULL; CK_ULONG ep11_pin_blob_len = 0; ep11_session_t *ep11_session = (ep11_session_t *) sess->private_data; + int curve_type = -1; UNUSED(h); @@ -4547,10 +4649,27 @@ static CK_RV rsa_ec_generate_keypair(STDLL_TokData_t * tokdata, return CKR_MECHANISM_INVALID; } + if (ktype == CKK_EC) { + attr = get_attribute_by_type(pPublicKeyTemplate, + ulPublicKeyAttributeCount, + CKA_ECDSA_PARAMS); + if (attr != NULL) { + for (i = 0; i < NUMEC; i++) { + if (der_ec_supported[i].data_size == attr->ulValueLen && + memcmp(attr->pValue, der_ec_supported[i].data, + attr->ulValueLen) == 0) { + curve_type = der_ec_supported[i].curve_type; + break; + } + } + } + } + rc = check_key_attributes(tokdata, ktype, CKO_PUBLIC_KEY, pPublicKeyTemplate, ulPublicKeyAttributeCount, &new_pPublicKeyTemplate, - &new_ulPublicKeyAttributeCount); + &new_ulPublicKeyAttributeCount, + curve_type); if (rc != CKR_OK) { TRACE_ERROR("%s RSA/EC check public key attributes failed with " "rc=0x%lx\n", __func__, rc); @@ -4560,7 +4679,8 @@ static CK_RV rsa_ec_generate_keypair(STDLL_TokData_t * tokdata, rc = check_key_attributes(tokdata, ktype, CKO_PRIVATE_KEY, pPrivateKeyTemplate, ulPrivateKeyAttributeCount, &new_pPrivateKeyTemplate, - &new_ulPrivateKeyAttributeCount); + &new_ulPrivateKeyAttributeCount, + curve_type); if (rc != CKR_OK) { TRACE_ERROR("%s RSA/EC check private key attributes failed with " "rc=0x%lx\n", __func__, rc); @@ -4874,7 +4994,7 @@ static CK_RV ibm_dilithium_generate_keypair(STDLL_TokData_t * tokdata, rc = check_key_attributes(tokdata, ktype, CKO_PUBLIC_KEY, pPublicKeyTemplate, ulPublicKeyAttributeCount, &new_pPublicKeyTemplate, - &new_ulPublicKeyAttributeCount); + &new_ulPublicKeyAttributeCount, -1); if (rc != CKR_OK) { TRACE_ERROR("%s Dilithium check public key attributes failed with " "rc=0x%lx\n", __func__, rc); @@ -4884,7 +5004,7 @@ static CK_RV ibm_dilithium_generate_keypair(STDLL_TokData_t * tokdata, rc = check_key_attributes(tokdata, ktype, CKO_PRIVATE_KEY, pPrivateKeyTemplate, ulPrivateKeyAttributeCount, &new_pPrivateKeyTemplate, - &new_ulPrivateKeyAttributeCount); + &new_ulPrivateKeyAttributeCount, -1); if (rc != CKR_OK) { TRACE_ERROR("%s Dilithium check private key attributes failed with " "rc=0x%lx\n", __func__, rc); @@ -6205,24 +6325,24 @@ CK_RV ep11tok_unwrap_key(STDLL_TokData_t * tokdata, SESSION * session, rc = CKR_TEMPLATE_INCONSISTENT; goto error; } - switch (*(CK_KEY_TYPE *) cla_attr->pValue) { + switch (*(CK_OBJECT_CLASS *) cla_attr->pValue) { case CKO_SECRET_KEY: rc = check_key_attributes(tokdata, *(CK_KEY_TYPE *) keytype_attr->pValue, CKO_SECRET_KEY, attrs, - attrs_len, &new_attrs, &new_attrs_len); + attrs_len, &new_attrs, &new_attrs_len, -1); break; case CKO_PUBLIC_KEY: rc = check_key_attributes(tokdata, *(CK_KEY_TYPE *) keytype_attr->pValue, CKO_PUBLIC_KEY, attrs, attrs_len, - &new_attrs, &new_attrs_len); + &new_attrs, &new_attrs_len, -1); break; case CKO_PRIVATE_KEY: rc = check_key_attributes(tokdata, *(CK_KEY_TYPE *) keytype_attr->pValue, CKO_PRIVATE_KEY, attrs, attrs_len, - &new_attrs, &new_attrs_len); + &new_attrs, &new_attrs_len, -1); break; default: TRACE_ERROR("%s Missing CKA_CLASS type of wrapped key\n", __func__); @@ -6297,7 +6417,7 @@ CK_RV ep11tok_unwrap_key(STDLL_TokData_t * tokdata, SESSION * session, goto error; } - switch (*(CK_KEY_TYPE *) cla_attr->pValue) { + switch (*(CK_OBJECT_CLASS *) cla_attr->pValue) { case CKO_SECRET_KEY: /* card provides bit length in csum last 4 bytes big endian */ if (cslen < 4) { @@ -6311,19 +6431,24 @@ CK_RV ep11tok_unwrap_key(STDLL_TokData_t * tokdata, SESSION * session, len = len / 8; /* comes in bits */ TRACE_INFO("%s m_UnwrapKey length %lu 0x%lx\n", __func__, len, len); - rc = build_attribute(CKA_VALUE_LEN, (CK_BYTE *)&len, sizeof(CK_ULONG), - &attr); - if (rc != CKR_OK) { - TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", __func__, - rc); - goto error; - } + switch (*(CK_KEY_TYPE *) keytype_attr->pValue) { + case CKK_AES: + case CKK_GENERIC_SECRET: + rc = build_attribute(CKA_VALUE_LEN, (CK_BYTE *)&len, + sizeof(CK_ULONG), &attr); + if (rc != CKR_OK) { + TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", + __func__, rc); + goto error; + } - rc = template_update_attribute(key_obj->template, attr); - if (rc != CKR_OK) { - TRACE_ERROR("%s template_update_attribute failed with rc=0x%lx\n", - __func__, rc); - goto error; + rc = template_update_attribute(key_obj->template, attr); + if (rc != CKR_OK) { + TRACE_ERROR("%s template_update_attribute failed with " + "rc=0x%lx\n", __func__, rc); + goto error; + } + break; } break; @@ -6383,57 +6508,88 @@ done: return rc; } - -/* mechanisms ep11 reports but should be hidden because e.g. - the EP11 card operates in a FIPS mode that forbides the mechanism, - add here other mechanisms if required */ -static const CK_MECHANISM_TYPE ep11_banned_mech_list[] = { -#ifdef DEFENSIVE_MECHLIST - CKM_DES_KEY_GEN, - CKM_DES_ECB, - CKM_DES_CBC, - CKM_DES_CBC_PAD, - CKM_GENERIC_SECRET_KEY_GEN, - - /* Wrong/outdated */ - CKM_EP11_SHA512_224, - CKM_EP11_SHA512_224_HMAC, - CKM_EP11_SHA512_224_HMAC_GENERAL, - CKM_EP11_SHA512_256, - CKM_EP11_SHA512_256_HMAC, - CKM_EP11_SHA512_256_HMAC_GENERAL, - - /* Vendor specific */ - CKM_IBM_ECDSA_SHA224, - CKM_IBM_ECDSA_SHA256, - CKM_IBM_ECDSA_SHA384, - CKM_IBM_ECDSA_SHA512, - CKM_IBM_EC_MULTIPLY, - CKM_IBM_EAC, - CKM_IBM_TESTCODE, - CKM_IBM_SHA512_256, - CKM_IBM_SHA512_224, - CKM_IBM_SHA512_256_HMAC, - CKM_IBM_SHA512_224_HMAC, - CKM_IBM_SHA512_256_KEY_DERIVATION, - CKM_IBM_SHA512_224_KEY_DERIVATION, - CKM_IBM_EDDSA_PH_SHA512, - CKM_IBM_SIPHASH, - CKM_IBM_CLEARKEY_TRANSPORT, - CKM_IBM_ATTRIBUTEBOUND_WRAP, - CKM_IBM_TRANSPORTKEY, - CKM_IBM_DH_PKCS_DERIVE_RAW, - CKM_IBM_ECDH1_DERIVE_RAW, - CKM_IBM_WIRETEST, - CKM_IBM_RETAINKEY, - CKM_IBM_CPACF_WRAP, - CKM_IBM_SM3, -#endif +static const CK_MECHANISM_TYPE ep11_supported_mech_list[] = { + CKM_AES_CBC, + CKM_AES_CBC_PAD, + CKM_AES_CMAC, + CKM_AES_ECB, + CKM_AES_KEY_GEN, + CKM_DES2_KEY_GEN, + CKM_DES3_CBC, + CKM_DES3_CBC_PAD, + CKM_DES3_CMAC, + CKM_DES3_ECB, + CKM_DES3_KEY_GEN, + CKM_DH_PKCS_DERIVE, + CKM_DH_PKCS_KEY_PAIR_GEN, + CKM_DH_PKCS_PARAMETER_GEN, + CKM_DSA, + CKM_DSA_KEY_PAIR_GEN, + CKM_DSA_PARAMETER_GEN, + CKM_DSA_SHA1, + CKM_EC_KEY_PAIR_GEN, + CKM_ECDH1_DERIVE, + CKM_ECDSA, + CKM_ECDSA_SHA1, + CKM_ECDSA_SHA224, + CKM_ECDSA_SHA256, + CKM_ECDSA_SHA384, + CKM_ECDSA_SHA512, + CKM_IBM_CMAC, + CKM_IBM_DILITHIUM, + CKM_IBM_EC_X25519, + CKM_IBM_EC_X448, + CKM_IBM_ED25519_SHA512, + CKM_IBM_ED448_SHA3, + CKM_IBM_SHA3_224, + CKM_IBM_SHA3_224_HMAC, + CKM_IBM_SHA3_256, + CKM_IBM_SHA3_256_HMAC, + CKM_IBM_SHA3_384, + CKM_IBM_SHA3_384_HMAC, + CKM_IBM_SHA3_512, + CKM_IBM_SHA3_512_HMAC, + CKM_PBE_SHA1_DES3_EDE_CBC, + CKM_RSA_PKCS, + CKM_RSA_PKCS_KEY_PAIR_GEN, + CKM_RSA_PKCS_OAEP, + CKM_RSA_PKCS_PSS, + CKM_RSA_X9_31, + CKM_RSA_X9_31_KEY_PAIR_GEN, + CKM_SHA1_KEY_DERIVATION, + CKM_SHA1_RSA_PKCS, + CKM_SHA1_RSA_PKCS_PSS, + CKM_SHA1_RSA_X9_31, + CKM_SHA224, + CKM_SHA224_HMAC, + CKM_SHA224_KEY_DERIVATION, + CKM_SHA224_RSA_PKCS, + CKM_SHA224_RSA_PKCS_PSS, + CKM_SHA256, + CKM_SHA256_HMAC, + CKM_SHA256_KEY_DERIVATION, + CKM_SHA256_RSA_PKCS, + CKM_SHA256_RSA_PKCS_PSS, + CKM_SHA384, + CKM_SHA384_HMAC, + CKM_SHA384_KEY_DERIVATION, + CKM_SHA384_RSA_PKCS, + CKM_SHA384_RSA_PKCS_PSS, + CKM_SHA512, + CKM_SHA512_224, + CKM_SHA512_224_HMAC, + CKM_SHA512_256, + CKM_SHA512_256_HMAC, + CKM_SHA512_HMAC, + CKM_SHA512_KEY_DERIVATION, + CKM_SHA512_RSA_PKCS, + CKM_SHA512_RSA_PKCS_PSS, + CKM_SHA_1, + CKM_SHA_1_HMAC, }; -static const CK_ULONG banned_mech_list_len = - (sizeof(ep11_banned_mech_list) / sizeof(CK_MECHANISM_TYPE)); - +static const CK_ULONG supported_mech_list_len = + (sizeof(ep11_supported_mech_list) / sizeof(CK_MECHANISM_TYPE)); /* filtering out some mechanisms we do not want to provide * makes it complicated @@ -6572,16 +6728,23 @@ CK_RV ep11tok_is_mechanism_supported(STDLL_TokData_t *tokdata, ep11_private_data_t *ep11_data = tokdata->private_data; CK_VERSION ver1_3 = { .major = 1, .minor = 3 }; CK_VERSION ver3 = { .major = 3, .minor = 0 }; + CK_BBOOL found = FALSE; CK_ULONG i; int status; - for (i = 0; i < banned_mech_list_len; i++) { - if (type == ep11_banned_mech_list[i]) { - TRACE_INFO("%s Mech '%s' banned\n", __func__, ep11_get_ckm(type)); - return CKR_MECHANISM_INVALID; + for (i = 0; i < supported_mech_list_len; i++) { + if (type == ep11_supported_mech_list[i]) { + found = TRUE; + break; } } + if (!found) { + TRACE_INFO("%s Mech '%s' not suppported\n", __func__, + ep11_get_ckm(type)); + return CKR_MECHANISM_INVALID; + } + if (check_cps_for_mechanism(ep11_data->cp_config, type, ep11_data->control_points, ep11_data->control_points_len, @@ -6659,7 +6822,7 @@ CK_RV ep11tok_is_mechanism_supported(STDLL_TokData_t *tokdata, break; case CKM_IBM_EC_C25519: - case CKM_IBM_EDDSA_SHA512: + case CKM_IBM_ED25519_SHA512: case CKM_IBM_EC_C448: case CKM_IBM_ED448_SHA3: if (compare_ck_version(&ep11_data->ep11_lib_version, &ver3) < 0) { @@ -6883,7 +7046,11 @@ static int read_adapter_config_file(STDLL_TokData_t * tokdata, int whitemode = 0; int anymode = 0; int apqn_i = 0; /* how many APQN numbers */ - char *conf_dir = getenv("OCK_EP11_TOKEN_DIR"); + /* Since the ep11 token config contains the path to libica that + * will later be dlopen()ed, we cannot use a token config + * directory from an untrusted environment. + */ + char *conf_dir = secure_getenv("OCK_EP11_TOKEN_DIR"); char fname[PATH_MAX]; int rc = 0; char *cfg_dir; @@ -8754,8 +8921,29 @@ static CK_RV version_query_handler(uint_32 adapter, uint_32 domain, } card_version->card_type = card_type; +#ifdef EP11_HSMSIM +#ifdef EP11_HSMSIM_FW_API + card_version->firmware_API_version = EP11_HSMSIM_FW_API; +#else card_version->firmware_API_version = xcp_info.firmwareApi; +#endif +#else + card_version->firmware_API_version = xcp_info.firmwareApi; +#endif +#ifdef EP11_HSMSIM +#ifdef EP11_HSMSIM_FW_VER_MAJOR + card_version->firmware_version.major = EP11_HSMSIM_FW_VER_MAJOR; +#ifdef EP11_HSMSIM_FW_VER_MINOR + card_version->firmware_version.minor = EP11_HSMSIM_FW_VER_MINOR; +#else + card_version->firmware_version.minor = 0; +#endif +#else + card_version->firmware_version = xcp_info.firmwareVersion; +#endif +#else card_version->firmware_version = xcp_info.firmwareVersion; +#endif card_version->next = qv->ep11_data->card_versions; qv->ep11_data->card_versions = card_version; diff --git a/usr/lib/ep11_stdll/ep11_stdll.mk b/usr/lib/ep11_stdll/ep11_stdll.mk index 99b3b37..0ca7cc7 100644 --- a/usr/lib/ep11_stdll/ep11_stdll.mk +++ b/usr/lib/ep11_stdll/ep11_stdll.mk @@ -34,7 +34,9 @@ opencryptoki_stdll_libpkcs11_ep11_la_SOURCES = \ 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/ep11_stdll/new_host.c usr/lib/ep11_stdll/ep11_specific.c + if ENABLE_LOCKS opencryptoki_stdll_libpkcs11_ep11_la_SOURCES += \ usr/lib/common/lock_btree.c usr/lib/common/lock_sess_mgr.c diff --git a/usr/lib/ep11_stdll/ep11cpfilter.conf b/usr/lib/ep11_stdll/ep11cpfilter.conf index e27c4ea..a06e5e2 100644 --- a/usr/lib/ep11_stdll/ep11cpfilter.conf +++ b/usr/lib/ep11_stdll/ep11cpfilter.conf @@ -67,7 +67,7 @@ XCP_CPB_ALG_DH: CKM_ECDH1_DERIVE, CKM_DH_PKCS_PARAMETER_GEN, CKM_DH_PKCS_KEY_PAI XCP_CPB_DERIVE: CKM_SHA1_KEY_DERIVATION, CKM_SHA256_KEY_DERIVATION, CKM_SHA384_KEY_DERIVATION, CKM_SHA512_KEY_DERIVATION, CKM_SHA224_KEY_DERIVATION, CKM_ECDH1_DERIVE, CKM_DH_PKCS_DERIVE # enable support of curve25519, c448 and related algorithms incl. EdDSA (ed25519 and ed448) -XCP_CPB_ALG_EC_25519: CKM_IBM_EC_C25519, CKM_IBM_EDDSA_SHA512, CKM_IBM_EC_C448, CKM_IBM_ED448_SHA3 +XCP_CPB_ALG_EC_25519: CKM_IBM_EC_C25519, CKM_IBM_ED25519_SHA512, CKM_IBM_EC_C448, CKM_IBM_ED448_SHA3 #allow non-BSI algorithms (as of 2017) including non-BSI keysizes XCP_CPB_ALG_NBSI2017: CKM_RSA_PKCS, CKM_SHA1_RSA_PKCS, CKM_SHA224_RSA_PKCS, CKM_SHA256_RSA_PKCS, CKM_SHA384_RSA_PKCS, CKM_SHA512_RSA_PKCS diff --git a/usr/lib/ep11_stdll/new_host.c b/usr/lib/ep11_stdll/new_host.c index d4bd40a..be92c63 100644 --- a/usr/lib/ep11_stdll/new_host.c +++ b/usr/lib/ep11_stdll/new_host.c @@ -106,13 +106,24 @@ CK_RV ST_Initialize(API_Slot_t *sltp, CK_SLOT_ID SlotNumber, bt_init(&sltp->TokData->publ_token_obj_btree, call_object_free); if (strlen(sinfp->tokname)) { - sprintf(abs_tokdir_name, "%s/%s", CONFIG_PATH, sinfp->tokname); - TRACE_DEVEL("Token directory: %s\n", abs_tokdir_name); - init_data_store(sltp->TokData, (char *) abs_tokdir_name, - sltp->TokData->data_store); + if (ock_snprintf(abs_tokdir_name, PATH_MAX, "%s/%s", + CONFIG_PATH, sinfp->tokname) != 0) { + TRACE_ERROR("abs_tokdir_name buffer overflow\n"); + rc = CKR_FUNCTION_FAILED; + } else { + TRACE_DEVEL("Token directory: %s\n", abs_tokdir_name); + rc = init_data_store(sltp->TokData, (char *) abs_tokdir_name, + sltp->TokData->data_store, + sizeof(sltp->TokData->data_store)); + } } else { - init_data_store(sltp->TokData, (char *) PK_DIR, - sltp->TokData->data_store); + rc = init_data_store(sltp->TokData, (char *) PK_DIR, + sltp->TokData->data_store, + sizeof(sltp->TokData->data_store)); + } + if (rc != CKR_OK) { + TRACE_ERROR("init_data_store failed with buffer error.\n"); + goto done; } sltp->TokData->version = sinfp->version; @@ -462,6 +473,9 @@ CK_RV SC_InitToken(STDLL_TokData_t *tokdata, CK_SLOT_ID sid, CK_CHAR_PTR pPin, memcpy(dat->so_login_key, login_key, 32); } tokdata->nv_token_data->token_info.flags |= CKF_TOKEN_INITIALIZED; + tokdata->nv_token_data->token_info.flags &= ~(CKF_USER_PIN_INITIALIZED | + CKF_USER_PIN_LOCKED | CKF_USER_PIN_FINAL_TRY | + CKF_USER_PIN_COUNT_LOW); memcpy(tokdata->nv_token_data->token_info.label, pLabel, 32); rc = save_token_data(tokdata, sid); @@ -1303,6 +1317,12 @@ CK_RV SC_Login(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession, goto done; } + if (!(*flags & CKF_USER_PIN_INITIALIZED)) { + TRACE_ERROR("%s\n", ock_err(ERR_USER_PIN_NOT_INITIALIZED)); + rc = CKR_USER_PIN_NOT_INITIALIZED; + goto done; + } + if (tokdata->version < TOK_NEW_DATA_STORE) { if (memcmp(tokdata->nv_token_data->user_pin_sha, "00000000000000000000", SHA1_HASH_SIZE) == 0) { @@ -2948,8 +2968,10 @@ CK_RV SC_Sign(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession, } done: - if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) - sign_mgr_cleanup(&sess->sign_ctx); + if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) { + if (sess != NULL) + sign_mgr_cleanup(&sess->sign_ctx); + } TRACE_INFO("C_Sign: rc = 0x%08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulDataLen); @@ -3029,7 +3051,7 @@ CK_RV SC_SignUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession, TRACE_DEVEL("ep11tok_sign_update() failed.\n"); done: - if (rc != CKR_OK) + if (rc != CKR_OK && sess != NULL) sign_mgr_cleanup(&sess->sign_ctx); TRACE_INFO("C_SignUpdate: rc = 0x%08lx, sess = %ld, datalen = %lu\n", @@ -3109,8 +3131,10 @@ CK_RV SC_SignFinal(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession, TRACE_ERROR("ep11tok_sign_final() failed.\n"); done: - if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) - sign_mgr_cleanup(&sess->sign_ctx); + if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) { + if (sess != NULL) + sign_mgr_cleanup(&sess->sign_ctx); + } TRACE_INFO("C_SignFinal: rc = 0x%08lx, sess = %ld\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle); @@ -3316,7 +3340,8 @@ CK_RV SC_Verify(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession, } done: - verify_mgr_cleanup(&sess->verify_ctx); + if (sess != NULL) + verify_mgr_cleanup(&sess->verify_ctx); TRACE_INFO("C_Verify: rc = 0x%08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulDataLen); @@ -3396,7 +3421,7 @@ CK_RV SC_VerifyUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession, TRACE_DEVEL("ep11tok_verify_update() failed.\n"); done: - if (rc != CKR_OK) + if (rc != CKR_OK && sess != NULL) verify_mgr_cleanup(&sess->verify_ctx); TRACE_INFO("C_VerifyUpdate: rc = 0x%08lx, sess = %ld, datalen = %lu\n", @@ -3471,7 +3496,8 @@ CK_RV SC_VerifyFinal(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession, TRACE_DEVEL("ep11tok_verify_final() failed.\n"); done: - verify_mgr_cleanup(&sess->verify_ctx); + if (sess != NULL) + verify_mgr_cleanup(&sess->verify_ctx); TRACE_INFO("C_VerifyFinal: rc = 0x%08lx, sess = %ld\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle); @@ -4119,6 +4145,77 @@ CK_RV SC_CancelFunction(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession) return CKR_FUNCTION_NOT_PARALLEL; } +CK_RV SC_IBM_ReencryptSingle(STDLL_TokData_t *tokdata, ST_SESSION_T *sSession, + CK_MECHANISM_PTR pDecrMech, + CK_OBJECT_HANDLE hDecrKey, + CK_MECHANISM_PTR pEncrMech, + CK_OBJECT_HANDLE hEncrKey, + CK_BYTE_PTR pEncryptedData, + CK_ULONG ulEncryptedDataLen, + CK_BYTE_PTR pReencryptedData, + CK_ULONG_PTR pulReencryptedDataLen) +{ + SESSION *sess = NULL; + CK_RV rc = CKR_OK; + + if (tokdata->initialized == FALSE) { + TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); + rc = CKR_CRYPTOKI_NOT_INITIALIZED; + goto done; + } + + if (!pDecrMech || !pEncrMech) { + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + rc = CKR_ARGUMENTS_BAD; + goto done; + } + + sess = session_mgr_find(tokdata, sSession->sessionh); + if (!sess) { + TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); + rc = CKR_SESSION_HANDLE_INVALID; + goto done; + } + + rc = valid_mech(tokdata, pDecrMech); + if (rc != CKR_OK) + goto done; + rc = valid_mech(tokdata, pEncrMech); + if (rc != CKR_OK) + goto done; + + if (pin_expired(&sess->session_info, + tokdata->nv_token_data->token_info.flags) == TRUE) { + TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); + rc = CKR_PIN_EXPIRED; + goto done; + } + + if (sess->decr_ctx.active == TRUE || sess->encr_ctx.active == TRUE) { + rc = CKR_OPERATION_ACTIVE; + TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); + goto done; + } + + rc = encr_mgr_reencrypt_single(tokdata, sess, &sess->decr_ctx, pDecrMech, + hDecrKey, &sess->encr_ctx, pEncrMech, + hEncrKey, pEncryptedData, ulEncryptedDataLen, + pReencryptedData, pulReencryptedDataLen); + if (rc != CKR_OK) + TRACE_DEVEL("encr_mgr_reencrypt_single() failed.\n"); + +done: + TRACE_INFO("SC_IBM_ReencryptSingle: rc = 0x%08lx, sess = %ld, " + "decrmech = 0x%lx, encrmech = 0x%lx\n", + rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, + (pDecrMech ? pDecrMech->mechanism : (CK_ULONG)-1), + (pEncrMech ? pEncrMech->mechanism : (CK_ULONG)-1)); + + if (sess != NULL) + session_mgr_put(tokdata, sess); + + return rc; +} void SC_SetFunctionList(void) { @@ -4183,4 +4280,6 @@ void SC_SetFunctionList(void) function_list.ST_GenerateRandom = SC_GenerateRandom; function_list.ST_GetFunctionStatus = NULL; // SC_GetFunctionStatus; function_list.ST_CancelFunction = NULL; // SC_CancelFunction; + + function_list.ST_IBM_ReencryptSingle = SC_IBM_ReencryptSingle; } diff --git a/usr/lib/ep11_stdll/tok_struct.h b/usr/lib/ep11_stdll/tok_struct.h index b900897..088153f 100644 --- a/usr/lib/ep11_stdll/tok_struct.h +++ b/usr/lib/ep11_stdll/tok_struct.h @@ -40,7 +40,7 @@ token_spec_t token_specific = { SW_CONFIG_PATH, "ep11tok", - 24, // keysize + TRUE, // secure key token // Token data info: { FALSE, // Don't use per guest data store @@ -131,7 +131,10 @@ token_spec_t token_specific = { NULL, // dsa_verify NULL, // get_mechanism_list NULL, // get mechanism_info - &token_specific_object_add + &token_specific_object_add, + NULL, // key_wrap + NULL, // key_unwrap + &token_specific_reencrypt_single, }; #endif diff --git a/usr/lib/ica_s390_stdll/ica_s390_stdll.mk b/usr/lib/ica_s390_stdll/ica_s390_stdll.mk index 0d972c5..d6b4379 100644 --- a/usr/lib/ica_s390_stdll/ica_s390_stdll.mk +++ b/usr/lib/ica_s390_stdll/ica_s390_stdll.mk @@ -33,7 +33,9 @@ opencryptoki_stdll_libpkcs11_ica_la_SOURCES = \ usr/lib/common/p11util.c 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/ica_s390_stdll/ica_specific.c + if ENABLE_LOCKS opencryptoki_stdll_libpkcs11_ica_la_SOURCES += \ usr/lib/common/lock_btree.c usr/lib/common/lock_sess_mgr.c diff --git a/usr/lib/ica_s390_stdll/ica_specific.c b/usr/lib/ica_s390_stdll/ica_specific.c index 8f58b9f..2ec054e 100644 --- a/usr/lib/ica_s390_stdll/ica_specific.c +++ b/usr/lib/ica_s390_stdll/ica_specific.c @@ -45,7 +45,7 @@ #endif #include -#define ICA_MAX_MECH_LIST_ENTRIES 84 +#define ICA_MAX_MECH_LIST_ENTRIES 98 typedef struct { ica_adapter_handle_t adapter_handle; @@ -161,6 +161,46 @@ typedef unsigned int (*ica_sha512_256_t)(unsigned int message_part, static ica_sha512_256_t p_ica_sha512_256; #endif +#ifdef SHA3_224 +typedef unsigned int (*ica_sha3_224_t)(unsigned int message_part, + unsigned int input_length, + unsigned char *input_data, + sha3_224_context_t *sha_context, + unsigned char *output_data); + +static ica_sha3_224_t p_ica_sha3_224; +#endif + +#ifdef SHA3_256 +typedef unsigned int (*ica_sha3_256_t)(unsigned int message_part, + unsigned int input_length, + unsigned char *input_data, + sha3_256_context_t *sha_context, + unsigned char *output_data); + +static ica_sha3_256_t p_ica_sha3_256; +#endif + +#ifdef SHA3_384 +typedef unsigned int (*ica_sha3_384_t)(unsigned int message_part, + unsigned int input_length, + unsigned char *input_data, + sha3_384_context_t *sha_context, + unsigned char *output_data); + +static ica_sha3_384_t p_ica_sha3_384; +#endif + +#ifdef SHA3_512 +typedef unsigned int (*ica_sha3_512_t)(unsigned int message_part, + unsigned int input_length, + unsigned char *input_data, + sha3_512_context_t *sha_context, + unsigned char *output_data); + +static ica_sha3_512_t p_ica_sha3_512; +#endif + static CK_RV load_libica(void) { void *ibmca_dso = NULL; @@ -191,6 +231,18 @@ static CK_RV load_libica(void) #ifdef SHA512_256 BIND(ibmca_dso, ica_sha512_256); #endif +#ifdef SHA3_224 + BIND(ibmca_dso, ica_sha3_224); +#endif +#ifdef SHA3_256 + BIND(ibmca_dso, ica_sha3_256); +#endif +#ifdef SHA3_384 + BIND(ibmca_dso, ica_sha3_384); +#endif +#ifdef SHA3_512 + BIND(ibmca_dso, ica_sha3_512); +#endif return CKR_OK; } @@ -308,22 +360,27 @@ static void adjust_des_key_parity_bits(CK_BYTE *des_key, CK_ULONG key_size, } } -CK_RV token_specific_des_key_gen(STDLL_TokData_t *tokdata, CK_BYTE *des_key, - CK_ULONG len, CK_ULONG keysize) +CK_RV token_specific_des_key_gen(STDLL_TokData_t *tokdata, CK_BYTE **des_key, + CK_ULONG *len, CK_ULONG keysize, + CK_BBOOL *is_opaque) { - UNUSED(keysize); + *des_key = malloc(keysize); + if (*des_key == NULL) + return CKR_HOST_MEMORY; + *len = keysize; + *is_opaque = FALSE; // Nothing different to do for DES or TDES here as this is just // random data... Validation handles the rest // Only check for weak keys when DES. - if (len == (3 * DES_KEY_SIZE)) { - rng_generate(tokdata, des_key, len); - adjust_des_key_parity_bits(des_key, len, ODD_PARITY); + if (keysize == (3 * DES_KEY_SIZE)) { + rng_generate(tokdata, *des_key, keysize); + adjust_des_key_parity_bits(*des_key, keysize, ODD_PARITY); } else { do { - rng_generate(tokdata, des_key, len); - adjust_des_key_parity_bits(des_key, len, ODD_PARITY); - } while (des_check_weak_key(des_key) == TRUE); + rng_generate(tokdata, *des_key, keysize); + adjust_des_key_parity_bits(*des_key, keysize, ODD_PARITY); + } while (des_check_weak_key(*des_key) == TRUE); } @@ -719,6 +776,26 @@ CK_RV token_specific_sha_init(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx, #endif devctxsize = sizeof(sha512_context_t); break; +#ifdef SHA3_224 + case CKM_IBM_SHA3_224: + devctxsize = sizeof(sha3_224_context_t); + break; +#endif +#ifdef SHA3_256 + case CKM_IBM_SHA3_256: + devctxsize = sizeof(sha3_256_context_t); + break; +#endif +#ifdef SHA3_384 + case CKM_IBM_SHA3_384: + devctxsize = sizeof(sha3_384_context_t); + break; +#endif +#ifdef SHA3_512 + case CKM_IBM_SHA3_512: + devctxsize = sizeof(sha3_512_context_t); + break; +#endif default: return CKR_MECHANISM_INVALID; } @@ -771,6 +848,30 @@ CK_RV token_specific_sha_init(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx, sc->hash_blksize = SHA512_BLOCK_SIZE; break; #endif +#ifdef SHA3_224 + case CKM_IBM_SHA3_224: + sc->hash_len = SHA3_224_HASH_SIZE; + sc->hash_blksize = SHA3_224_BLOCK_SIZE; + break; +#endif +#ifdef SHA3_256 + case CKM_IBM_SHA3_256: + sc->hash_len = SHA3_256_HASH_SIZE; + sc->hash_blksize = SHA3_256_BLOCK_SIZE; + break; +#endif +#ifdef SHA3_384 + case CKM_IBM_SHA3_384: + sc->hash_len = SHA3_384_HASH_SIZE; + sc->hash_blksize = SHA3_384_BLOCK_SIZE; + break; +#endif +#ifdef SHA3_512 + case CKM_IBM_SHA3_512: + sc->hash_len = SHA3_512_HASH_SIZE; + sc->hash_blksize = SHA3_512_BLOCK_SIZE; + break; +#endif } return CKR_OK; @@ -863,6 +964,58 @@ CK_RV token_specific_sha(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx, break; } #endif +#ifdef SHA3_224 + case CKM_IBM_SHA3_224: + { + sha3_224_context_t *ica_sha3_ctx = (sha3_224_context_t *) dev_ctx; + + if (p_ica_sha3_224 == NULL) + return CKR_MECHANISM_INVALID; + + rc = p_ica_sha3_224(sc->message_part, in_data_len, + in_data, ica_sha3_ctx, sc->hash); + break; + } +#endif +#ifdef SHA3_256 + case CKM_IBM_SHA3_256: + { + sha3_256_context_t *ica_sha3_ctx = (sha3_256_context_t *) dev_ctx; + + if (p_ica_sha3_256 == NULL) + return CKR_MECHANISM_INVALID; + + rc = p_ica_sha3_256(sc->message_part, in_data_len, + in_data, ica_sha3_ctx, sc->hash); + break; + } +#endif +#ifdef SHA3_384 + case CKM_IBM_SHA3_384: + { + sha3_384_context_t *ica_sha3_ctx = (sha3_384_context_t *) dev_ctx; + + if (p_ica_sha3_384 == NULL) + return CKR_MECHANISM_INVALID; + + rc = p_ica_sha3_384(sc->message_part, in_data_len, + in_data, ica_sha3_ctx, sc->hash); + break; + } +#endif +#ifdef SHA3_512 + case CKM_IBM_SHA3_512: + { + sha3_512_context_t *ica_sha3_ctx = (sha3_512_context_t *) dev_ctx; + + if (p_ica_sha3_512 == NULL) + return CKR_MECHANISM_INVALID; + + rc = p_ica_sha3_512(sc->message_part, in_data_len, + in_data, ica_sha3_ctx, sc->hash); + break; + } +#endif default: return CKR_MECHANISM_INVALID; } @@ -978,6 +1131,76 @@ static CK_RV ica_sha_call(DIGEST_CONTEXT *ctx, CK_BYTE *data, break; } #endif +#ifdef SHA3_224 + case CKM_IBM_SHA3_224: + { + sha3_224_context_t *ica_sha_ctx = (sha3_224_context_t *) dev_ctx; + + if (p_ica_sha3_224 == NULL) + return CKR_MECHANISM_INVALID; + + if (ica_sha_ctx->runningLength == 0) + sc->message_part = SHA_MSG_PART_FIRST; + else + sc->message_part = SHA_MSG_PART_MIDDLE; + ret = p_ica_sha3_224(sc->message_part, data_len, data, + ica_sha_ctx, sc->hash); + break; + } +#endif +#ifdef SHA3_256 + case CKM_IBM_SHA3_256: + { + sha3_256_context_t *ica_sha_ctx = (sha3_256_context_t *) dev_ctx; + + if (p_ica_sha3_256 == NULL) + return CKR_MECHANISM_INVALID; + + if (ica_sha_ctx->runningLength == 0) + sc->message_part = SHA_MSG_PART_FIRST; + else + sc->message_part = SHA_MSG_PART_MIDDLE; + ret = p_ica_sha3_256(sc->message_part, data_len, data, + ica_sha_ctx, sc->hash); + break; + } +#endif +#ifdef SHA3_384 + case CKM_IBM_SHA3_384: + { + sha3_384_context_t *ica_sha_ctx = (sha3_384_context_t *) dev_ctx; + + if (p_ica_sha3_384 == NULL) + return CKR_MECHANISM_INVALID; + + if (ica_sha_ctx->runningLengthLow == 0 && + ica_sha_ctx->runningLengthHigh == 0) + sc->message_part = SHA_MSG_PART_FIRST; + else + sc->message_part = SHA_MSG_PART_MIDDLE; + ret = p_ica_sha3_384(sc->message_part, data_len, data, + ica_sha_ctx, sc->hash); + break; + } +#endif +#ifdef SHA3_512 + case CKM_IBM_SHA3_512: + { + sha3_512_context_t *ica_sha_ctx = (sha3_512_context_t *) dev_ctx; + + if (p_ica_sha3_512 == NULL) + return CKR_MECHANISM_INVALID; + + if (ica_sha_ctx->runningLengthLow == 0 && + ica_sha_ctx->runningLengthHigh == 0) + sc->message_part = SHA_MSG_PART_FIRST; + else + sc->message_part = SHA_MSG_PART_MIDDLE; + ret = p_ica_sha3_512(sc->message_part, data_len, data, + ica_sha_ctx, sc->hash); + break; + } +#endif default: return CKR_MECHANISM_INVALID; } @@ -1188,6 +1411,80 @@ CK_RV token_specific_sha_final(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx, break; } #endif +#ifdef SHA3_224 + case CKM_IBM_SHA3_224: + { + sha3_224_context_t *ica_sha3_ctx = (sha3_224_context_t *) dev_ctx; + + if (p_ica_sha3_224 == NULL) + return CKR_MECHANISM_INVALID; + + /* accommodate multi-part when input was so small + * that we never got to call into libica until final + */ + if (ica_sha3_ctx->runningLength == 0) + sc->message_part = SHA_MSG_PART_ONLY; + rc = p_ica_sha3_224(sc->message_part, sc->tail_len, + sc->tail, ica_sha3_ctx, sc->hash); + break; + } +#endif +#ifdef SHA3_256 + case CKM_IBM_SHA3_256: + { + sha3_256_context_t *ica_sha3_ctx = (sha3_256_context_t *) dev_ctx; + + if (p_ica_sha3_256 == NULL) + return CKR_MECHANISM_INVALID; + + /* accommodate multi-part when input was so small + * that we never got to call into libica until final + */ + if (ica_sha3_ctx->runningLength == 0) + sc->message_part = SHA_MSG_PART_ONLY; + rc = p_ica_sha3_256(sc->message_part, sc->tail_len, + sc->tail, ica_sha3_ctx, sc->hash); + break; + } +#endif +#ifdef SHA3_384 + case CKM_IBM_SHA3_384: + { + sha3_384_context_t *ica_sha3_ctx = (sha3_384_context_t *) dev_ctx; + + if (p_ica_sha3_384 == NULL) + return CKR_MECHANISM_INVALID; + + /* accommodate multi-part when input was so small + * that we never got to call into libica until final + */ + if (ica_sha3_ctx->runningLengthLow == 0 + && ica_sha3_ctx->runningLengthHigh == 0) + sc->message_part = SHA_MSG_PART_ONLY; + rc = p_ica_sha3_384(sc->message_part, sc->tail_len, + sc->tail, ica_sha3_ctx, sc->hash); + break; + } +#endif +#ifdef SHA3_512 + case CKM_IBM_SHA3_512: + { + sha3_512_context_t *ica_sha3_ctx = (sha3_512_context_t *) dev_ctx; + + if (p_ica_sha3_512 == NULL) + return CKR_MECHANISM_INVALID; + + /* accommodate multi-part when input was so small + * that we never got to call into libica until final + */ + if (ica_sha3_ctx->runningLengthLow == 0 + && ica_sha3_ctx->runningLengthHigh == 0) + sc->message_part = SHA_MSG_PART_ONLY; + rc = p_ica_sha3_512(sc->message_part, sc->tail_len, + sc->tail, ica_sha3_ctx, sc->hash); + break; + } +#endif default: return CKR_MECHANISM_INVALID; } @@ -2569,12 +2866,17 @@ done: #ifndef NOAES -CK_RV token_specific_aes_key_gen(STDLL_TokData_t *tokdata, CK_BYTE *key, - CK_ULONG len, CK_ULONG keysize) +CK_RV token_specific_aes_key_gen(STDLL_TokData_t *tokdata, CK_BYTE **key, + CK_ULONG *len, CK_ULONG keysize, + CK_BBOOL *is_opaque) { - UNUSED(keysize); + *key = malloc(keysize); + if (*key == NULL) + return CKR_HOST_MEMORY; + *len = keysize; + *is_opaque = FALSE; - return rng_generate(tokdata, key, len); + return rng_generate(tokdata, *key, keysize); } CK_RV token_specific_aes_ecb(STDLL_TokData_t *tokdata, CK_BYTE *in_data, @@ -3364,6 +3666,8 @@ static const REF_MECH_LIST_ELEMENT ref_mech_list[] = { {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}}, @@ -3375,9 +3679,29 @@ static const REF_MECH_LIST_ELEMENT ref_mech_list[] = { {05, CKM_SHA512_HMAC_GENERAL, {0, 0, CKF_HW | 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}}, #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}}, +#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}}, +#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}}, +#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}}, +#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}}, #endif #if !(NOMD5) {53, CKM_MD5, {0, 0, CKF_HW | CKF_DIGEST}}, @@ -4058,8 +4382,8 @@ static CK_RV decompress_pubkey(unsigned int nid, goto end; } - if (!EC_POINT_set_compressed_coordinates_GFp(group, - point, bn_x, y_bit, ctx)) { + if (!EC_POINT_set_compressed_coordinates(group, + point, bn_x, y_bit, ctx)) { ret = CKR_FUNCTION_FAILED; goto end; } @@ -4069,7 +4393,7 @@ static CK_RV decompress_pubkey(unsigned int nid, goto end; } - if (!EC_POINT_get_affine_coordinates_GFp(group, point, bn_x, bn_y, ctx)) { + if (!EC_POINT_get_affine_coordinates(group, point, bn_x, bn_y, ctx)) { ret = CKR_FUNCTION_FAILED; goto end; } diff --git a/usr/lib/ica_s390_stdll/tok_struct.h b/usr/lib/ica_s390_stdll/tok_struct.h index 2b9f421..01fe88b 100644 --- a/usr/lib/ica_s390_stdll/tok_struct.h +++ b/usr/lib/ica_s390_stdll/tok_struct.h @@ -29,7 +29,7 @@ token_spec_t token_specific = { LITE_CONFIG_PATH, "lite", - 0, // keysize + FALSE, // Token data info: { FALSE, // Don't use per guest data store @@ -141,7 +141,10 @@ token_spec_t token_specific = { NULL, // dsa_verify &token_specific_get_mechanism_list, &token_specific_get_mechanism_info, - NULL // object_add + NULL, // object_add + NULL, // key_wrap + NULL, // key_unwrap + NULL, // reencrypt_single }; #endif diff --git a/usr/lib/icsf_stdll/icsf_specific.c b/usr/lib/icsf_stdll/icsf_specific.c index 8ad02e0..8ad7868 100644 --- a/usr/lib/icsf_stdll/icsf_specific.c +++ b/usr/lib/icsf_stdll/icsf_specific.c @@ -569,11 +569,20 @@ CK_RV login(STDLL_TokData_t * tokdata, LDAP ** ld, CK_SLOT_ID slot_id, CK_BYTE racf_pass[PIN_SIZE]; int mk_len = sizeof(mk); int racf_pass_len = sizeof(racf_pass); - char pk_dir_buf[PATH_MAX]; char fname[PATH_MAX]; /* Load master key */ - sprintf(fname, "%s/MK_SO", get_pk_dir(tokdata, pk_dir_buf)); + if (get_pk_dir(tokdata, fname, PATH_MAX) == NULL) { + TRACE_ERROR("pk_dir buffer overflow\n"); + return CKR_FUNCTION_FAILED; + } + + if (PATH_MAX - strlen(fname) > strlen("/MK_SO")) { + strcat(fname, "/MK_SO"); + } else { + TRACE_ERROR("MK_SO buffer overflow\n"); + return CKR_FUNCTION_FAILED; + } if (get_masterkey(pin, pin_len, fname, mk, &mk_len)) { TRACE_DEVEL("Failed to get masterkey \"%s\".\n", fname); return CKR_FUNCTION_FAILED; @@ -624,12 +633,22 @@ CK_RV reset_token_data(STDLL_TokData_t * tokdata, CK_SLOT_ID slot_id, /* Remove user's masterkey */ if (slot_data[slot_id]->mech == ICSF_CFG_MECH_SIMPLE) { - sprintf(fname, "%s/MK_USER", get_pk_dir(tokdata, pk_dir_buf)); + if (get_pk_dir(tokdata, pk_dir_buf, PATH_MAX) == NULL) { + TRACE_ERROR("pk_dir_buf overflow\n"); + return CKR_FUNCTION_FAILED; + } + if (ock_snprintf(fname, PATH_MAX, "%s/MK_USER", pk_dir_buf) != 0) { + TRACE_ERROR("MK_USER filename buffer overflow\n"); + return CKR_FUNCTION_FAILED; + } if (unlink(fname) && errno == ENOENT) TRACE_WARNING("Failed to remove \"%s\".\n", fname); /* Load master key */ - sprintf(fname, "%s/MK_SO", get_pk_dir(tokdata, pk_dir_buf)); + if (ock_snprintf(fname, PATH_MAX, "%s/MK_SO", pk_dir_buf) != 0) { + TRACE_ERROR("MK_SO filename buffer overflow\n"); + return CKR_FUNCTION_FAILED; + } if (get_masterkey(pin, pin_len, fname, mk, &mk_len)) { TRACE_DEVEL("Failed to load masterkey \"%s\".\n", fname); return CKR_FUNCTION_FAILED; @@ -659,6 +678,9 @@ CK_RV reset_token_data(STDLL_TokData_t * tokdata, CK_SLOT_ID slot_id, load_token_data(tokdata, slot_id); init_slotInfo(&tokdata->slot_info); tokdata->nv_token_data->token_info.flags |= CKF_TOKEN_INITIALIZED; + tokdata->nv_token_data->token_info.flags &= ~(CKF_USER_PIN_INITIALIZED | + CKF_USER_PIN_LOCKED | CKF_USER_PIN_FINAL_TRY | + CKF_USER_PIN_COUNT_LOW); if (slot_data[slot_id]->mech == ICSF_CFG_MECH_SIMPLE) { /* Save master key */ @@ -789,7 +811,14 @@ CK_RV icsftok_init_pin(STDLL_TokData_t * tokdata, SESSION * sess, * racf passwd. */ if (slot_data[sid]->mech == ICSF_CFG_MECH_SIMPLE) { - sprintf(fname, "%s/MK_USER", get_pk_dir(tokdata, pk_dir_buf)); + if (get_pk_dir(tokdata, pk_dir_buf, PATH_MAX) == NULL) { + TRACE_ERROR("pk_dir_buf overflow\n"); + return CKR_FUNCTION_FAILED; + } + if (ock_snprintf(fname, PATH_MAX, "%s/MK_USER", pk_dir_buf) != 0) { + TRACE_ERROR("MK_USER filename buffer overflow\n"); + return CKR_FUNCTION_FAILED; + } rc = secure_masterkey(tokdata->master_key, AES_KEY_SIZE_256, pPin, ulPinLen, fname); @@ -828,7 +857,6 @@ CK_RV icsftok_set_pin(STDLL_TokData_t * tokdata, SESSION * sess, CK_BYTE old_hash_sha[SHA1_HASH_SIZE]; CK_SLOT_ID sid; char fname[PATH_MAX]; - char pk_dir_buf[PATH_MAX]; /* get slot id */ sid = sess->session_info.slotID; @@ -863,7 +891,16 @@ CK_RV icsftok_set_pin(STDLL_TokData_t * tokdata, SESSION * sess, } /* if using simple auth, encrypt masterkey with new pin */ if (slot_data[sid]->mech == ICSF_CFG_MECH_SIMPLE) { - sprintf(fname, "%s/MK_USER", get_pk_dir(tokdata, pk_dir_buf)); + if (get_pk_dir(tokdata, fname, PATH_MAX) == NULL) { + TRACE_ERROR("pk_dir buffer overflow\n"); + return CKR_FUNCTION_FAILED; + } + if (PATH_MAX - strlen(fname) > strlen("/MK_USER")) { + strcat(fname, "/MK_USER"); + } else { + TRACE_ERROR("MK_USER buffer overflow\n"); + return CKR_FUNCTION_FAILED; + } rc = secure_masterkey(tokdata->master_key, AES_KEY_SIZE_256, pNewPin, ulNewLen, fname); if (rc != CKR_OK) { @@ -910,7 +947,17 @@ CK_RV icsftok_set_pin(STDLL_TokData_t * tokdata, SESSION * sess, /* * if using simle auth, encrypt masterkey with new pin */ - sprintf(fname, "%s/MK_SO", get_pk_dir(tokdata, pk_dir_buf)); + if (get_pk_dir(tokdata, fname, PATH_MAX) == NULL) { + TRACE_ERROR("pk_dir buffer overflow\n"); + return CKR_FUNCTION_FAILED; + } + if (PATH_MAX - strlen(fname) > strlen("/MK_SO")) { + strcat(fname, "/MK_SO"); + } else { + TRACE_ERROR("MK_SO buffer overflow\n"); + return CKR_FUNCTION_FAILED; + } + rc = secure_masterkey(tokdata->master_key, AES_KEY_SIZE_256, pNewPin, ulNewLen, fname); if (rc != CKR_OK) { @@ -1224,7 +1271,6 @@ CK_RV icsftok_login(STDLL_TokData_t * tokdata, SESSION * sess, char fname[PATH_MAX]; CK_BYTE hash_sha[SHA1_HASH_SIZE]; int mklen; - char pk_dir_buf[PATH_MAX]; CK_SLOT_ID slot_id = sess->session_info.slotID; /* Check Slot ID */ @@ -1265,7 +1311,16 @@ CK_RV icsftok_login(STDLL_TokData_t * tokdata, SESSION * sess, /* now load the master key */ if (slot_data[slot_id]->mech == ICSF_CFG_MECH_SIMPLE) { - sprintf(fname, "%s/MK_USER", get_pk_dir(tokdata, pk_dir_buf)); + if (get_pk_dir(tokdata, fname, PATH_MAX) == NULL) { + TRACE_ERROR("pk_dir buffer overflow\n"); + return CKR_FUNCTION_FAILED; + } + if (PATH_MAX - strlen(fname) > strlen("/MK_USER")) { + strcat(fname, "/MK_USER"); + } else { + TRACE_ERROR("MK_USER buffer overflow\n"); + return CKR_FUNCTION_FAILED; + } rc = get_masterkey(pPin, ulPinLen, fname, tokdata->master_key, &mklen); if (rc != CKR_OK) { @@ -1286,7 +1341,16 @@ CK_RV icsftok_login(STDLL_TokData_t * tokdata, SESSION * sess, if (slot_data[slot_id]->mech == ICSF_CFG_MECH_SIMPLE) { /* now load the master key */ - sprintf(fname, "%s/MK_SO", get_pk_dir(tokdata, pk_dir_buf)); + if (get_pk_dir(tokdata, fname, PATH_MAX) == NULL) { + TRACE_ERROR("pk_dir buffer overflow\n"); + return CKR_FUNCTION_FAILED; + } + if (PATH_MAX - strlen(fname) > strlen("/MK_SO")) { + strcat(fname, "/MK_SO"); + } else { + TRACE_ERROR("MK_SO buffer overflow\n"); + return CKR_FUNCTION_FAILED; + } rc = get_masterkey(pPin, ulPinLen, fname, tokdata->master_key, &mklen); if (rc != CKR_OK) { diff --git a/usr/lib/icsf_stdll/icsf_stdll.mk b/usr/lib/icsf_stdll/icsf_stdll.mk index 44a7ab1..788478c 100644 --- a/usr/lib/icsf_stdll/icsf_stdll.mk +++ b/usr/lib/icsf_stdll/icsf_stdll.mk @@ -43,10 +43,12 @@ opencryptoki_stdll_libpkcs11_icsf_la_SOURCES = \ 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 + if ENABLE_LOCKS opencryptoki_stdll_libpkcs11_icsf_la_SOURCES += \ usr/lib/common/lock_btree.c usr/lib/common/lock_sess_mgr.c diff --git a/usr/lib/icsf_stdll/new_host.c b/usr/lib/icsf_stdll/new_host.c index f8e518f..82eb844 100644 --- a/usr/lib/icsf_stdll/new_host.c +++ b/usr/lib/icsf_stdll/new_host.c @@ -104,13 +104,24 @@ CK_RV ST_Initialize(API_Slot_t *sltp, CK_SLOT_ID SlotNumber, bt_init(&sltp->TokData->publ_token_obj_btree, call_object_free); if (strlen(sinfp->tokname)) { - sprintf(abs_tokdir_name, "%s/%s", CONFIG_PATH, sinfp->tokname); - TRACE_DEVEL("Token directory: %s\n", abs_tokdir_name); - init_data_store(sltp->TokData, (char *) abs_tokdir_name, - sltp->TokData->data_store); + if (ock_snprintf(abs_tokdir_name, PATH_MAX, "%s/%s", + CONFIG_PATH, sinfp->tokname) != 0) { + TRACE_ERROR("abs_tokdir_name buffer overflow\n"); + rc = CKR_FUNCTION_FAILED; + } else { + TRACE_DEVEL("Token directory: %s\n", abs_tokdir_name); + rc = init_data_store(sltp->TokData, (char *) abs_tokdir_name, + sltp->TokData->data_store, + sizeof(sltp->TokData->data_store)); + } } else { - init_data_store(sltp->TokData, (char *) PK_DIR, - sltp->TokData->data_store); + rc = init_data_store(sltp->TokData, (char *) PK_DIR, + sltp->TokData->data_store, + sizeof(sltp->TokData->data_store)); + } + if (rc != CKR_OK) { + TRACE_ERROR("init_data_store failed with buffer error.\n"); + goto done; } sltp->TokData->version = sinfp->version; @@ -854,6 +865,12 @@ CK_RV SC_Login(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession, goto done; } + if (!(*flags & CKF_USER_PIN_INITIALIZED)) { + TRACE_ERROR("%s\n", ock_err(ERR_USER_PIN_NOT_INITIALIZED)); + rc = CKR_USER_PIN_NOT_INITIALIZED; + goto done; + } + rc = icsftok_login(tokdata, sess, userType, pPin, ulPinLen); if (rc == CKR_OK) { *flags &= ~(CKF_USER_PIN_LOCKED | @@ -2231,8 +2248,10 @@ CK_RV SC_Sign(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession, TRACE_DEVEL("icsftok_sign() failed.\n"); done: - if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || pSignature)) - sign_mgr_cleanup(&sess->sign_ctx); + if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || pSignature)) { + if (sess != NULL) + sign_mgr_cleanup(&sess->sign_ctx); + } TRACE_INFO("C_Sign: rc = 0x%08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulDataLen); @@ -2281,7 +2300,7 @@ CK_RV SC_SignUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession, if (rc != CKR_OK) TRACE_DEVEL("icsftok_sign_update() failed.\n"); done: - if (rc != CKR_OK) + if (rc != CKR_OK && sess != NULL) sign_mgr_cleanup(&sess->sign_ctx); TRACE_INFO("C_SignUpdate: rc = 0x%08lx, sess = %ld, datalen = %lu\n", @@ -2332,8 +2351,10 @@ CK_RV SC_SignFinal(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession, TRACE_ERROR("icsftok_sign_final() failed.\n"); done: - if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || pSignature)) - sign_mgr_cleanup(&sess->sign_ctx); + if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || pSignature)) { + if (sess != NULL) + sign_mgr_cleanup(&sess->sign_ctx); + } TRACE_INFO("C_SignFinal: rc = 0x%08lx, sess = %ld\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle); @@ -2484,7 +2505,8 @@ CK_RV SC_Verify(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession, TRACE_DEVEL("icsftok_verify() failed.\n"); done: - verify_mgr_cleanup(&sess->verify_ctx); + if (sess != NULL) + verify_mgr_cleanup(&sess->verify_ctx); TRACE_INFO("C_Verify: rc = 0x%08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulDataLen); @@ -2534,7 +2556,7 @@ CK_RV SC_VerifyUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession, TRACE_DEVEL("icsftok_verify_update() failed.\n"); done: - if (rc != CKR_OK) + if (rc != CKR_OK && sess != NULL) verify_mgr_cleanup(&sess->verify_ctx); TRACE_INFO("C_VerifyUpdate: rc = 0x%08lx, sess = %ld, datalen = %lu\n", @@ -2585,7 +2607,8 @@ CK_RV SC_VerifyFinal(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession, TRACE_DEVEL("icsftok_verify_final() failed.\n"); done: - verify_mgr_cleanup(&sess->verify_ctx); + if (sess != NULL) + verify_mgr_cleanup(&sess->verify_ctx); TRACE_INFO("C_VerifyFinal: rc = 0x%08lx, sess = %ld\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle); @@ -3244,6 +3267,77 @@ CK_RV SC_CancelFunction(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession) return CKR_FUNCTION_NOT_PARALLEL; } +CK_RV SC_IBM_ReencryptSingle(STDLL_TokData_t *tokdata, ST_SESSION_T *sSession, + CK_MECHANISM_PTR pDecrMech, + CK_OBJECT_HANDLE hDecrKey, + CK_MECHANISM_PTR pEncrMech, + CK_OBJECT_HANDLE hEncrKey, + CK_BYTE_PTR pEncryptedData, + CK_ULONG ulEncryptedDataLen, + CK_BYTE_PTR pReencryptedData, + CK_ULONG_PTR pulReencryptedDataLen) +{ + SESSION *sess = NULL; + CK_RV rc = CKR_OK; + + if (tokdata->initialized == FALSE) { + TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); + rc = CKR_CRYPTOKI_NOT_INITIALIZED; + goto done; + } + + if (!pDecrMech || !pEncrMech) { + TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); + rc = CKR_ARGUMENTS_BAD; + goto done; + } + + sess = session_mgr_find(tokdata, sSession->sessionh); + if (!sess) { + TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); + rc = CKR_SESSION_HANDLE_INVALID; + goto done; + } + + rc = valid_mech(tokdata, pDecrMech, CKF_DECRYPT); + if (rc != CKR_OK) + goto done; + rc = valid_mech(tokdata, pEncrMech, CKF_ENCRYPT); + if (rc != CKR_OK) + goto done; + + if (pin_expired(&sess->session_info, + tokdata->nv_token_data->token_info.flags) == TRUE) { + TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); + rc = CKR_PIN_EXPIRED; + goto done; + } + + if (sess->decr_ctx.active == TRUE || sess->encr_ctx.active == TRUE) { + rc = CKR_OPERATION_ACTIVE; + TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); + goto done; + } + + rc = encr_mgr_reencrypt_single(tokdata, sess, &sess->decr_ctx, pDecrMech, + hDecrKey, &sess->encr_ctx, pEncrMech, + hEncrKey, pEncryptedData, ulEncryptedDataLen, + pReencryptedData, pulReencryptedDataLen); + if (rc != CKR_OK) + TRACE_DEVEL("encr_mgr_reencrypt_single() failed.\n"); + +done: + TRACE_INFO("SC_IBM_ReencryptSingle: rc = 0x%08lx, sess = %ld, " + "decrmech = 0x%lx, encrmech = 0x%lx\n", + rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, + (pDecrMech ? pDecrMech->mechanism : (CK_ULONG)-1), + (pEncrMech ? pEncrMech->mechanism : (CK_ULONG)-1)); + + if (sess != NULL) + session_mgr_put(tokdata, sess); + + return rc; +} void SC_SetFunctionList(void) { @@ -3308,4 +3402,6 @@ void SC_SetFunctionList(void) function_list.ST_GenerateRandom = SC_GenerateRandom; function_list.ST_GetFunctionStatus = NULL; // SC_GetFunctionStatus; function_list.ST_CancelFunction = NULL; // SC_CancelFunction; + + function_list.ST_IBM_ReencryptSingle = SC_IBM_ReencryptSingle; } diff --git a/usr/lib/icsf_stdll/tok_struct.h b/usr/lib/icsf_stdll/tok_struct.h index af76845..5fa5e3f 100644 --- a/usr/lib/icsf_stdll/tok_struct.h +++ b/usr/lib/icsf_stdll/tok_struct.h @@ -32,8 +32,7 @@ token_spec_t token_specific = { ICSF_CONFIG_PATH, "icsf", - // Key token size (0 is default) - 0, + FALSE, // Token data info: { FALSE, // Don't use per guest data store @@ -124,7 +123,10 @@ token_spec_t token_specific = { NULL, // dsa_verify NULL, // get_mechanism_list NULL, // get_mechanism_info - NULL // object_add + NULL, // object_add + NULL, // key_wrap + NULL, // key_unwrap + NULL, // reencrypt_single }; #endif diff --git a/usr/lib/soft_stdll/soft_specific.c b/usr/lib/soft_stdll/soft_specific.c index f7cafab..25a97e2 100644 --- a/usr/lib/soft_stdll/soft_specific.c +++ b/usr/lib/soft_stdll/soft_specific.c @@ -24,6 +24,12 @@ #include #include +#include + +#if OPENSSL_VERSION_NUMBER < 0x10101000L +#define NO_EC 1 +#endif + #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" @@ -47,6 +53,7 @@ #include #include #include +#include /* * In order to make opencryptoki compatible with @@ -120,6 +127,8 @@ static const MECH_LIST_ELEMENT soft_mech_list[] = { {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_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}}, {CKM_DES3_CMAC_GENERAL, {16, 24, CKF_SIGN | CKF_VERIFY}}, #if !(NOSHA1) @@ -139,8 +148,32 @@ static const MECH_LIST_ELEMENT soft_mech_list[] = { {CKM_SHA512, {0, 0, CKF_DIGEST}}, {CKM_SHA512_HMAC, {0, 0, CKF_SIGN | CKF_VERIFY}}, {CKM_SHA512_HMAC_GENERAL, {0, 0, CKF_SIGN | CKF_VERIFY}}, +#ifdef NID_sha512_224WithRSAEncryption {CKM_SHA512_224, {0, 0, CKF_DIGEST}}, + {CKM_SHA512_224_HMAC, {0, 0, CKF_SIGN | CKF_VERIFY}}, + {CKM_SHA512_224_HMAC_GENERAL, {0, 0, CKF_SIGN | CKF_VERIFY}}, +#endif +#ifdef NID_sha512_256WithRSAEncryption {CKM_SHA512_256, {0, 0, CKF_DIGEST}}, + {CKM_SHA512_256_HMAC, {0, 0, CKF_SIGN | CKF_VERIFY}}, + {CKM_SHA512_256_HMAC_GENERAL, {0, 0, CKF_SIGN | CKF_VERIFY}}, +#endif +#ifdef NID_sha3_224 + {CKM_IBM_SHA3_224, {0, 0, CKF_DIGEST}}, + {CKM_IBM_SHA3_224_HMAC, {0, 0, CKF_SIGN | CKF_VERIFY}}, +#endif +#ifdef NID_sha3_256 + {CKM_IBM_SHA3_256, {0, 0, CKF_DIGEST}}, + {CKM_IBM_SHA3_256_HMAC, {0, 0, CKF_SIGN | CKF_VERIFY}}, +#endif +#ifdef NID_sha3_384 + {CKM_IBM_SHA3_384, {0, 0, CKF_DIGEST}}, + {CKM_IBM_SHA3_384_HMAC, {0, 0, CKF_SIGN | CKF_VERIFY}}, +#endif +#ifdef NID_sha3_512 + {CKM_IBM_SHA3_512, {0, 0, CKF_DIGEST}}, + {CKM_IBM_SHA3_512_HMAC, {0, 0, CKF_SIGN | CKF_VERIFY}}, +#endif #if !(NOMD2) {CKM_MD2, {0, 0, CKF_DIGEST}}, {CKM_MD2_HMAC, {0, 0, CKF_SIGN | CKF_VERIFY}}, @@ -162,10 +195,29 @@ static const MECH_LIST_ELEMENT soft_mech_list[] = { {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_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}}, {CKM_AES_CMAC_GENERAL, {16, 32, CKF_SIGN | CKF_VERIFY}}, #endif - {CKM_GENERIC_SECRET_KEY_GEN, {80, 2048, CKF_GENERATE}} + {CKM_GENERIC_SECRET_KEY_GEN, {80, 2048, CKF_GENERATE}}, +#if !(NO_EC) + {CKM_EC_KEY_PAIR_GEN, {160, 521, CKF_GENERATE_KEY_PAIR | + CKF_EC_NAMEDCURVE | CKF_EC_F_P}}, + {CKM_ECDSA, {160, 521, CKF_SIGN | CKF_VERIFY | CKF_EC_NAMEDCURVE | + CKF_EC_F_P}}, + {CKM_ECDSA_SHA1, {160, 521, CKF_SIGN | CKF_VERIFY | CKF_EC_NAMEDCURVE | + CKF_EC_F_P}}, + {CKM_ECDSA_SHA224, {160, 521, CKF_SIGN | CKF_VERIFY | CKF_EC_NAMEDCURVE | + CKF_EC_F_P}}, + {CKM_ECDSA_SHA256, {160, 521, CKF_SIGN | CKF_VERIFY | CKF_EC_NAMEDCURVE | + CKF_EC_F_P}}, + {CKM_ECDSA_SHA384, {160, 521, CKF_SIGN | CKF_VERIFY | CKF_EC_NAMEDCURVE | + CKF_EC_F_P}}, + {CKM_ECDSA_SHA512, {160, 521, CKF_SIGN | CKF_VERIFY | CKF_EC_NAMEDCURVE | + CKF_EC_F_P}}, + {CKM_ECDH1_DERIVE, {160, 521, CKF_DERIVE | CKF_EC_NAMEDCURVE | CKF_EC_F_P}}, +#endif }; static const CK_ULONG soft_mech_list_len = @@ -195,20 +247,25 @@ CK_RV token_specific_final(STDLL_TokData_t *tokdata, return CKR_OK; } -CK_RV token_specific_des_key_gen(STDLL_TokData_t *tokdata, CK_BYTE *des_key, - CK_ULONG len, CK_ULONG keysize) +CK_RV token_specific_des_key_gen(STDLL_TokData_t *tokdata, CK_BYTE **des_key, + CK_ULONG *len, CK_ULONG keysize, + CK_BBOOL *is_opaque) { - UNUSED(keysize); + *des_key = malloc(keysize); + if (*des_key == NULL) + return CKR_HOST_MEMORY; + *len = keysize; + *is_opaque = FALSE; // Nothing different to do for DES or TDES here as this is just // random data... Validation handles the rest - // Only check for weak keys when single DES. - if (len == (3 * DES_KEY_SIZE)) { - rng_generate(tokdata, des_key, len); + // Only check for weak keys when DES. + if (keysize == (3 * DES_KEY_SIZE)) { + rng_generate(tokdata, *des_key, keysize); } else { do { - rng_generate(tokdata, des_key, len); - } while (des_check_weak_key(des_key) == TRUE); + rng_generate(tokdata, *des_key, keysize);; + } while (des_check_weak_key(*des_key) == TRUE); } // we really need to validate the key for parity etc... @@ -224,6 +281,7 @@ CK_RV token_specific_des_ecb(STDLL_TokData_t *tokdata, CK_ULONG *out_data_len, OBJECT *key, CK_BYTE encrypt) { +#if OPENSSL_VERSION_NUMBER < 0x10100000L CK_ULONG rc; DES_key_schedule des_key2; const_DES_cblock key_val_SSL, in_key_data; @@ -244,7 +302,7 @@ CK_RV token_specific_des_ecb(STDLL_TokData_t *tokdata, // the des decrypt will only fail if the data length is not evenly divisible // by 8 - if (in_data_len % 8) { + if (in_data_len % DES_BLOCK_SIZE) { TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } @@ -273,6 +331,53 @@ CK_RV token_specific_des_ecb(STDLL_TokData_t *tokdata, } 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 + if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { + TRACE_ERROR("template_attribute_find(CKA_VALUE) failed.\n"); + return CKR_FUNCTION_FAILED; + } + + 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 = ERR_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 = ERR_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_RV token_specific_des_cbc(STDLL_TokData_t *tokdata, @@ -282,6 +387,7 @@ CK_RV token_specific_des_cbc(STDLL_TokData_t *tokdata, CK_ULONG *out_data_len, OBJECT *key, CK_BYTE *init_v, CK_BYTE encrypt) { +#if OPENSSL_VERSION_NUMBER < 0x10100000L CK_ULONG rc; CK_ATTRIBUTE *attr = NULL; DES_cblock ivec; @@ -302,7 +408,7 @@ CK_RV token_specific_des_cbc(STDLL_TokData_t *tokdata, 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 % 8) { + if (in_data_len % DES_BLOCK_SIZE) { TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } @@ -320,6 +426,53 @@ CK_RV token_specific_des_cbc(STDLL_TokData_t *tokdata, } 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 + if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { + TRACE_ERROR("template_attribute_find(CKA_VALUE) failed.\n"); + return CKR_FUNCTION_FAILED; + } + + 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 = ERR_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 = ERR_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_RV token_specific_tdes_ecb(STDLL_TokData_t *tokdata, @@ -329,6 +482,7 @@ CK_RV token_specific_tdes_ecb(STDLL_TokData_t *tokdata, 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]; @@ -373,7 +527,7 @@ CK_RV token_specific_tdes_ecb(STDLL_TokData_t *tokdata, // the des decrypt will only fail if the data length is not evenly divisible // by 8 - if (in_data_len % 8) { + if (in_data_len % DES_BLOCK_SIZE) { TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } @@ -401,6 +555,67 @@ CK_RV token_specific_tdes_ecb(STDLL_TokData_t *tokdata, } 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_find(key->template, CKA_KEY_TYPE, &attr); + if (rc == FALSE) { + TRACE_ERROR("template_attribute_find(CKA_KEY_TYPE) failed.\n"); + return CKR_FUNCTION_FAILED; + } + keytype = *(CK_KEY_TYPE *)attr->pValue; + + // get the key value + if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { + TRACE_ERROR("template_attribute_find(CKA_VALUE) failed.\n"); + return CKR_FUNCTION_FAILED; + } + + 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 = ERR_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 = ERR_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_RV token_specific_tdes_cbc(STDLL_TokData_t *tokdata, @@ -410,6 +625,7 @@ CK_RV token_specific_tdes_cbc(STDLL_TokData_t *tokdata, 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]; @@ -455,7 +671,7 @@ CK_RV token_specific_tdes_cbc(STDLL_TokData_t *tokdata, // the des decrypt will only fail if the data length is not evenly divisible // by 8 - if (in_data_len % 8) { + if (in_data_len % DES_BLOCK_SIZE) { TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } @@ -480,6 +696,91 @@ CK_RV token_specific_tdes_cbc(STDLL_TokData_t *tokdata, } 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_ULONG rc; + int outlen; + + UNUSED(tokdata); + + // get the key type + rc = template_attribute_find(key->template, CKA_KEY_TYPE, &attr); + if (rc == FALSE) { + TRACE_ERROR("template_attribute_find(CKA_KEY_TYPE) failed.\n"); + return CKR_FUNCTION_FAILED; + } + keytype = *(CK_KEY_TYPE *)attr->pValue; + + // get the key value + if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { + TRACE_ERROR("template_attribute_find(CKA_VALUE) failed.\n"); + return CKR_FUNCTION_FAILED; + } + + 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 = ERR_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 = ERR_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_RV token_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 = 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; } // convert from the local PKCS11 template representation to @@ -589,6 +890,12 @@ static void *rsa_convert_private_key(OBJECT *key_obj) 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); @@ -599,6 +906,7 @@ static void *rsa_convert_private_key(OBJECT *key_obj) 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 } @@ -700,9 +1008,13 @@ static CK_RV os_specific_rsa_keygen(TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl) CK_RV rc; CK_ULONG BNLength; RSA *rsa = NULL; - const BIGNUM *bignum; + 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 flag = template_attribute_find(publ_tmpl, CKA_MODULUS_BITS, &attr); if (!flag) { @@ -729,28 +1041,59 @@ static CK_RV os_specific_rsa_keygen(TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl) } e = BN_new(); - rsa = RSA_new(); - - if (e == NULL || rsa == NULL) { + 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; } - - // Now fill in the objects.. - // - // modulus: n - // -#ifdef OLDER_OPENSSL 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); @@ -1001,13 +1344,25 @@ static CK_RV os_specific_rsa_keygen(TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl) template_update_attribute(priv_tmpl, attr); done: +#ifdef OLDER_OPENSSL if (e != NULL) BN_free(e); if (rsa != NULL) RSA_free(rsa); - if (ssl_ptr != NULL) + 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; } @@ -1031,6 +1386,7 @@ 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; @@ -1057,46 +1413,171 @@ done: RSA_free(rsa); return rc; -} - -static CK_RV os_specific_rsa_decrypt(CK_BYTE *in_data, - CK_ULONG in_data_len, - CK_BYTE *out_data, OBJECT *key_obj) -{ +#else + EVP_PKEY_CTX *ctx = NULL; + EVP_PKEY *pkey = NULL; + RSA *rsa = NULL; CK_RV rc; - RSA *rsa; - int size; + size_t outlen = in_data_len; - // Convert the local key representation to an RSA key representaion - rsa = (RSA *) rsa_convert_private_key(key_obj); + 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 the private decryption - size = - RSA_private_decrypt(in_data_len, in_data, out_data, rsa, - RSA_NO_PADDING); - if (size == -1) { + 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 */ - rc = CKR_OK; - -done: - RSA_free(rsa); - - 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; + } -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) -{ + 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 +} + +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]; @@ -1798,12 +2279,17 @@ error: #ifndef NOAES -CK_RV token_specific_aes_key_gen(STDLL_TokData_t *tokdata, CK_BYTE *key, - CK_ULONG len, CK_ULONG keysize) +CK_RV token_specific_aes_key_gen(STDLL_TokData_t *tokdata, CK_BYTE **key, + CK_ULONG *len, CK_ULONG keysize, + CK_BBOOL *is_opaque) { - UNUSED(keysize); + *key = malloc(keysize); + if (*key == NULL) + return CKR_HOST_MEMORY; + *len = keysize; + *is_opaque = FALSE; - return rng_generate(tokdata, key, len); + return rng_generate(tokdata, *key, keysize); } CK_RV token_specific_aes_ecb(STDLL_TokData_t *tokdata, @@ -1813,6 +2299,7 @@ CK_RV token_specific_aes_ecb(STDLL_TokData_t *tokdata, 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; @@ -1851,6 +2338,63 @@ CK_RV token_specific_aes_ecb(STDLL_TokData_t *tokdata, *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 + if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { + TRACE_ERROR("template_attribute_find(CKA_VALUE) failed.\n"); + return CKR_FUNCTION_FAILED; + } + + 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 = ERR_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 = ERR_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_RV token_specific_aes_cbc(STDLL_TokData_t *tokdata, @@ -1860,6 +2404,7 @@ CK_RV token_specific_aes_cbc(STDLL_TokData_t *tokdata, 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; @@ -1888,6 +2433,87 @@ CK_RV token_specific_aes_cbc(STDLL_TokData_t *tokdata, *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 + if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { + TRACE_ERROR("template_attribute_find(CKA_VALUE) failed.\n"); + return CKR_FUNCTION_FAILED; + } + + 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; + } + + ctx = EVP_CIPHER_CTX_new(); + if (ctx == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + rc = ERR_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 = ERR_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_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); + + free(out_buf); + + return rc; } #endif @@ -1976,6 +2602,7 @@ CK_RV token_specific_dh_pkcs_key_pair_gen(STDLL_TokData_t *tokdata, TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl) { +#if OPENSSL_VERSION_NUMBER < 0x10100000L CK_BBOOL rc; CK_ATTRIBUTE *prime_attr = NULL; CK_ATTRIBUTE *base_attr = NULL; @@ -2023,16 +2650,13 @@ CK_RV token_specific_dh_pkcs_key_pair_gen(STDLL_TokData_t *tokdata, BN_bin2bn((unsigned char *) prime_attr->pValue, prime_attr->ulValueLen, bn_p); BN_bin2bn((unsigned char *) base_attr->pValue, base_attr->ulValueLen, bn_g); -#ifdef OLDER_OPENSSL dh->p = bn_p; dh->g = bn_g; -#else - DH_set0_pqg(dh, bn_p, NULL, bn_g); -#endif // 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, @@ -2042,11 +2666,7 @@ CK_RV token_specific_dh_pkcs_key_pair_gen(STDLL_TokData_t *tokdata, // pub_key // //temp_bn = BN_new(); -#ifdef OLDER_OPENSSL temp_bn = dh->pub_key; -#else - DH_get0_key(dh, &temp_bn, NULL); -#endif temp_bn_len = BN_num_bytes(temp_bn); temp_byte = malloc(temp_bn_len); temp_bn_len = BN_bn2bin(temp_bn, temp_byte); @@ -2054,6 +2674,8 @@ CK_RV token_specific_dh_pkcs_key_pair_gen(STDLL_TokData_t *tokdata, 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; } template_update_attribute(publ_tmpl, temp_attr); @@ -2063,11 +2685,7 @@ CK_RV token_specific_dh_pkcs_key_pair_gen(STDLL_TokData_t *tokdata, // priv_key // //temp_bn = BN_new(); -#ifdef OLDER_OPENSSL temp_bn = dh->priv_key; -#else - DH_get0_key(dh, NULL, &temp_bn); -#endif temp_bn_len = BN_num_bytes(temp_bn); temp_byte = malloc(temp_bn_len); temp_bn_len = BN_bn2bin(temp_bn, temp_byte); @@ -2075,6 +2693,8 @@ CK_RV token_specific_dh_pkcs_key_pair_gen(STDLL_TokData_t *tokdata, 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; } template_update_attribute(priv_tmpl, temp_attr); @@ -2096,6 +2716,7 @@ CK_RV token_specific_dh_pkcs_key_pair_gen(STDLL_TokData_t *tokdata, prime_attr->ulValueLen, &temp_attr); // in bytes if (rc != CKR_OK) { TRACE_DEVEL("build_attribute failed\n"); + DH_free(dh); return CKR_FUNCTION_FAILED; } template_update_attribute(priv_tmpl, temp_attr); @@ -2105,6 +2726,7 @@ CK_RV token_specific_dh_pkcs_key_pair_gen(STDLL_TokData_t *tokdata, base_attr->ulValueLen, &temp_attr); // in bytes if (rc != CKR_OK) { TRACE_DEVEL("build_attribute failed\n"); + DH_free(dh); return CKR_FUNCTION_FAILED; } template_update_attribute(priv_tmpl, temp_attr); @@ -2113,121 +2735,276 @@ CK_RV token_specific_dh_pkcs_key_pair_gen(STDLL_TokData_t *tokdata, DH_free(dh); return CKR_OK; -} /* end token_specific_dh_key_pair_gen() */ -#endif -/* End code contributed by Corrent corp. */ - -CK_RV token_specific_get_mechanism_list(STDLL_TokData_t *tokdata, - CK_MECHANISM_TYPE_PTR pMechanismList, - CK_ULONG_PTR pulCount) -{ - return ock_generic_get_mechanism_list(tokdata, pMechanismList, pulCount); -} - -CK_RV token_specific_get_mechanism_info(STDLL_TokData_t *tokdata, - CK_MECHANISM_TYPE type, - CK_MECHANISM_INFO_PTR pInfo) -{ - return ock_generic_get_mechanism_info(tokdata, type, pInfo); -} - -CK_RV token_specific_sha_init(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx, - CK_MECHANISM *mech) -{ - int rc; - CK_ULONG len; +#else + 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 = NULL, *temp_byte2 = NULL; + CK_ULONG temp_bn_len; + DH *dh = NULL; + BIGNUM *bn_p = NULL; + BIGNUM *bn_g = NULL; + const BIGNUM *temp_bn = NULL; + EVP_PKEY *params = NULL, *pkey = NULL; + EVP_PKEY_CTX *ctx = NULL; UNUSED(tokdata); - switch (mech->mechanism) { - case CKM_SHA_1: - len = sizeof(SHA_CTX); - break; - case CKM_SHA224: - len = sizeof(SHA256_CTX); - break; - case CKM_SHA256: - len = sizeof(SHA256_CTX); - break; - case CKM_SHA384: - len = sizeof(SHA512_CTX); - break; - case CKM_SHA512: - case CKM_SHA512_224: - case CKM_SHA512_256: - len = sizeof(SHA512_CTX); - break; - default: - return CKR_MECHANISM_INVALID; + rc = template_attribute_find(publ_tmpl, CKA_PRIME, &prime_attr); + rc &= template_attribute_find(publ_tmpl, CKA_BASE, &base_attr); + + if (rc == FALSE) { + TRACE_ERROR("Could not find CKA_PRIME or CKA_BASE for the key\n"); + rv = CKR_FUNCTION_FAILED; + goto done; } - ctx->context_len = len; - ctx->context = (CK_BYTE *) malloc(len); - if (ctx->context == NULL) { - TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); - return CKR_HOST_MEMORY; + if ((prime_attr->ulValueLen > 256) || (prime_attr->ulValueLen < 64)) { + TRACE_ERROR("CKA_PRIME attribute value is invalid.\n"); + rv = CKR_ATTRIBUTE_VALUE_INVALID; + goto done; } - switch (mech->mechanism) { - case CKM_SHA_1: - rc = SHA1_Init((SHA_CTX *)ctx->context); + 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 + bn_p = BN_new(); + bn_g = BN_new(); + if (bn_g == NULL || bn_p == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + rv = CKR_HOST_MEMORY; + goto done; + } + // 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_set0_pqg(dh, bn_p, NULL, bn_g); + /* bn_p and bn_q freed together with dh */ + bn_p = NULL; + bn_g = NULL; + + params = EVP_PKEY_new(); + if (params == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + rv = CKR_HOST_MEMORY; + goto done; + } + + if (EVP_PKEY_assign_DH(params, dh) != 1) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rv = CKR_FUNCTION_FAILED; + goto done; + } + dh = NULL; /* freed together with params */ + + ctx = EVP_PKEY_CTX_new(params, NULL); + if (ctx == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + rv = CKR_HOST_MEMORY; + goto done; + } + + if (EVP_PKEY_keygen_init(ctx) != 1 + || EVP_PKEY_keygen(ctx, &pkey) != 1 + /* dh is freed together with pkey */ + || (dh = EVP_PKEY_get0_DH(pkey)) == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); + rv = CKR_FUNCTION_FAILED; + goto done; + } + + // Extract the public and private key components from the DH struct, + // and insert them in the publ_tmpl and priv_tmpl + + // + // pub_key + // + DH_get0_key(dh, &temp_bn, NULL); + + 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"); + rv = CKR_FUNCTION_FAILED; + goto done; + } + template_update_attribute(publ_tmpl, temp_attr); + + // + // priv_key + // + DH_get0_key(dh, NULL, &temp_bn); + temp_bn_len = BN_num_bytes(temp_bn); + temp_byte2 = malloc(temp_bn_len); + temp_bn_len = BN_bn2bin(temp_bn, temp_byte2); + // in bytes + rc = build_attribute(CKA_VALUE, temp_byte2, temp_bn_len, &temp_attr); + OPENSSL_cleanse(temp_byte2, temp_bn_len); + if (rc != CKR_OK) { + TRACE_DEVEL("build_attribute failed\n"); + rv = CKR_FUNCTION_FAILED; + goto done; + } + template_update_attribute(priv_tmpl, temp_attr); + + // 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("%s\n", ock_err(ERR_HOST_MEMORY)); + rv = CKR_HOST_MEMORY; + goto done; + } + 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; + template_update_attribute(priv_tmpl, value_bits_attr); + + // 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"); + rv = CKR_FUNCTION_FAILED; + goto done; + } + template_update_attribute(priv_tmpl, temp_attr); + + 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"); + rv = CKR_FUNCTION_FAILED; + goto done; + } + template_update_attribute(priv_tmpl, temp_attr); + + rv = CKR_OK; +done: + if (bn_g != NULL) + BN_free(bn_g); + if (bn_p != NULL) + BN_free(bn_p); + if (pkey != NULL) + EVP_PKEY_free(pkey); + if (ctx != NULL) + EVP_PKEY_CTX_free(ctx); + free(temp_byte); + free(temp_byte2); + return rv; +#endif +} /* end token_specific_dh_key_pair_gen() */ +#endif +/* End code contributed by Corrent corp. */ + +CK_RV token_specific_get_mechanism_list(STDLL_TokData_t *tokdata, + CK_MECHANISM_TYPE_PTR pMechanismList, + CK_ULONG_PTR pulCount) +{ + return ock_generic_get_mechanism_list(tokdata, pMechanismList, pulCount); +} + +CK_RV token_specific_get_mechanism_info(STDLL_TokData_t *tokdata, + CK_MECHANISM_TYPE type, + CK_MECHANISM_INFO_PTR pInfo) +{ + return ock_generic_get_mechanism_info(tokdata, type, pInfo); +} + +CK_RV token_specific_sha_init(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx, + CK_MECHANISM *mech) +{ + const EVP_MD *md = NULL; + + UNUSED(tokdata); + + ctx->context_len = 1; /* Dummy length, size of EVP_MD_CTX is unknown */ +#if OPENSSL_VERSION_NUMBER < 0x10101000L + ctx->context = (CK_BYTE *)EVP_MD_CTX_create(); +#else + ctx->context = (CK_BYTE *)EVP_MD_CTX_new(); +#endif + if (ctx->context == NULL) { + TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); + return CKR_HOST_MEMORY; + } + + switch (mech->mechanism) { + case CKM_SHA_1: + md = EVP_sha1(); break; case CKM_SHA224: - rc = SHA224_Init((SHA256_CTX *)ctx->context); + md = EVP_sha224(); break; case CKM_SHA256: - rc = SHA256_Init((SHA256_CTX *)ctx->context); + md = EVP_sha256(); break; case CKM_SHA384: - rc = SHA384_Init((SHA512_CTX *)ctx->context); + 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: - rc = SHA512_Init((SHA512_CTX *)ctx->context); + 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; - default: /* cannot happen */ - rc = CKR_MECHANISM_INVALID; } - if (!rc) { - free(ctx->context); + if (md == NULL || + !EVP_DigestInit_ex((EVP_MD_CTX *)ctx->context, md, NULL)) { +#if OPENSSL_VERSION_NUMBER < 0x10101000L + EVP_MD_CTX_destroy((EVP_MD_CTX *)ctx->context); +#else + EVP_MD_CTX_free((EVP_MD_CTX *)ctx->context); +#endif ctx->context = NULL; ctx->context_len = 0; - return CKR_FUNCTION_FAILED; - } - switch (mech->mechanism) { - case CKM_SHA512_224: - { - SHA512_CTX *c = (SHA512_CTX *)ctx->context; - - /* SHA-512/224 uses a distinct initial hash value */ - c->h[0] = 0x8c3d37c819544da2ULL; - c->h[1] = 0x73e1996689dcd4d6ULL; - c->h[2] = 0x1dfab7ae32ff9c82ULL; - c->h[3] = 0x679dd514582f9fcfULL; - c->h[4] = 0x0f6d2b697bd44da8ULL; - c->h[5] = 0x77e36f7304c48942ULL; - c->h[6] = 0x3f9d85a86a1d36c8ULL; - c->h[7] = 0x1112e6ad91d692a1ULL; - break; - } - case CKM_SHA512_256: - { - SHA512_CTX *c = (SHA512_CTX *)ctx->context; - - /* SHA-512/256 uses a distinct initial hash value */ - c->h[0] = 0x22312194fc2bf72cULL; - c->h[1] = 0x9f555fa3c84c64c2ULL; - c->h[2] = 0x2393b86b6f53b151ULL; - c->h[3] = 0x963877195940eabdULL; - c->h[4] = 0x96283ee2a88effe3ULL; - c->h[5] = 0xbe5e1e2553863992ULL; - c->h[6] = 0x2b0199fc2c85b8aaULL; - c->h[7] = 0x0eb72ddc81c52ca2ULL; - break; - } + return CKR_FUNCTION_FAILED; } return CKR_OK; @@ -2237,9 +3014,8 @@ 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 hlen; - CK_BYTE temp_out_data[MAX_SHA_HASH_SIZE]; - CK_BYTE *orig_out_data = out_data; + unsigned int len; + CK_RV rc = CKR_OK; UNUSED(tokdata); @@ -2249,90 +3025,32 @@ CK_RV token_specific_sha(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx, if (!in_data || !out_data) return CKR_ARGUMENTS_BAD; - switch (ctx->mech.mechanism) { - case CKM_SHA_1: - hlen = SHA1_HASH_SIZE; - break; - case CKM_SHA224: - hlen = SHA224_HASH_SIZE; - break; - case CKM_SHA256: - hlen = SHA256_HASH_SIZE; - break; - case CKM_SHA384: - hlen = SHA384_HASH_SIZE; - break; - case CKM_SHA512: - hlen = SHA512_HASH_SIZE; - break; - case CKM_SHA512_224: - hlen = SHA224_HASH_SIZE; - break; - case CKM_SHA512_256: - hlen = SHA256_HASH_SIZE; - break; - default: - return CKR_MECHANISM_INVALID; - } - - if (*out_data_len < hlen) + if (*out_data_len < (CK_ULONG)EVP_MD_CTX_size((EVP_MD_CTX *)ctx->context)) return CKR_BUFFER_TOO_SMALL; - switch (ctx->mech.mechanism) { - case CKM_SHA_1: - if (!SHA1_Update((SHA_CTX *)ctx->context, in_data, in_data_len) - || !SHA1_Final(out_data, (SHA_CTX *)ctx->context)) - goto error; - break; - case CKM_SHA224: - if (!SHA224_Update((SHA256_CTX *)ctx->context, in_data, in_data_len) - || !SHA224_Final(out_data, (SHA256_CTX *)ctx->context)) - goto error; - break; - case CKM_SHA256: - if (!SHA256_Update((SHA256_CTX *)ctx->context, in_data, in_data_len) - || !SHA256_Final(out_data, (SHA256_CTX *)ctx->context)) - goto error; - break; - case CKM_SHA384: - if (!SHA384_Update((SHA512_CTX *)ctx->context, in_data, in_data_len) - || !SHA384_Final(out_data, (SHA512_CTX *)ctx->context)) - goto error; - break; - case CKM_SHA512: - if (!SHA512_Update((SHA512_CTX *)ctx->context, in_data, in_data_len) - || !SHA512_Final(out_data, (SHA512_CTX *)ctx->context)) - goto error; - break; - case CKM_SHA512_224: - case CKM_SHA512_256: - out_data = temp_out_data; - - if (!SHA512_Update((SHA512_CTX *)ctx->context, in_data, in_data_len) - || !SHA512_Final(out_data, (SHA512_CTX *)ctx->context)) - goto error; - - memcpy(orig_out_data, temp_out_data, hlen); - OPENSSL_cleanse(temp_out_data, sizeof(temp_out_data)); - break; + if (!EVP_DigestUpdate((EVP_MD_CTX *)ctx->context, in_data, in_data_len) || + !EVP_DigestFinal((EVP_MD_CTX *)ctx->context, out_data, &len)) { + rc = CKR_FUNCTION_FAILED; + goto out; } - *out_data_len = hlen; - return CKR_OK; + *out_data_len = len; -error: - free(ctx->context); +out: +#if OPENSSL_VERSION_NUMBER < 0x10101000L + EVP_MD_CTX_destroy((EVP_MD_CTX *)ctx->context); +#else + EVP_MD_CTX_free((EVP_MD_CTX *)ctx->context); +#endif ctx->context = NULL; ctx->context_len = 0; - return CKR_FUNCTION_FAILED; + return rc; } CK_RV token_specific_sha_update(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len) { - int rc; - UNUSED(tokdata); if (!ctx || !ctx->context) @@ -2341,30 +3059,12 @@ CK_RV token_specific_sha_update(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx, if (!in_data) return CKR_ARGUMENTS_BAD; - switch (ctx->mech.mechanism) { - case CKM_SHA_1: - rc = SHA1_Update((SHA_CTX *) ctx->context, in_data, in_data_len); - break; - case CKM_SHA224: - rc = SHA224_Update((SHA256_CTX*) ctx->context, in_data, in_data_len); - break; - case CKM_SHA256: - rc = SHA256_Update((SHA256_CTX *) ctx->context, in_data, in_data_len); - break; - case CKM_SHA384: - rc = SHA384_Update((SHA512_CTX *) ctx->context, in_data, in_data_len); - break; - case CKM_SHA512: - case CKM_SHA512_224: - case CKM_SHA512_256: - rc = SHA512_Update((SHA512_CTX *) ctx->context, in_data, in_data_len); - break; - default: - return CKR_MECHANISM_INVALID; - } - - if (!rc) { - free(ctx->context); + if (!EVP_DigestUpdate((EVP_MD_CTX *)ctx->context, in_data, in_data_len)) { +#if OPENSSL_VERSION_NUMBER < 0x10101000L + EVP_MD_CTX_destroy((EVP_MD_CTX *)ctx->context); +#else + EVP_MD_CTX_free((EVP_MD_CTX *)ctx->context); +#endif ctx->context = NULL; ctx->context_len = 0; return CKR_FUNCTION_FAILED; @@ -2376,9 +3076,8 @@ CK_RV token_specific_sha_update(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx, CK_RV token_specific_sha_final(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len) { - unsigned int hlen; - CK_BYTE temp_out_data[MAX_SHA_HASH_SIZE]; - CK_BYTE *orig_out_data = out_data; + unsigned int len; + CK_RV rc = CKR_OK; UNUSED(tokdata); @@ -2388,76 +3087,25 @@ CK_RV token_specific_sha_final(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx, if (!out_data) return CKR_ARGUMENTS_BAD; - switch (ctx->mech.mechanism) { - case CKM_SHA_1: - hlen = SHA1_HASH_SIZE; - break; - case CKM_SHA224: - hlen = SHA224_HASH_SIZE; - break; - case CKM_SHA256: - hlen = SHA256_HASH_SIZE; - break; - case CKM_SHA384: - hlen = SHA384_HASH_SIZE; - break; - case CKM_SHA512: - hlen = SHA512_HASH_SIZE; - break; - case CKM_SHA512_224: - hlen = SHA224_HASH_SIZE; - break; - case CKM_SHA512_256: - hlen = SHA256_HASH_SIZE; - break; - default: - return CKR_MECHANISM_INVALID; - } - - if (*out_data_len < hlen) + if (*out_data_len < (CK_ULONG)EVP_MD_CTX_size((EVP_MD_CTX *)ctx->context)) return CKR_BUFFER_TOO_SMALL; - switch (ctx->mech.mechanism) { - case CKM_SHA_1: - if (!SHA1_Final(out_data, (SHA_CTX *)ctx->context)) - goto error; - break; - case CKM_SHA224: - if (!SHA224_Final(out_data, (SHA256_CTX *)ctx->context)) - goto error; - break; - case CKM_SHA256: - if (!SHA256_Final(out_data, (SHA256_CTX *)ctx->context)) - goto error; - break; - case CKM_SHA384: - if (!SHA384_Final(out_data, (SHA512_CTX *)ctx->context)) - goto error; - break; - case CKM_SHA512: - if (!SHA512_Final(out_data, (SHA512_CTX *)ctx->context)) - goto error; - break; - case CKM_SHA512_224: - case CKM_SHA512_256: - out_data = temp_out_data; - - if (!SHA512_Final(out_data, (SHA512_CTX *)ctx->context)) - goto error; - - memcpy(orig_out_data, temp_out_data, hlen); - OPENSSL_cleanse(temp_out_data, sizeof(temp_out_data)); - break; + if (!EVP_DigestFinal((EVP_MD_CTX *)ctx->context, out_data, &len)) { + rc = CKR_FUNCTION_FAILED; + goto out; } + *out_data_len = len; - *out_data_len = hlen; - return CKR_OK; - -error: - free(ctx->context); +out: +#if OPENSSL_VERSION_NUMBER < 0x10101000L + EVP_MD_CTX_destroy((EVP_MD_CTX *)ctx->context); +#else + EVP_MD_CTX_free((EVP_MD_CTX *)ctx->context); +#endif ctx->context = NULL; ctx->context_len = 0; - return CKR_FUNCTION_FAILED; + + return rc; } static CK_RV softtok_hmac_init(STDLL_TokData_t *tokdata, @@ -2518,6 +3166,38 @@ static CK_RV softtok_hmac_init(STDLL_TokData_t *tokdata, 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)); @@ -2537,7 +3217,7 @@ static CK_RV softtok_hmac_init(STDLL_TokData_t *tokdata, rc = CKR_OK; done: -if (pkey != NULL) + if (pkey != NULL) EVP_PKEY_free(pkey); object_put(tokdata, key, TRUE); @@ -2587,15 +3267,27 @@ static CK_RV softtok_hmac(SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, 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: @@ -2610,6 +3302,26 @@ static CK_RV softtok_hmac(SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, 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; @@ -2771,6 +3483,26 @@ static CK_RV softtok_hmac_final(SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *signature, 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; @@ -2891,6 +3623,7 @@ 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; @@ -2970,6 +3703,126 @@ CK_RV token_specific_tdes_cmac(STDLL_TokData_t *tokdata, CK_BYTE *message, } 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 + rc = template_attribute_find(key->template, CKA_KEY_TYPE, &attr); + if (rc == FALSE) { + TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); + rv = CKR_FUNCTION_FAILED; + goto err; + } + keytype = *(CK_KEY_TYPE *) attr->pValue; + + // get the key value + if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { + TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); + rv = CKR_FUNCTION_FAILED; + goto err; + } + 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 } @@ -2977,6 +3830,7 @@ 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; @@ -3050,4 +3904,654 @@ CK_RV token_specific_aes_cmac(STDLL_TokData_t *tokdata, CK_BYTE *message, } 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 + if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { + TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); + rv = CKR_FUNCTION_FAILED; + 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_BYTE *ecpoint = NULL; + CK_ULONG ecpoint_len, field_len, privlen, padlen; + CK_BYTE form, *temp = NULL; + CK_RV rc; + + /* CKA_EC_POINT contains the EC point as OCTET STRING */ + rc = ber_decode_OCTET_STRING((CK_BYTE *)data, &ecpoint, &ecpoint_len, + &field_len); + if (rc != CKR_OK || field_len != data_len) { + TRACE_DEVEL("ber_decode_OCTET_STRING failed\n"); + rc = CKR_ATTRIBUTE_VALUE_INVALID; + goto out; + } + + /* Check for public key without format byte */ + privlen = (EC_GROUP_order_bits(EC_KEY_get0_group(ec_key)) + 7) / 8; + form = ecpoint[0] & ~0x01; + if (ecpoint_len <= 2 * privlen && + form != POINT_CONVERSION_COMPRESSED && + form != POINT_CONVERSION_UNCOMPRESSED && + form != POINT_CONVERSION_HYBRID) { + temp = malloc(1 + 2 * privlen); + if (temp == NULL) { + rc = CKR_HOST_MEMORY; + goto out; + } + + padlen = 2 * privlen - ecpoint_len; + temp[0] = POINT_CONVERSION_UNCOMPRESSED; + memset(temp + 1, 0, padlen); + memcpy(temp + 1 + padlen, ecpoint, ecpoint_len); + + ecpoint = temp; + ecpoint_len = 1 + 2 * privlen; + } + + 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 (temp != NULL) + free(temp); + + 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_find(template, CKA_CLASS, &attr); + if (rc == FALSE) { + TRACE_ERROR("Could not find CKA_CLASS in the template\n"); + rc = CKR_TEMPLATE_INCOMPLETE; + goto out; + } + + keyclass = *(CK_OBJECT_CLASS *) attr->pValue; + + if (!template_attribute_find(template, CKA_ECDSA_PARAMS, &attr)) { + TRACE_ERROR("Could not find CKA_ECDSA_PARAMS in the template\n"); + rc = CKR_TEMPLATE_INCOMPLETE; + 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_find(template, CKA_EC_POINT, &attr); + if (rc == FALSE) { + TRACE_ERROR("Could not find CKA_EC_POINT in the template\n"); + rc = CKR_TEMPLATE_INCOMPLETE; + goto out; + } + + rc = fill_ec_key_from_pubkey(ec_key, attr->pValue, attr->ulValueLen); + if (rc != CKR_OK) { + TRACE_DEVEL("fill_ec_key_from_pubkey failed\n"); + goto out; + } + break; + + case CKO_PRIVATE_KEY: + rc = template_attribute_find(template, CKA_VALUE, &attr); + if (rc == FALSE) { + TRACE_ERROR("Could not find CKA_VALUE in the template\n"); + rc = CKR_TEMPLATE_INCOMPLETE; + 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); + + if (!template_attribute_find(publ_tmpl, CKA_ECDSA_PARAMS, &attr)) { + TRACE_ERROR("Could not find CKA_ECDSA_PARAMS in the template\n"); + rc = CKR_TEMPLATE_INCOMPLETE; + 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; + } + template_update_attribute(publ_tmpl, ec_point_attr); + + 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; + } + template_update_attribute(priv_tmpl, value_attr); + + /* 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; + } + template_update_attribute(priv_tmpl, parms_attr); + + 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; +} + +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) +{ + 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; +} + +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) +{ + 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; +} + +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) +{ + 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); + if (rc != CKR_OK) { + TRACE_DEVEL("fill_ec_key_from_privkey 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; +} + +#endif + +CK_RV token_specific_object_add(STDLL_TokData_t * tokdata, SESSION * sess, + OBJECT * obj) +{ + CK_ATTRIBUTE *attr = NULL; + CK_KEY_TYPE keytype; +#ifndef NO_EC + EC_KEY *ec_key = NULL; + CK_RV rc; +#endif + + UNUSED(tokdata); + UNUSED(sess); + + if (template_attribute_find(obj->template, CKA_KEY_TYPE, &attr) == FALSE) + return CKR_OK; + + keytype = *(CK_KEY_TYPE *)attr->pValue; + + switch (keytype) { +#ifndef NO_EC + case CKK_EC: + /* Check if OpenSSL supports the curve */ + rc = make_ec_key_from_template(obj->template, &ec_key); + if (ec_key != NULL) + EC_KEY_free(ec_key); + return rc; +#endif + + default: + return CKR_OK;; + } +} + diff --git a/usr/lib/soft_stdll/soft_stdll.mk b/usr/lib/soft_stdll/soft_stdll.mk index cecb16a..664399b 100644 --- a/usr/lib/soft_stdll/soft_stdll.mk +++ b/usr/lib/soft_stdll/soft_stdll.mk @@ -31,7 +31,9 @@ opencryptoki_stdll_libpkcs11_sw_la_SOURCES = \ usr/lib/common/template.c usr/lib/common/p11util.c \ 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/soft_stdll/soft_specific.c + usr/lib/common/shared_memory.c usr/lib/common/profile_obj.c \ + usr/lib/soft_stdll/soft_specific.c + if ENABLE_LOCKS opencryptoki_stdll_libpkcs11_sw_la_SOURCES += \ usr/lib/common/lock_btree.c usr/lib/common/lock_sess_mgr.c diff --git a/usr/lib/soft_stdll/tok_struct.h b/usr/lib/soft_stdll/tok_struct.h index 1ee86fc..4fc4a55 100644 --- a/usr/lib/soft_stdll/tok_struct.h +++ b/usr/lib/soft_stdll/tok_struct.h @@ -51,7 +51,7 @@ token_spec_t token_specific = { SW_CONFIG_PATH, "swtok", - 0, // keysize + FALSE, // Token data info: { FALSE, // Don't use per guest data store @@ -82,7 +82,7 @@ token_spec_t token_specific = { &token_specific_tdes_cbc, NULL, // des3_ofb NULL, // des3_cfb - NULL, // des3_mac + &token_specific_tdes_mac, &token_specific_tdes_cmac, // RSA &token_specific_rsa_decrypt, @@ -100,11 +100,18 @@ token_spec_t token_specific = { &token_specific_rsa_pss_sign, &token_specific_rsa_pss_verify, &token_specific_rsa_generate_keypair, +#ifndef NO_EC // Elliptic Curve + &token_specific_ec_sign, + &token_specific_ec_verify, + &token_specific_ec_generate_keypair, + &token_specific_ecdh_pkcs_derive, +#else NULL, // ec_sign NULL, // ec_verify NULL, // ec_generate_keypair NULL, // ecdh_derive +#endif /* Begin code contributed by Corrent corp. */ // DH #ifndef NODH @@ -146,10 +153,11 @@ token_spec_t token_specific = { NULL, // aes_gcm_final NULL, // aes_ofb NULL, // aes_cfb - NULL, // aes_mac #ifndef NOAES + &token_specific_aes_mac, &token_specific_aes_cmac, #else + NULL, // aes_mac NULL, // aes_cmac #endif // DSA @@ -158,7 +166,10 @@ token_spec_t token_specific = { 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 }; #endif diff --git a/usr/lib/tpm_stdll/tok_struct.h b/usr/lib/tpm_stdll/tok_struct.h index 74dd361..fa5dec3 100644 --- a/usr/lib/tpm_stdll/tok_struct.h +++ b/usr/lib/tpm_stdll/tok_struct.h @@ -23,7 +23,7 @@ struct token_specific_struct token_specific = { TPM_CONFIG_PATH, "tpm", - 0, + TRUE, // Token data info: { TRUE, // Use per guest data store @@ -114,5 +114,8 @@ struct token_specific_struct token_specific = { NULL, // dsa_verify &token_specific_get_mechanism_list, &token_specific_get_mechanism_info, - NULL // object_add + NULL, // object_add + &token_specific_key_wrap, + &token_specific_key_unwrap, + NULL, // reencrypt_single }; diff --git a/usr/lib/tpm_stdll/tpm_openssl.c b/usr/lib/tpm_stdll/tpm_openssl.c index e1fc080..7b15bbc 100644 --- a/usr/lib/tpm_stdll/tpm_openssl.c +++ b/usr/lib/tpm_stdll/tpm_openssl.c @@ -57,22 +57,31 @@ void openssl_print_errors() } #endif -RSA *openssl_gen_key() +RSA *openssl_gen_key(STDLL_TokData_t *tokdata) { - RSA *rsa; - int rc, counter = 0; + RSA *rsa = NULL; + int rc = 0, counter = 0; char buf[32]; #ifndef OLDER_OPENSSL - BIGNUM *bne; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *ctx = NULL; + BIGNUM *bne = NULL; #endif - token_specific_rng(NULL, (CK_BYTE *) buf, 32); + 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); @@ -80,29 +89,45 @@ regen_rsa_key: fprintf(stderr, "Error generating bne\n"); ERR_load_crypto_strings(); ERR_print_errors_fp(stderr); - return NULL; + goto err; } - rsa = RSA_new(); - rc = RSA_generate_key_ex(rsa, 2048, bne, NULL); - if (!rc) { -#endif + ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); + if (ctx == NULL) + goto err; + + if (EVP_PKEY_keygen_init(ctx) <= 0 + || EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 2048) <= 0 + || EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, bne) <= 0) { fprintf(stderr, "Error generating user's RSA key\n"); ERR_load_crypto_strings(); ERR_print_errors_fp(stderr); - return NULL; + goto err; } - + bne = NULL; // will be freed as part of the context + if (EVP_PKEY_keygen(ctx, &pkey) <= 0 + || (rsa = EVP_PKEY_get1_RSA(pkey)) == NULL) { + 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 + 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 " "valid RSA key, failed.\n", KEYGEN_RETRY); - return NULL; + goto err; } goto regen_rsa_key; break; @@ -116,7 +141,27 @@ regen_rsa_key: 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; +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, @@ -132,7 +177,11 @@ int openssl_write_key(STDLL_TokData_t * tokdata, RSA * rsa, char *filename, return -1; } - sprintf(loc, "%s/%s/%s", tokdata->pk_dir, pw->pw_name, filename); + if (ock_snprintf(loc, PATH_MAX, "%s/%s/%s", + tokdata->pk_dir, pw->pw_name, filename) != 0) { + TRACE_ERROR("key path too long\n"); + return -1; + } b = BIO_new_file(loc, "w"); if (!b) { @@ -172,7 +221,11 @@ CK_RV openssl_read_key(STDLL_TokData_t * tokdata, char *filename, return CKR_FUNCTION_FAILED; } - sprintf(loc, "%s/%s/%s", tokdata->pk_dir, pw->pw_name, filename); + if (ock_snprintf(loc, PATH_MAX, "%s/%s/%s", + tokdata->pk_dir, pw->pw_name, filename) != 0) { + TRACE_ERROR("key file name too long\n"); + return CKR_FUNCTION_FAILED; + } /* we can't allow a pin of NULL here, since openssl will try to prompt * for a password in PEM_read_bio_RSAPrivateKey */ diff --git a/usr/lib/tpm_stdll/tpm_specific.c b/usr/lib/tpm_stdll/tpm_specific.c index dc5f80f..16cf725 100644 --- a/usr/lib/tpm_stdll/tpm_specific.c +++ b/usr/lib/tpm_stdll/tpm_specific.c @@ -159,8 +159,6 @@ CK_RV token_specific_rng(STDLL_TokData_t * tokdata, CK_BYTE * output, TSS_HTPM hTPM; BYTE *random_bytes = NULL; - UNUSED(tokdata); - rc = Tspi_Context_GetTpmObject(tpm_data->tspContext, &hTPM); if (rc) { TRACE_ERROR("Tspi_Context_GetTpmObject: %x\n", rc); @@ -195,17 +193,21 @@ CK_RV token_specific_init(STDLL_TokData_t * tokdata, CK_SLOT_ID SlotNumber, tokdata->mech_list_len = tpm_mech_list_len; // if the user specific directory doesn't exist, create it - sprintf(path_buf, "%s", get_pk_dir(tokdata, fname)); - if (stat(path_buf, &statbuf) < 0) { - if (mkdir(path_buf, S_IRUSR | S_IWUSR | S_IXUSR) == -1) { - TRACE_ERROR("mkdir(%s): %s\n", path_buf, strerror(errno)); + if (get_pk_dir(tokdata, fname, PATH_MAX) == NULL) { + TRACE_ERROR("pk_dir buffer overflow\n"); + return CKR_FUNCTION_FAILED; + } + if (stat(fname, &statbuf) < 0) { + if (mkdir(fname, S_IRUSR | S_IWUSR | S_IXUSR) == -1) { + TRACE_ERROR("mkdir(%s): %s\n", fname, strerror(errno)); return CKR_FUNCTION_FAILED; } } // now create userdir/TOK_OBJ if it doesn't exist - strncat(path_buf, "/", sizeof(path_buf) - (strlen(path_buf) + 1)); - strncat(path_buf, PK_LITE_OBJ_DIR, - sizeof(path_buf) - (strlen(PK_LITE_OBJ_DIR) + 1)); + if (ock_snprintf(path_buf, PATH_MAX, "%s/%s", fname, PK_LITE_OBJ_DIR) != 0) { + TRACE_ERROR("userdir/TOK_OBJ path name overflow\n"); + return CKR_FUNCTION_FAILED; + } if (stat(path_buf, &statbuf) < 0) { if (mkdir(path_buf, S_IRUSR | S_IWUSR | S_IXUSR) == -1) { TRACE_ERROR("mkdir(%s): %s\n", path_buf, strerror(errno)); @@ -1389,7 +1391,7 @@ CK_RV token_create_private_tree(STDLL_TokData_t * tokdata, CK_BYTE * pinHash, unsigned char n[256], p[256]; /* all sw generated keys are 2048 bits */ - if ((rsa = openssl_gen_key()) == NULL) + if ((rsa = openssl_gen_key(tokdata)) == NULL) return CKR_HOST_MEMORY; if (openssl_get_modulus_and_prime(rsa, &size_n, n, &size_p, p) != 0) { @@ -1467,7 +1469,7 @@ CK_RV token_create_public_tree(STDLL_TokData_t * tokdata, CK_BYTE * pinHash, unsigned char n[256], p[256]; /* all sw generated keys are 2048 bits */ - if ((rsa = openssl_gen_key()) == NULL) + if ((rsa = openssl_gen_key(tokdata)) == NULL) return CKR_HOST_MEMORY; if (openssl_get_modulus_and_prime(rsa, &size_n, n, &size_p, p) != 0) { @@ -1632,10 +1634,9 @@ CK_RV token_migrate(STDLL_TokData_t * tokdata, int key_type, CK_BYTE * pin) return CKR_OK; } -CK_RV save_masterkey_private(STDLL_TokData_t * tokdata) +static CK_RV save_masterkey_private(STDLL_TokData_t * tokdata, char *fname) { tpm_private_data_t *tpm_data = (tpm_private_data_t *)tokdata->private_data; - char fname[PATH_MAX]; struct stat file_stat; int err; FILE *fp = NULL; @@ -1651,9 +1652,6 @@ CK_RV save_masterkey_private(STDLL_TokData_t * tokdata) TRACE_ERROR("getpwuid failed: %s\n", strerror(errno)); return CKR_FUNCTION_FAILED; } - //fp = fopen("/etc/pkcs11/tpm/MK_PRIVATE", "r"); - sprintf(fname, "%s/%s/%s", tokdata->pk_dir, pw->pw_name, - TPMTOK_MASTERKEY_PRIVATE); /* if file exists, assume its been written correctly before */ err = stat(fname, &file_stat); @@ -1737,8 +1735,11 @@ CK_RV load_masterkey_private(STDLL_TokData_t * tokdata) return CKR_FUNCTION_FAILED; } - sprintf(fname, "%s/%s/%s", tokdata->pk_dir, pw->pw_name, - TPMTOK_MASTERKEY_PRIVATE); + if (ock_snprintf(fname, PATH_MAX, "%s/%s/%s", tokdata->pk_dir, pw->pw_name, + TPMTOK_MASTERKEY_PRIVATE) != 0) { + TRACE_ERROR("tpm token master key private file buffer overflow\n"); + return CKR_FUNCTION_FAILED; + } /* if file exists, check its size */ err = stat(fname, &file_stat); @@ -1757,7 +1758,7 @@ CK_RV load_masterkey_private(STDLL_TokData_t * tokdata) return rc; } - return save_masterkey_private(tokdata); + return save_masterkey_private(tokdata, fname); } else { /* some error other than file doesn't exist */ TRACE_ERROR("stat of private masterkey failed: %s\n", strerror(errno)); @@ -2493,20 +2494,25 @@ CK_RV token_specific_final(STDLL_TokData_t *tokdata, return CKR_OK; } -CK_RV token_specific_des_key_gen(STDLL_TokData_t * tokdata, CK_BYTE * des_key, - CK_ULONG len, CK_ULONG keysize) +CK_RV token_specific_des_key_gen(STDLL_TokData_t *tokdata, CK_BYTE **des_key, + CK_ULONG *len, CK_ULONG keysize, + CK_BBOOL *is_opaque) { - UNUSED(keysize); + *des_key = malloc(keysize); + if (*des_key == NULL) + return CKR_HOST_MEMORY; + *len = keysize; + *is_opaque = FALSE; // Nothing different to do for DES or TDES here as this is just // random data... Validation handles the rest // Only check for weak keys when DES. - if (len == (3 * DES_KEY_SIZE)) { - rng_generate(tokdata, des_key, len); + if (keysize == (3 * DES_KEY_SIZE)) { + rng_generate(tokdata, *des_key, keysize); } else { do { - rng_generate(tokdata, des_key, len); - } while (des_check_weak_key(des_key) == TRUE); + rng_generate(tokdata, *des_key, keysize); + } while (des_check_weak_key(*des_key) == TRUE); } // we really need to validate the key for parity etc... @@ -2522,6 +2528,7 @@ CK_RV token_specific_des_ecb(STDLL_TokData_t * tokdata, CK_ULONG * out_data_len, OBJECT * key, CK_BYTE encrypt) { +#if OPENSSL_VERSION_NUMBER < 0x10100000L CK_ULONG rc; CK_ATTRIBUTE *attr = NULL; @@ -2543,7 +2550,7 @@ CK_RV token_specific_des_ecb(STDLL_TokData_t * tokdata, // the des decrypt will only fail if the data length is not evenly divisible // by 8 - if (in_data_len % 8) { + if (in_data_len % DES_BLOCK_SIZE) { TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } @@ -2572,6 +2579,53 @@ CK_RV token_specific_des_ecb(STDLL_TokData_t * tokdata, } 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 + if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { + TRACE_ERROR("template_attribute_find(CKA_VALUE) failed.\n"); + return CKR_FUNCTION_FAILED; + } + + 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 = ERR_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 = ERR_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_RV token_specific_des_cbc(STDLL_TokData_t * tokdata, @@ -2581,6 +2635,7 @@ CK_RV token_specific_des_cbc(STDLL_TokData_t * tokdata, CK_ULONG * out_data_len, OBJECT * key, CK_BYTE * init_v, CK_BYTE encrypt) { +#if OPENSSL_VERSION_NUMBER < 0x10100000L CK_ULONG rc; CK_ATTRIBUTE *attr = NULL; @@ -2603,7 +2658,7 @@ CK_RV token_specific_des_cbc(STDLL_TokData_t * tokdata, 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 % 8) { + if (in_data_len % DES_BLOCK_SIZE) { TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } @@ -2621,6 +2676,53 @@ CK_RV token_specific_des_cbc(STDLL_TokData_t * tokdata, 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 + if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { + TRACE_ERROR("template_attribute_find(CKA_VALUE) failed.\n"); + return CKR_FUNCTION_FAILED; + } + + 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 = ERR_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 = ERR_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_RV token_specific_tdes_ecb(STDLL_TokData_t * tokdata, @@ -2630,6 +2732,7 @@ CK_RV token_specific_tdes_ecb(STDLL_TokData_t * tokdata, 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; @@ -2676,7 +2779,7 @@ CK_RV token_specific_tdes_ecb(STDLL_TokData_t * tokdata, // the des decrypt will only fail if the data length is not evenly divisible // by 8 - if (in_data_len % 8) { + if (in_data_len % DES_BLOCK_SIZE) { TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } @@ -2704,6 +2807,67 @@ CK_RV token_specific_tdes_ecb(STDLL_TokData_t * tokdata, } 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_find(key->template, CKA_KEY_TYPE, &attr); + if (rc == FALSE) { + TRACE_ERROR("template_attribute_find(CKA_KEY_TYPE) failed.\n"); + return CKR_FUNCTION_FAILED; + } + keytype = *(CK_KEY_TYPE *)attr->pValue; + + // get the key value + if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { + TRACE_ERROR("template_attribute_find(CKA_VALUE) failed.\n"); + return CKR_FUNCTION_FAILED; + } + + 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 = ERR_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 = ERR_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_RV token_specific_tdes_cbc(STDLL_TokData_t * tokdata, @@ -2713,6 +2877,7 @@ CK_RV token_specific_tdes_cbc(STDLL_TokData_t * tokdata, 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; @@ -2760,7 +2925,7 @@ CK_RV token_specific_tdes_cbc(STDLL_TokData_t * tokdata, // the des decrypt will only fail if the data length is not evenly divisible // by 8 - if (in_data_len % 8) { + if (in_data_len % DES_BLOCK_SIZE) { TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } @@ -2785,6 +2950,67 @@ CK_RV token_specific_tdes_cbc(STDLL_TokData_t * tokdata, } 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_ULONG rc; + int outlen; + + UNUSED(tokdata); + + // get the key type + rc = template_attribute_find(key->template, CKA_KEY_TYPE, &attr); + if (rc == FALSE) { + TRACE_ERROR("template_attribute_find(CKA_KEY_TYPE) failed.\n"); + return CKR_FUNCTION_FAILED; + } + keytype = *(CK_KEY_TYPE *)attr->pValue; + + // get the key value + if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { + TRACE_ERROR("template_attribute_find(CKA_VALUE) failed.\n"); + return CKR_FUNCTION_FAILED; + } + + 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 = ERR_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 = ERR_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 } /* wrap the 20 bytes of auth data @authData and store in an attribute of the two @@ -3461,12 +3687,17 @@ CK_RV token_specific_rsa_verify_recover(STDLL_TokData_t * tokdata, return rc; } -CK_RV token_specific_aes_key_gen(STDLL_TokData_t * tokdata, CK_BYTE * key, - CK_ULONG len, CK_ULONG keysize) +CK_RV token_specific_aes_key_gen(STDLL_TokData_t *tokdata, CK_BYTE **key, + CK_ULONG *len, CK_ULONG keysize, + CK_BBOOL *is_opaque) { - UNUSED(keysize); + *key = malloc(keysize); + if (*key == NULL) + return CKR_HOST_MEMORY; + *len = keysize; + *is_opaque = FALSE; - return token_specific_rng(tokdata, key, len); + return rng_generate(tokdata, *key, keysize); } CK_RV token_specific_aes_ecb(STDLL_TokData_t * tokdata, @@ -3476,6 +3707,7 @@ CK_RV token_specific_aes_ecb(STDLL_TokData_t * tokdata, 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; @@ -3515,6 +3747,67 @@ CK_RV token_specific_aes_ecb(STDLL_TokData_t * tokdata, *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 + if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { + TRACE_ERROR("template_attribute_find(CKA_VALUE) failed.\n"); + return CKR_FUNCTION_FAILED; + } + + 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 = ERR_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 = ERR_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_RV token_specific_aes_cbc(STDLL_TokData_t * tokdata, @@ -3524,6 +3817,7 @@ CK_RV token_specific_aes_cbc(STDLL_TokData_t * tokdata, 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; @@ -3553,6 +3847,67 @@ CK_RV token_specific_aes_cbc(STDLL_TokData_t * tokdata, *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 + if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { + TRACE_ERROR("template_attribute_find(CKA_VALUE) failed.\n"); + return CKR_FUNCTION_FAILED; + } + + 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 = ERR_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 = ERR_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_RV token_specific_get_mechanism_list(STDLL_TokData_t * tokdata, @@ -3681,3 +4036,156 @@ CK_RV token_specific_init_token_data(STDLL_TokData_t * tokdata, /* do nothing. */ return CKR_OK; } + +CK_RV token_specific_key_wrap(STDLL_TokData_t *tokdata, SESSION *session, + CK_MECHANISM *mech, CK_BBOOL length_only, + OBJECT *wrapping_key, OBJECT *key, + CK_BYTE *wrapped_key, CK_ULONG *wrapped_key_len, + CK_BBOOL *not_opaque) +{ + CK_ATTRIBUTE *attr; + CK_OBJECT_CLASS class; + CK_KEY_TYPE keytype; + + UNUSED(tokdata); + UNUSED(session); + UNUSED(length_only); + UNUSED(wrapped_key); + UNUSED(wrapped_key_len); + + if (!template_attribute_find(wrapping_key->template, CKA_CLASS, &attr)) + return CKR_KEY_NOT_WRAPPABLE; + class = *(CK_OBJECT_CLASS *)attr->pValue; + + if (class != CKO_SECRET_KEY) + return CKR_KEY_NOT_WRAPPABLE; + + if (!template_attribute_find(key->template, CKA_CLASS, &attr)) + return CKR_KEY_NOT_WRAPPABLE; + class = *(CK_OBJECT_CLASS *)attr->pValue; + + if (class != CKO_SECRET_KEY) + return CKR_KEY_NOT_WRAPPABLE; + + if (!template_attribute_find(wrapping_key->template, CKA_KEY_TYPE, &attr)) + return CKR_KEY_NOT_WRAPPABLE; + keytype = *(CK_KEY_TYPE *) attr->pValue; + + switch (mech->mechanism) { + case CKM_DES_ECB: + case CKM_DES_CBC: + case CKM_DES_CBC_PAD: + if (keytype != CKK_DES) + return CKR_WRAPPING_KEY_TYPE_INCONSISTENT; + break; + case CKM_DES3_ECB: + case CKM_DES3_CBC: + case CKM_DES3_CBC_PAD: + if (keytype != CKK_DES2 && keytype != CKK_DES3) + return CKR_WRAPPING_KEY_TYPE_INCONSISTENT; + break; + case CKM_AES_ECB: + case CKM_AES_CBC: + case CKM_AES_CBC_PAD: + if (keytype != CKK_AES) + return CKR_WRAPPING_KEY_TYPE_INCONSISTENT; + break; + default: + return CKR_KEY_NOT_WRAPPABLE; + } + + if (!template_attribute_find(key->template, CKA_KEY_TYPE, &attr)) + return CKR_WRAPPING_KEY_TYPE_INCONSISTENT; + keytype = *(CK_KEY_TYPE *) attr->pValue; + + switch (keytype) { + case CKK_DES: + case CKK_DES2: + case CKK_DES3: + case CKK_AES: + case CKK_GENERIC_SECRET: + break; + default: + return CKR_KEY_NOT_WRAPPABLE; + } + + /* Symmetric keys are not opaque, so we can let common code do the wrap */ + *not_opaque = TRUE; + return CKR_OK; +} + +CK_RV token_specific_key_unwrap(STDLL_TokData_t *tokdata, SESSION *session, + CK_MECHANISM *mech, + CK_BYTE *wrapped_key, CK_ULONG wrapped_key_len, + OBJECT *unwrapping_key, OBJECT *unwrapped_key, + CK_BBOOL *not_opaque) +{ + CK_ATTRIBUTE *attr; + CK_OBJECT_CLASS class; + CK_KEY_TYPE keytype; + + UNUSED(tokdata); + UNUSED(session); + UNUSED(wrapped_key); + UNUSED(wrapped_key_len); + + if (!template_attribute_find(unwrapping_key->template, CKA_CLASS, &attr)) + return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT; + class = *(CK_OBJECT_CLASS *)attr->pValue; + + if (class != CKO_SECRET_KEY) + return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT; + + if (!template_attribute_find(unwrapped_key->template, CKA_CLASS, &attr)) + return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT; + class = *(CK_OBJECT_CLASS *)attr->pValue; + + if (class != CKO_SECRET_KEY) + return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT; + + if (!template_attribute_find(unwrapping_key->template, CKA_KEY_TYPE, &attr)) + return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT; + keytype = *(CK_KEY_TYPE *) attr->pValue; + + switch (mech->mechanism) { + case CKM_DES_ECB: + case CKM_DES_CBC: + case CKM_DES_CBC_PAD: + if (keytype != CKK_DES) + return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT; + break; + case CKM_DES3_ECB: + case CKM_DES3_CBC: + case CKM_DES3_CBC_PAD: + if (keytype != CKK_DES2 && keytype != CKK_DES3) + return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT; + break; + case CKM_AES_ECB: + case CKM_AES_CBC: + case CKM_AES_CBC_PAD: + if (keytype != CKK_AES) + return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT; + break; + default: + return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT; + } + + if (!template_attribute_find(unwrapped_key->template, CKA_KEY_TYPE, &attr)) + return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT; + keytype = *(CK_KEY_TYPE *) attr->pValue; + + switch (keytype) { + case CKK_DES: + case CKK_DES2: + case CKK_DES3: + case CKK_AES: + case CKK_GENERIC_SECRET: + break; + default: + return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT; + } + + /* Symmetric keys are not opaque, so we can let common code do the unwrap */ + *not_opaque = TRUE; + return CKR_OK; +} diff --git a/usr/lib/tpm_stdll/tpm_specific.h b/usr/lib/tpm_stdll/tpm_specific.h index 541b679..81af274 100644 --- a/usr/lib/tpm_stdll/tpm_specific.h +++ b/usr/lib/tpm_stdll/tpm_specific.h @@ -56,7 +56,7 @@ /* retry count for generating software RSA keys */ #define KEYGEN_RETRY 5 -RSA *openssl_gen_key(); +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 *, diff --git a/usr/lib/tpm_stdll/tpm_stdll.mk b/usr/lib/tpm_stdll/tpm_stdll.mk index 49d7886..9b56604 100644 --- a/usr/lib/tpm_stdll/tpm_stdll.mk +++ b/usr/lib/tpm_stdll/tpm_stdll.mk @@ -32,7 +32,8 @@ opencryptoki_stdll_libpkcs11_tpm_la_SOURCES = \ 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/tpm_stdll/tpm_specific.c \ + usr/lib/common/shared_memory.c usr/lib/common/profile_obj.c \ + usr/lib/tpm_stdll/tpm_specific.c \ usr/lib/tpm_stdll/tpm_openssl.c usr/lib/tpm_stdll/tpm_util.c if ENABLE_LOCKS diff --git a/usr/sbin/p11sak/p11sak.c b/usr/sbin/p11sak/p11sak.c index 63dcae4..c783b29 100644 --- a/usr/sbin/p11sak/p11sak.c +++ b/usr/sbin/p11sak/p11sak.c @@ -17,9 +17,8 @@ #include #include - #include - +#include "p11util.h" #include "p11sak.h" static const char *default_pkcs11lib = "libopencryptoki.so"; @@ -36,11 +35,11 @@ static void unload_pkcs11lib(void) static void load_pkcs11lib(void) { CK_RV rc; - CK_RV(*pfoo) (); + CK_RV (*pfoo)(); const char *libname; /* check for environment variable PKCSLIB */ - libname = getenv("PKCSLIB"); + libname = secure_getenv("PKCSLIB"); if (libname == NULL || strlen(libname) < 1) libname = default_pkcs11lib; @@ -52,28 +51,30 @@ static void load_pkcs11lib(void) } /* get function list */ - *(void **)(&pfoo) = dlsym(pkcs11lib, "C_GetFunctionList"); + *(void**) (&pfoo) = dlsym(pkcs11lib, "C_GetFunctionList"); if (!pfoo) { dlclose(pkcs11lib); printf("Error: failed to resolve symbol '%s' from pkcs11 lib '%s'\n", - "C_GetFunctionList", libname); + "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)\n", - libname, rc); + printf( + "Error: C_GetFunctionList() on pkcs11 lib '%s' failed with rc = 0x%lX - %s)\n", + libname, rc, p11_get_ckr(rc)); exit(99); } atexit(unload_pkcs11lib); } -static CK_RV get_pin(char **pin, size_t *pinlen) { +static CK_RV get_pin(char **pin, size_t *pinlen) +{ struct termios old, new; int nread; - char *buff = NULL; + char *user_input = NULL; size_t buflen; CK_RV rc = 0; @@ -87,9 +88,9 @@ static CK_RV get_pin(char **pin, size_t *pinlen) { return -1; /* read the pin - * Note: getline will allocate memory for buff. free it when done. + * Note: getline will allocate memory for user_input. free it when done. */ - nread = getline(&buff, &buflen, stdin); + nread = getline(&user_input, &buflen, stdin); if (nread == -1) { rc = -1; goto done; @@ -113,20 +114,21 @@ static CK_RV get_pin(char **pin, size_t *pinlen) { } /* strip the carriage return since not part of pin. */ - buff[nread - 1] = '\0'; - memcpy(*pin, buff, nread); + user_input[nread - 1] = '\0'; + memcpy(*pin, user_input, nread); /* don't include the terminating null in the pinlen */ *pinlen = nread - 1; - done: if (buff) - free(buff); + done: if (user_input) + free(user_input); return rc; } /** * Translates the given key type to its string representation. */ -static const char* kt2str(p11sak_kt ktype) { +static const char* kt2str(p11sak_kt ktype) +{ switch (ktype) { case kt_DES: return "DES"; @@ -155,7 +157,8 @@ static const char* kt2str(p11sak_kt ktype) { /** * Translates the given key type to its CK_KEY_TYPE */ -static CK_RV kt2CKK(p11sak_kt ktype, CK_KEY_TYPE *a_key_type) { +static CK_RV kt2CKK(p11sak_kt ktype, CK_KEY_TYPE *a_key_type) +{ switch (ktype) { case kt_DES: *a_key_type = CKK_DES; @@ -183,7 +186,8 @@ static CK_RV kt2CKK(p11sak_kt ktype, CK_KEY_TYPE *a_key_type) { /** * Translates the given key type to its CK_OBJECT_CLASS */ -static CK_RV kt2CKO(p11sak_kt ktype, CK_OBJECT_CLASS *a_cko) { +static CK_RV kt2CKO(p11sak_kt ktype, CK_OBJECT_CLASS *a_cko) +{ switch (ktype) { case kt_SECRET: *a_cko = CKO_SECRET_KEY; @@ -203,7 +207,8 @@ static CK_RV kt2CKO(p11sak_kt ktype, CK_OBJECT_CLASS *a_cko) { * Translates the given p11sak command to its string representation. * no_cmd, gen_key, list_key */ -static const char* cmd2str(p11sak_cmd cmd) { +static const char* cmd2str(p11sak_cmd cmd) +{ switch (cmd) { case no_cmd: return "no_cmd"; @@ -211,6 +216,8 @@ static const char* cmd2str(p11sak_cmd cmd) { return "generate-key"; case list_key: return "list-key"; + case remove_key: + return "remove-key"; default: return "unknown p11sak cmd"; } @@ -218,7 +225,8 @@ static const char* cmd2str(p11sak_cmd cmd) { /** * Translates the given attribute type to its long name. */ -static const char* CKA2a(CK_ATTRIBUTE_TYPE attr_type) { +static const char* CKA2a(CK_ATTRIBUTE_TYPE attr_type) +{ switch (attr_type) { case CKA_TOKEN: return "CKA_TOKEN"; @@ -259,7 +267,10 @@ static const char* CKA2a(CK_ATTRIBUTE_TYPE attr_type) { /** * Translates the given key type to its related char string. */ -static const char* CKK2a(CK_KEY_TYPE t) { +static const char* CKK2a(CK_KEY_TYPE t) +{ + // if new cases are added, the buffer = malloc() + // in tok_key_get_key_type() needs to be updated switch (t) { case CKK_DES: return "DES"; @@ -284,7 +295,8 @@ static const char* CKK2a(CK_KEY_TYPE t) { /** * Translates the given bool to its related char string. */ -static const char* CK_BBOOL2a(CK_BBOOL b) { +static const char* CK_BBOOL2a(CK_BBOOL b) +{ switch (b) { case 0: return "CK_FALSE"; @@ -297,7 +309,8 @@ static const char* CK_BBOOL2a(CK_BBOOL b) { /** * Translates the given ULONG value to a byte string. */ -static CK_BYTE* CK_ULONG2bigint(CK_ULONG ul, CK_BYTE *bytes, CK_ULONG *len) { +static CK_BYTE* CK_ULONG2bigint(CK_ULONG ul, CK_BYTE *bytes, CK_ULONG *len) +{ CK_BYTE *ulp; CK_ULONG tul = 1; CK_BYTE *tulp; @@ -327,16 +340,19 @@ static CK_BYTE* CK_ULONG2bigint(CK_ULONG ul, CK_BYTE *bytes, CK_ULONG *len) { /** * print help functions */ -static void print_cmd_help(void) { +static void print_cmd_help(void) +{ printf("\n Usage: p11sak COMMAND [ARGS] [OPTIONS]\n"); printf("\n Commands:\n"); printf(" generate-key Generate a key\n"); printf(" list-key List keys in the repository\n"); + printf(" remove-key Delete keys in the repository\n"); printf("\n Options:\n"); printf(" -h, --help Show this help\n\n"); } -static void print_listkeys_help(void) { +static void print_listkeys_help(void) +{ printf("\n Usage: p11sak list-key [ARGS] [OPTIONS]\n"); printf("\n Args:\n"); printf(" des\n"); @@ -355,14 +371,15 @@ static void print_listkeys_help(void) { printf(" -h, --help Show this help\n\n"); } -static void print_gen_help(void) { +static void print_gen_help(void) +{ printf("\n Usage: p11sak generate-key [ARGS] [OPTIONS]\n"); printf("\n Args:\n"); printf(" des\n"); printf(" 3des\n"); printf(" aes [128 | 192 | 256]\n"); printf(" rsa [1024 | 2048 | 4096]\n"); - printf(" ec [prime256v1 | secp384r1 | secp521]\n"); + printf(" ec [prime256v1 | secp384r1 | secp521r1]\n"); printf("\n Options:\n"); printf( " --slot SLOTID openCryptoki repository token SLOTID.\n"); @@ -376,7 +393,28 @@ static void print_gen_help(void) { printf(" -h, --help Show this help\n\n"); } -static void print_gen_des_help(void) { +static void print_removekeys_help(void) +{ + printf("\n Usage: p11sak remove-key [ARGS] [OPTIONS]\n"); + printf("\n Args:\n"); + printf(" des\n"); + printf(" 3des\n"); + printf(" aes\n"); + printf(" rsa\n"); + printf(" ec\n"); + printf("\n Options:\n"); + printf( + " --slot SLOTID openCryptoki repository token SLOTID.\n"); + printf(" --pin PIN pkcs11 user PIN\n"); + printf( + " --label LABEL Key label LABEL to be removed\n"); + printf( + " -f, --force Force remove all keys of given cipher type\n"); + printf(" -h, --help Show this help\n\n"); +} + +static void print_gen_des_help(void) +{ printf("\n Options:\n"); printf( " --slot SLOTID openCryptoki repository token SLOTID.\n"); @@ -388,7 +426,8 @@ static void print_gen_des_help(void) { printf(" -h, --help Show this help\n\n"); } -static void print_gen_aes_help(void) { +static void print_gen_aes_help(void) +{ printf("\n Usage: p11sak generate-key aes [ARGS] [OPTIONS]\n"); printf("\n Args:\n"); printf(" 128\n"); @@ -405,7 +444,8 @@ static void print_gen_aes_help(void) { printf(" -h, --help Show this help\n\n"); } -static void print_gen_rsa_help(void) { +static void print_gen_rsa_help(void) +{ printf("\n Usage: p11sak generate-key rsa [ARGS] [OPTIONS] [ARGS]\n"); printf("\n Args:\n"); printf(" 1024\n"); @@ -424,12 +464,13 @@ static void print_gen_rsa_help(void) { printf(" -h, --help Show this help\n\n"); } -static void print_gen_ec_help(void) { +static void print_gen_ec_help(void) +{ printf("\n Usage: p11sak generate-key ec [ARGS] [OPTIONS]\n"); printf("\n Args:\n"); printf(" prime256v1\n"); printf(" secp384r1\n"); - printf(" secp521\n"); + printf(" secp521r1\n"); printf("\n Options:\n"); printf( " --slot SLOTID openCryptoki repository token SLOTID.\n"); @@ -443,7 +484,8 @@ static void print_gen_ec_help(void) { /** * Print help for generate-key command */ -static CK_RV print_gen_keys_help(p11sak_kt *kt) { +static CK_RV print_gen_keys_help(p11sak_kt *kt) +{ switch (*kt) { case kt_DES: @@ -475,7 +517,8 @@ static CK_RV print_gen_keys_help(p11sak_kt *kt) { /** * Print help for attributes */ -static void print_gen_attr_help(void) { +static void print_gen_attr_help(void) +{ printf("\n"); printf(" Setting CK_ATTRIBUTE\n"); printf("\n"); @@ -507,7 +550,8 @@ static void print_gen_attr_help(void) { * pubattr >= x elements, prvattr >= y elements */ static CK_RV read_rsa_args(CK_ULONG modulusbits, CK_ULONG exponent, - CK_ATTRIBUTE *pubattr, CK_ULONG *pubcount) { + CK_ATTRIBUTE *pubattr, CK_ULONG *pubcount) +{ CK_ULONG *mod_bits; CK_ULONG ulpubexp; CK_BYTE *pubexp; @@ -547,7 +591,8 @@ static CK_RV read_rsa_args(CK_ULONG modulusbits, CK_ULONG exponent, * 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) +{ pubattr[*pubcount].type = CKA_EC_PARAMS; if (strcmp(ECcurve, "prime256v1") == 0) { pubattr[*pubcount].pValue = (CK_BYTE*) prime256v1; @@ -611,7 +656,7 @@ static CK_RV read_ec_args(const char *ECcurve, CK_ATTRIBUTE *pubattr, pubattr[*pubcount].ulValueLen = sizeof(brainpoolP512t1); } else { printf("Unexpected case while parsing EC curves.\n"); - printf("Note: not all tokens support all curves."); + printf("Note: not all tokens support all curves.\n"); return CKR_ARGUMENTS_BAD; } (*pubcount)++; @@ -622,7 +667,9 @@ static CK_RV read_ec_args(const char *ECcurve, CK_ATTRIBUTE *pubattr, * Builds two CKA_LABEL attributes from given label. */ static CK_RV set_labelpair_attr(const char *label, CK_ATTRIBUTE *pubattr, - CK_ULONG *pubcount, CK_ATTRIBUTE *prvattr, CK_ULONG *prvcount) { + CK_ULONG *pubcount, CK_ATTRIBUTE *prvattr, + CK_ULONG *prvcount) +{ char *publabel; char *prvlabel; @@ -655,7 +702,8 @@ static CK_RV set_labelpair_attr(const char *label, CK_ATTRIBUTE *pubattr, /** * Set mechanism according to given key type. */ -static CK_RV key_pair_gen_mech(p11sak_kt kt, CK_MECHANISM *pmech) { +static CK_RV key_pair_gen_mech(p11sak_kt kt, CK_MECHANISM *pmech) +{ pmech->pParameter = NULL_PTR; pmech->ulParameterLen = 0; switch (kt) { @@ -685,7 +733,9 @@ static CK_RV key_pair_gen_mech(p11sak_kt kt, CK_MECHANISM *pmech) { * Set default asymmetric key attributes. */ static CK_RV set_battr(const char *attr_string, CK_ATTRIBUTE *pubattr, - CK_ULONG *pubcount, CK_ATTRIBUTE *prvattr, CK_ULONG *prvcount) { + CK_ULONG *pubcount, CK_ATTRIBUTE *prvattr, + CK_ULONG *prvcount) +{ int i = 0; pubattr[*pubcount].type = CKA_TOKEN; @@ -760,7 +810,8 @@ static CK_RV set_battr(const char *attr_string, CK_ATTRIBUTE *pubattr, return CKR_OK; } -static CK_ULONG char2attrtype(char c) { +static CK_ULONG char2attrtype(char c) +{ switch (c) { case 'T': return CKA_TOKEN; @@ -797,7 +848,8 @@ static CK_ULONG char2attrtype(char c) { } } -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_string) +{ int i; if (!attr_string) @@ -813,9 +865,10 @@ static void set_bool_attr_from_string(CK_ATTRIBUTE *attr, char *attr_string) { * 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) { - CK_RV ret; + 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) */ @@ -841,13 +894,13 @@ static CK_RV tok_key_gen(CK_SESSION_HANDLE session, CK_ULONG keylength, 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 }, + 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) } }; @@ -860,43 +913,47 @@ static CK_RV tok_key_gen(CK_SESSION_HANDLE session, CK_ULONG keylength, } /* generate key */ - ret = funcs->C_GenerateKey(session, pmech, tmplt, num_attrs, phkey); - if (ret != CKR_OK) { + rc = funcs->C_GenerateKey(session, pmech, tmplt, 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)\n", ret); + printf("in tok_key_gen() (error code 0x%lX: %s)\n", rc, + p11_get_ckr(rc)); } - return ret; + 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) { + 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_RV ret; + CK_RV rc; printf("Generate asymmetric key: %s\n", kt2str(kt)); - ret = funcs->C_GenerateKeyPair(session, pmech, pubattr, pubcount, prvattr, + rc = funcs->C_GenerateKeyPair(session, pmech, pubattr, pubcount, prvattr, prvcount, phpubkey, phprvkey); - if (ret != CKR_OK) { - printf("Key pair generation failed (error code 0x%lX)\n", ret); - return ret; + if (rc != CKR_OK) { + printf("Key pair generation failed (error code 0x%lX: %s)\n", rc, + p11_get_ckr(rc)); + return rc; } printf("Asymmetric key pair generation successful!\n"); return CKR_OK; } - /** - * + * Initialize key object list */ -static CK_RV tok_key_list_init(CK_SESSION_HANDLE session, p11sak_kt kt, char *label) { +static CK_RV tok_key_list_init(CK_SESSION_HANDLE session, p11sak_kt kt, + char *label) +{ CK_RV rc; CK_ULONG count; @@ -923,13 +980,15 @@ static CK_RV tok_key_list_init(CK_SESSION_HANDLE session, p11sak_kt kt, char *la if (kt < kt_SECRET) { rc = kt2CKK(kt, &a_key_type); if (rc != CKR_OK) { - printf("Keytype could not be set (error code 0x%lX)\n", rc); + printf("Keytype could not be set (error code 0x%lX: %s)\n", rc, + p11_get_ckr(rc)); return rc; } } else { rc = kt2CKO(kt, &a_cko); if (rc != CKR_OK) { - printf("Keyobject could not be set (error code 0x%lX)\n", rc); + printf("Keyobject could not be set (error code 0x%lX: %s)\n", rc, + p11_get_ckr(rc)); return rc; } } @@ -969,18 +1028,19 @@ static CK_RV tok_key_list_init(CK_SESSION_HANDLE session, p11sak_kt kt, char *la 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)\n", rc); + printf("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) { +static CK_BBOOL attr_na(const CK_ATTRIBUTE attr, p11sak_kt ktype) +{ switch (ktype) { case kt_DES: case kt_3DES: @@ -1022,11 +1082,11 @@ static CK_BBOOL attr_na(const CK_ATTRIBUTE attr, p11sak_kt ktype) { return 0; } } - /** * Columns: T P M R L S E D G V W U X A N */ -static CK_ATTRIBUTE_TYPE col2type(int col) { +static CK_ATTRIBUTE_TYPE col2type(int col) +{ switch (col) { case 0: return CKA_TOKEN; @@ -1063,7 +1123,8 @@ static CK_ATTRIBUTE_TYPE col2type(int col) { } } -static void short_print(int col, CK_ATTRIBUTE attr[], p11sak_kt ktype) { +static void short_print(int col, CK_ATTRIBUTE attr[], p11sak_kt ktype) +{ int j = 0; int attr_count = 0; @@ -1092,11 +1153,12 @@ static void short_print(int col, CK_ATTRIBUTE attr[], p11sak_kt ktype) { return; } /** - * + * Print attributes of secure keys */ -static CK_RV sec_key_print_attributes(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE hkey, - int long_print) { - CK_RV ret; +static CK_RV sec_key_print_attributes(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE hkey, int long_print) +{ + CK_RV rc; int i; /* Boolean Attributes */ @@ -1119,20 +1181,20 @@ static CK_RV sec_key_print_attributes(CK_SESSION_HANDLE session, CK_OBJECT_HANDL 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 }, }; + 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_ULONG count = sizeof(bool_tmplt) / sizeof(CK_ATTRIBUTE); - ret = funcs->C_GetAttributeValue(session, hkey, bool_tmplt, count); - if (ret != CKR_OK) { - printf("Attribute retrieval failed (error code 0x%lX)\n", ret); - return ret; + rc = funcs->C_GetAttributeValue(session, hkey, bool_tmplt, count); + if (rc != CKR_OK) { + printf("Attribute retrieval failed (error code 0x%lX: %s)\n", rc, + p11_get_ckr(rc)); + return rc; } if (long_print) { @@ -1156,11 +1218,12 @@ static CK_RV sec_key_print_attributes(CK_SESSION_HANDLE session, CK_OBJECT_HANDL return CKR_OK; } /** - * + * Print attributes of private keys */ static CK_RV priv_key_print_attributes(CK_SESSION_HANDLE session, - CK_OBJECT_HANDLE hkey, int long_print) { - CK_RV ret; + CK_OBJECT_HANDLE hkey, int long_print) +{ + CK_RV rc; int i = 0; /* Boolean Attributes */ @@ -1180,18 +1243,19 @@ static CK_RV priv_key_print_attributes(CK_SESSION_HANDLE session, 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 } }; + 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_ULONG count = sizeof(bool_tmplt) / sizeof(CK_ATTRIBUTE); - ret = funcs->C_GetAttributeValue(session, hkey, bool_tmplt, count); - if (ret != CKR_OK) { - printf("Attribute retrieval failed (error code 0x%lX)\n", ret); - return ret; + rc = funcs->C_GetAttributeValue(session, hkey, bool_tmplt, count); + if (rc != CKR_OK) { + printf("Attribute retrieval failed (error code 0x%lX: %s)\n", rc, + p11_get_ckr(rc)); + return rc; } /* Long print */ @@ -1216,13 +1280,13 @@ static CK_RV priv_key_print_attributes(CK_SESSION_HANDLE session, return CKR_OK; } - /** - * + * Print attributes of public keys */ -static CK_RV pub_key_print_attributes(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE hkey, - int long_print) { - CK_RV ret; +static CK_RV pub_key_print_attributes(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE hkey, int long_print) +{ + CK_RV rc; int i = 0; /* Boolean Attributes */ @@ -1238,15 +1302,16 @@ static CK_RV pub_key_print_attributes(CK_SESSION_HANDLE session, CK_OBJECT_HANDL 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 } }; + 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_ULONG count = sizeof(bool_tmplt) / sizeof(CK_ATTRIBUTE); - ret = funcs->C_GetAttributeValue(session, hkey, bool_tmplt, count); - if (ret != CKR_OK) { - printf("Attribute retrieval failed (error code 0x%lX)\n", ret); - return ret; + rc = funcs->C_GetAttributeValue(session, hkey, bool_tmplt, count); + if (rc != CKR_OK) { + printf("Attribute retrieval failed (error code 0x%lX: %s)\n", rc, + p11_get_ckr(rc)); + return rc; } /* Long print */ @@ -1271,20 +1336,21 @@ static CK_RV pub_key_print_attributes(CK_SESSION_HANDLE session, CK_OBJECT_HANDL return CKR_OK; } - /** - * + * Get label attribute of key */ -static CK_RV tok_key_get_label_attr(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE hkey, - char **plabel) { - CK_RV ret; +static CK_RV tok_key_get_label_attr(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE hkey, char **plabel) +{ + CK_RV rc; char *label; CK_ATTRIBUTE template[1] = { { CKA_LABEL, NULL_PTR, 0 } }; - ret = funcs->C_GetAttributeValue(session, hkey, template, 1); - if (ret != CKR_OK) { - printf("Key cannot show CKA_LABEL attribute (error code 0x%lX)\n", ret); - return ret; + 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", + rc, p11_get_ckr(rc)); + return rc; } label = malloc(template[0].ulValueLen); @@ -1294,11 +1360,11 @@ static CK_RV tok_key_get_label_attr(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE } template[0].pValue = label; - ret = funcs->C_GetAttributeValue(session, hkey, template, 1); - if (ret != CKR_OK) { - printf("Error retrieving CKA_LABEL attribute (error code 0x%lX)\n", - ret); - return ret; + rc = funcs->C_GetAttributeValue(session, hkey, template, 1); + if (rc != CKR_OK) { + printf("Error retrieving CKA_LABEL attribute (error code 0x%lX: %s)\n", + rc, p11_get_ckr(rc)); + return rc; } label[template[0].ulValueLen] = 0; @@ -1306,13 +1372,14 @@ static CK_RV tok_key_get_label_attr(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE return CKR_OK; } - /** - * + * Get key type */ static CK_RV tok_key_get_key_type(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE hkey, - CK_OBJECT_CLASS *keyclass, char **ktype, CK_ULONG *klength) { - CK_RV ret; + CK_OBJECT_CLASS *keyclass, char **ktype, + CK_ULONG *klength) +{ + CK_RV rc; char *buffer; CK_OBJECT_CLASS oclass; CK_KEY_TYPE kt; @@ -1321,15 +1388,20 @@ static CK_RV tok_key_get_key_type(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE hk CK_ATTRIBUTE template[1] = { { CKA_CLASS, &oclass, sizeof(CK_OBJECT_CLASS) } }; - ret = funcs->C_GetAttributeValue(session, hkey, template, 1); - if (ret != CKR_OK) { - printf("Object does not have CKA_CLASS attribute (error code 0x%lX)\n", - ret); - return ret; + rc = funcs->C_GetAttributeValue(session, hkey, template, 1); + if (rc != CKR_OK) { + printf( + "Object does not have CKA_CLASS attribute (error code 0x%lX: %s)\n", + rc, p11_get_ckr(rc)); + return rc; } - buffer = malloc(16); - + // the buffer holds the following string + // "public " + CKK2a(kt) with kt = "unknown key type" being the longest kt string + // or "private " + CKK2a(kt) with kt = "unknown key type" being the longest kt string + // Hence, the size of the string is 25 Bytes including the '\0' character + // Use 32 Bytes as multiple of 8 + buffer = malloc(32); if (!buffer) { return CKR_HOST_MEMORY; } @@ -1344,18 +1416,26 @@ static CK_RV tok_key_get_key_type(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE hk case CKO_PRIVATE_KEY: strcpy(buffer, "private "); break; + default: + // FIXIT - return code to represent object class invalid + rc = CKR_KEY_HANDLE_INVALID; + printf("Object handle invalid (error code 0x%lX: %s)\n", + rc, p11_get_ckr(rc)); + free(buffer); + return rc; } template[0].type = CKA_KEY_TYPE; template[0].pValue = &kt; template[0].ulValueLen = sizeof(CK_KEY_TYPE); - ret = funcs->C_GetAttributeValue(session, hkey, template, 1); - if (ret != CKR_OK) { - printf( - "Object does not have CKA_KEY_TYPE attribute (error code 0x%lX)\n", - ret); - return ret; + 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", + rc, p11_get_ckr(rc)); + free(buffer); + return rc; } + strcat(buffer, CKK2a(kt)); *klength = 0; @@ -1365,15 +1445,18 @@ static CK_RV tok_key_get_key_type(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE hk template[0].type = CKA_VALUE_LEN; template[0].pValue = &vl; template[0].ulValueLen = sizeof(CK_ULONG); - ret = funcs->C_GetAttributeValue(session, hkey, template, 1); - if (ret != CKR_OK) { - printf( - "Object does not have CKA_VALUE_LEN attribute (error code 0x%lX)\n", - ret); - return ret; + 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", + rc, p11_get_ckr(rc)); + free(buffer); + return rc; } *klength = vl * 8; break; + default: + // Fall through - template values set above + break; } *ktype = buffer; @@ -1385,8 +1468,9 @@ static CK_RV tok_key_get_key_type(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE hk /** * Check args for gen_key command. */ -static CK_RV check_args_gen_key(p11sak_kt *kt, CK_ULONG keylength, char *ECcurve) { - +static CK_RV check_args_gen_key(p11sak_kt *kt, CK_ULONG keylength, + char *ECcurve) +{ switch (*kt) { case kt_DES: case kt_3DES: @@ -1431,18 +1515,14 @@ static CK_RV check_args_gen_key(p11sak_kt *kt, CK_ULONG keylength, char *ECcurve return CKR_OK; } - /** * Check args for list_key command. */ -static CK_RV check_args_list_key(p11sak_kt *kt) { +static CK_RV check_args_list_key(p11sak_kt *kt) +{ switch (*kt) { case kt_AES: -// *kt = kt_AES; -// break; case kt_RSAPKCS: -// *kt = kt_RSAPKCS; -// break; case kt_DES: case kt_3DES: case kt_EC: @@ -1460,11 +1540,35 @@ static CK_RV check_args_list_key(p11sak_kt *kt) { return CKR_OK; } /** + * Check args for remove-key command. + */ +static CK_RV check_args_remove_key(p11sak_kt *kt) +{ + switch (*kt) { + case kt_DES: + case kt_3DES: + case kt_AES: + case kt_RSAPKCS: + case kt_EC: + case kt_GENERIC: + case kt_SECRET: + case kt_PUBLIC: + case kt_PRIVATE: + break; + default: + printf("Cipher key type [%d] is not set or not supported\n", *kt); + print_gen_help(); + return CKR_ARGUMENTS_BAD; + } + + return CKR_OK; +} +/** * Parse p11sak command from argv. */ -static p11sak_cmd parse_cmd(const char *arg) { +static p11sak_cmd parse_cmd(const char *arg) +{ p11sak_cmd cmd = no_cmd; - ; if ((strcmp(arg, "generate-key") == 0) || (strcmp(arg, "gen-key") == 0) || (strcmp(arg, "gen") == 0)) { @@ -1472,6 +1576,9 @@ static p11sak_cmd parse_cmd(const char *arg) { } else if ((strcmp(arg, "list-key") == 0) || (strcmp(arg, "ls-key") == 0) || (strcmp(arg, "ls") == 0)) { cmd = list_key; + } else if ((strcmp(arg, "remove-key") == 0) || (strcmp(arg, "rm-key") == 0) + || (strcmp(arg, "rm") == 0)) { + cmd = remove_key; } else { printf("Unknown command %s\n", cmd2str(cmd)); cmd = no_cmd; @@ -1479,7 +1586,8 @@ static p11sak_cmd parse_cmd(const char *arg) { return cmd; } -static CK_BBOOL last_parm_is_help(char *argv[], int argc) { +static CK_BBOOL last_parm_is_help(char *argv[], int argc) +{ if (strcmp(argv[argc - 1], "-h") == 0 || strcmp(argv[argc - 1], "--help") == 0) { return 1; @@ -1488,26 +1596,29 @@ static CK_BBOOL last_parm_is_help(char *argv[], int argc) { return 0; } -static CK_ULONG get_ulong_arg(int pos, char *argv[], int argc) { +static CK_ULONG get_ulong_arg(int pos, char *argv[], int argc) +{ if (pos < argc) return atol(argv[pos]); else return 0; } -static char* get_string_arg(int pos, char *argv[], int argc) { +static char* get_string_arg(int pos, char *argv[], int argc) +{ if (pos < argc) return argv[pos]; else return NULL; } - /** * Parse the list-key args. */ static CK_RV parse_list_key_args(char *argv[], int argc, p11sak_kt *kt, - CK_ULONG *keylength, CK_SLOT_ID *slot, char **pin, int *long_print) { - CK_RV ret; + CK_ULONG *keylength, CK_SLOT_ID *slot, + char **pin, int *long_print) +{ + CK_RV rc; int i; if (last_parm_is_help(argv, argc)) { @@ -1523,7 +1634,6 @@ static CK_RV parse_list_key_args(char *argv[], int argc, p11sak_kt *kt, } else if (strcmp(argv[i], "3DES") == 0 || strcmp(argv[i], "3des") == 0) { *kt = kt_3DES; - *keylength = 192; } else if (strcmp(argv[i], "AES") == 0 || strcmp(argv[i], "aes") == 0) { *kt = kt_AES; } else if (strcmp(argv[i], "RSA") == 0 || strcmp(argv[i], "rsa") == 0) { @@ -1542,12 +1652,22 @@ static CK_RV parse_list_key_args(char *argv[], int argc, p11sak_kt *kt, } else if (strcmp(argv[i], "PRIVATE") == 0 || strcmp(argv[i], "private") == 0) { *kt = kt_PRIVATE; - /* Get options */ + /* Get options */ } else if (strcmp(argv[i], "--slot") == 0) { - *slot = (CK_ULONG) atol(argv[i + 1]); + if (i + 1 < argc) { + *slot = (CK_ULONG) atol(argv[i + 1]); + } else { + printf("--slot argument is missing.\n"); + return CKR_ARGUMENTS_BAD; + } i++; } else if (strcmp(argv[i], "--pin") == 0) { - *pin = argv[i + 1]; + if (i + 1 < argc) { + *pin = argv[i + 1]; + } else { + printf("--pin argument is missing.\n"); + return CKR_ARGUMENTS_BAD; + } i++; } else if ((strcmp(argv[i], "-l") == 0) || (strcmp(argv[i], "--long") == 0)) { @@ -1557,28 +1677,30 @@ static CK_RV parse_list_key_args(char *argv[], int argc, p11sak_kt *kt, print_listkeys_help(); return CKR_ARGUMENTS_BAD; } else { - printf("Unknown argument or option %s for command list-key\n", argv[i]); + printf("Unknown argument or option %s for command list-key\n", + argv[i]); return CKR_ARGUMENTS_BAD; } } - ret = check_args_list_key(kt); + rc = check_args_list_key(kt); if (*slot == 0) { printf("Slot number must be specified.\n"); - ret = CKR_ARGUMENTS_BAD; + rc = CKR_ARGUMENTS_BAD; } - - return ret; + return rc; } /** * Parse the generate-key args. */ static CK_RV parse_gen_key_args(char *argv[], int argc, p11sak_kt *kt, - CK_ULONG *keylength, char **ECcurve, CK_SLOT_ID *slot, - char **pin, CK_ULONG *exponent, char **label, char **attr_string) { - CK_RV ret; + CK_ULONG *keylength, char **ECcurve, + CK_SLOT_ID *slot, char **pin, CK_ULONG *exponent, + char **label, char **attr_string) +{ + CK_RV rc; int i; for (i = 2; i < argc; i++) { @@ -1602,28 +1724,54 @@ static CK_RV parse_gen_key_args(char *argv[], int argc, p11sak_kt *kt, *kt = kt_EC; *ECcurve = get_string_arg(i + 1, argv, argc); i++; - /* Get options */ + /* Get options */ } else if (strcmp(argv[i], "--slot") == 0) { - *slot = (CK_ULONG) atol(argv[i + 1]); + if (i + 1 < argc) { + *slot = (CK_ULONG) atol(argv[i + 1]); + } else { + printf("--slot argument is missing.\n"); + return CKR_ARGUMENTS_BAD; + } i++; } else if (strcmp(argv[i], "--pin") == 0) { - *pin = argv[i + 1]; + if (i + 1 < argc) { + *pin = argv[i + 1]; + } else { + printf("--pin argument is missing.\n"); + return CKR_ARGUMENTS_BAD; + } i++; } else if (strcmp(argv[i], "--label") == 0) { - *label = argv[i + 1]; + if (i + 1 < argc) { + *label = argv[i + 1]; + } else { + printf("--label