Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package libzpc for openSUSE:Factory checked in at 2024-01-15 22:20:19 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libzpc (Old) and /work/SRC/openSUSE:Factory/.libzpc.new.21961 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libzpc" Mon Jan 15 22:20:19 2024 rev:6 rq:1138764 version:1.2.0 Changes: -------- --- /work/SRC/openSUSE:Factory/libzpc/libzpc.changes 2023-09-21 22:23:37.626125418 +0200 +++ /work/SRC/openSUSE:Factory/.libzpc.new.21961/libzpc.changes 2024-01-15 22:20:45.594219730 +0100 @@ -1,0 +2,9 @@ +Mon Jan 15 07:16:57 UTC 2024 - Nikolay Gueorguiev <nikolay.gueorgu...@suse.com> + +- Upgrade libzpc to version 1.2.0 (jsc#PED-3335) + * Support for get/set intermediate iv for CBC and XTS + * Support for internal iv for GCM + * Exploit KBLOB2PROTK3 ioctl for clear AES and EC keys + * Fix AES EP11 version 6 key support for generate and import_clear + +------------------------------------------------------------------- Old: ---- libzpc-1.1.1.tar.gz New: ---- libzpc-1.2.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libzpc.spec ++++++ --- /var/tmp/diff_new_pack.ddMcbG/_old 2024-01-15 22:20:46.834265303 +0100 +++ /var/tmp/diff_new_pack.ddMcbG/_new 2024-01-15 22:20:46.834265303 +0100 @@ -1,7 +1,7 @@ # # spec file for package libzpc # -# Copyright (c) 2023 SUSE LLC +# Copyright (c) 2024 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,7 +17,7 @@ Name: libzpc -Version: 1.1.1 +Version: 1.2.0 Release: 0 Summary: IBM Z Protected-key Crypto library License: Apache-2.0 ++++++ libzpc-1.1.1.tar.gz -> libzpc-1.2.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzpc-1.1.1/.travis.yml new/libzpc-1.2.0/.travis.yml --- old/libzpc-1.1.1/.travis.yml 2023-09-15 12:52:28.000000000 +0200 +++ new/libzpc-1.2.0/.travis.yml 2024-01-12 10:26:07.000000000 +0100 @@ -1,6 +1,6 @@ arch: s390x os: linux -dist: bionic +dist: focal language: cpp sudo: required env: | diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzpc-1.1.1/CHANGES.md new/libzpc-1.2.0/CHANGES.md --- old/libzpc-1.1.1/CHANGES.md 2023-09-15 12:52:28.000000000 +0200 +++ new/libzpc-1.2.0/CHANGES.md 2024-01-12 10:26:07.000000000 +0100 @@ -1,6 +1,13 @@ Changelog {#changes} === +**Version 1.2.0** + +- Support for get/set intermediate iv for CBC and XTS +- Support for internal iv for GCM +- Fix AES EP11 version 6 key support for generate and import_clear +- Exploit KBLOB2PROTK3 ioctl for clear AES and EC keys + **Version 1.1.1** - Exploit PKEY_KBLOB2PROTK2 for AES EP11 version 6 keys diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzpc-1.1.1/CMakeLists.txt new/libzpc-1.2.0/CMakeLists.txt --- old/libzpc-1.1.1/CMakeLists.txt 2023-09-15 12:52:28.000000000 +0200 +++ new/libzpc-1.2.0/CMakeLists.txt 2024-01-12 10:26:07.000000000 +0100 @@ -2,8 +2,8 @@ set(ZPC_NAME "libzpc" ) set(ZPC_DESCRIPTION "IBM Z Protected-key Crypto library") set(ZPC_VERSION_MAJOR 1 ) -set(ZPC_VERSION_MINOR 1 ) -set(ZPC_VERSION_PATCH 1 ) +set(ZPC_VERSION_MINOR 2 ) +set(ZPC_VERSION_PATCH 0 ) ########################################################### cmake_minimum_required( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzpc-1.1.1/include/zpc/aes_cbc.h new/libzpc-1.2.0/include/zpc/aes_cbc.h --- old/libzpc-1.1.1/include/zpc/aes_cbc.h 2023-09-15 12:52:28.000000000 +0200 +++ new/libzpc-1.2.0/include/zpc/aes_cbc.h 2024-01-12 10:26:07.000000000 +0100 @@ -53,6 +53,26 @@ __attribute__((visibility("default"))) int zpc_aes_cbc_set_iv(struct zpc_aes_cbc *ctx, const unsigned char *iv); /** + * Get the intermediate initialization vector to be used in the context + * of an AES-CBC operation. + * \param[in,out] ctx AES-CBC context + * \param[out] iv application provided buffer with 16 bytes size to + * receive the 16 byte intermediate iv + * \return 0 on success. Otherwise, a non-zero error code is returned. + */ +__attribute__((visibility("default"))) +int zpc_aes_cbc_get_intermediate_iv(struct zpc_aes_cbc *ctx, unsigned char iv[16]); +/** + * Set the intermediate initialization vector to be used in the context + * of an AES-CBC operation. An initial iv must be set before via + * zpc_aes_cbc_set_iv. + * \param[in,out] ctx AES-CBC context + * \param[in] iv 16 byte intermediate iv + * \return 0 on success. Otherwise, a non-zero error code is returned. + */ +__attribute__((visibility("default"))) +int zpc_aes_cbc_set_intermediate_iv(struct zpc_aes_cbc *ctx, const unsigned char iv[16]); +/** * Do an AES-CBC encryption operation. * \param[in,out] ctx AES-CBC context * \param[out] ct ciphertext diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzpc-1.1.1/include/zpc/aes_gcm.h new/libzpc-1.2.0/include/zpc/aes_gcm.h --- old/libzpc-1.1.1/include/zpc/aes_gcm.h 2023-09-15 12:52:28.000000000 +0200 +++ new/libzpc-1.2.0/include/zpc/aes_gcm.h 2024-01-12 10:26:07.000000000 +0100 @@ -43,6 +43,18 @@ __attribute__((visibility("default"))) int zpc_aes_gcm_set_key(struct zpc_aes_gcm *ctx, struct zpc_aes_key *key); /** + * Create the initialization vector to be used in the context + * of an AES-GCM operation. The minimum and recommended iv length is 12 bytes. + * \param[in,out] ctx AES-GCM context + * \param[in/out] iv application provided buffer of at least ivlen bytes to + * receive the internally created initialization vector + * \param[in] ivlen initialization vector length [bytes] + * \return 0 on success. Otherwise, a non-zero error code is returned. + */ +__attribute__((visibility("default"))) +int zpc_aes_gcm_create_iv(struct zpc_aes_gcm *ctx, unsigned char *iv, + size_t ivlen); +/** * Set the initialization vector to be used in the context * of an AES-GCM operation. * \param[in,out] ctx AES-GCM context diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzpc-1.1.1/include/zpc/aes_xts.h new/libzpc-1.2.0/include/zpc/aes_xts.h --- old/libzpc-1.1.1/include/zpc/aes_xts.h 2023-09-15 12:52:28.000000000 +0200 +++ new/libzpc-1.2.0/include/zpc/aes_xts.h 2024-01-12 10:26:07.000000000 +0100 @@ -55,6 +55,26 @@ __attribute__((visibility("default"))) int zpc_aes_xts_set_iv(struct zpc_aes_xts *ctx, const unsigned char *iv); /** + * Get the intermediate initialization vector to be used in the context + * of an AES-XTS operation. + * \param[in,out] ctx AES-XTS context + * \param[out] iv application provided buffer with 16 bytes size to + * receive the 16 byte intermediate iv + * \return 0 on success. Otherwise, a non-zero error code is returned. + */ +__attribute__((visibility("default"))) +int zpc_aes_xts_get_intermediate_iv(struct zpc_aes_xts *ctx, unsigned char iv[16]); +/** + * Set the intermediate initialization vector to be used in the context + * of an AES-XTS operation. An initial iv must be set before via + * zpc_aes_xts_set_iv. + * \param[in,out] ctx AES-XTS context + * \param[in] iv 16 byte intermediate iv + * \return 0 on success. Otherwise, a non-zero error code is returned. + */ +__attribute__((visibility("default"))) +int zpc_aes_xts_set_intermediate_iv(struct zpc_aes_xts *ctx, const unsigned char iv[16]); +/** * Do an AES-XTS encryption operation. * \param[in,out] ctx AES-XTS context * \param[out] ct ciphertext diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzpc-1.1.1/include/zpc/error.h new/libzpc-1.2.0/include/zpc/error.h --- old/libzpc-1.1.1/include/zpc/error.h 2023-09-15 12:52:28.000000000 +0200 +++ new/libzpc-1.2.0/include/zpc/error.h 2024-01-12 10:26:07.000000000 +0100 @@ -458,6 +458,18 @@ # define ZPC_ERROR_AES_NO_CCA_CIPHERKEY_TOKEN 75 /** + * \def ZPC_ERROR_RNDGEN + * \brief error creating random bytes. + */ +# define ZPC_ERROR_RNDGEN 76 + +/** + * \def ZPC_ERROR_GCM_IV_CREATED_INTERNALLY + * \brief invalid usage of a gcm context with an internally created iv. + */ +# define ZPC_ERROR_GCM_IV_CREATED_INTERNALLY 77 + +/** * \fn const char *zpc_error_string(int err) * \brief Map an error code to the corresponding error string. * \param[in] err An error code. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzpc-1.1.1/libzpc.map new/libzpc-1.2.0/libzpc.map --- old/libzpc-1.1.1/libzpc.map 2023-09-15 12:52:28.000000000 +0200 +++ new/libzpc-1.2.0/libzpc.map 2024-01-12 10:26:07.000000000 +0100 @@ -84,3 +84,15 @@ local: *; } ZPC_1.0; +ZPC_1.2.0 { +global: + zpc_aes_xts_get_intermediate_iv; + zpc_aes_xts_set_intermediate_iv; + zpc_aes_cbc_get_intermediate_iv; + zpc_aes_cbc_set_intermediate_iv; + zpc_aes_gcm_create_iv; + +local: *; +} ZPC_1.1.0; + + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzpc-1.1.1/libzpc.spec new/libzpc-1.2.0/libzpc.spec --- old/libzpc-1.1.1/libzpc.spec 2023-09-15 12:52:28.000000000 +0200 +++ new/libzpc-1.2.0/libzpc.spec 2024-01-12 10:26:07.000000000 +0100 @@ -1,5 +1,5 @@ Name: libzpc -Version: 1.1.1 +Version: 1.2.0 Release: 1%{?dist} Summary: Open Source library for the IBM Z Protected-key crypto feature @@ -88,6 +88,10 @@ %changelog +* Thu Dec 07 2023 Joerg Schmidbauer <jschm...@de.ibm.com> - 1.2.0 +- Support for get/set intermediate iv for CBC and XTS. +- Support for internal iv for GCM. + * Fri Sep 15 2023 Joerg Schmidbauer <jschm...@de.ibm.com> - 1.1.1 - Exploit PKEY_KBLOB2PROTK2 for AES EP11 version 6 keys. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzpc-1.1.1/src/aes_cbc.c new/libzpc-1.2.0/src/aes_cbc.c --- old/libzpc-1.1.1/src/aes_cbc.c 2023-09-15 12:52:28.000000000 +0200 +++ new/libzpc-1.2.0/src/aes_cbc.c 2024-01-12 10:26:07.000000000 +0100 @@ -24,7 +24,7 @@ #include <stdlib.h> #include <string.h> -static void __aes_cbc_set_iv(struct zpc_aes_cbc *, const u8 *); +static void __aes_cbc_set_iv(struct zpc_aes_cbc *, const u8 iv[16]); static int __aes_cbc_crypt(struct zpc_aes_cbc *, u8 *, const u8 *, size_t, unsigned long); static void __aes_cbc_reset(struct zpc_aes_cbc *); @@ -188,6 +188,83 @@ } int +zpc_aes_cbc_get_intermediate_iv(struct zpc_aes_cbc *aes_cbc, unsigned char iv[16]) +{ + int rc; + + if (pkeyfd < 0) { + rc = ZPC_ERROR_DEVPKEY; + goto ret; + } + if (!hwcaps.aes_cbc) { + rc = ZPC_ERROR_HWCAPS; + goto ret; + } + if (aes_cbc == NULL) { + rc = ZPC_ERROR_ARG1NULL; + goto ret; + } + + if (iv == NULL) { + rc = ZPC_ERROR_ARG2NULL; + goto ret; + } + + if (aes_cbc->iv_set != 1) { + rc = ZPC_ERROR_IVNOTSET; + goto ret; + } + + memcpy(iv, aes_cbc->param.cv, 16); + rc = 0; + +ret: + DEBUG("return %d (%s)", rc, zpc_error_string(rc)); + return rc; +} + +int +zpc_aes_cbc_set_intermediate_iv(struct zpc_aes_cbc *aes_cbc, const unsigned char iv[16]) +{ + int rc; + + if (pkeyfd < 0) { + rc = ZPC_ERROR_DEVPKEY; + goto ret; + } + if (!hwcaps.aes_cbc) { + rc = ZPC_ERROR_HWCAPS; + goto ret; + } + if (aes_cbc == NULL) { + rc = ZPC_ERROR_ARG1NULL; + goto ret; + } + if (iv == NULL) { + rc = ZPC_ERROR_ARG2NULL; + goto ret; + } + + if (aes_cbc->key_set != 1) { + rc = ZPC_ERROR_KEYNOTSET; + goto ret; + } + + if (aes_cbc->iv_set != 1) { + rc = ZPC_ERROR_IVNOTSET; + goto ret; + } + + __aes_cbc_set_iv(aes_cbc, iv); + DEBUG("aes-cbc context at %p: intermediate iv set", aes_cbc); + aes_cbc->iv_set = 1; + rc = 0; +ret: + DEBUG("return %d (%s)", rc, zpc_error_string(rc)); + return rc; +} + +int zpc_aes_cbc_encrypt(struct zpc_aes_cbc *aes_cbc, u8 * c, const u8 * m, size_t mlen) { @@ -392,7 +469,7 @@ } static void -__aes_cbc_set_iv(struct zpc_aes_cbc *aes_cbc, const u8 * iv) +__aes_cbc_set_iv(struct zpc_aes_cbc *aes_cbc, const u8 iv[16]) { assert(aes_cbc != NULL); assert(iv != NULL); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzpc-1.1.1/src/aes_gcm.c new/libzpc-1.2.0/src/aes_gcm.c --- old/libzpc-1.1.1/src/aes_gcm.c 2023-09-15 12:52:28.000000000 +0200 +++ new/libzpc-1.2.0/src/aes_gcm.c 2024-01-12 10:26:07.000000000 +0100 @@ -150,6 +150,68 @@ } int +zpc_aes_gcm_create_iv(struct zpc_aes_gcm *aes_gcm, u8 *iv, size_t ivlen) +{ + u8 *iv_tmp = NULL; + int rc; + + if (pkeyfd < 0) { + rc = ZPC_ERROR_DEVPKEY; + goto ret; + } + if (!hwcaps.aes_gcm) { + rc = ZPC_ERROR_HWCAPS; + goto ret; + } + if (aes_gcm == NULL) { + rc = ZPC_ERROR_ARG1NULL; + goto ret; + } + if (iv == NULL) { + rc = ZPC_ERROR_ARG2NULL; + goto ret; + } + + /* 12 <= iv bit-length <= 2^64 - 1, iv bit-length % 8 == 0 */ + if (ivlen < GCM_RECOMMENDED_IV_LENGTH || ivlen > GCM_MAX_IV_LENGTH) { + rc = ZPC_ERROR_IVSIZE; + goto ret; + } + if (aes_gcm->key_set != 1) { + rc = ZPC_ERROR_KEYNOTSET; + goto ret; + } + + iv_tmp = calloc(ivlen, 1); + if (!iv_tmp) { + rc = ZPC_ERROR_MALLOC; + goto ret; + } + + if (local_rng(iv_tmp, ivlen) != 0) { + rc = ZPC_ERROR_RNDGEN; + goto ret; + } + + aes_gcm->iv_created = 0; + rc = zpc_aes_gcm_set_iv(aes_gcm, iv_tmp, ivlen); + if (rc != 0) + goto ret; + + DEBUG("aes-gcm context at %p: iv created and set", aes_gcm); + aes_gcm->iv_set = 1; + aes_gcm->iv_created = 1; + memcpy(iv, iv_tmp, ivlen); + rc = 0; + +ret: + if (iv_tmp != NULL) + free(iv_tmp); + DEBUG("return %d (%s)", rc, zpc_error_string(rc)); + return rc; +} + +int zpc_aes_gcm_set_iv(struct zpc_aes_gcm *aes_gcm, const u8 * iv, size_t ivlen) { struct cpacf_kma_gcm_aes_param *param; @@ -179,7 +241,7 @@ goto ret; } /* 1 <= iv bit-length <= 2^64 - 1, iv bit-length % 8 == 0 */ - if (ivlen < 1 || ivlen > SIZE_MAX - 16) { + if (ivlen < 1 || ivlen > GCM_MAX_IV_LENGTH) { rc = ZPC_ERROR_IVSIZE; goto ret; } @@ -188,6 +250,10 @@ rc = ZPC_ERROR_KEYNOTSET; goto ret; } + if (aes_gcm->iv_created == 1) { + rc = ZPC_ERROR_GCM_IV_CREATED_INTERNALLY; + goto ret; + } rc = -1; for (i = 0; i < 2 && rc != 0; i++) { @@ -282,7 +348,7 @@ rc = ZPC_ERROR_ARG5NULL; goto ret; } - if (aadlen > (2ULL << 61) - 1) { + if (aes_gcm->param.taadl / 8 + aadlen > GCM_MAX_TOTAL_AAD_LENGTH) { rc = ZPC_ERROR_AADLEN; goto ret; } @@ -295,7 +361,7 @@ rc = ZPC_ERROR_ARG7NULL; goto ret; } - if (mlen > (2ULL << 36) - 256) { + if (aes_gcm->param.tpcl / 8 + mlen > GCM_MAX_TOTAL_PLAINTEXT_LENGTH) { rc = ZPC_ERROR_MLEN; goto ret; } @@ -411,7 +477,7 @@ rc = ZPC_ERROR_ARG5NULL; goto ret; } - if (aadlen > (2ULL << 61) - 1) { + if (aes_gcm->param.taadl / 8 + aadlen > GCM_MAX_TOTAL_AAD_LENGTH) { rc = ZPC_ERROR_AADLEN; goto ret; } @@ -424,7 +490,7 @@ rc = ZPC_ERROR_ARG7NULL; goto ret; } - if (clen > (2ULL << 36) - 256) { + if (aes_gcm->param.tpcl / 8 + clen > GCM_MAX_TOTAL_PLAINTEXT_LENGTH) { rc = ZPC_ERROR_CLEN; goto ret; } @@ -441,6 +507,10 @@ rc = ZPC_ERROR_IVNOTSET; goto ret; } + if (aes_gcm->iv_created) { + rc = ZPC_ERROR_GCM_IV_CREATED_INTERNALLY; + goto ret; + } if ((m != NULL && c != NULL) || tag != NULL) { flags |= CPACF_KMA_LAAD; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzpc-1.1.1/src/aes_gcm_local.h new/libzpc-1.2.0/src/aes_gcm_local.h --- old/libzpc-1.1.1/src/aes_gcm_local.h 2023-09-15 12:52:28.000000000 +0200 +++ new/libzpc-1.2.0/src/aes_gcm_local.h 2024-01-12 10:26:07.000000000 +0100 @@ -17,6 +17,27 @@ * Internal aes_gcm interface. */ +#define GCM_RECOMMENDED_IV_LENGTH 12 + +/* + * NIST SP 800-38d: 1 <= bitlen(iv) <= 2^64 - 1 + * => 1 <= bytelen(iv) <= 2^61 - 1 + */ +#define GCM_MAX_IV_LENGTH ((2ULL << 61) - 1) + +/* + * NIST SP 800-38d: bitlen(A) <= 2^64 - 1 + * => 0 <= bytelen(A) <= 2^61 - 1 + */ +#define GCM_MAX_TOTAL_AAD_LENGTH ((2ULL << 61) - 1) + +/* + * NIST SP 800-38d: bitlen(P) <= 2^39 - 256; + * => 0 <= bytelen(P) <= 2^36 - 32 + */ +#define GCM_MAX_TOTAL_PLAINTEXT_LENGTH ((2ULL << 36) - 32) + + struct zpc_aes_gcm { struct cpacf_kma_gcm_aes_param param; struct zpc_aes_key *aes_key; @@ -25,6 +46,7 @@ int key_set; int iv_set; + int iv_created; }; #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzpc-1.1.1/src/aes_key.c new/libzpc-1.2.0/src/aes_key.c --- old/libzpc-1.1.1/src/aes_key.c 2023-09-15 12:52:28.000000000 +0200 +++ new/libzpc-1.2.0/src/aes_key.c 2024-01-12 10:26:07.000000000 +0100 @@ -30,6 +30,7 @@ static int aes_key_blob_is_pkey_extractable(struct zpc_aes_key *aes_key, const unsigned char *buf, size_t buflen); static int aes_key_add_ep11_header(struct zpc_aes_key *aes_key); +static int aes_key_blob_has_a_session(struct zpc_aes_key *aes_key); int zpc_aes_key_alloc(struct zpc_aes_key **aes_key) @@ -418,7 +419,7 @@ zpc_aes_key_import_clear(struct zpc_aes_key *aes_key, const unsigned char *key) { struct pkey_clr2seck2 clr2seck2; - unsigned int flags; + unsigned int flags, hdr_to_add = 0; int rc, rv; UNUSED(rv); @@ -469,31 +470,62 @@ clr2seck2.apqns = aes_key->apqns; clr2seck2.apqn_entries = aes_key->napqns; clr2seck2.type = aes_key->type; + if (aes_key->type == ZPC_AES_KEY_TYPE_EP11) + clr2seck2.type = TOKVER_EP11_AES_WITH_HEADER; /* 0x06 */ clr2seck2.size = aes_key->keysize; clr2seck2.keygenflags = flags; memcpy(&clr2seck2.clrkey, key, aes_key->keysize / 8); clr2seck2.key = aes_key->cur.sec; clr2seck2.keylen = sizeof(aes_key->cur.sec); + /* + * If it's an EP11 key, we first try to import the clear key as a type 6 key + * (TOKVER_EP11_AES_WITH_HEADER). This may fail on older kernels. If it + * fails, we try to import as a type 3 (TOKVER_EP11_AES) key and add the + * type 6 header manually below. If successful, we end up with a type 6 + * key in both cases. + */ rc = ioctl(pkeyfd, PKEY_CLR2SECK2, &clr2seck2); + DEBUG("ioctl PKEY_CLR2SECK2 as aes ep11 type 6 key returned %d", rc); if (rc != 0) { - rc = ZPC_ERROR_IOCTLCLR2SECK2; - goto ret; + if (aes_key->type == ZPC_AES_KEY_TYPE_EP11) { + DEBUG("ioctl PKEY_CLR2SECK2 as aes ep11 type 6 key returned %d", rc); + /* Retry with a type 3 key */ + clr2seck2.type = TOKVER_EP11_AES; /* 0x03 */ + rc = ioctl(pkeyfd, PKEY_CLR2SECK2, &clr2seck2); + DEBUG("ioctl PKEY_CLR2SECK2 as aes ep11 type 3 key returned %d", rc); + if (rc != 0) { + rc = ZPC_ERROR_IOCTLCLR2SECK2; + goto ret; + } + hdr_to_add = 1; + } else { + rc = ZPC_ERROR_IOCTLCLR2SECK2; + goto ret; + } } aes_key->cur.seclen = clr2seck2.keylen; - rc = aes_key_sec2prot(aes_key, AES_KEY_SEC_CUR); + rc = aes_key_clr2prot(aes_key, key, aes_key->keysize / 8); if (rc) { - goto ret; + rc = aes_key_sec2prot(aes_key, AES_KEY_SEC_CUR); + if (rc) { + goto ret; + } } - if (aes_key->type == ZPC_AES_KEY_TYPE_EP11) { + if (aes_key->type == ZPC_AES_KEY_TYPE_EP11 && hdr_to_add) { rc = aes_key_add_ep11_header(aes_key); if (rc) goto ret; } + if (aes_key->type == ZPC_AES_KEY_TYPE_EP11 && aes_key_blob_has_a_session(aes_key)) + DEBUG("This aes ep11 key has a session id"); + else + DEBUG("This aes ep11 key has no session id"); + DEBUG("aes key at %p: key set", aes_key); aes_key->key_set = 1; rc = 0; @@ -656,7 +688,7 @@ { struct pkey_genseck2 genseck2; struct pkey_genprotk genprotk; - unsigned int flags; + unsigned int flags, hdr_to_add = 0; int rc, rv; UNUSED(rv); @@ -733,15 +765,38 @@ genseck2.apqns = aes_key->apqns; genseck2.apqn_entries = aes_key->napqns; genseck2.type = aes_key->type; + if (aes_key->type == ZPC_AES_KEY_TYPE_EP11) + genseck2.type = TOKVER_EP11_AES_WITH_HEADER; /* 0x06 */ genseck2.size = aes_key->keysize; genseck2.keygenflags = flags; genseck2.key = aes_key->cur.sec; genseck2.keylen = sizeof(aes_key->cur.sec); + /* + * If it's an EP11 key, we first try to generate a type 6 key + * (TOKVER_EP11_AES_WITH_HEADER). This may fail on older kernels. If it + * fails, we try to generate a type 3 (TOKVER_EP11_AES) key and add the + * type 6 header manually below. If successful, we end up with a type 6 + * key in both cases. + */ rc = ioctl(pkeyfd, PKEY_GENSECK2, &genseck2); + DEBUG("ioctl PKEY_GENSECK2 as aes ep11 type 6 key returned %d", rc); if (rc != 0) { - rc = ZPC_ERROR_IOCTLGENSECK2; - goto ret; + if (aes_key->type == ZPC_AES_KEY_TYPE_EP11) { + DEBUG("ioctl PKEY_GENSECK2 as aes ep11 type 6 key returned %d", rc); + /* Retry to generate a type 3 key */ + genseck2.type = TOKVER_EP11_AES; /* 0x03 */; + rc = ioctl(pkeyfd, PKEY_GENSECK2, &genseck2); + DEBUG("ioctl PKEY_GENSECK2 as aes ep11 type 3 key returned %d", rc); + if (rc != 0) { + rc = ZPC_ERROR_IOCTLGENSECK2; + goto ret; + } + hdr_to_add = 1; + } else { + rc = ZPC_ERROR_IOCTLGENSECK2; + goto ret; + } } aes_key->cur.seclen = genseck2.keylen; @@ -750,12 +805,17 @@ if (rc) goto ret; - if (aes_key->type == ZPC_AES_KEY_TYPE_EP11) { + if (aes_key->type == ZPC_AES_KEY_TYPE_EP11 && hdr_to_add) { rc = aes_key_add_ep11_header(aes_key); if (rc) goto ret; } + if (aes_key->type == ZPC_AES_KEY_TYPE_EP11 && aes_key_blob_has_a_session(aes_key)) + DEBUG("This aes ep11 key has a session id"); + else + DEBUG("This aes ep11 key has no session id"); + DEBUG("aes key at %p: key set to generated secure key", aes_key); aes_key->key_set = 1; rc = 0; @@ -1101,6 +1161,47 @@ return aes_key_sec2prot_without_header(aes_key, sec); } +int aes_key_clr2prot(struct zpc_aes_key *aes_key, const unsigned char *key, + unsigned int keylen) +{ + struct pkey_kblob2pkey3 io; + unsigned char buf[sizeof(struct clearkeytoken) + 32]; + struct clearkeytoken *clrtok = (struct clearkeytoken *)&buf; + int rc; + + memset(buf, 0, sizeof(buf)); + clrtok->version = 0x02; + switch (keylen) { + case 16: + clrtok->keytype = PKEY_KEYTYPE_AES_128; + break; + case 24: + clrtok->keytype = PKEY_KEYTYPE_AES_192; + break; + default: + clrtok->keytype = PKEY_KEYTYPE_AES_256; + break; + } + memcpy(clrtok->clearkey, key, keylen); + clrtok->len = keylen; + + memset(&io, 0, sizeof(io)); + io.key = buf; + io.keylen = sizeof(struct clearkeytoken) + keylen; + io.apqns = aes_key->apqns; + io.apqn_entries = aes_key->napqns; + io.pkeytype = aes_key->type; + io.pkeylen = sizeof(aes_key->prot.protkey); + io.pkey = (unsigned char *)&aes_key->prot.protkey; + + rc = ioctl(pkeyfd, PKEY_KBLOB2PROTK3, &io); + if (rc != 0) { + return ZPC_ERROR_IOCTLBLOB2PROTK3; + } + + return 0; +} + int aes_key_check(const struct zpc_aes_key *aes_key) { @@ -1198,7 +1299,18 @@ ep11hdr = (struct ep11kblob_header *)aes_key->cur.sec; ep11hdr->len = sizeof(struct ep11kblob_header) + aes_key->cur.seclen; ep11hdr->version = TOKVER_EP11_AES_WITH_HEADER; + ep11hdr->bitlen = aes_key->keysize; aes_key->cur.seclen = ep11hdr->len; return 0; } + +static int aes_key_blob_has_a_session(struct zpc_aes_key *aes_key) +{ + u8 session[32] = { 0, }; + + if (memcmp(aes_key->cur.sec + sizeof(struct ep11kblob_header), session, 32) == 0) + return 0; + + return 1; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzpc-1.1.1/src/aes_key_local.h new/libzpc-1.2.0/src/aes_key_local.h --- old/libzpc-1.1.1/src/aes_key_local.h 2023-09-15 12:52:28.000000000 +0200 +++ new/libzpc-1.2.0/src/aes_key_local.h 2024-01-12 10:26:07.000000000 +0100 @@ -62,5 +62,7 @@ int aes_key_sec2prot(struct zpc_aes_key *, enum aes_key_sec sec); int aes_key_check(const struct zpc_aes_key *); +int aes_key_clr2prot(struct zpc_aes_key *, const unsigned char *key, + unsigned int keylen); #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzpc-1.1.1/src/aes_xts.c new/libzpc-1.2.0/src/aes_xts.c --- old/libzpc-1.1.1/src/aes_xts.c 2023-09-15 12:52:28.000000000 +0200 +++ new/libzpc-1.2.0/src/aes_xts.c 2024-01-12 10:26:07.000000000 +0100 @@ -25,6 +25,7 @@ #include <string.h> static int __aes_xts_set_iv(struct zpc_aes_xts *, const u8 *); +static int __aes_xts_set_intermediate_iv(struct zpc_aes_xts *, const u8 iv[16]); static int __aes_xts_crypt(struct zpc_aes_xts *, u8 *, const u8 *, size_t, unsigned long); static void __aes_xts_reset(struct zpc_aes_xts *); @@ -260,6 +261,87 @@ } int +zpc_aes_xts_get_intermediate_iv(struct zpc_aes_xts *aes_xts, unsigned char iv[16]) +{ + int rc, off1; + + if (pkeyfd < 0) { + rc = ZPC_ERROR_DEVPKEY; + goto ret; + } + if (!hwcaps.aes_xts) { + rc = ZPC_ERROR_HWCAPS; + goto ret; + } + if (aes_xts == NULL) { + rc = ZPC_ERROR_ARG1NULL; + goto ret; + } + + if (iv == NULL) { + rc = ZPC_ERROR_ARG2NULL; + goto ret; + } + + if (aes_xts->iv_set != 1) { + rc = ZPC_ERROR_IVNOTSET; + goto ret; + } + + off1 = AES_XTS_KM_XTSPARAM(aes_xts->aes_key1->keysize); + memcpy(iv, aes_xts->param_km + off1, 16); + rc = 0; + +ret: + DEBUG("return %d (%s)", rc, zpc_error_string(rc)); + return rc; +} + +int +zpc_aes_xts_set_intermediate_iv(struct zpc_aes_xts *aes_xts, const unsigned char iv[16]) +{ + int rc; + + if (pkeyfd < 0) { + rc = ZPC_ERROR_DEVPKEY; + goto ret; + } + if (!hwcaps.aes_xts) { + rc = ZPC_ERROR_HWCAPS; + goto ret; + } + if (aes_xts == NULL) { + rc = ZPC_ERROR_ARG1NULL; + goto ret; + } + if (iv == NULL) { + rc = ZPC_ERROR_ARG2NULL; + goto ret; + } + + if (aes_xts->key_set != 1) { + rc = ZPC_ERROR_KEYNOTSET; + goto ret; + } + + if (aes_xts->iv_set != 1) { + rc = ZPC_ERROR_IVNOTSET; + goto ret; + } + + rc = __aes_xts_set_intermediate_iv(aes_xts, iv); + if (rc) + goto ret; + + aes_xts->iv_set = 1; + + DEBUG("aes-xts context at %p: intermediate iv set", aes_xts); +ret: + DEBUG("return %d (%s)", rc, zpc_error_string(rc)); + return rc; +} + +int zpc_aes_xts_encrypt(struct zpc_aes_xts *aes_xts, u8 * c, const u8 * m, size_t mlen) { @@ -503,6 +585,24 @@ return rc; } +static int +__aes_xts_set_intermediate_iv(struct zpc_aes_xts *aes_xts, const u8 iv[16]) +{ + int rc, off1; + + assert(aes_xts != NULL); + assert(iv != NULL); + assert(aes_xts->aes_key1 != NULL); + assert(aes_xts->aes_key2 != NULL); + assert(aes_xts->key_set == 1); + + off1 = AES_XTS_KM_XTSPARAM(aes_xts->aes_key1->keysize); + memcpy(aes_xts->param_km + off1, iv, 16); + rc = 0; + + return rc; +} + static int __aes_xts_crypt(struct zpc_aes_xts *aes_xts, u8 * out, const u8 * in, size_t inlen, unsigned long flags) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzpc-1.1.1/src/ecc_key.c new/libzpc-1.2.0/src/ecc_key.c --- old/libzpc-1.1.1/src/ecc_key.c 2023-09-15 12:52:28.000000000 +0200 +++ new/libzpc-1.2.0/src/ecc_key.c 2024-01-12 10:26:07.000000000 +0100 @@ -30,6 +30,7 @@ extern const size_t curve2puboffset[]; extern const size_t curve2macedspkilen[]; extern const size_t curve2rawspkilen[]; +extern const u32 curve2pkey_keytype[]; static void __ec_key_reset(struct zpc_ec_key *); static int ec_key_check_ep11_spki(const struct zpc_ec_key *ec_key, @@ -811,9 +812,12 @@ goto ret; } - rc = ec_key_sec2prot(ec_key, EC_KEY_SEC_CUR); + rc = ec_key_clr2prot(ec_key, privkey, privlen); if (rc) { - goto ret; + rc = ec_key_sec2prot(ec_key, EC_KEY_SEC_CUR); + if (rc) { + goto ret; + } } DEBUG("ec key at %p: private/protected key set", ec_key); @@ -1269,6 +1273,68 @@ io.apqns = ec_key->apqns; io.apqn_entries = ec_key->napqns; io.pkeytype = (ec_key->type == ZPC_EC_KEY_TYPE_CCA ? PKEY_TYPE_CCA_ECC : PKEY_TYPE_EP11_ECC); + io.pkeylen = sizeof(ec_key->prot.protkey); + io.pkey = (unsigned char *)&ec_key->prot.protkey; + + rc = ioctl(pkeyfd, PKEY_KBLOB2PROTK3, &io); + if (rc != 0) { + return ZPC_ERROR_IOCTLBLOB2PROTK3; + } + + return 0; +} + +int ec_key_clr2prot(struct zpc_ec_key *ec_key, const unsigned char *privkey, + unsigned int privlen) +{ + struct pkey_kblob2pkey3 io; + unsigned char buf[sizeof(struct clearkeytoken) + 80]; + struct clearkeytoken *clrtok = (struct clearkeytoken *)&buf; + int rc; + + memset(buf, 0, sizeof(buf)); + clrtok->version = 0x02; + clrtok->keytype = curve2pkey_keytype[ec_key->curve]; + switch (clrtok->keytype) { + case PKEY_KEYTYPE_ECC_P256: + case PKEY_KEYTYPE_ECC_P384: + case PKEY_KEYTYPE_ECC_ED25519: + memcpy(clrtok->clearkey, privkey, privlen); + clrtok->len = privlen; + break; + case PKEY_KEYTYPE_ECC_P521: + memcpy(clrtok->clearkey + 80 - privlen, privkey, privlen); + clrtok->len = 80; + break; + case PKEY_KEYTYPE_ECC_ED448: + memcpy(clrtok->clearkey + 64 - privlen, privkey, privlen); + clrtok->len = 64; + break; + default: /* should not occur */ + return ZPC_ERROR_EC_INVALID_CURVE; + } + + memset(&io, 0, sizeof(io)); + io.key = buf; + switch (clrtok->keytype) { + case PKEY_KEYTYPE_ECC_P256: + case PKEY_KEYTYPE_ECC_P384: + case PKEY_KEYTYPE_ECC_ED25519: + io.keylen = sizeof(struct clearkeytoken) + privlen; + break; + case PKEY_KEYTYPE_ECC_P521: + io.keylen = sizeof(struct clearkeytoken) + 80; + break; + case PKEY_KEYTYPE_ECC_ED448: + io.keylen = sizeof(struct clearkeytoken) + 64; + break; + default: /* should not occur */ + return ZPC_ERROR_EC_INVALID_CURVE; + } + + io.apqns = ec_key->apqns; + io.apqn_entries = ec_key->napqns; + io.pkeytype = (ec_key->type == ZPC_EC_KEY_TYPE_CCA ? PKEY_TYPE_CCA_ECC : PKEY_TYPE_EP11_ECC); io.pkeylen = sizeof(ec_key->prot.protkey); io.pkey = (unsigned char *)&ec_key->prot.protkey; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzpc-1.1.1/src/ecc_key_local.h new/libzpc-1.2.0/src/ecc_key_local.h --- old/libzpc-1.1.1/src/ecc_key_local.h 2023-09-15 12:52:28.000000000 +0200 +++ new/libzpc-1.2.0/src/ecc_key_local.h 2024-01-12 10:26:07.000000000 +0100 @@ -63,4 +63,6 @@ const unsigned char *privkey, unsigned int privlen); int ec_key_sec2prot(struct zpc_ec_key *, enum ec_key_sec sec); int ec_key_check(const struct zpc_ec_key *); +int ec_key_clr2prot(struct zpc_ec_key *ec_key, const unsigned char *privkey, + unsigned int privlen); #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzpc-1.1.1/src/error.c new/libzpc-1.2.0/src/error.c --- old/libzpc-1.1.1/src/error.c 2023-09-15 12:52:28.000000000 +0200 +++ new/libzpc-1.2.0/src/error.c 2024-01-12 10:26:07.000000000 +0100 @@ -93,6 +93,8 @@ "The given buffer does not contain a valid EP11 AES secure key token.", "The given buffer does not contain a valid CCA datakey token", "The given buffer does not contain a valid CCA cipherkey token", + "Error creating random bytes", + "Invalid usage of a gcm context with an internally created iv" "LAST" }; const char *rc; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzpc-1.1.1/src/misc.c new/libzpc-1.2.0/src/misc.c --- old/libzpc-1.1.1/src/misc.c 2023-09-15 12:52:28.000000000 +0200 +++ new/libzpc-1.2.0/src/misc.c 2024-01-12 10:26:07.000000000 +0100 @@ -10,12 +10,36 @@ #include <assert.h> #include <stdlib.h> #include <string.h> +#include <fcntl.h> +#include <unistd.h> static int ishexdigit(const char); static unsigned char hexdigit2byte(char); static char byte2hexdigit(unsigned char); int +local_rng(u8 *output, size_t bytes) +{ + int ranfd; + int rlen; + unsigned int totallen = 0; + + ranfd = open("/dev/prandom", O_RDONLY); + if (ranfd < 0) + ranfd = open("/dev/urandom", O_RDONLY); + if (ranfd >= 0) { + do { + rlen = read(ranfd, output + totallen, bytes - totallen); + totallen += rlen; + } while (totallen < bytes); + close(ranfd); + return 0; + } + + return -1; +} + +int hexstr2buf(u8 * buf, size_t *buflen, const char *hex) { size_t i; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzpc-1.1.1/src/misc.h new/libzpc-1.2.0/src/misc.h --- old/libzpc-1.1.1/src/misc.h 2023-09-15 12:52:28.000000000 +0200 +++ new/libzpc-1.2.0/src/misc.h 2024-01-12 10:26:07.000000000 +0100 @@ -27,5 +27,6 @@ int memcmp_consttime(const void *, const void *, size_t); int hexstr2buf(u8 *, size_t *, const char *); void buf2hexstr(char *, size_t, const unsigned char *, size_t); +int local_rng(u8 *output, size_t bytes); #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzpc-1.1.1/src/zkey/pkey.c new/libzpc-1.2.0/src/zkey/pkey.c --- old/libzpc-1.1.1/src/zkey/pkey.c 2023-09-15 12:52:28.000000000 +0200 +++ new/libzpc-1.2.0/src/zkey/pkey.c 2024-01-12 10:26:07.000000000 +0100 @@ -418,3 +418,11 @@ sizeof(ed25519_maced_spki_t) - EP11_SPKI_MACLEN, sizeof(ed448_maced_spki_t) - EP11_SPKI_MACLEN, }; + +const u32 curve2pkey_keytype[] = { + PKEY_KEYTYPE_ECC_P256, + PKEY_KEYTYPE_ECC_P384, + PKEY_KEYTYPE_ECC_P521, + PKEY_KEYTYPE_ECC_ED25519, + PKEY_KEYTYPE_ECC_ED448, +}; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzpc-1.1.1/src/zkey/pkey.h new/libzpc-1.2.0/src/zkey/pkey.h --- old/libzpc-1.1.1/src/zkey/pkey.h 2023-09-15 12:52:28.000000000 +0200 +++ new/libzpc-1.2.0/src/zkey/pkey.h 2024-01-12 10:26:07.000000000 +0100 @@ -259,6 +259,22 @@ #define PKEY_KEYTYPE_AES_192 2 #define PKEY_KEYTYPE_AES_256 3 #define PKEY_KEYTYPE_ECC 4 +#define PKEY_KEYTYPE_ECC_P256 5 +#define PKEY_KEYTYPE_ECC_P384 6 +#define PKEY_KEYTYPE_ECC_P521 7 +#define PKEY_KEYTYPE_ECC_ED25519 8 +#define PKEY_KEYTYPE_ECC_ED448 9 + +/* inside view of a clear key token (type 0x00 version 0x02) */ +struct clearkeytoken { + u8 type; /* 0x00 for PAES specific key tokens */ + u8 res0[3]; + u8 version; /* 0x02 for clear key token */ + u8 res1[3]; + u32 keytype; /* key type, one of the PKEY_KEYTYPE_* values */ + u32 len; /* bytes actually stored in clearkey[] */ + u8 clearkey[]; /* clear key value */ +} __packed; struct pkey_genseck { u16 cardnr; /* in: card to use or FFFF for any */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzpc-1.1.1/test/t_aes_cbc.cc new/libzpc-1.2.0/test/t_aes_cbc.cc --- old/libzpc-1.1.1/test/t_aes_cbc.cc 2023-09-15 12:52:28.000000000 +0200 +++ new/libzpc-1.2.0/test/t_aes_cbc.cc 2024-01-12 10:26:07.000000000 +0100 @@ -690,6 +690,128 @@ free(ct); } +TEST(aes_cbc, stream_inplace_kat3) +{ + TESTLIB_ENV_AES_KEY_CHECK(); + + TESTLIB_AES_CBC_HW_CAPS_CHECK(); + + TESTLIB_AES_KERNEL_CAPS_CHECK(); + + size_t keylen, ivlen, msglen, ctlen; + unsigned char buf[4096], iv2[16]; + const char *mkvp, *apqns[257]; + struct zpc_aes_key *aes_key; + struct zpc_aes_cbc *aes_cbc1, *aes_cbc2; + unsigned int flags; + int type, rc; + + const char *keystr = "b6f9afbfe5a1562bba1368fc72ac9d9c"; + const char *ivstr = "3f9d5ebe250ee7ce384b0d00ee849322"; + const char *msgstr = "db397ec22718dbffb9c9d13de0efcd4611bf792be4fce0dc5f25d4f577ed8cdbd4eb9208d593dda3d4653954ab64f05676caa3ce9bfa795b08b67ceebc923fdc89a8c431188e9e482d8553982cf304d1"; + const char *ctstr = "10ea27b19e16b93af169c4a88e06e35c99d8b420980b058e34b4b8f132b13766f72728202b089f428fecdb41c79f8aa0d0ef68f5786481cca29e2126f69bc14160f1ae2187878ba5c49cf3961e1b7ee9"; + + type = testlib_env_aes_key_type(); + flags = testlib_env_aes_key_flags(); + mkvp = testlib_env_aes_key_mkvp(); + (void)testlib_env_aes_key_apqns(apqns); + + TESTLIB_AES_SW_CAPS_CHECK(type); + + u8 *key = testlib_hexstr2buf(keystr, &keylen); + ASSERT_NE(key, nullptr); + u8 *iv = testlib_hexstr2buf(ivstr, &ivlen); + ASSERT_NE(iv, nullptr); + u8 *msg = testlib_hexstr2buf(msgstr, &msglen); + ASSERT_NE(msg, nullptr); + u8 *ct = testlib_hexstr2buf(ctstr, &ctlen); + ASSERT_NE(ct, nullptr); + + rc = zpc_aes_key_alloc(&aes_key); + EXPECT_EQ(rc, 0); + rc = zpc_aes_cbc_alloc(&aes_cbc1); + EXPECT_EQ(rc, 0); + rc = zpc_aes_cbc_alloc(&aes_cbc2); + EXPECT_EQ(rc, 0); + + rc = zpc_aes_key_set_type(aes_key, type); + EXPECT_EQ(rc, 0); + if (mkvp != NULL) { + rc = zpc_aes_key_set_mkvp(aes_key, mkvp); + EXPECT_EQ(rc, 0); + } else { + rc = zpc_aes_key_set_apqns(aes_key, apqns); + EXPECT_EQ(rc, 0); + } + rc = zpc_aes_key_set_flags(aes_key, flags); + EXPECT_EQ(rc, 0); + + rc = zpc_aes_key_set_size(aes_key, keylen * 8); + EXPECT_EQ(rc, 0); + + rc = zpc_aes_key_import_clear(aes_key, key); + EXPECT_EQ(rc, 0); + + rc = zpc_aes_cbc_set_key(aes_cbc1, aes_key); + EXPECT_EQ(rc, 0); + rc = zpc_aes_cbc_set_key(aes_cbc2, aes_key); + EXPECT_EQ(rc, 0); + + /* Encrypt first chunk with first ctx */ + memcpy(buf, msg, msglen); + rc = zpc_aes_cbc_set_iv(aes_cbc1, iv); + EXPECT_EQ(rc, 0); + rc = zpc_aes_cbc_encrypt(aes_cbc1, buf, buf, 16); + EXPECT_EQ(rc, 0); + + /* Get intermediate iv from first ctx */ + rc = zpc_aes_cbc_get_intermediate_iv(aes_cbc1, iv2); + EXPECT_EQ(rc, 0); + + /* Encrypt a 2nd chunk with 2nd ctx */ + rc = zpc_aes_cbc_set_iv(aes_cbc2, iv); + EXPECT_EQ(rc, 0); + rc = zpc_aes_cbc_set_intermediate_iv(aes_cbc2, iv2); + EXPECT_EQ(rc, 0); + rc = zpc_aes_cbc_encrypt(aes_cbc2, buf + 16, buf + 16, msglen - 16); + EXPECT_EQ(rc, 0); + + EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); + + /* Decrypt first chunk with first ctx */ + memcpy(buf, ct, ctlen); + rc = zpc_aes_cbc_set_iv(aes_cbc1, iv); + EXPECT_EQ(rc, 0); + rc = zpc_aes_cbc_decrypt(aes_cbc1, buf, buf, 16); + EXPECT_EQ(rc, 0); + + /* Get intermediate iv from first ctx */ + rc = zpc_aes_cbc_get_intermediate_iv(aes_cbc1, iv2); + EXPECT_EQ(rc, 0); + + /* Decrypt remaining chunk with 2nd ctx */ + rc = zpc_aes_cbc_set_iv(aes_cbc2, iv); + EXPECT_EQ(rc, 0); + rc = zpc_aes_cbc_set_intermediate_iv(aes_cbc2, iv2); + EXPECT_EQ(rc, 0); + rc = zpc_aes_cbc_decrypt(aes_cbc2, buf + 16, buf + 16, msglen - 16); + EXPECT_EQ(rc, 0); + + EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); + + zpc_aes_cbc_free(&aes_cbc1); + EXPECT_EQ(aes_cbc1, nullptr); + zpc_aes_cbc_free(&aes_cbc2); + EXPECT_EQ(aes_cbc2, nullptr); + zpc_aes_key_free(&aes_key); + EXPECT_EQ(aes_key, nullptr); + + free(key); + free(iv); + free(msg); + free(ct); +} + TEST(aes_cbc, nist_kat) { TESTLIB_ENV_AES_KEY_CHECK(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzpc-1.1.1/test/t_aes_gcm.cc new/libzpc-1.2.0/test/t_aes_gcm.cc --- old/libzpc-1.1.1/test/t_aes_gcm.cc 2023-09-15 12:52:28.000000000 +0200 +++ new/libzpc-1.2.0/test/t_aes_gcm.cc 2024-01-12 10:26:07.000000000 +0100 @@ -210,6 +210,109 @@ EXPECT_EQ(aes_key, nullptr); } +TEST(aes_gcm, create_iv) +{ + struct zpc_aes_key *aes_key; + struct zpc_aes_gcm *aes_gcm1, *aes_gcm2; + const char *mkvp, *apqns[257]; + u8 aad[99], m[99], tag[16], tmp_tag[16], buf[99], pt[99]; + u8 iv_buf[4096]; + int rc, size, type; + unsigned int flags; + + TESTLIB_ENV_AES_KEY_CHECK(); + + TESTLIB_AES_GCM_HW_CAPS_CHECK(); + + TESTLIB_AES_KERNEL_CAPS_CHECK(); + + size = testlib_env_aes_key_size(); + type = testlib_env_aes_key_type(); + flags = testlib_env_aes_key_flags(); + mkvp = testlib_env_aes_key_mkvp(); + (void)testlib_env_aes_key_apqns(apqns); + + TESTLIB_AES_SW_CAPS_CHECK(type); + + rc = zpc_aes_key_alloc(&aes_key); + EXPECT_EQ(rc, 0); + rc = zpc_aes_gcm_alloc(&aes_gcm1); + EXPECT_EQ(rc, 0); + rc = zpc_aes_gcm_alloc(&aes_gcm2); + EXPECT_EQ(rc, 0); + + rc = zpc_aes_gcm_create_iv(aes_gcm1, iv_buf, 0); + EXPECT_EQ(rc, ZPC_ERROR_IVSIZE); + rc = zpc_aes_gcm_create_iv(aes_gcm1, iv_buf, 1234); + EXPECT_EQ(rc, ZPC_ERROR_KEYNOTSET); + + rc = zpc_aes_key_set_size(aes_key, size); + EXPECT_EQ(rc, 0); + rc = zpc_aes_key_set_type(aes_key, type); + EXPECT_EQ(rc, 0); + rc = zpc_aes_key_set_flags(aes_key, flags); + EXPECT_EQ(rc, 0); + if (mkvp != NULL) { + rc = zpc_aes_key_set_mkvp(aes_key, mkvp); + EXPECT_EQ(rc, 0); + } else { + rc = zpc_aes_key_set_apqns(aes_key, apqns); + EXPECT_EQ(rc, 0); + } + + rc = zpc_aes_key_generate(aes_key); + EXPECT_EQ(rc, 0); + rc = zpc_aes_gcm_set_key(aes_gcm1, aes_key); + EXPECT_EQ(rc, 0); + rc = zpc_aes_gcm_set_key(aes_gcm2, aes_key); + EXPECT_EQ(rc, 0); + + rc = zpc_aes_gcm_create_iv(aes_gcm1, iv_buf, SIZE_MAX); + EXPECT_EQ(rc, ZPC_ERROR_IVSIZE); + rc = zpc_aes_gcm_create_iv(aes_gcm1, iv_buf, 11); + EXPECT_EQ(rc, ZPC_ERROR_IVSIZE); + rc = zpc_aes_gcm_create_iv(aes_gcm1, iv_buf, 12); + EXPECT_EQ(rc, 0); + + /* Create internal iv for encrypt/decrypt */ + rc = zpc_aes_gcm_create_iv(aes_gcm1, iv_buf, 1234); + EXPECT_EQ(rc, 0); + + /* Encrypt in-place with internally created iv */ + rc = zpc_aes_gcm_encrypt(aes_gcm1, buf, tag, sizeof(tag), aad, sizeof(aad), m, sizeof(m)); + EXPECT_EQ(rc, 0); + + /* + * Try to use set_iv on first ctx with already created internal iv. This + * fails because it is not allowed to overwrite an internal iv. + */ + rc = zpc_aes_gcm_set_iv(aes_gcm1, iv_buf, 78); + EXPECT_EQ(rc, ZPC_ERROR_GCM_IV_CREATED_INTERNALLY); + + /* + * Try to use same ctx for decrypt: this fails, because the initial iv + * is not available because set_iv is not allowed on this ctx after + * creating an internal iv. + */ + memcpy(tmp_tag, tag, sizeof(tag)); + rc = zpc_aes_gcm_decrypt(aes_gcm1, pt, tmp_tag, sizeof(tmp_tag), aad, sizeof(aad), buf, sizeof(buf)); + EXPECT_EQ(rc, ZPC_ERROR_GCM_IV_CREATED_INTERNALLY); + + /* Decrypt in-place with internally created iv and 2nd ctx */ + rc = zpc_aes_gcm_set_iv(aes_gcm2, iv_buf, 1234); + EXPECT_EQ(rc, 0); + rc = zpc_aes_gcm_decrypt(aes_gcm2, pt, tag, sizeof(tag), aad, sizeof(aad), buf, sizeof(buf)); + EXPECT_EQ(rc, 0); + EXPECT_TRUE(memcmp(pt, m, sizeof(m)) == 0); + + zpc_aes_gcm_free(&aes_gcm1); + EXPECT_EQ(aes_gcm1, nullptr); + zpc_aes_gcm_free(&aes_gcm2); + EXPECT_EQ(aes_gcm2, nullptr); + zpc_aes_key_free(&aes_key); + EXPECT_EQ(aes_key, nullptr); +} + TEST(aes_gcm, encrypt) { struct zpc_aes_key *aes_key; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzpc-1.1.1/test/t_aes_key.cc new/libzpc-1.2.0/test/t_aes_key.cc --- old/libzpc-1.1.1/test/t_aes_key.cc 2023-09-15 12:52:28.000000000 +0200 +++ new/libzpc-1.2.0/test/t_aes_key.cc 2024-01-12 10:26:07.000000000 +0100 @@ -628,7 +628,8 @@ { struct zpc_aes_key *aes_key, *aes_key2; u8 buf[1000], buf2[1000], buf3[1000]; - unsigned int flags; + u8 session[32]; + unsigned int flags, key_had_a_session = 0; const char *apqns[257]; int rc, size, type; size_t buflen = sizeof(buf); @@ -692,15 +693,27 @@ rc = zpc_aes_key_export(aes_key, buf, &buflen); EXPECT_EQ(rc, 0); + /* Check if the key contains a session id. In this case let's save the + * session before converting the blob into an "old style" key. */ + memset(session, 0, 32); + ep11hdr = (struct ep11kblob_header *)buf; + if (ep11hdr->version == 0x06 && + memcmp(buf + sizeof(struct ep11kblob_header), session, 32) != 0) { + memcpy(session, buf + sizeof(struct ep11kblob_header), 32); + key_had_a_session = 1; + } + /* Convert blob into an "old style" TOKVER_EP11_AES without header. For * backward compatibility such keys are still accepted, but internally * converted into "new style" keys with header. */ memset(buf3, 0, sizeof(buf3)); buf3len = buflen - sizeof(struct ep11kblob_header); memcpy(buf3, buf + sizeof(struct ep11kblob_header), buf3len); + memset(buf3, 0, 32); ep11hdr = (struct ep11kblob_header *)buf3; ep11hdr->version = 0x03; /* TOKVER_EP11_AES */ ep11hdr->len = buf3len; + ep11hdr->bitlen = size; /* Import "old style" key */ rc = zpc_aes_key_import(aes_key2, buf3, buf3len); @@ -711,13 +724,17 @@ rc = zpc_aes_key_export(aes_key2, buf2, &buf2len); EXPECT_EQ(rc, 0); + /* If the original key had a session id, restore it now */ + if (key_had_a_session) + memcpy(buf2 + sizeof(struct ep11kblob_header), session, 32); + EXPECT_EQ(buf2len, buflen); EXPECT_TRUE(memcmp(buf2, buf, buflen) == 0); /* Now try a TOKVER_EP11_AES key that has an overlayed header, but the * remaining 16 bytes of the session id field are not zero. This key * is considered as corrupted. */ - memset(buf3 + 16, 0x5c, 16); + memset(buf3 + 16, 0x5c, sizeof(struct ep11kblob_header)); rc = zpc_aes_key_import(aes_key2, buf3, buf3len); EXPECT_EQ(rc, ZPC_ERROR_AES_NO_EP11_SECUREKEY_TOKEN); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzpc-1.1.1/test/t_aes_xts.cc new/libzpc-1.2.0/test/t_aes_xts.cc --- old/libzpc-1.1.1/test/t_aes_xts.cc 2023-09-15 12:52:28.000000000 +0200 +++ new/libzpc-1.2.0/test/t_aes_xts.cc 2024-01-12 10:26:07.000000000 +0100 @@ -842,6 +842,166 @@ free(ct); } +TEST(aes_xts, stream_inplace_kat3) +{ + TESTLIB_ENV_AES_KEY_CHECK(); + + TESTLIB_AES_XTS_HW_CAPS_CHECK(); + + TESTLIB_AES_KERNEL_CAPS_CHECK(); + + size_t keylen, ivlen, msglen, ctlen; + unsigned char buf[4096], iv2[16]; + const char *mkvp, *apqns[257]; + struct zpc_aes_key *aes_key1, *aes_key2; + struct zpc_aes_xts *aes_xts1, *aes_xts2; + unsigned int flags; + int type, rc, size, i; + + const char *keystr[] = { + "63f36e9c397c6523c99f1644ecb1a5d9bc0f2f55fbe324444c390fae752ad4d7", + "88dfd7c83cb121968feb417520555b36c0f63b662570eac12ea96cbe188ad5b1a44db23ac6470316cba0041cadf248f6d9a7713f454e663f3e3987585cebbf96", + }; + const char *ivstr[] = { + "cdb1bd3486f353cc160a840beadf0329", + "0ee84632b838dd528f1d96c76439805c", + }; + const char *msgstr[] = { + "9a0149888bf76160a81428bc9140eccd26ed18368e24d49b9cc512929a88ad1e66c763f4f56b63bb9dd9508c5d4df465", + "ec36551c70efcdf85de7a39988978263ad261e83996dad219a0058e02187384f2d0754ff9cfa000bec448fafd2cfa738", + }; + const char *ctstr[] = { + "0eeef28ca159b805f5c215610551678ab772f279374fb140ab550768db42cf6cb73637641934195ffc08cf5a9188b82b", + "a55d533c9c5885562b92d4582ea69db8e2ba9c0b967a9f0167700b043525a47bafe7d630774eaf4a1dc9fbcf94a1fda4", + }; + + size = testlib_env_aes_key_size(); + type = testlib_env_aes_key_type(); + flags = testlib_env_aes_key_flags(); + mkvp = testlib_env_aes_key_mkvp(); + (void)testlib_env_aes_key_apqns(apqns); + + TESTLIB_AES_SW_CAPS_CHECK(type); + + TESTLIB_AES_XTS_KEY_SIZE_CHECK(size); + + i = size == 128 ? 0 : 1; + + u8 *key1 = testlib_hexstr2buf(keystr[i], &keylen); + ASSERT_NE(key1, nullptr); + keylen /= 2; + u8 *key2 = key1 + keylen; + u8 *iv = testlib_hexstr2buf(ivstr[i], &ivlen); + ASSERT_NE(iv, nullptr); + u8 *msg = testlib_hexstr2buf(msgstr[i], &msglen); + ASSERT_NE(msg, nullptr); + u8 *ct = testlib_hexstr2buf(ctstr[i], &ctlen); + ASSERT_NE(ct, nullptr); + + rc = zpc_aes_key_alloc(&aes_key1); + EXPECT_EQ(rc, 0); + rc = zpc_aes_key_alloc(&aes_key2); + EXPECT_EQ(rc, 0); + + rc = zpc_aes_xts_alloc(&aes_xts1); + EXPECT_EQ(rc, 0); + rc = zpc_aes_xts_alloc(&aes_xts2); + EXPECT_EQ(rc, 0); + + rc = zpc_aes_key_set_type(aes_key1, type); + EXPECT_EQ(rc, 0); + if (mkvp != NULL) { + rc = zpc_aes_key_set_mkvp(aes_key1, mkvp); + EXPECT_EQ(rc, 0); + } else { + rc = zpc_aes_key_set_apqns(aes_key1, apqns); + EXPECT_EQ(rc, 0); + } + rc = zpc_aes_key_set_flags(aes_key1, flags); + EXPECT_EQ(rc, 0); + rc = zpc_aes_key_set_size(aes_key1, keylen * 8); + EXPECT_EQ(rc, 0); + rc = zpc_aes_key_import_clear(aes_key1, key1); + EXPECT_EQ(rc, 0); + + rc = zpc_aes_key_set_type(aes_key2, type); + EXPECT_EQ(rc, 0); + if (mkvp != NULL) { + rc = zpc_aes_key_set_mkvp(aes_key2, mkvp); + EXPECT_EQ(rc, 0); + } else { + rc = zpc_aes_key_set_apqns(aes_key2, apqns); + EXPECT_EQ(rc, 0); + } + rc = zpc_aes_key_set_flags(aes_key2, flags); + EXPECT_EQ(rc, 0); + rc = zpc_aes_key_set_size(aes_key2, keylen * 8); + EXPECT_EQ(rc, 0); + rc = zpc_aes_key_import_clear(aes_key2, key2); + EXPECT_EQ(rc, 0); + + rc = zpc_aes_xts_set_key(aes_xts1, aes_key1, aes_key2); + EXPECT_EQ(rc, 0); + rc = zpc_aes_xts_set_key(aes_xts2, aes_key1, aes_key2); + EXPECT_EQ(rc, 0); + + /* Encrypt first chunk with first ctx */ + memcpy(buf, msg, msglen); + rc = zpc_aes_xts_set_iv(aes_xts1, iv); + EXPECT_EQ(rc, 0); + rc = zpc_aes_xts_encrypt(aes_xts1, buf, buf, 16); + EXPECT_EQ(rc, 0); + + /* Get intermediate iv from first ctx */ + rc = zpc_aes_xts_get_intermediate_iv(aes_xts1, iv2); + EXPECT_EQ(rc, 0); + + /* Encrypt a 2nd chunk with 2nd ctx */ + rc = zpc_aes_xts_set_iv(aes_xts2, iv); + EXPECT_EQ(rc, 0); + rc = zpc_aes_xts_set_intermediate_iv(aes_xts2, iv2); + EXPECT_EQ(rc, 0); + rc = zpc_aes_xts_encrypt(aes_xts2, buf + 16, buf + 16, msglen - 16); + EXPECT_EQ(rc, 0); + + EXPECT_TRUE(memcmp(buf, ct, msglen) == 0); + + /* Decrypt first chunk with first ctx */ + memcpy(buf, ct, ctlen); + rc = zpc_aes_xts_set_iv(aes_xts1, iv); + EXPECT_EQ(rc, 0); + rc = zpc_aes_xts_decrypt(aes_xts1, buf, buf, 16); + EXPECT_EQ(rc, 0); + + /* Get intermediate iv from first ctx */ + rc = zpc_aes_xts_get_intermediate_iv(aes_xts1, iv2); + EXPECT_EQ(rc, 0); + + /* Decrypt remaining chunk with 2nd ctx */ + rc = zpc_aes_xts_set_iv(aes_xts2, iv); + EXPECT_EQ(rc, 0); + rc = zpc_aes_xts_set_intermediate_iv(aes_xts2, iv2); + EXPECT_EQ(rc, 0); + rc = zpc_aes_xts_decrypt(aes_xts2, buf + 16, buf + 16, msglen - 16); + EXPECT_EQ(rc, 0); + + EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); + + zpc_aes_xts_free(&aes_xts1); + EXPECT_EQ(aes_xts1, nullptr); + zpc_aes_xts_free(&aes_xts2); + EXPECT_EQ(aes_xts2, nullptr); + zpc_aes_key_free(&aes_key1); + EXPECT_EQ(aes_key1, nullptr); + zpc_aes_key_free(&aes_key2); + EXPECT_EQ(aes_key2, nullptr); + + free(key1); + free(iv); + free(msg); + free(ct); +} + TEST(aes_xts, nist_kat) { TESTLIB_ENV_AES_KEY_CHECK(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libzpc-1.1.1/test/t_error.cc new/libzpc-1.2.0/test/t_error.cc --- old/libzpc-1.1.1/test/t_error.cc 2023-09-15 12:52:28.000000000 +0200 +++ new/libzpc-1.2.0/test/t_error.cc 2024-01-12 10:26:07.000000000 +0100 @@ -21,6 +21,6 @@ errstr = zpc_error_string(-1); EXPECT_TRUE(strcmp(errstr, "undefined error code") == 0); - errstr = zpc_error_string(76); + errstr = zpc_error_string(78); EXPECT_TRUE(strcmp(errstr, "LAST") == 0); }