mirror of
git://git.openembedded.org/meta-openembedded
synced 2026-09-29 03:12:02 +00:00
CVE-2023-5992: A vulnerability was found in OpenSC where PKCS#1 encryption padding removal is not implemented as side-channel resistant. This issue may result in the potential leak of private data. Reference: [https://nvd.nist.gov/vuln/detail/CVE-2023-5992] [https://github.com/OpenSC/OpenSC/wiki/CVE-2023-5992] Upstream patches: [https://github.com/OpenSC/OpenSC/pull/2948] [https://github.com/OpenSC/OpenSC/pull/3016] Signed-off-by: Zhang Peng <peng.zhang1.cn@windriver.com> Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com>
110 lines
4.3 KiB
Diff
110 lines
4.3 KiB
Diff
From 663dcbae0d92a05eba28ca56b80346b2fbe5a6d5 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= <vhanulik@redhat.com>
|
|
Date: Thu, 16 Nov 2023 15:49:15 +0100
|
|
Subject: [PATCH 04/10] framework-pkcs15.c: Handle PKCS#1 v1.5 depadding
|
|
constant-time
|
|
|
|
In order to not disclose time side-channel when the depadding
|
|
fails, do the same operations as for case when depadding ends
|
|
with success.
|
|
|
|
CVE: CVE-2023-5992
|
|
Upstream-Status: Backport [https://github.com/OpenSC/OpenSC/pull/2948]
|
|
|
|
Signed-off-by: Zhang Peng <peng.zhang1.cn@windriver.com>
|
|
---
|
|
src/pkcs11/framework-pkcs15.c | 54 ++++++++++++++++++++++++++---------
|
|
1 file changed, 41 insertions(+), 13 deletions(-)
|
|
|
|
diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c
|
|
index 4fc8f13ab..8376057ea 100644
|
|
--- a/src/pkcs11/framework-pkcs15.c
|
|
+++ b/src/pkcs11/framework-pkcs15.c
|
|
@@ -18,6 +18,7 @@
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
+#include "common/constant-time.h"
|
|
#include "config.h"
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
@@ -4341,7 +4342,8 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_session *session, void *obj,
|
|
struct pkcs15_fw_data *fw_data = NULL;
|
|
struct pkcs15_prkey_object *prkey;
|
|
unsigned char decrypted[512]; /* FIXME: Will not work for keys above 4096 bits */
|
|
- int buff_too_small, rv, flags = 0, prkey_has_path = 0;
|
|
+ int rv, flags = 0, prkey_has_path = 0;
|
|
+ CK_ULONG mask, good, rv_pkcs11;
|
|
|
|
sc_log(context, "Initiating decryption.");
|
|
|
|
@@ -4415,27 +4417,53 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_session *session, void *obj,
|
|
rv = sc_pkcs15_decipher(fw_data->p15_card, prkey->prv_p15obj, flags,
|
|
pEncryptedData, ulEncryptedDataLen, decrypted, sizeof(decrypted));
|
|
|
|
- if (rv < 0 && !sc_pkcs11_conf.lock_login && !prkey_has_path)
|
|
+ /* skip for PKCS#1 v1.5 padding prevent side channel attack */
|
|
+ if (!(flags & SC_ALGORITHM_RSA_PAD_PKCS1) &&
|
|
+ rv < 0 && !sc_pkcs11_conf.lock_login && !prkey_has_path)
|
|
if (reselect_app_df(fw_data->p15_card) == SC_SUCCESS)
|
|
rv = sc_pkcs15_decipher(fw_data->p15_card, prkey->prv_p15obj, flags,
|
|
pEncryptedData, ulEncryptedDataLen, decrypted, sizeof(decrypted));
|
|
|
|
sc_unlock(p11card->card);
|
|
|
|
- sc_log(context, "Decryption complete. Result %d.", rv);
|
|
+ sc_log(context, "Decryption complete.");
|
|
|
|
- if (rv < 0)
|
|
- return sc_to_cryptoki_error(rv, "C_Decrypt");
|
|
+ /* Handle following code in constant-time
|
|
+ * to prevent Marvin attack for PKCS#1 v1.5 padding. */
|
|
|
|
- buff_too_small = (*pulDataLen < (CK_ULONG)rv);
|
|
- *pulDataLen = rv;
|
|
- if (pData == NULL_PTR)
|
|
- return CKR_OK;
|
|
- if (buff_too_small)
|
|
- return CKR_BUFFER_TOO_SMALL;
|
|
- memcpy(pData, decrypted, *pulDataLen);
|
|
+ /* only padding error must be handled in constant-time way,
|
|
+ * other error can be returned straight away */
|
|
+ if ((~constant_time_eq_s(rv, SC_ERROR_WRONG_PADDING) & constant_time_lt_s(sizeof(decrypted), rv)))
|
|
+ return sc_to_cryptoki_error(rv, "C_Decrypt");
|
|
|
|
- return CKR_OK;
|
|
+ /* check rv for padding error */
|
|
+ good = ~constant_time_eq_s(rv, SC_ERROR_WRONG_PADDING);
|
|
+ rv_pkcs11 = sc_to_cryptoki_error(SC_ERROR_WRONG_PADDING, "C_Decrypt");
|
|
+ rv_pkcs11 = constant_time_select_s(good, CKR_OK, rv_pkcs11);
|
|
+
|
|
+ if (pData == NULL_PTR) {
|
|
+ /* set length only if no error */
|
|
+ *pulDataLen = constant_time_select_s(good, rv, *pulDataLen);
|
|
+ /* return error only if original rv < 0 */
|
|
+ return rv_pkcs11;
|
|
+ }
|
|
+
|
|
+ /* check whether *pulDataLen < rv and set return value for small output buffer */
|
|
+ mask = good & constant_time_lt_s(*pulDataLen, rv);
|
|
+ rv_pkcs11 = constant_time_select_s(mask, CKR_BUFFER_TOO_SMALL, rv_pkcs11);
|
|
+ good &= ~mask;
|
|
+
|
|
+ /* move everything from decrypted into out buffer constant-time, if rv is ok */
|
|
+ for (CK_ULONG i = 0; i < *pulDataLen; i++) { /* iterate over whole pData to not disclose real depadded length */
|
|
+ CK_ULONG msg_index;
|
|
+ mask = good & constant_time_lt_s(i, sizeof(decrypted)); /* i should be in the bounds of decrypted */
|
|
+ mask &= constant_time_lt_s(i, constant_time_select_s(good, rv, 0)); /* check that is in bounds of depadded message */
|
|
+ msg_index = constant_time_select_s(mask, i, 0);
|
|
+ pData[i] = constant_time_select_8(mask, decrypted[msg_index], pData[i]);
|
|
+ }
|
|
+ *pulDataLen = constant_time_select_s(good, rv, *pulDataLen);
|
|
+ /* do not log error code to prevent side channel attack */
|
|
+ return rv_pkcs11;
|
|
}
|
|
|
|
|
|
--
|
|
2.50.0
|
|
|