import CS opencryptoki-3.22.0-3.el9

This commit is contained in:
eabdullin 2024-03-28 11:17:33 +00:00
parent d227b6c0fd
commit 782f2d4ee2
12 changed files with 2343 additions and 278 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
SOURCES/opencryptoki-3.21.0.tar.gz
SOURCES/opencryptoki-3.22.0.tar.gz

View File

@ -1 +1 @@
4a0f2ed8f965a948057ab833f1fafabf58929d3f SOURCES/opencryptoki-3.21.0.tar.gz
4618b82afde56a8177e888c26d336c6f521bed8a SOURCES/opencryptoki-3.22.0.tar.gz

View File

@ -1,34 +0,0 @@
commit 2ba0f41ef5e14d4b509c8854e27cf98e3ee89445
Author: Ingo Franzki <ifranzki@linux.ibm.com>
Date: Mon Jul 10 13:22:48 2023 +0200
p11sak: Fix parsing of slot number 0
Running command 'p11sak list-key aes --slot 0' may result in
'p11sak: Invalid argument '0' for option '-s/--slot''
This is because of the error checking after strtoul() within function
process_number_argument(). In case errno is not zero, it treats a
parsed value of zero as an error.
Under certain circumstances, errno is non-zero already before calling
strtoul(), and stays non-zero in case of strtoul() succeeds. This leads to
an incorrect error checking, and it is treated as error.
Initialize errno to zero before calling strtoul() to avoid such false error
detection.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
diff --git a/usr/sbin/p11sak/p11sak.c b/usr/sbin/p11sak/p11sak.c
index 6e11cb41..38665bbd 100644
--- a/usr/sbin/p11sak/p11sak.c
+++ b/usr/sbin/p11sak/p11sak.c
@@ -1712,6 +1712,7 @@ static CK_RV process_number_argument(const struct p11sak_arg *arg, char *val)
{
char *endptr;
+ errno = 0;
*arg->value.number = strtoul(val, &endptr, 0);
if ((errno == ERANGE && *arg->value.number == ULONG_MAX) ||

View File

@ -1,52 +0,0 @@
commit 4ff774568e334a719fc8de16fe2309e2070f0da8
Author: Ingo Franzki <ifranzki@linux.ibm.com>
Date: Mon May 22 11:40:01 2023 +0200
p11sak: Fix user confirmation prompt behavior when stdin is closed
Treat any error during user confirmation prompt as 'cancel' and skip all
operations.
One can for example close stdin during a user prompt via CTRL+D. This was
erroneously treated as positive confirmation and therefore caused the
operation to be performed on the current key object and all further objects
matching the filter as well, instead of canceling the operation entirely.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
diff --git a/usr/sbin/p11sak/p11sak.c b/usr/sbin/p11sak/p11sak.c
index d75d8343..5b54b538 100644
--- a/usr/sbin/p11sak/p11sak.c
+++ b/usr/sbin/p11sak/p11sak.c
@@ -4736,6 +4736,7 @@ static CK_RV handle_key_remove(CK_OBJECT_HANDLE key, CK_OBJECT_CLASS class,
data->num_skipped++;
return CKR_OK;
case 'c':
+ case '\0':
data->skip_all = true;
data->num_skipped++;
return CKR_OK;
@@ -4825,6 +4826,7 @@ static CK_RV handle_key_set_attr(CK_OBJECT_HANDLE key, CK_OBJECT_CLASS class,
data->num_skipped++;
return CKR_OK;
case 'c':
+ case '\0':
data->skip_all = true;
data->num_skipped++;
return CKR_OK;
@@ -4974,6 +4976,7 @@ static CK_RV handle_key_copy(CK_OBJECT_HANDLE key, CK_OBJECT_CLASS class,
data->num_skipped++;
return CKR_OK;
case 'c':
+ case '\0':
data->skip_all = true;
data->num_skipped++;
return CKR_OK;
@@ -6983,6 +6986,7 @@ static CK_RV handle_key_export(CK_OBJECT_HANDLE key, CK_OBJECT_CLASS class,
data->num_skipped++;
return CKR_OK;
case 'c':
+ case '\0':
data->skip_all = true;
data->num_skipped++;
return CKR_OK;

View File

@ -1,96 +0,0 @@
commit 92999f344a3ad99a67a1bcfd9ad28f28c33e51bc
Author: Ingo Franzki <ifranzki@linux.ibm.com>
Date: Mon Jul 10 10:19:13 2023 +0200
p11sak: Fix listing of key objects when other object types are present
A command like 'p11sak list-key all --slot N ...' fails with
p11sak: Attribute CKA_KEY_TYPE is not available in key object
p11sak: Failed to iterate over key objects for key type All: 0xD0: CKR_TEMPLATE_INCOMPLETE
p11sak: Failed to perform the 'list-key' command: CKR_TEMPLATE_INCOMPLETE
when the object repository contains other, non-key objects, e.g. certificates.
When 'all' is used as key type, then no filter for CKA_KEY_TYPE is used
with C_FindObjects(), and thus other non-key objects also match the filter.
When a specific key type is specified, then only such objects match that
have the desired CKA_KEY_TYPE attribute value.
Fix this by checking the object class in get_key_infos() and skip the object,
if it is not a key object.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
diff --git a/usr/sbin/p11sak/p11sak.c b/usr/sbin/p11sak/p11sak.c
index a6213720..6e11cb41 100644
--- a/usr/sbin/p11sak/p11sak.c
+++ b/usr/sbin/p11sak/p11sak.c
@@ -3403,6 +3403,16 @@ static CK_RV get_key_infos(CK_OBJECT_HANDLE key, CK_OBJECT_CLASS *class,
}
}
+ switch (class_val) {
+ case CKO_PUBLIC_KEY:
+ case CKO_PRIVATE_KEY:
+ case CKO_SECRET_KEY:
+ break;
+ default:
+ free(attrs[0].pValue);
+ return CKR_KEY_NEEDED;
+ }
+
for (i = 0; i < num_attrs; i++) {
if (attrs[i].ulValueLen == CK_UNAVAILABLE_INFORMATION) {
warnx("Attribute %s is not available in key object",
@@ -3614,6 +3624,10 @@ static CK_RV iterate_key_objects(const struct p11sak_keytype *keytype,
if (manual_filtering) {
rc = get_key_infos(keys[i], NULL, NULL, NULL, &label,
NULL, NULL);
+ if (rc == CKR_KEY_NEEDED) {
+ rc = CKR_OK;
+ goto next;
+ }
if (rc != CKR_OK)
break;
@@ -3672,6 +3686,10 @@ done_find:
for (i = 0; i < num_matched_keys; i++) {
rc = get_key_infos(matched_keys[i], &class, &ktype, &keysize,
&label, &typestr, &type);
+ if (rc == CKR_KEY_NEEDED) {
+ rc = CKR_OK;
+ goto next2;
+ }
if (rc != CKR_OK)
break;
@@ -3680,6 +3698,7 @@ done_find:
if (rc != CKR_OK)
break;
+next2:
if (label != NULL)
free(label);
label = NULL;
@@ -4480,10 +4499,20 @@ static CK_RV p11sak_list_key_compare(CK_OBJECT_HANDLE key1,
*result = 0;
rc = get_key_infos(key1, &class1, &ktype1, &keysize1, &label1, NULL, NULL);
+ if (rc == CKR_KEY_NEEDED) {
+ rc = CKR_OK;
+ *result = 1; /* non-key objects are always greater than key objects */
+ goto done;
+ }
if (rc != CKR_OK)
goto done;
rc = get_key_infos(key2, &class2, &ktype2, &keysize2, &label2, NULL, NULL);
+ if (rc == CKR_KEY_NEEDED) {
+ rc = CKR_OK;
+ *result = -1; /* key objects are always smaller than non-key objects */
+ goto done;
+ }
if (rc != CKR_OK)
goto done;

View File

@ -1,84 +0,0 @@
commit f4166214552a92d8d66de8011ab11c9c2c6bb0a4
Author: Ingo Franzki <ifranzki@linux.ibm.com>
Date: Mon May 22 13:31:21 2023 +0200
pkcsstats: Fix handling of user name
The struct passwd returned by getpwuid() is a pointer to a static area, that
may get overwritten by subsequent calls to getpwuid() or similar.
Actually, C_Initialize() itself is using getpwuid() internally, and thus will
interfere with the getpwuid() usage in pkcsstats.
Make a copy of the returned user name before calling C_Initialize() in
init_ock() to ensure to work with the desired user name, and not with anything
left over from previous calls.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
diff --git a/usr/sbin/pkcsstats/pkcsstats.c b/usr/sbin/pkcsstats/pkcsstats.c
index c2444cf5..a842a295 100644
--- a/usr/sbin/pkcsstats/pkcsstats.c
+++ b/usr/sbin/pkcsstats/pkcsstats.c
@@ -783,6 +783,7 @@ int main(int argc, char **argv)
int opt = 0;
struct passwd *pswd = NULL;
int user_id = -1;
+ char *user_name = NULL;
bool summary = false, all_users = false, all_mechs = false;
bool reset = false, reset_all = false;
bool delete = false, delete_all = false;
@@ -903,19 +904,27 @@ int main(int argc, char **argv)
}
}
+ user_name = strdup(pswd->pw_name);
+ if (user_name == NULL) {
+ warnx("Failed to get current user name");
+ exit(EXIT_FAILURE);
+ }
+
if (delete) {
if (slot_id_specified) {
warnx("Options -s/--slot and -d/--delete can not be specified together");
+ free(user_name);
exit(EXIT_FAILURE);
}
- rc = delete_shm(user_id, pswd->pw_name);
+ rc = delete_shm(user_id, user_name);
goto done;
}
if (delete_all) {
if (slot_id_specified) {
warnx("Options -s/--slot and -D/--delete-all can not be specified together");
+ free(user_name);
exit(EXIT_FAILURE);
}
@@ -932,7 +941,7 @@ int main(int argc, char **argv)
goto done;
if (reset) {
- rc = reset_shm(user_id, pswd->pw_name, num_slots, slots,
+ rc = reset_shm(user_id, user_name, num_slots, slots,
slot_id_specified, slot_id);
goto done;
}
@@ -968,7 +977,7 @@ int main(int argc, char **argv)
rc = display_summary(&dd);
goto done;
} else {
- rc = display_stats(user_id, pswd->pw_name, &dd);
+ rc = display_stats(user_id, user_name, &dd);
goto done;
}
@@ -984,5 +993,7 @@ done:
dlclose(dll);
}
+ free(user_name);
+
return rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}

View File

@ -0,0 +1,153 @@
commit f931d6e47bf2fb26aa9cf52e231d13edc1c837a1
Author: Ingo Franzki <ifranzki@linux.ibm.com>
Date: Tue Dec 12 17:16:56 2023 +0100
COMMON: Update rsa_parse_block_type_2() to not leak the message length
Take the implementation of OpenSSL function RSA_padding_check_PKCS1_type_2()
in crypto/rsa/rsa_pk1.c instead of ossl_rsa_padding_check_PKCS1_type_2(), since
the latter leaks the message size.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
diff --git a/usr/lib/common/mech_rsa.c b/usr/lib/common/mech_rsa.c
index 326c5795..7bab1a84 100644
--- a/usr/lib/common/mech_rsa.c
+++ b/usr/lib/common/mech_rsa.c
@@ -29,6 +29,7 @@
#include "constant_time.h"
#include <openssl/crypto.h>
+#include <openssl/rsa.h>
CK_BBOOL is_rsa_mechanism(CK_MECHANISM_TYPE mech)
{
@@ -293,13 +294,16 @@ static CK_RV rsa_parse_block_type_2(CK_BYTE *in_data,
CK_BYTE *out_data,
CK_ULONG *out_data_len)
{
- unsigned int ok = 0, found, zero;
- size_t zero_index = 0, msg_index, mlen;
- size_t i, j;
+ int i;
+ unsigned char *em = NULL;
+ unsigned int good, found_zero_byte, mask, equals0;
+ int zero_index = 0, msg_index, mlen = -1;
+ int out_len = *out_data_len;
+ int rsa_size = in_data_len;
/*
* The implementation of this function is copied from OpenSSL's function
- * ossl_rsa_padding_check_PKCS1_type_2() in crypto/rsa/rsa_pk1.c
+ * RSA_padding_check_PKCS1_type_2() in crypto/rsa/rsa_pk1.c
* and is slightly modified to fit to the OpenCryptoki environment.
*
* The OpenSSL code is licensed under the Apache License 2.0.
@@ -324,55 +328,86 @@ static CK_RV rsa_parse_block_type_2(CK_BYTE *in_data,
* PKCS#1 v1.5 decryption. See "PKCS #1 v2.2: RSA Cryptography Standard",
* section 7.2.2.
*/
- if (in_data_len < 11) {
+ if (rsa_size < RSA_PKCS1_PADDING_SIZE) {
TRACE_DEVEL("%s\n", ock_err(ERR_FUNCTION_FAILED));
return CKR_FUNCTION_FAILED;
}
- ok = constant_time_is_zero(in_data[0]);
- ok &= constant_time_eq(in_data[1], 2);
+ em = malloc(rsa_size);
+ if (em == NULL) {
+ TRACE_DEVEL("%s\n", ock_err(ERR_HOST_MEMORY));
+ return CKR_HOST_MEMORY;
+ }
+
+ /* in_data_len is always equal to rsa_size */
+ memcpy(em, in_data, rsa_size);
+
+ good = constant_time_is_zero(em[0]);
+ good &= constant_time_eq(em[1], 2);
/* scan over padding data */
- found = 0;
- for (i = 2; i < in_data_len; i++) {
- zero = constant_time_is_zero(in_data[i]);
+ found_zero_byte = 0;
+ for (i = 2; i < rsa_size; i++) {
+ equals0 = constant_time_is_zero(em[i]);
- zero_index = constant_time_select_int(~found & zero, i, zero_index);
- found |= zero;
+ zero_index = constant_time_select_int(~found_zero_byte & equals0,
+ i, zero_index);
+ found_zero_byte |= equals0;
}
/*
- * PS must be at least 8 bytes long, and it starts two bytes into |enc_msg|.
+ * PS must be at least 8 bytes long, and it starts two bytes into |em|.
* If we never found a 0-byte, then |zero_index| is 0 and the check
* also fails.
*/
- ok &= constant_time_ge(zero_index, 2 + 8);
+ good &= constant_time_ge(zero_index, 2 + 8);
/*
* Skip the zero byte. This is incorrect if we never found a zero-byte
* but in this case we also do not copy the message out.
*/
msg_index = zero_index + 1;
- mlen = in_data_len - msg_index;
+ mlen = rsa_size - msg_index;
/*
* For good measure, do this check in constant time as well.
*/
- ok &= constant_time_ge(*out_data_len, mlen);
+ good &= constant_time_ge(out_len, mlen);
/*
- * since at this point the |msg_index| does not provide the signal
- * indicating if the padding check failed or not, we don't have to worry
- * about leaking the length of returned message, we still need to ensure
- * that we read contents of both buffers so that cache accesses don't leak
- * the value of |good|
+ * Move the result in-place by |rsa_size|-RSA_PKCS1_PADDING_SIZE-|mlen|
+ * bytes to the left.
+ * Then if |good| move |mlen| bytes from |em|+RSA_PKCS1_PADDING_SIZE to
+ * |out_data|. Otherwise leave |out_data| unchanged.
+ * Copy the memory back in a way that does not reveal the size of
+ * the data being copied via a timing side channel. This requires copying
+ * parts of the buffer multiple times based on the bits set in the real
+ * length. Clear bits do a non-copy with identical access pattern.
+ * The loop below has overall complexity of O(N*log(N)).
*/
- for (i = msg_index, j = 0; i < in_data_len && j < *out_data_len; i++, j++)
- out_data[j] = constant_time_select_8(ok, in_data[i], out_data[j]);
+ out_len = constant_time_select_int(
+ constant_time_lt(rsa_size - RSA_PKCS1_PADDING_SIZE, out_len),
+ rsa_size - RSA_PKCS1_PADDING_SIZE,
+ out_len);
+ for (msg_index = 1; msg_index < rsa_size - RSA_PKCS1_PADDING_SIZE;
+ msg_index <<= 1) {
+ mask = ~constant_time_eq(
+ msg_index & (rsa_size - RSA_PKCS1_PADDING_SIZE - mlen), 0);
+ for (i = RSA_PKCS1_PADDING_SIZE; i < rsa_size - msg_index; i++)
+ em[i] = constant_time_select_8(mask, em[i + msg_index], em[i]);
+ }
+ for (i = 0; i < out_len; i++) {
+ mask = good & constant_time_lt(i, mlen);
+ out_data[i] = constant_time_select_8(
+ mask, em[i + RSA_PKCS1_PADDING_SIZE], out_data[i]);
+ }
+
+ OPENSSL_cleanse(em, rsa_size);
+ free(em);
- *out_data_len = j;
+ *out_data_len = constant_time_select_int(good, mlen, 0);
- return constant_time_select_int(ok, CKR_OK, CKR_ENCRYPTED_DATA_INVALID);
+ return constant_time_select_int(good, CKR_OK, CKR_ENCRYPTED_DATA_INVALID);
}
CK_RV rsa_parse_block(CK_BYTE *in_data,

View File

@ -0,0 +1,737 @@
commit 5f1a4f8641306ee192b70c8a32c9ee8a0fe9be5f
Author: Ingo Franzki <ifranzki@linux.ibm.com>
Date: Mon Jan 15 12:53:37 2024 +0100
common: Add support for implicit rejection for RSA PKCS#1 v1.5 de-padding
Implicit rejection returns a pseudo random message in case the RSA PKCS#1 v1.5
padding is incorrect, but returns no error. The pseudo random message is based
on static secret data (the private exponent) and the provided ciphertext, so
that the attacker cannot determine that the returned value is randomly generated
instead of the result of decryption and de-padding.
The implicit rejection algorithm is the same as used by OpenSSL.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
diff --git a/COPYRIGHTS b/COPYRIGHTS
index 2bb3dffe..21b6b702 100644
--- a/COPYRIGHTS
+++ b/COPYRIGHTS
@@ -12,19 +12,29 @@ For code originating from OpenSSL:
* Note that in OpenSSL the file crypto/bn/rsa_sup_mul.c does no longer
* exist, it was removed with commit https://github.com/openssl/openssl/commit/4209ce68d8fe8b1506494efa03d378d05baf9ff8
* - usr/lib/common/constant_time.h: Copied unchanged from OpenSSL from
- include/internal/constant_time.h
+ * include/internal/constant_time.h
* - The implementation of function rsa_parse_block_type_2() in
* usr/lib/common/mech_rsa.c is copied from OpenSSL's function
* ossl_rsa_padding_check_PKCS1_type_2() in crypto/rsa/rsa_pk1.c
* and is slightly modified to fit to the OpenCryptoki environment.
* See comment in function rsa_parse_block_type_2() for a list of changes.
+ * - The implementation of function openssl_specific_rsa_derive_kdk() in
+ * usr/lib/common/mech_openssl.c is copied from OpenSSL's function
+ * derive_kdk() in crypto/rsa/rsa_ossl.c and is slightly modified to fit to
+ * the OpenCryptoki environment. See comment in function
+ * openssl_specific_rsa_derive_kdk() for a list of changes.
+ * - The implementation of function openssl_specific_rsa_prf() in
+ * usr/lib/common/mech_openssl.c is copied from OpenSSL's function
+ * ossl_rsa_prf() in crypto/rsa/rsapk1.c and is slightly modified to fit to
+ * the OpenCryptoki environment. See comment in function
+ * openssl_specific_rsa_prf() for a list of changes.
* - The implementation of function decode_eme_oaep() in
* usr/lib/common/mech_rsa.c is copied from OpenSSL's function
* RSA_padding_check_PKCS1_OAEP_mgf1() in crypto/rsa/rsa_oaep.c and is
* slightly modified to fit to the OpenCryptoki environment. See comment in
* function decode_eme_oaep() for a list of changes.
*
- * Copyright 1999-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* The OpenSSL code is licensed under the Apache License 2.0 (the "License").
* You can obtain a copy in the file LICENSE in the OpenSSL source distribution
diff --git a/usr/lib/common/h_extern.h b/usr/lib/common/h_extern.h
index a88b57d0..29496d99 100644
--- a/usr/lib/common/h_extern.h
+++ b/usr/lib/common/h_extern.h
@@ -731,7 +731,8 @@ CK_RV rsa_format_block(STDLL_TokData_t *tokdata,
CK_RV rsa_parse_block(CK_BYTE *in_data,
CK_ULONG in_data_len,
CK_BYTE *out_data,
- CK_ULONG *out_data_len, CK_ULONG type);
+ CK_ULONG *out_data_len, CK_ULONG type,
+ CK_BYTE *kdk, CK_ULONG kdklen);
CK_RV get_mgf_mech(CK_RSA_PKCS_MGF_TYPE mgf, CK_MECHANISM_TYPE *mech);
@@ -3179,6 +3180,14 @@ CK_RV openssl_specific_hmac_update(SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data,
CK_RV openssl_specific_hmac_final(SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *signature,
CK_ULONG *sig_len, CK_BBOOL sign);
+CK_RV openssl_specific_rsa_derive_kdk(STDLL_TokData_t *tokdata, OBJECT *key_obj,
+ const CK_BYTE *in, CK_ULONG inlen,
+ CK_BYTE *kdk, CK_ULONG kdklen);
+CK_RV openssl_specific_rsa_prf(CK_BYTE *out, CK_ULONG outlen,
+ const char *label, CK_ULONG labellen,
+ const CK_BYTE *kdk, CK_ULONG kdklen,
+ uint16_t bitlen);
+
#include "tok_spec_struct.h"
extern token_spec_t token_specific;
diff --git a/usr/lib/common/mech_openssl.c b/usr/lib/common/mech_openssl.c
index 9983fcb3..da515289 100644
--- a/usr/lib/common/mech_openssl.c
+++ b/usr/lib/common/mech_openssl.c
@@ -1154,6 +1154,7 @@ CK_RV openssl_specific_rsa_pkcs_decrypt(STDLL_TokData_t *tokdata,
CK_RV rc;
CK_BYTE out[MAX_RSA_KEYLEN];
CK_ULONG modulus_bytes;
+ unsigned char kdk[SHA256_HASH_SIZE] = { 0 };
modulus_bytes = in_data_len;
@@ -1163,7 +1164,16 @@ CK_RV openssl_specific_rsa_pkcs_decrypt(STDLL_TokData_t *tokdata,
goto done;
}
- rc = rsa_parse_block(out, modulus_bytes, out_data, out_data_len, PKCS_BT_2);
+ rc = openssl_specific_rsa_derive_kdk(tokdata, key_obj,
+ in_data, in_data_len,
+ kdk, sizeof(kdk));
+ if (rc != CKR_OK) {
+ TRACE_DEVEL("openssl_specific_rsa_derive_kdk failed\n");
+ goto done;
+ }
+
+ rc = rsa_parse_block(out, modulus_bytes, out_data, out_data_len, PKCS_BT_2,
+ kdk, sizeof(kdk));
done:
OPENSSL_cleanse(out, sizeof(out));
@@ -1254,7 +1264,7 @@ CK_RV openssl_specific_rsa_pkcs_verify(STDLL_TokData_t *tokdata, SESSION *sess,
}
rc = rsa_parse_block(out, modulus_bytes, out_data, &out_data_len,
- PKCS_BT_1);
+ PKCS_BT_1, NULL, 0);
if (rc == CKR_ENCRYPTED_DATA_INVALID) {
TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID));
return CKR_SIGNATURE_INVALID;
@@ -1318,7 +1328,8 @@ CK_RV openssl_specific_rsa_pkcs_verify_recover(STDLL_TokData_t *tokdata,
return rc;
}
- rc = rsa_parse_block(out, modulus_bytes, out_data, out_data_len, PKCS_BT_1);
+ rc = rsa_parse_block(out, modulus_bytes, out_data, out_data_len, PKCS_BT_1,
+ NULL, 0);
if (rc == CKR_ENCRYPTED_DATA_INVALID) {
TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID));
return CKR_SIGNATURE_INVALID;
@@ -4983,3 +4994,388 @@ done:
ctx->context = NULL;
return rv;
}
+
+static CK_RV calc_rsa_priv_exp(STDLL_TokData_t *tokdata, OBJECT *key_obj,
+ CK_BYTE *priv_exp, CK_ULONG priv_exp_len)
+{
+ CK_ATTRIBUTE *modulus = NULL, *pub_exp = NULL;
+ CK_ATTRIBUTE *prime1 = NULL, *prime2 = NULL;
+ BN_CTX *bn_ctx;
+ BIGNUM *n, *e, *p, *q, *d;
+ CK_RV rc;
+
+ UNUSED(tokdata);
+
+ bn_ctx = BN_CTX_secure_new();
+ if (bn_ctx == NULL) {
+ TRACE_ERROR("BN_CTX_secure_new failed\n");
+ return CKR_FUNCTION_FAILED;
+ }
+
+ /* Get modulus a BIGNUM */
+ rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS,
+ &modulus);
+ if (rc != CKR_OK) {
+ TRACE_ERROR("Failed to get CKA_MODULUS\n");
+ goto done;
+ }
+
+ n = BN_CTX_get(bn_ctx);
+ if (n == NULL ||
+ BN_bin2bn(modulus->pValue, modulus->ulValueLen, n) == NULL) {
+ TRACE_ERROR("BN_CTX_get/BN_bin2bn failed for modulus\n");
+ rc = CKR_FUNCTION_FAILED;
+ goto done;
+ }
+ BN_set_flags(n, BN_FLG_CONSTTIME);
+
+ /* Get public exponent a BIGNUM */
+ rc = template_attribute_get_non_empty(key_obj->template,
+ CKA_PUBLIC_EXPONENT, &pub_exp);
+ if (rc != CKR_OK) {
+ TRACE_ERROR("Failed to get CKA_PUBLIC_EXPONENT\n");
+ goto done;
+ }
+
+ e = BN_CTX_get(bn_ctx);
+ if (e == NULL ||
+ BN_bin2bn(pub_exp->pValue, pub_exp->ulValueLen, e) == NULL) {
+ TRACE_ERROR("BN_CTX_get/BN_bin2bn failed for public exponent\n");
+ rc = CKR_FUNCTION_FAILED;
+ goto done;
+ }
+ BN_set_flags(e, BN_FLG_CONSTTIME);
+
+ /* Get prime1 a BIGNUM */
+ rc = template_attribute_get_non_empty(key_obj->template, CKA_PRIME_1,
+ &prime1);
+ if (rc != CKR_OK) {
+ TRACE_ERROR("Failed to get CKA_PRIME_1\n");
+ goto done;
+ }
+
+ p = BN_CTX_get(bn_ctx);
+ if (p == NULL ||
+ BN_bin2bn(prime1->pValue, prime1->ulValueLen, p) == NULL) {
+ TRACE_ERROR("BN_CTX_get/BN_bin2bn failed for prime1\n");
+ rc = CKR_FUNCTION_FAILED;
+ goto done;
+ }
+ BN_set_flags(p, BN_FLG_CONSTTIME);
+
+ /* Get prime2 a BIGNUM */
+ rc = template_attribute_get_non_empty(key_obj->template, CKA_PRIME_2,
+ &prime2);
+ if (rc != CKR_OK) {
+ TRACE_ERROR("Failed to get CKA_PRIME_2\n");
+ goto done;
+ }
+
+ q = BN_CTX_get(bn_ctx);
+ if (q == NULL ||
+ BN_bin2bn(prime2->pValue, prime2->ulValueLen, q) == NULL) {
+ TRACE_ERROR("BN_CTX_get/BN_bin2bn failed for prime2\n");
+ rc = CKR_FUNCTION_FAILED;
+ goto done;
+ }
+ BN_set_flags(q, BN_FLG_CONSTTIME);
+
+ d = BN_CTX_get(bn_ctx);
+ if (d == NULL) {
+ TRACE_ERROR("BN_CTX_get failed to get d\n");
+ rc = CKR_FUNCTION_FAILED;
+ goto done;
+ }
+ BN_set_flags(d, BN_FLG_CONSTTIME);
+
+ /*
+ * phi(n) = (p - 1 )(q - 1) = n - p - q + 1
+ * d = e ^{-1} mod phi(n).
+ */
+ if (BN_copy(d, n) == NULL ||
+ BN_sub(d, d, p) == 0 ||
+ BN_sub(d, d, q) == 0 ||
+ BN_add_word(d, 1) == 0 ||
+ BN_mod_inverse(d, e, d, bn_ctx) == NULL) {
+ TRACE_ERROR("Failed to calculate private key part d\n");
+ rc = CKR_FUNCTION_FAILED;
+ goto done;
+ }
+
+ if (BN_bn2binpad(d, priv_exp, priv_exp_len) <= 0) {
+ TRACE_ERROR("BN_bn2binpad failed\n");
+ rc = CKR_FUNCTION_FAILED;
+ goto done;
+ }
+
+done:
+ BN_CTX_free(bn_ctx);
+
+ return rc;
+}
+
+CK_RV openssl_specific_rsa_derive_kdk(STDLL_TokData_t *tokdata, OBJECT *key_obj,
+ const CK_BYTE *in, CK_ULONG inlen,
+ CK_BYTE *kdk, CK_ULONG kdklen)
+{
+ CK_ATTRIBUTE *priv_exp_attr = NULL, *modulus = NULL;
+ CK_BYTE *priv_exp = NULL, *buf = NULL;
+ EVP_PKEY *pkey = NULL;
+ EVP_MD_CTX *mdctx = NULL;
+ const EVP_MD *md = NULL;
+ size_t md_len;
+ unsigned char d_hash[SHA256_HASH_SIZE] = { 0 };
+ CK_RV rc;
+
+ /*
+ * The implementation of this function is copied from OpenSSL's function
+ * derive_kdk() in crypto/rsa/rsa_ossl.c and is slightly modified to fit to
+ * the OpenCryptoki environment.
+ * Changes include:
+ * - Different variable and define names.
+ * - Usage of TRACE_ERROR to report errors and issue debug messages.
+ * - Different return codes.
+ * - Different code to get the private key component 'd'.
+ * - Use of the EVP APIs instead of the internal APIs for Digest and HMAC
+ * operations.
+ */
+
+ if (kdklen != SHA256_HASH_SIZE) {
+ TRACE_ERROR("KDK length is wrong\n");
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS,
+ &modulus);
+ if (rc != CKR_OK) {
+ TRACE_ERROR("Failed to get CKA_MODULUS\n");
+ return rc;
+ }
+
+ buf = calloc(1, modulus->ulValueLen);
+ if (buf == NULL) {
+ TRACE_ERROR("Failed to allocate a buffer for private exponent\n");
+ return CKR_HOST_MEMORY;
+ }
+
+ rc = template_attribute_get_non_empty(key_obj->template,
+ CKA_PRIVATE_EXPONENT, &priv_exp_attr);
+ if (rc != CKR_OK && rc != CKR_TEMPLATE_INCOMPLETE) {
+ TRACE_ERROR("Failed to get CKA_PRIVATE_EXPONENT\n");
+ goto out;
+ }
+
+ if (priv_exp_attr == NULL) {
+ rc = calc_rsa_priv_exp(tokdata, key_obj, buf, modulus->ulValueLen);
+ if (rc != CKR_OK) {
+ TRACE_ERROR("calc_rsa_priv_exp failed\n");
+ goto out;
+ }
+ priv_exp = buf;
+ } else {
+ if (priv_exp_attr->ulValueLen < modulus->ulValueLen) {
+ memcpy(buf + modulus->ulValueLen - priv_exp_attr->ulValueLen,
+ priv_exp_attr->pValue, priv_exp_attr->ulValueLen);
+ priv_exp = buf;
+ } else {
+ priv_exp = (CK_BYTE *)priv_exp_attr->pValue +
+ priv_exp_attr->ulValueLen - modulus->ulValueLen;
+ }
+ }
+
+ /*
+ * we use hardcoded hash so that migrating between versions that use
+ * different hash doesn't provide a Bleichenbacher oracle:
+ * if the attacker can see that different versions return different
+ * messages for the same ciphertext, they'll know that the message is
+ * synthetically generated, which means that the padding check failed
+ */
+ md = EVP_sha256();
+ if (md == NULL) {
+ TRACE_ERROR("EVP_sha256 failed\n");
+ rc = CKR_FUNCTION_FAILED;
+ goto out;
+ }
+
+ if (EVP_Digest(priv_exp, modulus->ulValueLen, d_hash, NULL,
+ md, NULL) <= 0) {
+ TRACE_ERROR("EVP_Digest failed\n");
+ rc = CKR_FUNCTION_FAILED;
+ goto out;
+ }
+
+ pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, d_hash, sizeof(d_hash));
+ if (pkey == NULL) {
+ TRACE_ERROR("EVP_PKEY_new_mac_key() failed.\n");
+ rc = CKR_FUNCTION_FAILED;
+ goto out;
+ }
+
+ mdctx = EVP_MD_CTX_create();
+ if (mdctx == NULL) {
+ TRACE_ERROR("EVP_MD_CTX_create() failed.\n");
+ rc = CKR_FUNCTION_FAILED;
+ goto out;
+ }
+
+ if (EVP_DigestSignInit(mdctx, NULL, md, NULL, pkey) != 1) {
+ TRACE_ERROR("EVP_DigestSignInit failed\n");
+ rc = CKR_FUNCTION_FAILED;
+ goto out;
+ }
+
+ if (inlen < modulus->ulValueLen) {
+ memset(buf, 0, modulus->ulValueLen - inlen);
+ if (EVP_DigestSignUpdate(mdctx, buf, modulus->ulValueLen - inlen)!= 1) {
+ TRACE_ERROR("EVP_DigestSignUpdate failed\n");
+ rc = CKR_FUNCTION_FAILED;
+ goto out;
+ }
+ }
+ if (EVP_DigestSignUpdate(mdctx, in, inlen) != 1) {
+ TRACE_ERROR("EVP_DigestSignUpdate failed\n");
+ rc = CKR_FUNCTION_FAILED;
+ goto out;
+ }
+
+ md_len = kdklen;
+ if (EVP_DigestSignFinal(mdctx, kdk, &md_len) != 1 ||
+ md_len != kdklen) {
+ TRACE_ERROR("EVP_DigestSignFinal failed\n");
+ rc = CKR_FUNCTION_FAILED;
+ goto out;
+ }
+
+ rc = CKR_OK;
+
+out:
+ if (buf != NULL)
+ free(buf);
+ if (pkey != NULL)
+ EVP_PKEY_free(pkey);
+ if (mdctx != NULL)
+ EVP_MD_CTX_free(mdctx);
+
+ return rc;
+}
+
+CK_RV openssl_specific_rsa_prf(CK_BYTE *out, CK_ULONG outlen,
+ const char *label, CK_ULONG labellen,
+ const CK_BYTE *kdk, CK_ULONG kdklen,
+ uint16_t bitlen)
+{
+ CK_RV rc;
+ CK_ULONG pos;
+ uint16_t iter = 0;
+ unsigned char be_iter[sizeof(iter)];
+ unsigned char be_bitlen[sizeof(bitlen)];
+ EVP_PKEY *pkey = NULL;
+ EVP_MD_CTX *mdctx = NULL;
+ unsigned char hmac_out[SHA256_HASH_SIZE];
+ size_t md_len;
+
+ /*
+ * The implementation of this function is copied from OpenSSL's function
+ * ossl_rsa_prf() in crypto/rsa/rsapk1.c and is slightly modified to fit to
+ * the providers environment.
+ * Changes include:
+ * - Different variable and define names.
+ * - Usage of TRACE_ERROR report errors and issue debug messages.
+ * - Different return codes.
+ * - Use of the EVP API instead of the internal APIs for HMAC operations.
+ */
+
+ if (kdklen != SHA256_HASH_SIZE) {
+ TRACE_ERROR("invalid kdklen\n");
+ return CKR_ARGUMENTS_BAD;
+ }
+ if (outlen * 8 != bitlen) {
+ TRACE_ERROR("invalid outlen\n");
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ be_bitlen[0] = (bitlen >> 8) & 0xff;
+ be_bitlen[1] = bitlen & 0xff;
+
+ pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, kdk, kdklen);
+ if (pkey == NULL) {
+ TRACE_ERROR("EVP_PKEY_new_mac_key() failed.\n");
+ rc = CKR_FUNCTION_FAILED;
+ goto out;
+ }
+
+ mdctx = EVP_MD_CTX_create();
+ if (mdctx == NULL) {
+ TRACE_ERROR("EVP_MD_CTX_create() failed.\n");
+ rc = CKR_FUNCTION_FAILED;
+ goto out;
+ }
+
+ /*
+ * we use hardcoded hash so that migrating between versions that use
+ * different hash doesn't provide a Bleichenbacher oracle:
+ * if the attacker can see that different versions return different
+ * messages for the same ciphertext, they'll know that the message is
+ * synthetically generated, which means that the padding check failed
+ */
+ for (pos = 0; pos < outlen; pos += SHA256_HASH_SIZE, iter++) {
+ if (EVP_DigestSignInit(mdctx, NULL, EVP_sha256(), NULL, pkey) != 1) {
+ TRACE_ERROR("EVP_DigestSignInit failed\n");
+ rc = CKR_FUNCTION_FAILED;
+ goto out;
+ }
+
+ be_iter[0] = (iter >> 8) & 0xff;
+ be_iter[1] = iter & 0xff;
+
+ if (EVP_DigestSignUpdate(mdctx, be_iter, sizeof(be_iter)) != 1) {
+ TRACE_ERROR("EVP_DigestSignUpdate failed\n");
+ rc = CKR_FUNCTION_FAILED;
+ goto out;
+ }
+ if (EVP_DigestSignUpdate(mdctx, (unsigned char *)label, labellen) != 1) {
+ TRACE_ERROR("EVP_DigestSignUpdate failed\n");
+ rc = CKR_FUNCTION_FAILED;
+ goto out;
+ }
+ if (EVP_DigestSignUpdate(mdctx, be_bitlen, sizeof(be_bitlen)) != 1) {
+ TRACE_ERROR("EVP_DigestSignUpdate failed\n");
+ rc = CKR_FUNCTION_FAILED;
+ goto out;
+ }
+
+ /*
+ * HMAC_Final requires the output buffer to fit the whole MAC
+ * value, so we need to use the intermediate buffer for the last
+ * unaligned block
+ */
+ md_len = SHA256_HASH_SIZE;
+ if (pos + SHA256_HASH_SIZE > outlen) {
+ md_len = sizeof(hmac_out);
+ if (EVP_DigestSignFinal(mdctx, hmac_out, &md_len) != 1) {
+ TRACE_ERROR("EVP_DigestSignFinal failed\n");
+ rc = CKR_FUNCTION_FAILED;
+ goto out;
+ }
+ memcpy(out + pos, hmac_out, outlen - pos);
+ } else {
+ md_len = outlen - pos;
+ if (EVP_DigestSignFinal(mdctx, out + pos, &md_len) != 1) {
+ TRACE_ERROR("EVP_DigestSignFinal failed\n");
+ rc = CKR_FUNCTION_FAILED;
+ goto out;
+ }
+ }
+ }
+
+ rc = CKR_OK;
+
+out:
+ if (pkey != NULL)
+ EVP_PKEY_free(pkey);
+ if (mdctx != NULL)
+ EVP_MD_CTX_free(mdctx);
+
+ return rc;
+}
+
diff --git a/usr/lib/common/mech_rsa.c b/usr/lib/common/mech_rsa.c
index 7bab1a84..7dc9589a 100644
--- a/usr/lib/common/mech_rsa.c
+++ b/usr/lib/common/mech_rsa.c
@@ -289,21 +289,34 @@ static CK_RV rsa_parse_block_type_1(CK_BYTE *in_data,
return rc;
}
+#define MAX_LEN_GEN_TRIES 128
+
static CK_RV rsa_parse_block_type_2(CK_BYTE *in_data,
CK_ULONG in_data_len,
CK_BYTE *out_data,
- CK_ULONG *out_data_len)
+ CK_ULONG *out_data_len,
+ CK_BYTE *kdk, CK_ULONG kdklen)
{
- int i;
- unsigned char *em = NULL;
- unsigned int good, found_zero_byte, mask, equals0;
- int zero_index = 0, msg_index, mlen = -1;
- int out_len = *out_data_len;
- int rsa_size = in_data_len;
+ unsigned int good = 0, found_zero_byte, equals0;
+ size_t zero_index = 0, msg_index;
+ unsigned char *synthetic = NULL;
+ int synthetic_length;
+ uint16_t len_candidate;
+ unsigned char candidate_lengths[MAX_LEN_GEN_TRIES * sizeof(len_candidate)];
+ uint16_t len_mask;
+ uint16_t max_sep_offset;
+ int synth_msg_index = 0;
+ size_t i, j;
+ CK_RV rc;
+
+ if (kdk == NULL || kdklen == 0) {
+ TRACE_DEVEL("%s\n", ock_err(ERR_ARGUMENTS_BAD));
+ return CKR_ARGUMENTS_BAD;
+ }
/*
* The implementation of this function is copied from OpenSSL's function
- * RSA_padding_check_PKCS1_type_2() in crypto/rsa/rsa_pk1.c
+ * ossl_rsa_padding_check_PKCS1_type_2() in crypto/rsa/rsa_pk1.c
* and is slightly modified to fit to the OpenCryptoki environment.
*
* The OpenSSL code is licensed under the Apache License 2.0.
@@ -328,27 +341,67 @@ static CK_RV rsa_parse_block_type_2(CK_BYTE *in_data,
* PKCS#1 v1.5 decryption. See "PKCS #1 v2.2: RSA Cryptography Standard",
* section 7.2.2.
*/
- if (rsa_size < RSA_PKCS1_PADDING_SIZE) {
+ if (in_data_len < RSA_PKCS1_PADDING_SIZE) {
TRACE_DEVEL("%s\n", ock_err(ERR_FUNCTION_FAILED));
return CKR_FUNCTION_FAILED;
}
- em = malloc(rsa_size);
- if (em == NULL) {
- TRACE_DEVEL("%s\n", ock_err(ERR_HOST_MEMORY));
+ /* Generate a random message to return in case the padding checks fail. */
+ synthetic = calloc(1, in_data_len);
+ if (synthetic == NULL) {
+ TRACE_ERROR("Failed to allocate synthetic buffer");
return CKR_HOST_MEMORY;
}
- /* in_data_len is always equal to rsa_size */
- memcpy(em, in_data, rsa_size);
+ rc = openssl_specific_rsa_prf(synthetic, in_data_len, "message", 7,
+ kdk, kdklen, in_data_len * 8);
+ if (rc != CKR_OK)
+ goto out;
+
+ /* decide how long the random message should be */
+ rc = openssl_specific_rsa_prf(candidate_lengths,
+ sizeof(candidate_lengths),
+ "length", 6, kdk, kdklen,
+ MAX_LEN_GEN_TRIES *
+ sizeof(len_candidate) * 8);
+ if (rc != CKR_OK)
+ goto out;
- good = constant_time_is_zero(em[0]);
- good &= constant_time_eq(em[1], 2);
+ /*
+ * max message size is the size of the modulus size minus 2 bytes for
+ * version and padding type and a minimum of 8 bytes padding
+ */
+ len_mask = max_sep_offset = in_data_len - 2 - 8;
+ /*
+ * we want a mask so let's propagate the high bit to all positions less
+ * significant than it
+ */
+ len_mask |= len_mask >> 1;
+ len_mask |= len_mask >> 2;
+ len_mask |= len_mask >> 4;
+ len_mask |= len_mask >> 8;
+
+ synthetic_length = 0;
+ for (i = 0; i < MAX_LEN_GEN_TRIES * (int)sizeof(len_candidate);
+ i += sizeof(len_candidate)) {
+ len_candidate = (candidate_lengths[i] << 8) |
+ candidate_lengths[i + 1];
+ len_candidate &= len_mask;
+
+ synthetic_length = constant_time_select_int(
+ constant_time_lt(len_candidate, max_sep_offset),
+ len_candidate, synthetic_length);
+ }
+
+ synth_msg_index = in_data_len - synthetic_length;
+
+ good = constant_time_is_zero(in_data[0]);
+ good &= constant_time_eq(in_data[1], 2);
/* scan over padding data */
found_zero_byte = 0;
- for (i = 2; i < rsa_size; i++) {
- equals0 = constant_time_is_zero(em[i]);
+ for (i = 2; i < in_data_len; i++) {
+ equals0 = constant_time_is_zero(in_data[i]);
zero_index = constant_time_select_int(~found_zero_byte & equals0,
i, zero_index);
@@ -356,7 +409,7 @@ static CK_RV rsa_parse_block_type_2(CK_BYTE *in_data,
}
/*
- * PS must be at least 8 bytes long, and it starts two bytes into |em|.
+ * PS must be at least 8 bytes long, and it starts two bytes into |in_data|.
* If we never found a 0-byte, then |zero_index| is 0 and the check
* also fails.
*/
@@ -367,53 +420,41 @@ static CK_RV rsa_parse_block_type_2(CK_BYTE *in_data,
* but in this case we also do not copy the message out.
*/
msg_index = zero_index + 1;
- mlen = rsa_size - msg_index;
/*
- * For good measure, do this check in constant time as well.
+ * old code returned an error in case the decrypted message wouldn't fit
+ * into the |out_data|, since that would leak information, return the
+ * synthetic message instead
*/
- good &= constant_time_ge(out_len, mlen);
+ good &= constant_time_ge(*out_data_len, in_data_len - msg_index);
+
+ msg_index = constant_time_select_int(good, msg_index, synth_msg_index);
/*
- * Move the result in-place by |rsa_size|-RSA_PKCS1_PADDING_SIZE-|mlen|
- * bytes to the left.
- * Then if |good| move |mlen| bytes from |em|+RSA_PKCS1_PADDING_SIZE to
- * |out_data|. Otherwise leave |out_data| unchanged.
- * Copy the memory back in a way that does not reveal the size of
- * the data being copied via a timing side channel. This requires copying
- * parts of the buffer multiple times based on the bits set in the real
- * length. Clear bits do a non-copy with identical access pattern.
- * The loop below has overall complexity of O(N*log(N)).
+ * since at this point the |msg_index| does not provide the signal
+ * indicating if the padding check failed or not, we don't have to worry
+ * about leaking the length of returned message, we still need to ensure
+ * that we read contents of both buffers so that cache accesses don't leak
+ * the value of |good|
*/
- out_len = constant_time_select_int(
- constant_time_lt(rsa_size - RSA_PKCS1_PADDING_SIZE, out_len),
- rsa_size - RSA_PKCS1_PADDING_SIZE,
- out_len);
- for (msg_index = 1; msg_index < rsa_size - RSA_PKCS1_PADDING_SIZE;
- msg_index <<= 1) {
- mask = ~constant_time_eq(
- msg_index & (rsa_size - RSA_PKCS1_PADDING_SIZE - mlen), 0);
- for (i = RSA_PKCS1_PADDING_SIZE; i < rsa_size - msg_index; i++)
- em[i] = constant_time_select_8(mask, em[i + msg_index], em[i]);
- }
- for (i = 0; i < out_len; i++) {
- mask = good & constant_time_lt(i, mlen);
- out_data[i] = constant_time_select_8(
- mask, em[i + RSA_PKCS1_PADDING_SIZE], out_data[i]);
- }
+ for (i = msg_index, j = 0; i < in_data_len && j < *out_data_len;
+ i++, j++)
+ out_data[j] = constant_time_select_8(good, in_data[i], synthetic[i]);
- OPENSSL_cleanse(em, rsa_size);
- free(em);
+ *out_data_len = j;
- *out_data_len = constant_time_select_int(good, mlen, 0);
+out:
+ if (synthetic != NULL)
+ free(synthetic);
- return constant_time_select_int(good, CKR_OK, CKR_ENCRYPTED_DATA_INVALID);
+ return rc;
}
CK_RV rsa_parse_block(CK_BYTE *in_data,
CK_ULONG in_data_len,
CK_BYTE *out_data,
- CK_ULONG *out_data_len, CK_ULONG type)
+ CK_ULONG *out_data_len, CK_ULONG type,
+ CK_BYTE *kdk, CK_ULONG kdklen)
{
switch (type) {
case PKCS_BT_1:
@@ -421,7 +462,7 @@ CK_RV rsa_parse_block(CK_BYTE *in_data,
out_data, out_data_len);
case PKCS_BT_2:
return rsa_parse_block_type_2(in_data, in_data_len,
- out_data, out_data_len);
+ out_data, out_data_len, kdk, kdklen);
}
return CKR_ARGUMENTS_BAD;

View File

@ -0,0 +1,387 @@
commit e2b496f58a84c2f537667655fe08a0d4923f0c70
Author: Ingo Franzki <ifranzki@linux.ibm.com>
Date: Fri Jan 12 09:36:27 2024 +0100
Constant time fixes for C_Decrypt return code handling
Return code handling of C_Decrypt, C_DecryptUpdate, and C_DecryptFinal must
be performed in a constant time manner for RSA mechanisms. Otherwise it
may cause a timing side channel that may be used to perform a Bleichenbacher
style attack.
Handling of error situations with CKR_BUFFER_TOO_SMALL or size-query calls,
where the output buffer is NULL and the required size of the output buffer
is to be returned, do not need to be performed in constant time, since
these cases are shortcut anyway, and the result is only dependent on the
modulus size of the RSA key (which is public information anyway).
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
diff --git a/usr/lib/common/new_host.c b/usr/lib/common/new_host.c
index 8a1e8723..bbb0f601 100644
--- a/usr/lib/common/new_host.c
+++ b/usr/lib/common/new_host.c
@@ -47,6 +47,7 @@
#include "trace.h"
#include "slotmgr.h"
#include "attributes.h"
+#include "constant_time.h"
#include "../api/apiproto.h"
#include "../api/policy.h"
@@ -2345,6 +2346,7 @@ CK_RV SC_Decrypt(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
SESSION *sess = NULL;
CK_BBOOL length_only = FALSE;
CK_RV rc = CKR_OK;
+ unsigned int mask;
if (tokdata->initialized == FALSE) {
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
@@ -2377,11 +2379,19 @@ CK_RV SC_Decrypt(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
rc = decr_mgr_decrypt(tokdata, sess, length_only, &sess->decr_ctx,
pEncryptedData, ulEncryptedDataLen, pData,
pulDataLen);
- if (!is_rsa_mechanism(sess->decr_ctx.mech.mechanism) && rc != CKR_OK)
+ /* (!is_rsa_mechanism(sess->decr_ctx.mech.mechanism) && rc != CKR_OK) */
+ mask = ~constant_time_is_zero(
+ is_rsa_mechanism(sess->decr_ctx.mech.mechanism));
+ mask &= ~constant_time_eq(rc, CKR_OK);
+ if (mask)
TRACE_DEVEL("decr_mgr_decrypt() failed.\n");
done:
- if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) {
+ /* (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) */
+ mask = ~constant_time_eq(rc, CKR_OK);
+ mask |= constant_time_is_zero(length_only);
+ mask &= ~constant_time_eq(rc, CKR_BUFFER_TOO_SMALL);
+ if (mask) {
if (sess)
decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx);
}
@@ -2404,6 +2414,7 @@ CK_RV SC_DecryptUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
SESSION *sess = NULL;
CK_BBOOL length_only = FALSE;
CK_RV rc = CKR_OK;
+ unsigned int mask;
if (tokdata->initialized == FALSE) {
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
@@ -2436,11 +2447,18 @@ CK_RV SC_DecryptUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
rc = decr_mgr_decrypt_update(tokdata, sess, length_only,
&sess->decr_ctx, pEncryptedPart,
ulEncryptedPartLen, pPart, pulPartLen);
- if (!is_rsa_mechanism(sess->decr_ctx.mech.mechanism) && rc != CKR_OK)
+ /* (!is_rsa_mechanism(sess->decr_ctx.mech.mechanism) && rc != CKR_OK) */
+ mask = ~constant_time_is_zero(
+ is_rsa_mechanism(sess->decr_ctx.mech.mechanism));
+ mask &= ~constant_time_eq(rc, CKR_OK);
+ if (mask)
TRACE_DEVEL("decr_mgr_decrypt_update() failed.\n");
done:
- if (rc != CKR_OK && rc != CKR_BUFFER_TOO_SMALL && sess != NULL) {
+ /* (rc != CKR_OK && rc != CKR_BUFFER_TOO_SMALL */
+ mask = ~constant_time_eq(rc, CKR_OK);
+ mask &= ~constant_time_eq(rc, CKR_BUFFER_TOO_SMALL);
+ if (mask) {
if (sess)
decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx);
}
@@ -2462,6 +2480,7 @@ CK_RV SC_DecryptFinal(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
SESSION *sess = NULL;
CK_BBOOL length_only = FALSE;
CK_RV rc = CKR_OK;
+ unsigned int mask;
if (tokdata->initialized == FALSE) {
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
@@ -2493,11 +2512,19 @@ CK_RV SC_DecryptFinal(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
rc = decr_mgr_decrypt_final(tokdata, sess, length_only, &sess->decr_ctx,
pLastPart, pulLastPartLen);
- if (!is_rsa_mechanism(sess->decr_ctx.mech.mechanism) && rc != CKR_OK)
+ /* (!is_rsa_mechanism(sess->decr_ctx.mech.mechanism) && rc != CKR_OK) */
+ mask = ~constant_time_is_zero(
+ is_rsa_mechanism(sess->decr_ctx.mech.mechanism));
+ mask &= ~constant_time_eq(rc, CKR_OK);
+ if (mask)
TRACE_DEVEL("decr_mgr_decrypt_final() failed.\n");
done:
- if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) {
+ /* (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) */
+ mask = ~constant_time_eq(rc, CKR_OK);
+ mask |= constant_time_is_zero(length_only);
+ mask &= ~constant_time_eq(rc, CKR_BUFFER_TOO_SMALL);
+ if (mask) {
if (sess)
decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx);
}
diff --git a/usr/lib/ep11_stdll/ep11_specific.c b/usr/lib/ep11_stdll/ep11_specific.c
index 073b349f..6d08b95e 100644
--- a/usr/lib/ep11_stdll/ep11_specific.c
+++ b/usr/lib/ep11_stdll/ep11_specific.c
@@ -9552,10 +9552,12 @@ CK_RV ep11tok_decrypt_final(STDLL_TokData_t * tokdata, SESSION * session,
rc = constant_time_select(constant_time_eq(rc, CKR_OK),
ep11_error_to_pkcs11_error(rc, session),
rc);
- if (rc != CKR_OK) {
- TRACE_ERROR("%s rc=0x%lx\n", __func__, rc);
- } else {
- TRACE_INFO("%s rc=0x%lx\n", __func__, rc);
+ if (!is_rsa_mechanism(ctx->mech.mechanism)) {
+ if (rc != CKR_OK) {
+ TRACE_ERROR("%s rc=0x%lx\n", __func__, rc);
+ } else {
+ TRACE_INFO("%s rc=0x%lx\n", __func__, rc);
+ }
}
done:
@@ -9611,10 +9613,12 @@ CK_RV ep11tok_decrypt(STDLL_TokData_t * tokdata, SESSION * session,
rc = constant_time_select(constant_time_eq(rc, CKR_OK),
ep11_error_to_pkcs11_error(rc, session),
rc);
- if (rc != CKR_OK) {
- TRACE_ERROR("%s rc=0x%lx\n", __func__, rc);
- } else {
- TRACE_INFO("%s rc=0x%lx\n", __func__, rc);
+ if (!is_rsa_mechanism(ctx->mech.mechanism)) {
+ if (rc != CKR_OK) {
+ TRACE_ERROR("%s rc=0x%lx\n", __func__, rc);
+ } else {
+ TRACE_INFO("%s rc=0x%lx\n", __func__, rc);
+ }
}
done:
@@ -9676,10 +9680,12 @@ CK_RV ep11tok_decrypt_update(STDLL_TokData_t * tokdata, SESSION * session,
rc = constant_time_select(constant_time_eq(rc, CKR_OK),
ep11_error_to_pkcs11_error(rc, session),
rc);
- if (rc != CKR_OK) {
- TRACE_ERROR("%s rc=0x%lx\n", __func__, rc);
- } else {
- TRACE_INFO("%s rc=0x%lx\n", __func__, rc);
+ if (!is_rsa_mechanism(ctx->mech.mechanism)) {
+ if (rc != CKR_OK) {
+ TRACE_ERROR("%s rc=0x%lx\n", __func__, rc);
+ } else {
+ TRACE_INFO("%s rc=0x%lx\n", __func__, rc);
+ }
}
done:
diff --git a/usr/lib/ep11_stdll/new_host.c b/usr/lib/ep11_stdll/new_host.c
index 55e34c18..299a1d3c 100644
--- a/usr/lib/ep11_stdll/new_host.c
+++ b/usr/lib/ep11_stdll/new_host.c
@@ -38,6 +38,7 @@
#include "slotmgr.h"
#include "attributes.h"
#include "ep11_specific.h"
+#include "constant_time.h"
#include "../api/apiproto.h"
#include "../api/policy.h"
@@ -2466,6 +2467,7 @@ CK_RV SC_Decrypt(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
SESSION *sess = NULL;
CK_BBOOL length_only = FALSE;
CK_RV rc = CKR_OK;
+ unsigned int mask;
if (tokdata->initialized == FALSE) {
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
@@ -2513,17 +2515,29 @@ CK_RV SC_Decrypt(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
length_only, sess->decr_ctx.key,
pEncryptedData, ulEncryptedDataLen,
pData, pulDataLen);
- if (!is_rsa_mechanism(sess->decr_ctx.mech.mechanism) && rc != CKR_OK)
+ /* (!is_rsa_mechanism(sess->decr_ctx.mech.mechanism) && rc != CKR_OK) */
+ mask = ~constant_time_is_zero(
+ is_rsa_mechanism(sess->decr_ctx.mech.mechanism));
+ mask &= ~constant_time_eq(rc, CKR_OK);
+ if (mask)
TRACE_DEVEL("ep11tok_decrypt_single() failed.\n");
} else {
rc = ep11tok_decrypt(tokdata, sess, pEncryptedData, ulEncryptedDataLen,
pData, pulDataLen);
- if (!is_rsa_mechanism(sess->decr_ctx.mech.mechanism) && rc != CKR_OK)
+ /* (!is_rsa_mechanism(sess->decr_ctx.mech.mechanism) && rc != CKR_OK) */
+ mask = ~constant_time_is_zero(
+ is_rsa_mechanism(sess->decr_ctx.mech.mechanism));
+ mask &= ~constant_time_eq(rc, CKR_OK);
+ if (mask)
TRACE_DEVEL("ep11tok_decrypt() failed.\n");
}
done:
- if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) {
+ /* (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) */
+ mask = ~constant_time_eq(rc, CKR_OK);
+ mask |= constant_time_is_zero(length_only);
+ mask &= ~constant_time_eq(rc, CKR_BUFFER_TOO_SMALL);
+ if (mask) {
if (sess)
decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx);
}
@@ -2545,6 +2559,7 @@ CK_RV SC_DecryptUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
{
SESSION *sess = NULL;
CK_RV rc = CKR_OK;
+ unsigned int mask;
if (tokdata->initialized == FALSE) {
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
@@ -2596,11 +2611,18 @@ CK_RV SC_DecryptUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
rc = ep11tok_decrypt_update(tokdata, sess, pEncryptedPart,
ulEncryptedPartLen, pPart, pulPartLen);
- if (!is_rsa_mechanism(sess->decr_ctx.mech.mechanism) && rc != CKR_OK)
+ /* (!is_rsa_mechanism(sess->decr_ctx.mech.mechanism) && rc != CKR_OK) */
+ mask = ~constant_time_is_zero(
+ is_rsa_mechanism(sess->decr_ctx.mech.mechanism));
+ mask &= ~constant_time_eq(rc, CKR_OK);
+ if (mask)
TRACE_DEVEL("ep11tok_decrypt_update() failed.\n");
done:
- if (rc != CKR_OK && rc != CKR_BUFFER_TOO_SMALL && sess != NULL) {
+ /* (rc != CKR_OK && rc != CKR_BUFFER_TOO_SMALL */
+ mask = ~constant_time_eq(rc, CKR_OK);
+ mask &= ~constant_time_eq(rc, CKR_BUFFER_TOO_SMALL);
+ if (mask) {
if (sess)
decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx);
}
@@ -2622,6 +2644,7 @@ CK_RV SC_DecryptFinal(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
SESSION *sess = NULL;
CK_BBOOL length_only = FALSE;
CK_RV rc = CKR_OK;
+ unsigned int mask;
if (tokdata->initialized == FALSE) {
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
@@ -2670,10 +2693,18 @@ CK_RV SC_DecryptFinal(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
}
rc = ep11tok_decrypt_final(tokdata, sess, pLastPart, pulLastPartLen);
- if (!is_rsa_mechanism(sess->decr_ctx.mech.mechanism) && rc != CKR_OK)
+ /* (!is_rsa_mechanism(sess->decr_ctx.mech.mechanism) && rc != CKR_OK) */
+ mask = ~constant_time_is_zero(
+ is_rsa_mechanism(sess->decr_ctx.mech.mechanism));
+ mask &= ~constant_time_eq(rc, CKR_OK);
+ if (mask)
TRACE_DEVEL("ep11tok_decrypt_final() failed.\n");
done:
- if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) {
+ /* (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) */
+ mask = ~constant_time_eq(rc, CKR_OK);
+ mask |= constant_time_is_zero(length_only);
+ mask &= ~constant_time_eq(rc, CKR_BUFFER_TOO_SMALL);
+ if (mask) {
if (sess)
decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx);
}
diff --git a/usr/lib/icsf_stdll/new_host.c b/usr/lib/icsf_stdll/new_host.c
index 6c419750..d8064559 100644
--- a/usr/lib/icsf_stdll/new_host.c
+++ b/usr/lib/icsf_stdll/new_host.c
@@ -35,6 +35,8 @@
#include "slotmgr.h"
#include "attributes.h"
#include "icsf_specific.h"
+#include "constant_time.h"
+
#include "../api/apiproto.h"
#include "../api/policy.h"
@@ -1768,6 +1770,7 @@ CK_RV SC_Decrypt(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
SESSION *sess = NULL;
CK_BBOOL length_only = FALSE;
CK_RV rc = CKR_OK;
+ unsigned int mask;
if (tokdata->initialized == FALSE) {
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
@@ -1801,11 +1804,19 @@ CK_RV SC_Decrypt(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
rc = icsftok_decrypt(tokdata, sess, pEncryptedData, ulEncryptedDataLen,
pData, pulDataLen);
- if (!is_rsa_mechanism(sess->decr_ctx.mech.mechanism) && rc != CKR_OK)
+ /* (!is_rsa_mechanism(sess->decr_ctx.mech.mechanism) && rc != CKR_OK) */
+ mask = ~constant_time_is_zero(
+ is_rsa_mechanism(sess->decr_ctx.mech.mechanism));
+ mask &= ~constant_time_eq(rc, CKR_OK);
+ if (mask)
TRACE_DEVEL("icsftok_decrypt() failed.\n");
done:
- if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) {
+ /* (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) */
+ mask = ~constant_time_eq(rc, CKR_OK);
+ mask |= constant_time_is_zero(length_only);
+ mask &= ~constant_time_eq(rc, CKR_BUFFER_TOO_SMALL);
+ if (mask) {
if (sess)
decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx);
}
@@ -1827,6 +1838,7 @@ CK_RV SC_DecryptUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
{
SESSION *sess = NULL;
CK_RV rc = CKR_OK;
+ unsigned int mask;
if (tokdata->initialized == FALSE) {
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
@@ -1857,11 +1869,18 @@ CK_RV SC_DecryptUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
rc = icsftok_decrypt_update(tokdata, sess, pEncryptedPart,
ulEncryptedPartLen, pPart, pulPartLen);
- if (!is_rsa_mechanism(sess->decr_ctx.mech.mechanism) && rc != CKR_OK)
+ /* (!is_rsa_mechanism(sess->decr_ctx.mech.mechanism) && rc != CKR_OK) */
+ mask = ~constant_time_is_zero(
+ is_rsa_mechanism(sess->decr_ctx.mech.mechanism));
+ mask &= ~constant_time_eq(rc, CKR_OK);
+ if (mask)
TRACE_DEVEL("icsftok_decrypt_update() failed.\n");
done:
- if (rc != CKR_OK && rc != CKR_BUFFER_TOO_SMALL && sess != NULL) {
+ /* (rc != CKR_OK && rc != CKR_BUFFER_TOO_SMALL */
+ mask = ~constant_time_eq(rc, CKR_OK);
+ mask &= ~constant_time_eq(rc, CKR_BUFFER_TOO_SMALL);
+ if (mask) {
if (sess)
decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx);
}
@@ -1883,6 +1902,7 @@ CK_RV SC_DecryptFinal(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
SESSION *sess = NULL;
CK_BBOOL length_only = FALSE;
CK_RV rc = CKR_OK;
+ unsigned int mask;
if (tokdata->initialized == FALSE) {
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
@@ -1915,10 +1935,18 @@ CK_RV SC_DecryptFinal(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
length_only = TRUE;
rc = icsftok_decrypt_final(tokdata, sess, pLastPart, pulLastPartLen);
- if (!is_rsa_mechanism(sess->decr_ctx.mech.mechanism) && rc != CKR_OK)
+ /* (!is_rsa_mechanism(sess->decr_ctx.mech.mechanism) && rc != CKR_OK) */
+ mask = ~constant_time_is_zero(
+ is_rsa_mechanism(sess->decr_ctx.mech.mechanism));
+ mask &= ~constant_time_eq(rc, CKR_OK);
+ if (mask)
TRACE_DEVEL("icsftok_decrypt_final() failed.\n");
done:
- if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) {
+ /* (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) */
+ mask = ~constant_time_eq(rc, CKR_OK);
+ mask |= constant_time_is_zero(length_only);
+ mask &= ~constant_time_eq(rc, CKR_BUFFER_TOO_SMALL);
+ if (mask) {
if (sess)
decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,31 @@
commit d756ba1ec270a289950e66398c7e8be59c4a594d
Author: Ingo Franzki <ifranzki@linux.ibm.com>
Date: Fri Feb 9 14:07:34 2024 +0100
COMMON: Fix implicit rejection with RSA keys with empty CKA_PRIVATE_EXPONENT
An RSA key object that has no CKA_PRIVATE_EXPONENT may either don't have that
attribute at all, or may have an empty CKA_PRIVATE_EXPONENT attribute.
Both situations should be handed the same, and the private exponent of the
key needs to be calculated from the other key components.
Note that RSA key objects generated with a current soft or ICA token will
always have a valid CKA_PRIVATE_EXPONENT attribute, since this is provided
during key generation.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
diff --git a/usr/lib/common/mech_openssl.c b/usr/lib/common/mech_openssl.c
index da515289..14c82e2d 100644
--- a/usr/lib/common/mech_openssl.c
+++ b/usr/lib/common/mech_openssl.c
@@ -5160,7 +5160,8 @@ CK_RV openssl_specific_rsa_derive_kdk(STDLL_TokData_t *tokdata, OBJECT *key_obj,
rc = template_attribute_get_non_empty(key_obj->template,
CKA_PRIVATE_EXPONENT, &priv_exp_attr);
- if (rc != CKR_OK && rc != CKR_TEMPLATE_INCOMPLETE) {
+ if (rc != CKR_OK && rc != CKR_TEMPLATE_INCOMPLETE &&
+ rc != CKR_ATTRIBUTE_VALUE_INVALID) {
TRACE_ERROR("Failed to get CKA_PRIVATE_EXPONENT\n");
goto out;
}

View File

@ -1,7 +1,7 @@
Name: opencryptoki
Summary: Implementation of the PKCS#11 (Cryptoki) specification v3.0
Version: 3.21.0
Release: 8%{?dist}
Version: 3.22.0
Release: 3%{?dist}
License: CPL
URL: https://github.com/opencryptoki/opencryptoki
Source0: https://github.com/opencryptoki/%{name}/archive/v%{version}/%{name}-%{version}.tar.gz
@ -11,14 +11,12 @@ Patch1: opencryptoki-3.11.0-lockdir.patch
Patch2: opencryptoki-3.21.0-p11sak.patch
# upstream patches
# pkcsstats: Fix handling of user name
Patch100: opencryptoki-3.21.0-f4166214552a92d8d66de8011ab11c9c2c6bb0a4.patch
# p11sak: Fix user confirmation prompt behavior when stdin is closed
Patch101: opencryptoki-3.21.0-4ff774568e334a719fc8de16fe2309e2070f0da8.patch
# p11sak fails as soon as there reside non-key objects
Patch102: opencryptoki-3.21.0-92999f344a3ad99a67a1bcfd9ad28f28c33e51bc.patch
# opencryptoki p11sak tool: slot option does not accept argument 0 for slot index 0
Patch103: opencryptoki-3.21.0-2ba0f41ef5e14d4b509c8854e27cf98e3ee89445.patch
# CVE-2024-0914 opencryptoki: timing side-channel in handling of RSA PKCS#1 v1.5 padded ciphertexts
Patch20: opencryptoki-CVE-2024-0914-part1.patch
Patch21: opencryptoki-CVE-2024-0914-part2.patch
Patch22: opencryptoki-CVE-2024-0914-part3.patch
Patch23: opencryptoki-CVE-2024-0914-part4.patch
Patch24: opencryptoki-CVE-2024-0914-part5.patch
Requires(pre): coreutils diffutils
Requires: (selinux-policy >= 38.1.14-1 if selinux-policy-targeted)
@ -353,6 +351,18 @@ fi
%changelog
* Fri Feb 16 2024 Than Ngo <than@redhat.com> - 3.22.0-3
- Fix implicit rejection with RSA keys with empty CKA_PRIVATE_EXPONENT
Related: RHEL-22792
* Thu Feb 08 2024 Than Ngo <than@redhat.com> - 3.22.0-2
- timing side-channel in handling of RSA PKCS#1 v1.5 padded ciphertexts (Marvin)
Resolves: RHEL-22792
* Tue Nov 21 2023 Than Ngo <than@redhat.com> - 3.22.0-1
- Resolves: RHEL-11412, rebase to 3.22.0
- Resolves: RHEL-10569, openCryptoki for PKCS #11 3.0
* Fri Jul 14 2023 Than Ngo <than@redhat.com> - 3.21.0-8
- Resolves: #2222592, p11sak tool: slot option does not accept argument 0 for slot index 0
- Resolves: #2222596, p11sak fails as soon as there reside non-key objects