Compare commits
No commits in common. 'c9' and 'c9-beta' have entirely different histories.
@ -1 +1 @@
|
||||
SOURCES/opencryptoki-3.21.0.tar.gz
|
||||
SOURCES/opencryptoki-3.23.0.tar.gz
|
||||
|
@ -1 +1 @@
|
||||
4a0f2ed8f965a948057ab833f1fafabf58929d3f SOURCES/opencryptoki-3.21.0.tar.gz
|
||||
0d70d0a5170a79fc358107d07a62bea1b476e0cc SOURCES/opencryptoki-3.23.0.tar.gz
|
||||
|
@ -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) ||
|
@ -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;
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
commit 2d68f8626d15b9697a29a377a63bbdf35b42ee36
|
||||
Author: Joerg Schmidbauer <jschmidb@de.ibm.com>
|
||||
Date: Tue Feb 13 16:20:06 2024 +0100
|
||||
|
||||
EP11 pkey option: add new PKEY_MODE parms to ep11 config file
|
||||
|
||||
Add two new parameter values ENABLE4EXTR and ENABLE4ALL to the ep11token
|
||||
PKEY_MODE config option. Older ep11 card firmware enforces the restriction that
|
||||
keys can not have CKA_EXTRACTABLE=true and CKA_IBM_PROTKEY_EXTRACTABLE=true at
|
||||
the same time. With newer card firmware this restriction is removed and a new
|
||||
control point is introduced to allow checking for this feature.
|
||||
|
||||
Signed-off-by: Joerg Schmidbauer <jschmidb@de.ibm.com>
|
||||
|
||||
diff --git a/usr/lib/ep11_stdll/ep11tok.conf b/usr/lib/ep11_stdll/ep11tok.conf
|
||||
index 19c9963f..afe237b9 100644
|
||||
--- a/usr/lib/ep11_stdll/ep11tok.conf
|
||||
+++ b/usr/lib/ep11_stdll/ep11tok.conf
|
||||
@@ -104,7 +104,7 @@
|
||||
# disabled and additional hardware and firmware prerequisites are met. AES-XTS
|
||||
# is not supported via the EP11 coprocessor itself.
|
||||
#
|
||||
-# PKEY_MODE DISABLED | DEFAULT | ENABLE4NONEXTR
|
||||
+# PKEY_MODE DISABLED | DEFAULT | ENABLE4NONEXTR | ENABLE4EXTR | ENABLE4ALL
|
||||
#
|
||||
# DISABLED : Protected key support disabled. All key operations
|
||||
# are performed via EP11 coprocessor, even if a
|
||||
@@ -119,6 +119,22 @@
|
||||
# but not CKA_IBM_PROTKEY_EXTRACTABLE, new keys get
|
||||
# CKA_IBM_PROTKEY_EXTRACTABLE=true internally.
|
||||
#
|
||||
+# Control point 75 (XCP_CPB_ALLOW_COMBINED_EXTRACT) must be enabled for all
|
||||
+# APQNs accessible by the token for the following parameters.
|
||||
+#
|
||||
+# ENABLE4EXTR : If the application did not specify
|
||||
+# CKA_IBM_PROTKEY_EXTRACTABLE in its template, new keys
|
||||
+# of any type with CKA_EXTRACTABLE=true get
|
||||
+# CKA_IBM_PROTKEY_EXTRACTABLE=true and a protected key
|
||||
+# is automatically created at first use of the key.
|
||||
+#
|
||||
+# ENABLE4ALL : If the application did not specify
|
||||
+# CKA_IBM_PROTKEY_EXTRACTABLE in its template, new keys
|
||||
+# of any type, regardless of the CKA_EXTRACTABLE
|
||||
+# attribute, get CKA_IBM_PROTKEY_EXTRACTABLE=true and
|
||||
+# a protected key is automatically created at first
|
||||
+# use of the key.
|
||||
+#
|
||||
# --------------------------------------------------------------------------
|
||||
#
|
||||
# Specify the expected wrapping key verification pattern. When specified, all
|
@ -0,0 +1,222 @@
|
||||
commit a6192bb9c3263fb691da87b3a1ed5f66f887b09a
|
||||
Author: Joerg Schmidbauer <jschmidb@de.ibm.com>
|
||||
Date: Tue Feb 13 16:35:53 2024 +0100
|
||||
|
||||
EP11 pkey option: handle new PKEY_MODE parms for new objects
|
||||
|
||||
Signed-off-by: Joerg Schmidbauer <jschmidb@de.ibm.com>
|
||||
|
||||
diff --git a/usr/lib/ep11_stdll/ep11_specific.c b/usr/lib/ep11_stdll/ep11_specific.c
|
||||
index d5964a9c..d1efd8c5 100644
|
||||
--- a/usr/lib/ep11_stdll/ep11_specific.c
|
||||
+++ b/usr/lib/ep11_stdll/ep11_specific.c
|
||||
@@ -1239,6 +1239,33 @@ CK_RV ep11tok_pkey_check_aes_xts(STDLL_TokData_t *tokdata, OBJECT *key_obj,
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
+CK_RV ep11tok_pkey_add_protkey_attr_to_tmpl(TEMPLATE *tmpl)
|
||||
+{
|
||||
+ CK_ATTRIBUTE *pkey_attr = NULL;
|
||||
+ CK_BBOOL btrue = CK_TRUE;
|
||||
+ CK_RV ret;
|
||||
+
|
||||
+ if (!template_attribute_find(tmpl, CKA_IBM_PROTKEY_EXTRACTABLE, &pkey_attr)) {
|
||||
+ ret = build_attribute(CKA_IBM_PROTKEY_EXTRACTABLE, &btrue,
|
||||
+ sizeof(CK_BBOOL), &pkey_attr);
|
||||
+ if (ret != CKR_OK) {
|
||||
+ TRACE_ERROR("build_attribute failed with ret=0x%lx\n", ret);
|
||||
+ goto done;
|
||||
+ }
|
||||
+ ret = template_update_attribute(tmpl, pkey_attr);
|
||||
+ if (ret != CKR_OK) {
|
||||
+ TRACE_ERROR("update_attribute failed with ret=0x%lx\n", ret);
|
||||
+ free(pkey_attr);
|
||||
+ goto done;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ ret = CKR_OK;
|
||||
+
|
||||
+done:
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* This function is called whenever a new object is created. It sets
|
||||
* attribute CKA_IBM_PROTKEY_EXTRACTABLE according to the PKEY_MODE token
|
||||
@@ -1254,7 +1281,7 @@ CK_RV token_specific_set_attrs_for_new_object(STDLL_TokData_t *tokdata,
|
||||
CK_ULONG mode, TEMPLATE *tmpl)
|
||||
{
|
||||
ep11_private_data_t *ep11_data = tokdata->private_data;
|
||||
- CK_ATTRIBUTE *pkey_attr = NULL, *ecp_attr = NULL, *sensitive_attr = NULL;
|
||||
+ CK_ATTRIBUTE *ecp_attr = NULL, *sensitive_attr = NULL;
|
||||
CK_BBOOL extractable, sensitive, btrue = CK_TRUE;
|
||||
CK_BBOOL add_pkey_extractable = CK_FALSE;
|
||||
CK_RV ret;
|
||||
@@ -1314,23 +1341,62 @@ CK_RV token_specific_set_attrs_for_new_object(STDLL_TokData_t *tokdata,
|
||||
add_pkey_extractable = CK_TRUE;
|
||||
break;
|
||||
}
|
||||
-
|
||||
if (add_pkey_extractable) {
|
||||
- if (!template_attribute_find(tmpl, CKA_IBM_PROTKEY_EXTRACTABLE, &pkey_attr)) {
|
||||
- ret = build_attribute(CKA_IBM_PROTKEY_EXTRACTABLE,
|
||||
- (CK_BBOOL *)&btrue, sizeof(CK_BBOOL),
|
||||
- &pkey_attr);
|
||||
- if (ret != CKR_OK) {
|
||||
- TRACE_ERROR("build_attribute failed with ret=0x%lx\n", ret);
|
||||
- goto done;
|
||||
- }
|
||||
- ret = template_update_attribute(tmpl, pkey_attr);
|
||||
- if (ret != CKR_OK) {
|
||||
- TRACE_ERROR("update_attribute failed with ret=0x%lx\n", ret);
|
||||
- free(pkey_attr);
|
||||
- goto done;
|
||||
- }
|
||||
- }
|
||||
+ ret = ep11tok_pkey_add_protkey_attr_to_tmpl(tmpl);
|
||||
+ if (ret != CKR_OK)
|
||||
+ goto done;
|
||||
+ }
|
||||
+ break;
|
||||
+ case PKEY_MODE_ENABLE4EXTR:
|
||||
+ /* If the application did not specify CKA_IBM_PROTKEY_EXTRACTABLE in
|
||||
+ * its template, new keys of any type with CKA_EXTRACTABLE=true get
|
||||
+ * CKA_IBM_PROTKEY_EXTRACTABLE=true and a protected key is automatically
|
||||
+ * created at first use of the key.
|
||||
+ */
|
||||
+ switch (class) {
|
||||
+ case CKO_PUBLIC_KEY:
|
||||
+ if (template_attribute_get_non_empty(tmpl, CKA_EC_PARAMS, &ecp_attr) == CKR_OK &&
|
||||
+ pkey_op_supported_by_cpacf(ep11_data->msa_level, CKM_ECDSA, tmpl))
|
||||
+ add_pkey_extractable = CK_TRUE;
|
||||
+ /* Note that the explicit parm CKM_ECDSA just tells the
|
||||
+ * function that it's not AES here. It covers all EC and ED
|
||||
+ * mechs */
|
||||
+ break;
|
||||
+ default:
|
||||
+ ret = template_attribute_get_bool(tmpl, CKA_EXTRACTABLE, &extractable);
|
||||
+ if (ret == CKR_OK && extractable) // Einziger Unterschied: extractable, statt !extractable
|
||||
+ add_pkey_extractable = CK_TRUE;
|
||||
+ break;
|
||||
+ }
|
||||
+ if (add_pkey_extractable) {
|
||||
+ ret = ep11tok_pkey_add_protkey_attr_to_tmpl(tmpl);
|
||||
+ if (ret != CKR_OK)
|
||||
+ goto done;
|
||||
+ }
|
||||
+ break;
|
||||
+ case PKEY_MODE_ENABLE4ALL:
|
||||
+ /* If the application did not specify CKA_IBM_PROTKEY_EXTRACTABLE in
|
||||
+ * its template, new keys of any type, regardless of CKA_EXTRACTABLE,
|
||||
+ * get CKA_IBM_PROTKEY_EXTRACTABLE=true and a protected key is
|
||||
+ * automatically created at first use of the key.
|
||||
+ */
|
||||
+ switch (class) {
|
||||
+ case CKO_PUBLIC_KEY:
|
||||
+ if (template_attribute_get_non_empty(tmpl, CKA_EC_PARAMS, &ecp_attr) == CKR_OK &&
|
||||
+ pkey_op_supported_by_cpacf(ep11_data->msa_level, CKM_ECDSA, tmpl))
|
||||
+ add_pkey_extractable = CK_TRUE;
|
||||
+ /* Note that the explicit parm CKM_ECDSA just tells the
|
||||
+ * function that it's not AES here. It covers all EC and ED
|
||||
+ * mechs */
|
||||
+ break;
|
||||
+ default:
|
||||
+ add_pkey_extractable = CK_TRUE;
|
||||
+ break;
|
||||
+ }
|
||||
+ if (add_pkey_extractable) {
|
||||
+ ret = ep11tok_pkey_add_protkey_attr_to_tmpl(tmpl);
|
||||
+ if (ret != CKR_OK)
|
||||
+ goto done;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -12188,6 +12254,10 @@ static CK_RV ep11_config_set_pkey_mode(ep11_private_data_t *ep11_data,
|
||||
ep11_data->pkey_mode = PKEY_MODE_DEFAULT;
|
||||
else if (strcmp(strval, "ENABLE4NONEXTR") == 0)
|
||||
ep11_data->pkey_mode = PKEY_MODE_ENABLE4NONEXTR;
|
||||
+ else if (strcmp(strval, "ENABLE4EXTR") == 0)
|
||||
+ ep11_data->pkey_mode = PKEY_MODE_ENABLE4EXTR;
|
||||
+ else if (strcmp(strval, "ENABLE4ALL") == 0)
|
||||
+ ep11_data->pkey_mode = PKEY_MODE_ENABLE4ALL;
|
||||
else {
|
||||
TRACE_ERROR("%s unsupported PKEY mode : '%s'\n", __func__, strval);
|
||||
OCK_SYSLOG(LOG_ERR,"%s: Error: unsupported PKEY mode '%s' "
|
||||
@@ -13252,6 +13322,7 @@ typedef struct cp_handler_data {
|
||||
int first;
|
||||
size_t max_cp_index;
|
||||
CK_BBOOL error;
|
||||
+ CK_BBOOL allow_combined_extract;
|
||||
} cp_handler_data_t;
|
||||
|
||||
static CK_RV control_point_handler(uint_32 adapter, uint_32 domain,
|
||||
@@ -13329,6 +13400,27 @@ static CK_RV control_point_handler(uint_32 adapter, uint_32 domain,
|
||||
}
|
||||
}
|
||||
|
||||
+ /* Combined extract is only supported if all APQNs support it */
|
||||
+ if (max_cp_index < XCP_CPB_ALLOW_COMBINED_EXTRACT ||
|
||||
+ (cp[CP_BYTE_NO(XCP_CPB_ALLOW_COMBINED_EXTRACT)] &
|
||||
+ CP_BIT_MASK(XCP_CPB_ALLOW_COMBINED_EXTRACT)) == 0) {
|
||||
+ data->allow_combined_extract = CK_FALSE;
|
||||
+
|
||||
+ if (ep11_data->pkey_mode == PKEY_MODE_ENABLE4EXTR ||
|
||||
+ ep11_data->pkey_mode == PKEY_MODE_ENABLE4ALL) {
|
||||
+ TRACE_ERROR("Control point setting for adapter %02X.%04X does not "
|
||||
+ "allow combined extract, but PKEY_MODE ENABLE4EXTR or "
|
||||
+ "ENABLE4ALL specified in ep11 token config file.\n",
|
||||
+ adapter, domain);
|
||||
+ OCK_SYSLOG(LOG_ERR,
|
||||
+ "Control point setting for adapter %02X.%04X does not "
|
||||
+ "allow combined extract, but PKEY_MODE ENABLE4EXTR or "
|
||||
+ "ENABLE4ALL specified in ep11 token config file.\n",
|
||||
+ adapter, domain);
|
||||
+ data->error = TRUE;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/* Check FIPS-session related CPs for non-FIPS-session mode */
|
||||
if (!ep11_data->fips_session_mode) {
|
||||
if (max_cp_index >= XCP_CPB_ALLOW_NONSESSION &&
|
||||
@@ -13392,6 +13484,7 @@ static CK_RV get_control_points(STDLL_TokData_t * tokdata,
|
||||
* to older cards default to ON. CPs being OFF disable functionality.
|
||||
*/
|
||||
memset(data.combined_cp, 0xff, sizeof(data.combined_cp));
|
||||
+ data.allow_combined_extract = CK_TRUE;
|
||||
data.first = 1;
|
||||
rc = handle_all_ep11_cards(&ep11_data->target_list, control_point_handler,
|
||||
&data);
|
||||
@@ -13410,6 +13503,11 @@ static CK_RV get_control_points(STDLL_TokData_t * tokdata,
|
||||
print_control_points(cp, *cp_len, data.max_cp_index);
|
||||
#endif
|
||||
|
||||
+ if (data.allow_combined_extract == CK_FALSE)
|
||||
+ __sync_or_and_fetch(&ep11_data->pkey_combined_extract_supported, 0);
|
||||
+ else
|
||||
+ __sync_or_and_fetch(&ep11_data->pkey_combined_extract_supported, 1);
|
||||
+
|
||||
return data.error ? CKR_DEVICE_ERROR : CKR_OK;
|
||||
}
|
||||
|
||||
diff --git a/usr/lib/ep11_stdll/ep11_specific.h b/usr/lib/ep11_stdll/ep11_specific.h
|
||||
index deb8f45f..16d3c719 100644
|
||||
--- a/usr/lib/ep11_stdll/ep11_specific.h
|
||||
+++ b/usr/lib/ep11_stdll/ep11_specific.h
|
||||
@@ -241,6 +241,8 @@ typedef struct {
|
||||
#define PKEY_MODE_DISABLED 0
|
||||
#define PKEY_MODE_DEFAULT 1
|
||||
#define PKEY_MODE_ENABLE4NONEXTR 2
|
||||
+#define PKEY_MODE_ENABLE4EXTR 3
|
||||
+#define PKEY_MODE_ENABLE4ALL 4
|
||||
|
||||
#define PQC_BYTE_NO(idx) (((idx) - 1) / 8)
|
||||
#define PQC_BIT_IN_BYTE(idx) (((idx - 1)) % 8)
|
||||
@@ -278,6 +280,7 @@ typedef struct {
|
||||
int fips_session_mode;
|
||||
int optimize_single_ops;
|
||||
int pkey_mode;
|
||||
+ volatile int pkey_combined_extract_supported;
|
||||
volatile int pkey_wrap_supported;
|
||||
int pkey_wrap_support_checked;
|
||||
char pkey_mk_vp[PKEY_MK_VP_LENGTH];
|
@ -0,0 +1,62 @@
|
||||
commit 88a01a9c4ba237431d89e3999cd6fdfddd10a51a
|
||||
Author: Joerg Schmidbauer <jschmidb@de.ibm.com>
|
||||
Date: Thu Mar 7 17:42:11 2024 +0100
|
||||
|
||||
EP11 pkey option: handle new PKEY_MODE parms in eligibility check
|
||||
|
||||
Signed-off-by: Joerg Schmidbauer <jschmidb@de.ibm.com>
|
||||
|
||||
diff --git a/usr/lib/ep11_stdll/ep11_specific.c b/usr/lib/ep11_stdll/ep11_specific.c
|
||||
index d1efd8c5..a163587c 100644
|
||||
--- a/usr/lib/ep11_stdll/ep11_specific.c
|
||||
+++ b/usr/lib/ep11_stdll/ep11_specific.c
|
||||
@@ -1080,6 +1080,26 @@ static CK_BBOOL ep11tok_pkey_session_ok_for_obj(SESSION *session,
|
||||
return CK_TRUE;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Returns true if the given key object is eligible to get a protected key
|
||||
+ * attribute, false otherwise.
|
||||
+ */
|
||||
+CK_BBOOL ep11tok_pkey_obj_eligible_for_pkey_support(ep11_private_data_t *ep11_data,
|
||||
+ OBJECT *key_obj)
|
||||
+{
|
||||
+ if (object_is_attr_bound(key_obj) || !ep11_data->pkey_wrap_supported ||
|
||||
+ !object_is_pkey_extractable(key_obj)) {
|
||||
+ return CK_FALSE;
|
||||
+ }
|
||||
+
|
||||
+ if (!ep11_data->pkey_combined_extract_supported &&
|
||||
+ object_is_extractable(key_obj)) {
|
||||
+ return CK_FALSE;
|
||||
+ }
|
||||
+
|
||||
+ return CK_TRUE;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* Checks if the preconditions for using the related protected key of
|
||||
* the given secure key object are met. The caller of this routine must
|
||||
@@ -1135,6 +1155,8 @@ CK_RV ep11tok_pkey_check(STDLL_TokData_t *tokdata, SESSION *session,
|
||||
break;
|
||||
case PKEY_MODE_DEFAULT:
|
||||
case PKEY_MODE_ENABLE4NONEXTR:
|
||||
+ case PKEY_MODE_ENABLE4EXTR:
|
||||
+ case PKEY_MODE_ENABLE4ALL:
|
||||
/* Use existing pkeys, re-create invalid pkeys, and also create new
|
||||
* pkeys for secret/private keys that do not already have one. EC
|
||||
* public keys that are pkey-extractable, can always be used via CPACF
|
||||
@@ -1149,12 +1171,8 @@ CK_RV ep11tok_pkey_check(STDLL_TokData_t *tokdata, SESSION *session,
|
||||
if (ep11tok_pkey_get_firmware_mk_vp(tokdata, session) != CKR_OK)
|
||||
goto done;
|
||||
|
||||
- if (object_is_extractable(key_obj) ||
|
||||
- !object_is_pkey_extractable(key_obj) ||
|
||||
- object_is_attr_bound(key_obj) ||
|
||||
- !ep11_data->pkey_wrap_supported) {
|
||||
+ if (!ep11tok_pkey_obj_eligible_for_pkey_support(ep11_data, key_obj))
|
||||
goto done;
|
||||
- }
|
||||
|
||||
if (template_attribute_get_non_empty(key_obj->template,
|
||||
CKA_IBM_OPAQUE_PKEY,
|
@ -0,0 +1,555 @@
|
||||
commit b9e33fced0654aac939182957bf2eba2eda77872
|
||||
Author: Joerg Schmidbauer <jschmidb@de.ibm.com>
|
||||
Date: Wed Feb 21 13:48:15 2024 +0100
|
||||
|
||||
EP11 pkey option: add NO_PKEY compile option for EP11 token
|
||||
|
||||
On 32-bit s390 platforms, the pkey related assembler code parts won't
|
||||
compile. Therefore, add NO_PKEY compile switches where necessary.
|
||||
The NO_PKEY compile switch is already handled in configure.ac.
|
||||
|
||||
Signed-off-by: Joerg Schmidbauer <jschmidb@de.ibm.com>
|
||||
|
||||
diff --git a/usr/lib/ep11_stdll/ep11_specific.c b/usr/lib/ep11_stdll/ep11_specific.c
|
||||
index a163587c..114c4ce1 100644
|
||||
--- a/usr/lib/ep11_stdll/ep11_specific.c
|
||||
+++ b/usr/lib/ep11_stdll/ep11_specific.c
|
||||
@@ -60,7 +60,9 @@
|
||||
#include <openssl/ec.h>
|
||||
|
||||
#include "ep11_specific.h"
|
||||
+#ifndef NO_PKEY
|
||||
#include "pkey_utils.h"
|
||||
+#endif
|
||||
|
||||
CK_RV ep11tok_get_mechanism_list(STDLL_TokData_t * tokdata,
|
||||
CK_MECHANISM_TYPE_PTR mlist,
|
||||
@@ -256,11 +258,13 @@ static const version_req_t reencrypt_single_req_versions[] = {
|
||||
#define NUM_REENCRYPT_SINGLE_REQ (sizeof(reencrypt_single_req_versions) / \
|
||||
sizeof(version_req_t))
|
||||
|
||||
+#ifndef NO_PKEY
|
||||
static const CK_VERSION ibm_cex7p_cpacf_wrap_support = { .major = 7, .minor = 15 };
|
||||
static const version_req_t ibm_cpacf_wrap_req_versions[] = {
|
||||
{ .card_type = 7, .min_firmware_version = &ibm_cex7p_cpacf_wrap_support }
|
||||
};
|
||||
#define NUM_CPACF_WRAP_REQ (sizeof(ibm_cpacf_wrap_req_versions) / sizeof(version_req_t))
|
||||
+#endif /* NO_PKEY */
|
||||
|
||||
static const CK_ULONG ibm_cex_ab_ecdh_api_version = 3;
|
||||
static const version_req_t ibm_ab_ecdh_req_versions[] = {
|
||||
@@ -504,6 +508,7 @@ static CK_BBOOL ep11tok_pkey_option_disabled(STDLL_TokData_t *tokdata)
|
||||
return CK_FALSE;
|
||||
}
|
||||
|
||||
+#ifndef NO_PKEY
|
||||
/**
|
||||
* Callback function used by handle_all_ep11_cards() for creating a protected
|
||||
* key via the given APQN (adaper,domain).
|
||||
@@ -1283,6 +1288,7 @@ CK_RV ep11tok_pkey_add_protkey_attr_to_tmpl(TEMPLATE *tmpl)
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
+#endif /* NO_PKEY */
|
||||
|
||||
/**
|
||||
* This function is called whenever a new object is created. It sets
|
||||
@@ -1299,9 +1305,12 @@ CK_RV token_specific_set_attrs_for_new_object(STDLL_TokData_t *tokdata,
|
||||
CK_ULONG mode, TEMPLATE *tmpl)
|
||||
{
|
||||
ep11_private_data_t *ep11_data = tokdata->private_data;
|
||||
- CK_ATTRIBUTE *ecp_attr = NULL, *sensitive_attr = NULL;
|
||||
- CK_BBOOL extractable, sensitive, btrue = CK_TRUE;
|
||||
- CK_BBOOL add_pkey_extractable = CK_FALSE;
|
||||
+ CK_ATTRIBUTE *sensitive_attr = NULL;
|
||||
+ CK_BBOOL sensitive, btrue = CK_TRUE;
|
||||
+#ifndef NO_PKEY
|
||||
+ CK_ATTRIBUTE *ecp_attr = NULL;
|
||||
+ CK_BBOOL extractable, add_pkey_extractable = CK_FALSE;
|
||||
+#endif
|
||||
CK_RV ret;
|
||||
|
||||
UNUSED(mode);
|
||||
@@ -1331,6 +1340,7 @@ CK_RV token_specific_set_attrs_for_new_object(STDLL_TokData_t *tokdata,
|
||||
}
|
||||
}
|
||||
|
||||
+#ifndef NO_PKEY
|
||||
switch (ep11_data->pkey_mode) {
|
||||
case PKEY_MODE_DISABLED:
|
||||
/* Nothing to do */
|
||||
@@ -1423,6 +1433,7 @@ CK_RV token_specific_set_attrs_for_new_object(STDLL_TokData_t *tokdata,
|
||||
goto done;
|
||||
break;
|
||||
}
|
||||
+#endif /* NO_PKEY */
|
||||
|
||||
ret = CKR_OK;
|
||||
|
||||
@@ -1431,6 +1442,19 @@ done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
+#ifdef NO_PKEY
|
||||
+CK_BBOOL ep11tok_pkey_usage_ok(STDLL_TokData_t *tokdata, SESSION *session,
|
||||
+ CK_OBJECT_HANDLE hkey, CK_MECHANISM *mech)
|
||||
+{
|
||||
+ UNUSED(tokdata);
|
||||
+ UNUSED(session);
|
||||
+ UNUSED(hkey);
|
||||
+ UNUSED(mech);
|
||||
+
|
||||
+ return CK_FALSE;
|
||||
+}
|
||||
+#endif /* NO_PKEY */
|
||||
+
|
||||
static CK_RV check_ab_supported(CK_KEY_TYPE type) {
|
||||
switch(type) {
|
||||
case CKK_AES:
|
||||
@@ -2837,8 +2861,10 @@ CK_RV ep11tok_init(STDLL_TokData_t * tokdata, CK_SLOT_ID SlotNumber,
|
||||
goto error;
|
||||
}
|
||||
|
||||
+#ifndef NO_PKEY
|
||||
ep11_data->msa_level = get_msa_level();
|
||||
TRACE_INFO("MSA level = %i\n", ep11_data->msa_level);
|
||||
+#endif
|
||||
|
||||
if (pthread_mutex_init(&ep11_data->raw2key_wrap_blob_mutex, NULL) != 0) {
|
||||
TRACE_ERROR("Initializing Wrap-Blob lock failed.\n");
|
||||
@@ -2847,19 +2873,20 @@ CK_RV ep11tok_init(STDLL_TokData_t * tokdata, CK_SLOT_ID SlotNumber,
|
||||
}
|
||||
ep11_data->raw2key_wrap_blob_l = 0;
|
||||
|
||||
-
|
||||
if (pthread_mutex_init(&ep11_data->pkey_mutex, NULL) != 0) {
|
||||
TRACE_ERROR("Initializing PKEY lock failed.\n");
|
||||
rc = CKR_CANT_LOCK;
|
||||
goto error;
|
||||
}
|
||||
|
||||
+#ifndef NO_PKEY
|
||||
if (!ep11tok_pkey_option_disabled(tokdata) &&
|
||||
!ep11_data->fips_session_mode) {
|
||||
rc = ep11tok_pkey_get_firmware_mk_vp(tokdata, NULL);
|
||||
if (rc != CKR_OK && rc != CKR_FUNCTION_NOT_SUPPORTED)
|
||||
goto error;
|
||||
}
|
||||
+#endif /* NO_PKEY */
|
||||
|
||||
if (ep11_data->vhsm_mode || ep11_data->fips_session_mode) {
|
||||
if (pthread_mutex_init(&ep11_data->session_mutex, NULL) != 0) {
|
||||
@@ -3178,7 +3205,11 @@ static CK_RV import_aes_xts_key(STDLL_TokData_t *tokdata, SESSION *sess,
|
||||
if (rc != CKR_OK)
|
||||
goto import_aes_xts_key_end;
|
||||
|
||||
+#ifndef NO_PKEY
|
||||
rc = ep11tok_pkey_check_aes_xts(tokdata, aes_xts_key_obj, CKM_AES_XTS);
|
||||
+#else
|
||||
+ rc = CKR_FUNCTION_NOT_SUPPORTED;
|
||||
+#endif
|
||||
if (rc != CKR_OK) {
|
||||
TRACE_ERROR("%s EP11 AES XTS is not supported: rc=0x%lx\n", __func__, rc);
|
||||
goto import_aes_xts_key_end;
|
||||
@@ -4562,10 +4593,12 @@ CK_RV token_specific_object_add(STDLL_TokData_t * tokdata, SESSION * sess,
|
||||
return rc;
|
||||
}
|
||||
|
||||
+#ifndef NO_PKEY
|
||||
/* Ensure the firmware master key verification pattern is available */
|
||||
rc = ep11tok_pkey_get_firmware_mk_vp(tokdata, sess);
|
||||
if (rc != CKR_OK && rc != CKR_FUNCTION_NOT_SUPPORTED)
|
||||
return rc;
|
||||
+#endif /* NO_PKEY */
|
||||
|
||||
memset(blob, 0, sizeof(blob));
|
||||
memset(blobreenc, 0, sizeof(blobreenc));
|
||||
@@ -4797,10 +4830,12 @@ CK_RV ep11tok_generate_key(STDLL_TokData_t * tokdata, SESSION * session,
|
||||
goto error;
|
||||
}
|
||||
|
||||
+#ifndef NO_PKEY
|
||||
/* Ensure the firmware master key verification pattern is available */
|
||||
rc = ep11tok_pkey_get_firmware_mk_vp(tokdata, session);
|
||||
if (rc != CKR_OK && rc != CKR_FUNCTION_NOT_SUPPORTED)
|
||||
goto error;
|
||||
+#endif /* NO_PKEY */
|
||||
|
||||
rc = object_mgr_create_skel(tokdata, session, new_attrs, new_attrs_len,
|
||||
MODE_KEYGEN, CKO_SECRET_KEY, ktype, &key_obj);
|
||||
@@ -4820,7 +4855,11 @@ CK_RV ep11tok_generate_key(STDLL_TokData_t * tokdata, SESSION * session,
|
||||
|
||||
if (mech->mechanism == CKM_AES_XTS_KEY_GEN) {
|
||||
xts = TRUE;
|
||||
+#ifndef NO_PKEY
|
||||
rc = ep11tok_pkey_check_aes_xts(tokdata, key_obj, mech->mechanism);
|
||||
+#else
|
||||
+ rc = CKR_FUNCTION_NOT_SUPPORTED;
|
||||
+#endif
|
||||
if (rc != CKR_OK) {
|
||||
TRACE_ERROR("%s EP11 AES XTS is not supported: rc=0x%lx\n",
|
||||
__func__, rc);
|
||||
@@ -5812,7 +5851,9 @@ CK_RV token_specific_ec_sign(STDLL_TokData_t *tokdata, SESSION *session,
|
||||
CK_BYTE *out_data, CK_ULONG *out_data_len,
|
||||
OBJECT *key_obj )
|
||||
{
|
||||
+#ifndef NO_PKEY
|
||||
SIGN_VERIFY_CONTEXT *ctx = &(session->sign_ctx);
|
||||
+#endif
|
||||
CK_RV rc;
|
||||
size_t keyblobsize = 0;
|
||||
CK_BYTE *keyblob;
|
||||
@@ -5826,6 +5867,7 @@ CK_RV token_specific_ec_sign(STDLL_TokData_t *tokdata, SESSION *session,
|
||||
return rc;
|
||||
}
|
||||
|
||||
+#ifndef NO_PKEY
|
||||
rc = ep11tok_pkey_check(tokdata, session, key_obj, &ctx->mech);
|
||||
switch (rc) {
|
||||
case CKR_OK:
|
||||
@@ -5837,6 +5879,7 @@ CK_RV token_specific_ec_sign(STDLL_TokData_t *tokdata, SESSION *session,
|
||||
default:
|
||||
goto done;
|
||||
}
|
||||
+#endif /* NO_PKEY */
|
||||
|
||||
mech.mechanism = CKM_ECDSA;
|
||||
mech.pParameter = NULL;
|
||||
@@ -5856,7 +5899,9 @@ CK_RV token_specific_ec_sign(STDLL_TokData_t *tokdata, SESSION *session,
|
||||
TRACE_INFO("%s rc=0x%lx\n", __func__, rc);
|
||||
}
|
||||
|
||||
+#ifndef NO_PKEY
|
||||
done:
|
||||
+#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -5866,7 +5911,9 @@ CK_RV token_specific_ec_verify(STDLL_TokData_t *tokdata, SESSION *session,
|
||||
CK_BYTE *out_data, CK_ULONG out_data_len,
|
||||
OBJECT *key_obj )
|
||||
{
|
||||
+#ifndef NO_PKEY
|
||||
SIGN_VERIFY_CONTEXT *ctx = &(session->verify_ctx);
|
||||
+#endif
|
||||
CK_RV rc;
|
||||
CK_BYTE *spki;
|
||||
size_t spki_len = 0;
|
||||
@@ -5880,6 +5927,7 @@ CK_RV token_specific_ec_verify(STDLL_TokData_t *tokdata, SESSION *session,
|
||||
return rc;
|
||||
}
|
||||
|
||||
+#ifndef NO_PKEY
|
||||
rc = ep11tok_pkey_check(tokdata, session, key_obj, &ctx->mech);
|
||||
switch (rc) {
|
||||
case CKR_OK:
|
||||
@@ -5891,6 +5939,7 @@ CK_RV token_specific_ec_verify(STDLL_TokData_t *tokdata, SESSION *session,
|
||||
default:
|
||||
goto done;
|
||||
}
|
||||
+#endif /* NO_PKEY */
|
||||
|
||||
mech.mechanism = CKM_ECDSA;
|
||||
mech.pParameter = NULL;
|
||||
@@ -5911,7 +5960,9 @@ CK_RV token_specific_ec_verify(STDLL_TokData_t *tokdata, SESSION *session,
|
||||
TRACE_INFO("%s rc=0x%lx\n", __func__, rc);
|
||||
}
|
||||
|
||||
+#ifndef NO_PKEY
|
||||
done:
|
||||
+#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -5981,6 +6032,7 @@ CK_RV token_specific_reencrypt_single(STDLL_TokData_t *tokdata,
|
||||
return rc;
|
||||
}
|
||||
|
||||
+#ifndef NO_PKEY
|
||||
/**
|
||||
* This routine is currently only used when the operation is performed using
|
||||
* a protected key. Therefore we don't have (and don't need) an ep11
|
||||
@@ -6062,6 +6114,7 @@ CK_RV token_specific_aes_xts(STDLL_TokData_t *tokdata, SESSION *session,
|
||||
return pkey_aes_xts(key_obj, init_v, in_data, in_data_len,
|
||||
out_data, out_data_len, encrypt, initial, final, iv);
|
||||
}
|
||||
+#endif /* NO_PKEY */
|
||||
|
||||
struct EP11_KYBER_MECH {
|
||||
CK_MECHANISM mech;
|
||||
@@ -6829,10 +6882,12 @@ CK_RV ep11tok_derive_key(STDLL_TokData_t *tokdata, SESSION *session,
|
||||
goto error;
|
||||
}
|
||||
|
||||
+#ifndef NO_PKEY
|
||||
/* Ensure the firmware master key verification pattern is available */
|
||||
rc = ep11tok_pkey_get_firmware_mk_vp(tokdata, session);
|
||||
if (rc != CKR_OK && rc != CKR_FUNCTION_NOT_SUPPORTED)
|
||||
goto error;
|
||||
+#endif /* NO_PKEY */
|
||||
|
||||
/* Start creating the key object */
|
||||
rc = object_mgr_create_skel(tokdata, session, new_attrs1, new_attrs1_len,
|
||||
@@ -8554,10 +8609,12 @@ CK_RV ep11tok_generate_key_pair(STDLL_TokData_t * tokdata, SESSION * sess,
|
||||
if (rc != CKR_OK)
|
||||
goto error;
|
||||
|
||||
+#ifndef NO_PKEY
|
||||
/* Ensure the firmware master key verification pattern is available */
|
||||
rc = ep11tok_pkey_get_firmware_mk_vp(tokdata, sess);
|
||||
if (rc != CKR_OK && rc != CKR_FUNCTION_NOT_SUPPORTED)
|
||||
goto error;
|
||||
+#endif /* NO_PKEY */
|
||||
|
||||
/* Now build the skeleton key. */
|
||||
rc = object_mgr_create_skel(tokdata, sess, pPublicKeyTemplate,
|
||||
@@ -9202,6 +9259,7 @@ CK_RV ep11tok_sign_init(STDLL_TokData_t * tokdata, SESSION * session,
|
||||
goto done;
|
||||
}
|
||||
|
||||
+#ifndef NO_PKEY
|
||||
rc = ep11tok_pkey_check(tokdata, session, key_obj, mech);
|
||||
switch (rc) {
|
||||
case CKR_OK:
|
||||
@@ -9239,6 +9297,7 @@ CK_RV ep11tok_sign_init(STDLL_TokData_t * tokdata, SESSION * session,
|
||||
free(ep11_sign_state);
|
||||
goto done;
|
||||
}
|
||||
+#endif /* NO_PKEY */
|
||||
|
||||
if (mech->mechanism == CKM_IBM_ECDSA_OTHER) {
|
||||
rc = ep11tok_ecdsa_other_mech_adjust(mech, &mech_ep11);
|
||||
@@ -9340,6 +9399,9 @@ CK_RV ep11tok_sign(STDLL_TokData_t * tokdata, SESSION * session,
|
||||
CK_ULONG in_data_len, CK_BYTE * signature,
|
||||
CK_ULONG * sig_len)
|
||||
{
|
||||
+#ifdef NO_PKEY
|
||||
+ UNUSED(length_only);
|
||||
+#endif
|
||||
CK_RV rc;
|
||||
SIGN_VERIFY_CONTEXT *ctx = &session->sign_ctx;
|
||||
size_t keyblobsize = 0;
|
||||
@@ -9355,6 +9417,7 @@ CK_RV ep11tok_sign(STDLL_TokData_t * tokdata, SESSION * session,
|
||||
return rc;
|
||||
}
|
||||
|
||||
+#ifndef NO_PKEY
|
||||
if (ctx->pkey_active) {
|
||||
/* Note that Edwards curves in general are not yet supported in
|
||||
* opencryptoki. These two special IBM specific ED mechs are only
|
||||
@@ -9372,6 +9435,7 @@ CK_RV ep11tok_sign(STDLL_TokData_t * tokdata, SESSION * session,
|
||||
}
|
||||
goto done; /* no ep11 fallback possible */
|
||||
}
|
||||
+#endif /* NO_PKEY */
|
||||
|
||||
RETRY_SESSION_SINGLE_APQN_START(rc, tokdata)
|
||||
RETRY_UPDATE_BLOB_START(tokdata, target_info,
|
||||
@@ -9394,7 +9458,9 @@ CK_RV ep11tok_sign(STDLL_TokData_t * tokdata, SESSION * session,
|
||||
TRACE_INFO("%s rc=0x%lx\n", __func__, rc);
|
||||
}
|
||||
|
||||
+#ifndef NO_PKEY
|
||||
done:
|
||||
+#endif
|
||||
|
||||
object_put(tokdata, key_obj, TRUE);
|
||||
key_obj = NULL;
|
||||
@@ -9638,6 +9704,7 @@ CK_RV ep11tok_verify_init(STDLL_TokData_t * tokdata, SESSION * session,
|
||||
goto done;
|
||||
}
|
||||
|
||||
+#ifndef NO_PKEY
|
||||
rc = ep11tok_pkey_check(tokdata, session, key_obj, mech);
|
||||
switch (rc) {
|
||||
case CKR_OK:
|
||||
@@ -9675,6 +9742,7 @@ CK_RV ep11tok_verify_init(STDLL_TokData_t * tokdata, SESSION * session,
|
||||
free(ep11_sign_state);
|
||||
goto done;
|
||||
}
|
||||
+#endif /* NO_PKEY */
|
||||
|
||||
if (mech->mechanism == CKM_IBM_ECDSA_OTHER) {
|
||||
rc = ep11tok_ecdsa_other_mech_adjust(mech, &mech_ep11);
|
||||
@@ -9787,6 +9855,7 @@ CK_RV ep11tok_verify(STDLL_TokData_t * tokdata, SESSION * session,
|
||||
return rc;
|
||||
}
|
||||
|
||||
+#ifndef NO_PKEY
|
||||
if (ctx->pkey_active) {
|
||||
/* Note that Edwards curves in general are not yet supported in
|
||||
* opencryptoki. These two special IBM specific ED mechs are only
|
||||
@@ -9805,6 +9874,7 @@ CK_RV ep11tok_verify(STDLL_TokData_t * tokdata, SESSION * session,
|
||||
}
|
||||
goto done; /* no ep11 fallback possible */
|
||||
}
|
||||
+#endif /* NO_PKEY */
|
||||
|
||||
RETRY_SESSION_SINGLE_APQN_START(rc, tokdata)
|
||||
RETRY_UPDATE_BLOB_START(tokdata, target_info,
|
||||
@@ -9827,7 +9897,9 @@ CK_RV ep11tok_verify(STDLL_TokData_t * tokdata, SESSION * session,
|
||||
TRACE_INFO("%s rc=0x%lx\n", __func__, rc);
|
||||
}
|
||||
|
||||
+#ifndef NO_PKEY
|
||||
done:
|
||||
+#endif
|
||||
|
||||
object_put(tokdata, key_obj, TRUE);
|
||||
key_obj = NULL;
|
||||
@@ -10561,6 +10633,7 @@ static CK_RV ep11_ende_crypt_init(STDLL_TokData_t * tokdata, SESSION * session,
|
||||
goto error;
|
||||
}
|
||||
|
||||
+#ifndef NO_PKEY
|
||||
rc = ep11tok_pkey_check(tokdata, session, key_obj, mech);
|
||||
switch (rc) {
|
||||
case CKR_OK:
|
||||
@@ -10604,6 +10677,7 @@ static CK_RV ep11_ende_crypt_init(STDLL_TokData_t * tokdata, SESSION * session,
|
||||
free(ep11_state);
|
||||
goto done;
|
||||
}
|
||||
+#endif /* NO_PKEY */
|
||||
|
||||
/*
|
||||
* ep11_state is allocated large enough to hold 2 times the max state blob.
|
||||
@@ -11150,10 +11224,12 @@ CK_RV ep11tok_unwrap_key(STDLL_TokData_t * tokdata, SESSION * session,
|
||||
goto done;
|
||||
}
|
||||
|
||||
+#ifndef NO_PKEY
|
||||
/* Ensure the firmware master key verification pattern is available */
|
||||
rc = ep11tok_pkey_get_firmware_mk_vp(tokdata, session);
|
||||
if (rc != CKR_OK && rc != CKR_FUNCTION_NOT_SUPPORTED)
|
||||
goto error;
|
||||
+#endif /* NO_PKEY */
|
||||
|
||||
/* Start creating the key object */
|
||||
rc = object_mgr_create_skel(tokdata, session, new_attrs, new_attrs_len,
|
||||
@@ -11878,6 +11954,7 @@ CK_RV ep11tok_is_mechanism_supported(STDLL_TokData_t *tokdata,
|
||||
}
|
||||
break;
|
||||
|
||||
+#ifndef NO_PKEY
|
||||
case CKM_IBM_CPACF_WRAP:
|
||||
if (compare_ck_version(&ep11_data->ep11_lib_version, &ver3) <= 0) {
|
||||
TRACE_INFO("%s Mech '%s' banned due to host library version\n",
|
||||
@@ -11895,6 +11972,7 @@ CK_RV ep11tok_is_mechanism_supported(STDLL_TokData_t *tokdata,
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
+#endif /* NO_PKEY */
|
||||
|
||||
case CKM_IBM_BTC_DERIVE:
|
||||
if (compare_ck_version(&ep11_data->ep11_lib_version, &ver3_1) < 0) {
|
||||
@@ -12268,6 +12346,7 @@ static CK_RV ep11_config_set_pkey_mode(ep11_private_data_t *ep11_data,
|
||||
{
|
||||
if (strcmp(strval, "DISABLED") == 0)
|
||||
ep11_data->pkey_mode = PKEY_MODE_DISABLED;
|
||||
+#ifndef NO_PKEY
|
||||
else if (strcmp(strval, "DEFAULT") == 0)
|
||||
ep11_data->pkey_mode = PKEY_MODE_DEFAULT;
|
||||
else if (strcmp(strval, "ENABLE4NONEXTR") == 0)
|
||||
@@ -12276,6 +12355,7 @@ static CK_RV ep11_config_set_pkey_mode(ep11_private_data_t *ep11_data,
|
||||
ep11_data->pkey_mode = PKEY_MODE_ENABLE4EXTR;
|
||||
else if (strcmp(strval, "ENABLE4ALL") == 0)
|
||||
ep11_data->pkey_mode = PKEY_MODE_ENABLE4ALL;
|
||||
+#endif /* NO_PKEY */
|
||||
else {
|
||||
TRACE_ERROR("%s unsupported PKEY mode : '%s'\n", __func__, strval);
|
||||
OCK_SYSLOG(LOG_ERR,"%s: Error: unsupported PKEY mode '%s' "
|
||||
@@ -12456,7 +12536,11 @@ static CK_RV read_adapter_config_file(STDLL_TokData_t * tokdata,
|
||||
sizeof(ep11_data->token_config_filename) - 1] = '\0';
|
||||
|
||||
ep11_data->target_list.length = 0;
|
||||
+#ifndef NO_PKEY
|
||||
ep11_data->pkey_mode = PKEY_MODE_DEFAULT;
|
||||
+#else
|
||||
+ ep11_data->pkey_mode = PKEY_MODE_DISABLED;
|
||||
+#endif
|
||||
|
||||
/* Default to use default libica library for digests */
|
||||
ep11_data->digest_libica = 1;
|
||||
@@ -14695,10 +14779,12 @@ CK_RV token_specific_set_attribute_values(STDLL_TokData_t *tokdata,
|
||||
}
|
||||
}
|
||||
|
||||
+#ifndef NO_PKEY
|
||||
/* Ensure the firmware master key verification pattern is available */
|
||||
rc = ep11tok_pkey_get_firmware_mk_vp(tokdata, session);
|
||||
if (rc != CKR_OK && rc != CKR_FUNCTION_NOT_SUPPORTED)
|
||||
return rc;
|
||||
+#endif /* NO_PKEY */
|
||||
|
||||
node = new_tmpl->attribute_list;
|
||||
while (node) {
|
||||
@@ -14734,6 +14820,7 @@ CK_RV token_specific_set_attribute_values(STDLL_TokData_t *tokdata,
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
+#ifndef NO_PKEY
|
||||
case CKA_IBM_PROTKEY_EXTRACTABLE:
|
||||
if (ep11_data->pkey_wrap_supported) {
|
||||
rc = add_to_attribute_array(&attributes, &num_attributes,
|
||||
@@ -14746,6 +14833,7 @@ CK_RV token_specific_set_attribute_values(STDLL_TokData_t *tokdata,
|
||||
}
|
||||
}
|
||||
break;
|
||||
+#endif /* NO_PKEY */
|
||||
default:
|
||||
/* Either non-boolean, or read-only */
|
||||
break;
|
||||
diff --git a/usr/lib/ep11_stdll/ep11_stdll.mk b/usr/lib/ep11_stdll/ep11_stdll.mk
|
||||
index 6a1d68be..e543c514 100644
|
||||
--- a/usr/lib/ep11_stdll/ep11_stdll.mk
|
||||
+++ b/usr/lib/ep11_stdll/ep11_stdll.mk
|
||||
@@ -41,7 +41,7 @@ opencryptoki_stdll_libpkcs11_ep11_la_SOURCES = usr/lib/common/asn1.c \
|
||||
usr/lib/common/trace.c usr/lib/common/mech_list.c \
|
||||
usr/lib/common/shared_memory.c usr/lib/common/attributes.c \
|
||||
usr/lib/common/sw_crypt.c usr/lib/common/profile_obj.c \
|
||||
- usr/lib/common/dlist.c usr/lib/common/pkey_utils.c \
|
||||
+ usr/lib/common/dlist.c \
|
||||
usr/lib/ep11_stdll/new_host.c usr/lib/common/mech_openssl.c \
|
||||
usr/lib/ep11_stdll/ep11_specific.c \
|
||||
usr/lib/ep11_stdll/ep11_session.c \
|
||||
@@ -53,3 +53,8 @@ opencryptoki_stdll_libpkcs11_ep11_la_SOURCES = usr/lib/common/asn1.c \
|
||||
usr/lib/common/pqc_supported.c \
|
||||
usr/lib/hsm_mk_change/hsm_mk_change.c \
|
||||
usr/lib/common/btree.c usr/lib/common/sess_mgr.c
|
||||
+
|
||||
+if !NO_PKEY
|
||||
+opencryptoki_stdll_libpkcs11_ep11_la_SOURCES += \
|
||||
+ usr/lib/common/pkey_utils.c
|
||||
+endif
|
||||
diff --git a/usr/lib/ep11_stdll/tok_struct.h b/usr/lib/ep11_stdll/tok_struct.h
|
||||
index 304e3eb9..17a5bcf0 100644
|
||||
--- a/usr/lib/ep11_stdll/tok_struct.h
|
||||
+++ b/usr/lib/ep11_stdll/tok_struct.h
|
||||
@@ -115,8 +115,13 @@ token_spec_t token_specific = {
|
||||
// AES
|
||||
NULL, // aes_key_gen,
|
||||
NULL, // aes_xts_key_gen
|
||||
+#ifndef NO_PKEY
|
||||
&token_specific_aes_ecb,
|
||||
&token_specific_aes_cbc,
|
||||
+#else
|
||||
+ NULL, // aes_ecb
|
||||
+ NULL, // aes_cbc
|
||||
+#endif
|
||||
NULL, // aes_ctr
|
||||
NULL, // aes_gcm_init
|
||||
NULL, // aes_gcm
|
||||
@@ -125,8 +130,13 @@ token_spec_t token_specific = {
|
||||
NULL, // aes_ofb
|
||||
NULL, // aes_cfb
|
||||
NULL, // aes_mac
|
||||
+#ifndef NO_PKEY
|
||||
&token_specific_aes_cmac,
|
||||
&token_specific_aes_xts, // aes_xts
|
||||
+#else
|
||||
+ NULL, // aes_cmac
|
||||
+ NULL, // aes_xts
|
||||
+#endif
|
||||
// DSA
|
||||
NULL, // dsa_generate_keypair,
|
||||
NULL, // dsa_sign
|
@ -0,0 +1,61 @@
|
||||
commit 0bdcc661e64950e5ea11d950484631ba90e69426
|
||||
Author: Joerg Schmidbauer <jschmidb@de.ibm.com>
|
||||
Date: Thu Mar 7 17:51:40 2024 +0100
|
||||
|
||||
EP11 pkey option: consolidate code parts, no logic change
|
||||
|
||||
Signed-off-by: Joerg Schmidbauer <jschmidb@de.ibm.com>
|
||||
|
||||
diff --git a/usr/lib/ep11_stdll/ep11_specific.c b/usr/lib/ep11_stdll/ep11_specific.c
|
||||
index 114c4ce1..9f855934 100644
|
||||
--- a/usr/lib/ep11_stdll/ep11_specific.c
|
||||
+++ b/usr/lib/ep11_stdll/ep11_specific.c
|
||||
@@ -1369,11 +1369,6 @@ CK_RV token_specific_set_attrs_for_new_object(STDLL_TokData_t *tokdata,
|
||||
add_pkey_extractable = CK_TRUE;
|
||||
break;
|
||||
}
|
||||
- if (add_pkey_extractable) {
|
||||
- ret = ep11tok_pkey_add_protkey_attr_to_tmpl(tmpl);
|
||||
- if (ret != CKR_OK)
|
||||
- goto done;
|
||||
- }
|
||||
break;
|
||||
case PKEY_MODE_ENABLE4EXTR:
|
||||
/* If the application did not specify CKA_IBM_PROTKEY_EXTRACTABLE in
|
||||
@@ -1396,11 +1391,6 @@ CK_RV token_specific_set_attrs_for_new_object(STDLL_TokData_t *tokdata,
|
||||
add_pkey_extractable = CK_TRUE;
|
||||
break;
|
||||
}
|
||||
- if (add_pkey_extractable) {
|
||||
- ret = ep11tok_pkey_add_protkey_attr_to_tmpl(tmpl);
|
||||
- if (ret != CKR_OK)
|
||||
- goto done;
|
||||
- }
|
||||
break;
|
||||
case PKEY_MODE_ENABLE4ALL:
|
||||
/* If the application did not specify CKA_IBM_PROTKEY_EXTRACTABLE in
|
||||
@@ -1421,11 +1411,6 @@ CK_RV token_specific_set_attrs_for_new_object(STDLL_TokData_t *tokdata,
|
||||
add_pkey_extractable = CK_TRUE;
|
||||
break;
|
||||
}
|
||||
- if (add_pkey_extractable) {
|
||||
- ret = ep11tok_pkey_add_protkey_attr_to_tmpl(tmpl);
|
||||
- if (ret != CKR_OK)
|
||||
- goto done;
|
||||
- }
|
||||
break;
|
||||
default:
|
||||
TRACE_ERROR("PKEY_MODE %i unsupported.\n", ep11_data->pkey_mode);
|
||||
@@ -1433,6 +1418,12 @@ CK_RV token_specific_set_attrs_for_new_object(STDLL_TokData_t *tokdata,
|
||||
goto done;
|
||||
break;
|
||||
}
|
||||
+
|
||||
+ if (add_pkey_extractable) {
|
||||
+ ret = ep11tok_pkey_add_protkey_attr_to_tmpl(tmpl);
|
||||
+ if (ret != CKR_OK)
|
||||
+ goto done;
|
||||
+ }
|
||||
#endif /* NO_PKEY */
|
||||
|
||||
ret = CKR_OK;
|
@ -0,0 +1,26 @@
|
||||
commit 88761bc4bd560801ec8a18b96cc82586dd719ca3
|
||||
Author: Joerg Schmidbauer <jschmidb@de.ibm.com>
|
||||
Date: Tue Mar 12 17:13:33 2024 +0100
|
||||
|
||||
EP11: add check if protected-key support available at all
|
||||
|
||||
If it is already known that the PKEY wrap is not supported or not
|
||||
functioning (for whatever reason), then don't report the XTS
|
||||
mechanisms as supported.
|
||||
|
||||
Signed-off-by: Joerg Schmidbauer <jschmidb@de.ibm.com>
|
||||
|
||||
diff --git a/usr/lib/ep11_stdll/ep11_specific.c b/usr/lib/ep11_stdll/ep11_specific.c
|
||||
index 9f855934..7850e43f 100644
|
||||
--- a/usr/lib/ep11_stdll/ep11_specific.c
|
||||
+++ b/usr/lib/ep11_stdll/ep11_specific.c
|
||||
@@ -12001,7 +12001,8 @@ CK_RV ep11tok_is_mechanism_supported(STDLL_TokData_t *tokdata,
|
||||
|
||||
case CKM_AES_XTS:
|
||||
case CKM_AES_XTS_KEY_GEN:
|
||||
- if (ep11tok_pkey_option_disabled(tokdata) || ep11_data->msa_level < 4 ||
|
||||
+ if ((ep11_data->pkey_wrap_support_checked && !ep11_data->pkey_wrap_supported) ||
|
||||
+ ep11tok_pkey_option_disabled(tokdata) || ep11_data->msa_level < 4 ||
|
||||
ep11tok_is_mechanism_supported(tokdata, CKM_IBM_CPACF_WRAP) != CKR_OK ||
|
||||
ep11tok_is_mechanism_supported(tokdata, CKM_AES_KEY_GEN) != CKR_OK) {
|
||||
TRACE_INFO("%s Mech '%s' not suppported\n", __func__,
|
@ -0,0 +1,31 @@
|
||||
commit 99b87ff678abfb71ba05741d1942e8ac723110c8
|
||||
Author: Joerg Schmidbauer <jschmidb@de.ibm.com>
|
||||
Date: Tue Mar 12 17:30:36 2024 +0100
|
||||
|
||||
EP11: consider combined-extract for XTS pkey check
|
||||
|
||||
Signed-off-by: Joerg Schmidbauer <jschmidb@de.ibm.com>
|
||||
|
||||
diff --git a/usr/lib/ep11_stdll/ep11_specific.c b/usr/lib/ep11_stdll/ep11_specific.c
|
||||
index 7850e43f..e2c9a77e 100644
|
||||
--- a/usr/lib/ep11_stdll/ep11_specific.c
|
||||
+++ b/usr/lib/ep11_stdll/ep11_specific.c
|
||||
@@ -1248,14 +1248,15 @@ CK_BBOOL ep11tok_pkey_usage_ok(STDLL_TokData_t *tokdata, SESSION *session,
|
||||
CK_RV ep11tok_pkey_check_aes_xts(STDLL_TokData_t *tokdata, OBJECT *key_obj,
|
||||
CK_MECHANISM_TYPE type)
|
||||
{
|
||||
+ ep11_private_data_t *ep11_data = tokdata->private_data;
|
||||
+
|
||||
if (ep11tok_is_mechanism_supported(tokdata, type) != CKR_OK) {
|
||||
TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID));
|
||||
return CKR_MECHANISM_INVALID;
|
||||
}
|
||||
|
||||
- if (object_is_extractable(key_obj) ||
|
||||
- !object_is_pkey_extractable(key_obj) ||
|
||||
- object_is_attr_bound(key_obj)) {
|
||||
+ if (!ep11tok_pkey_obj_eligible_for_pkey_support(ep11_data, key_obj)) {
|
||||
+ TRACE_ERROR("Key not eligible for pkey support\n");
|
||||
return CKR_TEMPLATE_INCONSISTENT;
|
||||
}
|
||||
|
@ -0,0 +1,306 @@
|
||||
commit 5b20a1454ca464b07e7686340a579d8b1870e572
|
||||
Author: Ingo Franzki <ifranzki@linux.ibm.com>
|
||||
Date: Wed Mar 20 08:44:25 2024 +0100
|
||||
|
||||
EP11: Reject combined extract attribute settings if it is not supported
|
||||
|
||||
In case the control point setting of the adapters do not allow that attributes
|
||||
CKA_EXTRACTABLE and CKA_IBM_PROTKEY_EXTRACTABLE are both true, then reject
|
||||
this with CKR_TEMPLATE_INCONSISTENT.
|
||||
|
||||
The EP11 code would reject that with CKR_FUNCTION_CANCELED, which for EP11
|
||||
it means that it violates an internal policy (i.e. control point settings),
|
||||
but in PKCS#11 this return code has a totally different meaning. So reject
|
||||
such situations explicitly with the correct return code.
|
||||
|
||||
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
|
||||
|
||||
diff --git a/usr/lib/ep11_stdll/ep11_specific.c b/usr/lib/ep11_stdll/ep11_specific.c
|
||||
index e2c9a77e..b5d788bf 100644
|
||||
--- a/usr/lib/ep11_stdll/ep11_specific.c
|
||||
+++ b/usr/lib/ep11_stdll/ep11_specific.c
|
||||
@@ -1089,20 +1089,23 @@ static CK_BBOOL ep11tok_pkey_session_ok_for_obj(SESSION *session,
|
||||
* Returns true if the given key object is eligible to get a protected key
|
||||
* attribute, false otherwise.
|
||||
*/
|
||||
-CK_BBOOL ep11tok_pkey_obj_eligible_for_pkey_support(ep11_private_data_t *ep11_data,
|
||||
- OBJECT *key_obj)
|
||||
+static CK_RV ep11tok_pkey_obj_eligible_for_pkey_support(
|
||||
+ ep11_private_data_t *ep11_data,
|
||||
+ OBJECT *key_obj)
|
||||
{
|
||||
if (object_is_attr_bound(key_obj) || !ep11_data->pkey_wrap_supported ||
|
||||
!object_is_pkey_extractable(key_obj)) {
|
||||
- return CK_FALSE;
|
||||
+ return CKR_FUNCTION_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (!ep11_data->pkey_combined_extract_supported &&
|
||||
object_is_extractable(key_obj)) {
|
||||
- return CK_FALSE;
|
||||
+ TRACE_ERROR("Combined extract not supported, but CKA_EXTRACTABLE "
|
||||
+ "and CKA_IBM_PROTKEY_EXTRACTABLE are both TRUE\n");
|
||||
+ return CKR_TEMPLATE_INCONSISTENT;
|
||||
}
|
||||
|
||||
- return CK_TRUE;
|
||||
+ return CKR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1176,7 +1179,8 @@ CK_RV ep11tok_pkey_check(STDLL_TokData_t *tokdata, SESSION *session,
|
||||
if (ep11tok_pkey_get_firmware_mk_vp(tokdata, session) != CKR_OK)
|
||||
goto done;
|
||||
|
||||
- if (!ep11tok_pkey_obj_eligible_for_pkey_support(ep11_data, key_obj))
|
||||
+ ret = ep11tok_pkey_obj_eligible_for_pkey_support(ep11_data, key_obj);
|
||||
+ if (ret != CKR_OK)
|
||||
goto done;
|
||||
|
||||
if (template_attribute_get_non_empty(key_obj->template,
|
||||
@@ -1218,11 +1222,14 @@ done:
|
||||
/**
|
||||
* Wrapper function around ep11tok_pkey_check for the case where we don't
|
||||
* have a key object. This function is called externally from new_host.c.
|
||||
+ * Returns CKR_OK if pkey usage is OK, CKR_FUNCTION_NOT_SUPPORTED if pkey
|
||||
+ * is not supported, or any other return code in case of an error. In such
|
||||
+ * cases the calling function should itself return with an error, because
|
||||
+ * neither the secure key nor the protected key path will work.
|
||||
*/
|
||||
-CK_BBOOL ep11tok_pkey_usage_ok(STDLL_TokData_t *tokdata, SESSION *session,
|
||||
- CK_OBJECT_HANDLE hkey, CK_MECHANISM *mech)
|
||||
+CK_RV ep11tok_pkey_usage_ok(STDLL_TokData_t *tokdata, SESSION *session,
|
||||
+ CK_OBJECT_HANDLE hkey, CK_MECHANISM *mech)
|
||||
{
|
||||
- CK_BBOOL success = CK_FALSE;
|
||||
size_t keyblobsize = 0;
|
||||
CK_BYTE *keyblob;
|
||||
OBJECT *key_obj;
|
||||
@@ -1232,17 +1239,15 @@ CK_BBOOL ep11tok_pkey_usage_ok(STDLL_TokData_t *tokdata, SESSION *session,
|
||||
READ_LOCK);
|
||||
if (ret != CKR_OK) {
|
||||
TRACE_ERROR("%s no blob ret=0x%lx\n", __func__, ret);
|
||||
- return CK_FALSE;
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
ret = ep11tok_pkey_check(tokdata, session, key_obj, mech);
|
||||
- if (ret == CKR_OK)
|
||||
- success = CK_TRUE;
|
||||
|
||||
object_put(tokdata, key_obj, TRUE);
|
||||
key_obj = NULL;
|
||||
|
||||
- return success;
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
CK_RV ep11tok_pkey_check_aes_xts(STDLL_TokData_t *tokdata, OBJECT *key_obj,
|
||||
@@ -1255,7 +1260,8 @@ CK_RV ep11tok_pkey_check_aes_xts(STDLL_TokData_t *tokdata, OBJECT *key_obj,
|
||||
return CKR_MECHANISM_INVALID;
|
||||
}
|
||||
|
||||
- if (!ep11tok_pkey_obj_eligible_for_pkey_support(ep11_data, key_obj)) {
|
||||
+ if (ep11tok_pkey_obj_eligible_for_pkey_support(ep11_data,
|
||||
+ key_obj) != CKR_OK) {
|
||||
TRACE_ERROR("Key not eligible for pkey support\n");
|
||||
return CKR_TEMPLATE_INCONSISTENT;
|
||||
}
|
||||
@@ -1307,10 +1313,10 @@ CK_RV token_specific_set_attrs_for_new_object(STDLL_TokData_t *tokdata,
|
||||
{
|
||||
ep11_private_data_t *ep11_data = tokdata->private_data;
|
||||
CK_ATTRIBUTE *sensitive_attr = NULL;
|
||||
- CK_BBOOL sensitive, btrue = CK_TRUE;
|
||||
+ CK_BBOOL sensitive, extractable, pkey_extractable, btrue = CK_TRUE;
|
||||
#ifndef NO_PKEY
|
||||
CK_ATTRIBUTE *ecp_attr = NULL;
|
||||
- CK_BBOOL extractable, add_pkey_extractable = CK_FALSE;
|
||||
+ CK_BBOOL add_pkey_extractable = CK_FALSE;
|
||||
#endif
|
||||
CK_RV ret;
|
||||
|
||||
@@ -1341,6 +1347,25 @@ CK_RV token_specific_set_attrs_for_new_object(STDLL_TokData_t *tokdata,
|
||||
}
|
||||
}
|
||||
|
||||
+ if (!ep11_data->pkey_combined_extract_supported) {
|
||||
+ ret = template_attribute_get_bool(tmpl, CKA_EXTRACTABLE, &extractable);
|
||||
+ if (ret != CKR_OK)
|
||||
+ extractable = FALSE;
|
||||
+
|
||||
+ ret = template_attribute_get_bool(tmpl, CKA_IBM_PROTKEY_EXTRACTABLE,
|
||||
+ &pkey_extractable);
|
||||
+ if (ret != CKR_OK)
|
||||
+ pkey_extractable = FALSE;
|
||||
+
|
||||
+ if (extractable && pkey_extractable) {
|
||||
+ /* The EP11 call would return CKR_FUNCTION_CANCELED in that case */
|
||||
+ TRACE_ERROR("Combined extract not supported, but CKA_EXTRACTABLE "
|
||||
+ "and CKA_IBM_PROTKEY_EXTRACTABLE are both TRUE\n");
|
||||
+ ret = CKR_TEMPLATE_INCONSISTENT;
|
||||
+ goto done;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
#ifndef NO_PKEY
|
||||
switch (ep11_data->pkey_mode) {
|
||||
case PKEY_MODE_DISABLED:
|
||||
diff --git a/usr/lib/ep11_stdll/ep11_specific.h b/usr/lib/ep11_stdll/ep11_specific.h
|
||||
index 16d3c719..9ba28cb8 100644
|
||||
--- a/usr/lib/ep11_stdll/ep11_specific.h
|
||||
+++ b/usr/lib/ep11_stdll/ep11_specific.h
|
||||
@@ -585,8 +585,8 @@ CK_BBOOL ep11tok_libica_mech_available(STDLL_TokData_t *tokdata,
|
||||
CK_RV ep11tok_copy_firmware_info(STDLL_TokData_t *tokdata,
|
||||
CK_TOKEN_INFO_PTR pInfo);
|
||||
|
||||
-CK_BBOOL ep11tok_pkey_usage_ok(STDLL_TokData_t *tokdata, SESSION *session,
|
||||
- CK_OBJECT_HANDLE hkey, CK_MECHANISM *mech);
|
||||
+CK_RV ep11tok_pkey_usage_ok(STDLL_TokData_t *tokdata, SESSION *session,
|
||||
+ CK_OBJECT_HANDLE hkey, CK_MECHANISM *mech);
|
||||
|
||||
CK_RV ep11tok_set_operation_state(STDLL_TokData_t *tokdata, SESSION *session);
|
||||
|
||||
diff --git a/usr/lib/ep11_stdll/new_host.c b/usr/lib/ep11_stdll/new_host.c
|
||||
index 299a1d3c..f84d0810 100644
|
||||
--- a/usr/lib/ep11_stdll/new_host.c
|
||||
+++ b/usr/lib/ep11_stdll/new_host.c
|
||||
@@ -2080,9 +2080,15 @@ CK_RV SC_EncryptInit(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
||||
sess->encr_ctx.multi_init = FALSE;
|
||||
sess->encr_ctx.multi = FALSE;
|
||||
|
||||
+ rc = ep11tok_pkey_usage_ok(tokdata, sess, hKey, pMechanism);
|
||||
+ if (rc != CKR_OK && rc != CKR_FUNCTION_NOT_SUPPORTED) {
|
||||
+ /* CKR_FUNCTION_NOT_SUPPORTED indicates pkey support is not available,
|
||||
+ but the ep11 fallback can be tried */
|
||||
+ goto done;
|
||||
+ }
|
||||
if ((ep11tok_optimize_single_ops(tokdata) ||
|
||||
ep11tok_mech_single_only(pMechanism)) &&
|
||||
- !ep11tok_pkey_usage_ok(tokdata, sess, hKey, pMechanism)) {
|
||||
+ rc == CKR_FUNCTION_NOT_SUPPORTED) {
|
||||
/* In case of a single part encrypt operation we don't need the
|
||||
* EncryptInit, instead we can use the EncryptSingle which is much
|
||||
* faster. In case of multi-part operations we are doing the EncryptInit
|
||||
@@ -2179,9 +2185,16 @@ CK_RV SC_Encrypt(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
||||
goto done;
|
||||
}
|
||||
|
||||
+ rc = ep11tok_pkey_usage_ok(tokdata, sess, sess->encr_ctx.key,
|
||||
+ &sess->encr_ctx.mech);
|
||||
+ if (rc != CKR_OK && rc != CKR_FUNCTION_NOT_SUPPORTED) {
|
||||
+ /* CKR_FUNCTION_NOT_SUPPORTED indicates pkey support is not available,
|
||||
+ but the ep11 fallback can be tried */
|
||||
+ goto done;
|
||||
+ }
|
||||
if ((ep11tok_optimize_single_ops(tokdata) ||
|
||||
ep11tok_mech_single_only(&sess->encr_ctx.mech)) &&
|
||||
- !ep11tok_pkey_usage_ok(tokdata, sess, sess->encr_ctx.key, &sess->encr_ctx.mech)) {
|
||||
+ rc == CKR_FUNCTION_NOT_SUPPORTED) {
|
||||
rc = ep11tok_encrypt_single(tokdata, sess, &sess->encr_ctx.mech,
|
||||
length_only, sess->encr_ctx.key,
|
||||
pData, ulDataLen, pEncryptedData,
|
||||
@@ -2408,9 +2421,15 @@ CK_RV SC_DecryptInit(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
||||
sess->decr_ctx.multi_init = FALSE;
|
||||
sess->decr_ctx.multi = FALSE;
|
||||
|
||||
+ rc = ep11tok_pkey_usage_ok(tokdata, sess, hKey, pMechanism);
|
||||
+ if (rc != CKR_OK && rc != CKR_FUNCTION_NOT_SUPPORTED) {
|
||||
+ /* CKR_FUNCTION_NOT_SUPPORTED indicates pkey support is not available,
|
||||
+ but the ep11 fallback can be tried */
|
||||
+ goto done;
|
||||
+ }
|
||||
if ((ep11tok_optimize_single_ops(tokdata) ||
|
||||
ep11tok_mech_single_only(pMechanism)) &&
|
||||
- !ep11tok_pkey_usage_ok(tokdata, sess, hKey, pMechanism)) {
|
||||
+ rc == CKR_FUNCTION_NOT_SUPPORTED) {
|
||||
/* In case of a single part decrypt operation we don't need the
|
||||
* DecryptInit, instead we can use the EncryptSingle which is much
|
||||
* faster. In case of multi-part operations we are doing the DecryptInit
|
||||
@@ -2508,9 +2527,16 @@ CK_RV SC_Decrypt(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
||||
goto done;
|
||||
}
|
||||
|
||||
+ rc = ep11tok_pkey_usage_ok(tokdata, sess, sess->decr_ctx.key,
|
||||
+ &sess->decr_ctx.mech);
|
||||
+ if (rc != CKR_OK && rc != CKR_FUNCTION_NOT_SUPPORTED) {
|
||||
+ /* CKR_FUNCTION_NOT_SUPPORTED indicates pkey support is not available,
|
||||
+ but the ep11 fallback can be tried */
|
||||
+ goto done;
|
||||
+ }
|
||||
if ((ep11tok_optimize_single_ops(tokdata) ||
|
||||
ep11tok_mech_single_only(&sess->decr_ctx.mech)) &&
|
||||
- !ep11tok_pkey_usage_ok(tokdata, sess, sess->decr_ctx.key, &sess->decr_ctx.mech)) {
|
||||
+ rc == CKR_FUNCTION_NOT_SUPPORTED) {
|
||||
rc = ep11tok_decrypt_single(tokdata, sess, &sess->decr_ctx.mech,
|
||||
length_only, sess->decr_ctx.key,
|
||||
pEncryptedData, ulEncryptedDataLen,
|
||||
@@ -2992,9 +3018,15 @@ CK_RV SC_SignInit(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
||||
sess->sign_ctx.multi_init = FALSE;
|
||||
sess->sign_ctx.multi = FALSE;
|
||||
|
||||
+ rc = ep11tok_pkey_usage_ok(tokdata, sess, hKey, pMechanism);
|
||||
+ if (rc != CKR_OK && rc != CKR_FUNCTION_NOT_SUPPORTED) {
|
||||
+ /* CKR_FUNCTION_NOT_SUPPORTED indicates pkey support is not available,
|
||||
+ but the ep11 fallback can be tried */
|
||||
+ goto done;
|
||||
+ }
|
||||
if ((ep11tok_optimize_single_ops(tokdata) ||
|
||||
ep11tok_mech_single_only(pMechanism)) &&
|
||||
- !ep11tok_pkey_usage_ok(tokdata, sess, hKey, pMechanism)) {
|
||||
+ rc == CKR_FUNCTION_NOT_SUPPORTED) {
|
||||
/* In case of a single part sign operation we don't need the SignInit,
|
||||
* instead we can use the SignSingle which is much faster.
|
||||
* In case of multi-part operations we are doing the SignInit when
|
||||
@@ -3101,9 +3133,16 @@ CK_RV SC_Sign(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
||||
goto done;
|
||||
}
|
||||
|
||||
+ rc = ep11tok_pkey_usage_ok(tokdata, sess, sess->sign_ctx.key,
|
||||
+ &sess->sign_ctx.mech);
|
||||
+ if (rc != CKR_OK && rc != CKR_FUNCTION_NOT_SUPPORTED) {
|
||||
+ /* CKR_FUNCTION_NOT_SUPPORTED indicates pkey support is not available,
|
||||
+ but the ep11 fallback can be tried */
|
||||
+ goto done;
|
||||
+ }
|
||||
if ((ep11tok_optimize_single_ops(tokdata) ||
|
||||
ep11tok_mech_single_only(&sess->sign_ctx.mech)) &&
|
||||
- !ep11tok_pkey_usage_ok(tokdata, sess, sess->sign_ctx.key, &sess->sign_ctx.mech)) {
|
||||
+ rc == CKR_FUNCTION_NOT_SUPPORTED) {
|
||||
rc = ep11tok_sign_single(tokdata, sess, &sess->sign_ctx.mech,
|
||||
length_only, sess->sign_ctx.key,
|
||||
pData, ulDataLen, pSignature, pulSignatureLen);
|
||||
@@ -3391,9 +3430,15 @@ CK_RV SC_VerifyInit(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
||||
sess->verify_ctx.multi_init = FALSE;
|
||||
sess->verify_ctx.multi = FALSE;
|
||||
|
||||
+ rc = ep11tok_pkey_usage_ok(tokdata, sess, hKey, pMechanism);
|
||||
+ if (rc != CKR_OK && rc != CKR_FUNCTION_NOT_SUPPORTED) {
|
||||
+ /* CKR_FUNCTION_NOT_SUPPORTED indicates pkey support is not available,
|
||||
+ but the ep11 fallback can be tried */
|
||||
+ goto done;
|
||||
+ }
|
||||
if ((ep11tok_optimize_single_ops(tokdata) ||
|
||||
ep11tok_mech_single_only(pMechanism)) &&
|
||||
- !ep11tok_pkey_usage_ok(tokdata, sess, hKey, pMechanism)) {
|
||||
+ rc == CKR_FUNCTION_NOT_SUPPORTED) {
|
||||
/* In case of a single part verify operation we don't need the
|
||||
* VerifyInit, instead we can use the VerifySingle which is much
|
||||
* faster. In case of multi-part operations we are doing the VerifyInit
|
||||
@@ -3497,9 +3542,16 @@ CK_RV SC_Verify(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
||||
goto done;
|
||||
}
|
||||
|
||||
+ rc = ep11tok_pkey_usage_ok(tokdata, sess, sess->verify_ctx.key,
|
||||
+ &sess->verify_ctx.mech);
|
||||
+ if (rc != CKR_OK && rc != CKR_FUNCTION_NOT_SUPPORTED) {
|
||||
+ /* CKR_FUNCTION_NOT_SUPPORTED indicates pkey support is not available,
|
||||
+ but the ep11 fallback can be tried */
|
||||
+ goto done;
|
||||
+ }
|
||||
if ((ep11tok_optimize_single_ops(tokdata) ||
|
||||
ep11tok_mech_single_only(&sess->verify_ctx.mech)) &&
|
||||
- !ep11tok_pkey_usage_ok(tokdata, sess, sess->verify_ctx.key, &sess->verify_ctx.mech)) {
|
||||
+ rc == CKR_FUNCTION_NOT_SUPPORTED) {
|
||||
rc = ep11tok_verify_single(tokdata, sess, &sess->verify_ctx.mech,
|
||||
sess->verify_ctx.key, pData, ulDataLen,
|
||||
pSignature, ulSignatureLen);
|
@ -0,0 +1,36 @@
|
||||
commit 4fefcf517133260a7b63049d3a02c9249fe7776c
|
||||
Author: Ingo Franzki <ifranzki@linux.ibm.com>
|
||||
Date: Mon Apr 15 09:31:12 2024 +0200
|
||||
|
||||
EP11: Fix compile error with NO_PKEY defined
|
||||
|
||||
Function signature of ep11tok_pkey_usage_ok() has changed, also change the
|
||||
code inside the #ifdef NO_PKEY block.
|
||||
|
||||
Fixes: cf978b111205b206c7b3c53f424f7085913c00d0
|
||||
|
||||
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
|
||||
|
||||
diff --git a/usr/lib/ep11_stdll/ep11_specific.c b/usr/lib/ep11_stdll/ep11_specific.c
|
||||
index b5d788bf..e9007a16 100644
|
||||
--- a/usr/lib/ep11_stdll/ep11_specific.c
|
||||
+++ b/usr/lib/ep11_stdll/ep11_specific.c
|
||||
@@ -1460,15 +1460,15 @@ done:
|
||||
}
|
||||
|
||||
#ifdef NO_PKEY
|
||||
-CK_BBOOL ep11tok_pkey_usage_ok(STDLL_TokData_t *tokdata, SESSION *session,
|
||||
- CK_OBJECT_HANDLE hkey, CK_MECHANISM *mech)
|
||||
+CK_RV ep11tok_pkey_usage_ok(STDLL_TokData_t *tokdata, SESSION *session,
|
||||
+ CK_OBJECT_HANDLE hkey, CK_MECHANISM *mech)
|
||||
{
|
||||
UNUSED(tokdata);
|
||||
UNUSED(session);
|
||||
UNUSED(hkey);
|
||||
UNUSED(mech);
|
||||
|
||||
- return CK_FALSE;
|
||||
+ return CKR_FUNCTION_NOT_SUPPORTED;
|
||||
}
|
||||
#endif /* NO_PKEY */
|
||||
|
@ -1,153 +0,0 @@
|
||||
commit 47c55113f81794408a0afda2e19e1a5aa40d2212
|
||||
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,
|
@ -1,387 +0,0 @@
|
||||
commit 2fb51b9e4d390f889c109e1765c3284b5d6f5fb8
|
||||
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 df1f68f9..42793955 100644
|
||||
--- a/usr/lib/ep11_stdll/ep11_specific.c
|
||||
+++ b/usr/lib/ep11_stdll/ep11_specific.c
|
||||
@@ -10777,10 +10777,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:
|
||||
@@ -10836,10 +10838,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:
|
||||
@@ -10901,10 +10905,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 ce18f729..f7ee0546 100644
|
||||
--- a/usr/lib/ep11_stdll/new_host.c
|
||||
+++ b/usr/lib/ep11_stdll/new_host.c
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "slotmgr.h"
|
||||
#include "attributes.h"
|
||||
#include "ep11_specific.h"
|
||||
+#include "constant_time.h"
|
||||
|
||||
#include "../api/apiproto.h"
|
||||
#include "../api/policy.h"
|
||||
@@ -2465,6 +2466,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));
|
||||
@@ -2512,17 +2514,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);
|
||||
}
|
||||
@@ -2544,6 +2558,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));
|
||||
@@ -2595,11 +2610,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);
|
||||
}
|
||||
@@ -2621,6 +2643,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));
|
||||
@@ -2669,10 +2692,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 115fd40b..192fe128 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);
|
||||
}
|
@ -1,737 +0,0 @@
|
||||
commit 034d70ec4cfde81ea71cf8acbe9097fa15e49a02
|
||||
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 a14542fa..a6ee4c33 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;
|
File diff suppressed because it is too large
Load Diff
@ -1,31 +0,0 @@
|
||||
commit c859ed40828bf808e83a3f437c2e34c9c843a4c3
|
||||
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;
|
||||
}
|
Loading…
Reference in new issue