Compare commits
2 Commits
| Author | SHA256 | Date | |
|---|---|---|---|
| 8e5c96f332 | |||
| 5080d0e8e1 |
Binary file not shown.
922
opensc-CVE-2023-5992.patch
Normal file
922
opensc-CVE-2023-5992.patch
Normal file
@@ -0,0 +1,922 @@
|
||||
From b9e1d344df1f850a9b15bce6294f72c1620d0b45 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= <vhanulik@redhat.com>
|
||||
Date: Mon, 13 Nov 2023 13:54:54 +0100
|
||||
Subject: [PATCH 1/8] Reimplement removing of PKCS#1 v1.5 padding to be time
|
||||
constant
|
||||
|
||||
---
|
||||
src/common/Makefile.am | 6 +-
|
||||
src/common/constant-time.h | 128 ++++++++++++++++++++++++++++++++++++
|
||||
src/libopensc/internal.h | 4 +-
|
||||
src/libopensc/padding.c | 102 +++++++++++++++++++---------
|
||||
src/libopensc/pkcs15-sec.c | 5 +-
|
||||
src/minidriver/minidriver.c | 4 +-
|
||||
6 files changed, 210 insertions(+), 39 deletions(-)
|
||||
create mode 100644 src/common/constant-time.h
|
||||
|
||||
Index: opensc-0.24.0/src/common/Makefile.am
|
||||
===================================================================
|
||||
--- opensc-0.24.0.orig/src/common/Makefile.am
|
||||
+++ opensc-0.24.0/src/common/Makefile.am
|
||||
@@ -8,7 +8,8 @@ dist_noinst_DATA = \
|
||||
LICENSE.compat_getopt compat_getopt.txt \
|
||||
compat_getopt_main.c \
|
||||
README.compat_strlcpy compat_strlcpy.3
|
||||
-noinst_HEADERS = compat_strlcat.h compat_strlcpy.h compat_strnlen.h compat_getpass.h compat_getopt.h simclist.h libpkcs11.h libscdl.h compat_overflow.h
|
||||
+noinst_HEADERS = compat_strlcat.h compat_strlcpy.h compat_strnlen.h compat_getpass.h \
|
||||
+ compat_getopt.h simclist.h libpkcs11.h libscdl.h compat_overflow.h constant-time.h
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/src
|
||||
|
||||
@@ -43,7 +44,8 @@ TIDY_FILES = \
|
||||
compat___iob_func.c \
|
||||
compat_overflow.h compat_overflow.c \
|
||||
simclist.c simclist.h \
|
||||
- libpkcs11.c libscdl.c
|
||||
+ libpkcs11.c libscdl.c \
|
||||
+ constant-time.h
|
||||
|
||||
check-local:
|
||||
if [ -x "$(CLANGTIDY)" ]; then clang-tidy -config='' --checks='$(TIDY_CHECKS)' --warnings-as-errors='$(TIDY_CHECKS)' -header-filter=.* $(addprefix $(srcdir)/,$(TIDY_FILES)) -- $(TIDY_FLAGS); fi
|
||||
Index: opensc-0.24.0/src/common/constant-time.h
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ opensc-0.24.0/src/common/constant-time.h
|
||||
@@ -0,0 +1,128 @@
|
||||
+/* Original source: https://github.com/openssl/openssl/blob/9890cc42daff5e2d0cad01ac4bf78c391f599a6e/include/internal/constant_time.h */
|
||||
+
|
||||
+#ifndef CONSTANT_TIME_H
|
||||
+#define CONSTANT_TIME_H
|
||||
+
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+#if !defined(inline)
|
||||
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
||||
+#define constant_inline inline
|
||||
+#elif defined(__GNUC__) && __GNUC__ >= 2
|
||||
+#elif defined(__GNUC__) && __GNUC__ >= 2
|
||||
+#elif defined(_MSC_VER)
|
||||
+#define constant_inline __inline
|
||||
+#else
|
||||
+#define constant_inline
|
||||
+#endif
|
||||
+#else /* use what caller wants as inline may be from config.h */
|
||||
+#define constant_inline inline /* inline */
|
||||
+#endif
|
||||
+
|
||||
+/*-
|
||||
+ * The boolean methods return a bitmask of all ones (0xff...f) for true
|
||||
+ * and 0 for false. For example,
|
||||
+ * if (a < b) {
|
||||
+ * c = a;
|
||||
+ * } else {
|
||||
+ * c = b;
|
||||
+ * }
|
||||
+ * can be written as
|
||||
+ * unsigned int lt = constant_time_lt(a, b);
|
||||
+ * c = constant_time_select(lt, a, b);
|
||||
+ */
|
||||
+
|
||||
+static constant_inline unsigned int
|
||||
+value_barrier(unsigned int a)
|
||||
+{
|
||||
+ volatile unsigned int r = a;
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
+static constant_inline size_t
|
||||
+value_barrier_s(size_t a)
|
||||
+{
|
||||
+ volatile size_t r = a;
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
+/* MSB */
|
||||
+static constant_inline size_t
|
||||
+constant_time_msb_s(size_t a)
|
||||
+{
|
||||
+ return 0 - (a >> (sizeof(a) * 8 - 1));
|
||||
+}
|
||||
+
|
||||
+static constant_inline unsigned int
|
||||
+constant_time_msb(unsigned int a)
|
||||
+{
|
||||
+ return 0 - (a >> (sizeof(a) * 8 - 1));
|
||||
+}
|
||||
+
|
||||
+/* Select */
|
||||
+static constant_inline unsigned int
|
||||
+constant_time_select(unsigned int mask, unsigned int a, unsigned int b)
|
||||
+{
|
||||
+ return (value_barrier(mask) & a) | (value_barrier(~mask) & b);
|
||||
+}
|
||||
+
|
||||
+static constant_inline unsigned char
|
||||
+constant_time_select_8(unsigned char mask, unsigned char a, unsigned char b)
|
||||
+{
|
||||
+ return (unsigned char)constant_time_select(mask, a, b);
|
||||
+}
|
||||
+
|
||||
+static constant_inline size_t
|
||||
+constant_time_select_s(size_t mask, size_t a, size_t b)
|
||||
+{
|
||||
+ return (value_barrier_s(mask) & a) | (value_barrier_s(~mask) & b);
|
||||
+}
|
||||
+
|
||||
+/* Zero */
|
||||
+static constant_inline unsigned int
|
||||
+constant_time_is_zero(unsigned int a)
|
||||
+{
|
||||
+ return constant_time_msb(~a & (a - 1));
|
||||
+}
|
||||
+
|
||||
+static constant_inline size_t
|
||||
+constant_time_is_zero_s(size_t a)
|
||||
+{
|
||||
+ return constant_time_msb_s(~a & (a - 1));
|
||||
+}
|
||||
+
|
||||
+/* Comparison*/
|
||||
+static constant_inline size_t
|
||||
+constant_time_lt_s(size_t a, size_t b)
|
||||
+{
|
||||
+ return constant_time_msb_s(a ^ ((a ^ b) | ((a - b) ^ b)));
|
||||
+}
|
||||
+
|
||||
+static constant_inline unsigned int
|
||||
+constant_time_lt(unsigned int a, unsigned int b)
|
||||
+{
|
||||
+ return constant_time_msb(a ^ ((a ^ b) | ((a - b) ^ b)));
|
||||
+}
|
||||
+
|
||||
+static constant_inline unsigned int
|
||||
+constant_time_ge(unsigned int a, unsigned int b)
|
||||
+{
|
||||
+ return ~constant_time_lt(a, b);
|
||||
+}
|
||||
+
|
||||
+/* Equality*/
|
||||
+
|
||||
+static constant_inline unsigned int
|
||||
+constant_time_eq(unsigned int a, unsigned int b)
|
||||
+{
|
||||
+ return constant_time_is_zero(a ^ b);
|
||||
+}
|
||||
+
|
||||
+static constant_inline size_t
|
||||
+constant_time_eq_s(size_t a, size_t b)
|
||||
+{
|
||||
+ return constant_time_is_zero_s(a ^ b);
|
||||
+}
|
||||
+
|
||||
+#endif /* CONSTANT_TIME_H */
|
||||
Index: opensc-0.24.0/src/libopensc/internal.h
|
||||
===================================================================
|
||||
--- opensc-0.24.0.orig/src/libopensc/internal.h
|
||||
+++ opensc-0.24.0/src/libopensc/internal.h
|
||||
@@ -166,8 +166,8 @@ int _sc_card_add_xeddsa_alg(struct sc_ca
|
||||
|
||||
int sc_pkcs1_strip_01_padding(struct sc_context *ctx, const u8 *in_dat, size_t in_len,
|
||||
u8 *out_dat, size_t *out_len);
|
||||
-int sc_pkcs1_strip_02_padding(struct sc_context *ctx, const u8 *data, size_t len,
|
||||
- u8 *out_dat, size_t *out_len);
|
||||
+int sc_pkcs1_strip_02_padding_constant_time(sc_context_t *ctx, unsigned int n, const u8 *data,
|
||||
+ unsigned int data_len, u8 *out, unsigned int *out_len);
|
||||
int sc_pkcs1_strip_digest_info_prefix(unsigned int *algorithm,
|
||||
const u8 *in_dat, size_t in_len, u8 *out_dat, size_t *out_len);
|
||||
#ifdef ENABLE_OPENSSL
|
||||
Index: opensc-0.24.0/src/libopensc/padding.c
|
||||
===================================================================
|
||||
--- opensc-0.24.0.orig/src/libopensc/padding.c
|
||||
+++ opensc-0.24.0/src/libopensc/padding.c
|
||||
@@ -32,10 +32,13 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
+#include "common/constant-time.h"
|
||||
#include "internal.h"
|
||||
#include "pkcs11/pkcs11.h"
|
||||
/* TODO doxygen comments */
|
||||
|
||||
+#define SC_PKCS1_PADDING_MIN_SIZE 11
|
||||
+
|
||||
/*
|
||||
* Prefixes for pkcs-v1 signatures
|
||||
*/
|
||||
@@ -143,45 +146,82 @@ sc_pkcs1_strip_01_padding(struct sc_cont
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
-
|
||||
-/* remove pkcs1 BT02 padding (adding BT02 padding is currently not
|
||||
- * needed/implemented) */
|
||||
+/* Remove pkcs1 BT02 padding (adding BT02 padding is currently not
|
||||
+ * needed/implemented) in constant-time.
|
||||
+ * Original source: https://github.com/openssl/openssl/blob/9890cc42daff5e2d0cad01ac4bf78c391f599a6e/crypto/rsa/rsa_pk1.c#L171 */
|
||||
int
|
||||
-sc_pkcs1_strip_02_padding(sc_context_t *ctx, const u8 *data, size_t len, u8 *out, size_t *out_len)
|
||||
+sc_pkcs1_strip_02_padding_constant_time(sc_context_t *ctx, unsigned int n, const u8 *data, unsigned int data_len, u8 *out, unsigned int *out_len)
|
||||
{
|
||||
- unsigned int n = 0;
|
||||
-
|
||||
+ unsigned int i = 0;
|
||||
+ u8 *msg, *msg_orig = NULL;
|
||||
+ unsigned int good, found_zero_byte, mask;
|
||||
+ unsigned int zero_index = 0, msg_index, mlen = -1, len = 0;
|
||||
LOG_FUNC_CALLED(ctx);
|
||||
- if (data == NULL || len < 3)
|
||||
+
|
||||
+ if (data == NULL || data_len <= 0 || data_len > n || n < SC_PKCS1_PADDING_MIN_SIZE)
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
|
||||
|
||||
- /* skip leading zero byte */
|
||||
- if (*data == 0) {
|
||||
- data++;
|
||||
- len--;
|
||||
+ msg = msg_orig = calloc(n, sizeof(u8));
|
||||
+ if (msg == NULL)
|
||||
+ LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
|
||||
+
|
||||
+ /*
|
||||
+ * We can not check length of input data straight away and still we need to read
|
||||
+ * from input even when the input is not as long as needed to keep the time constant.
|
||||
+ * If data has wrong size, it is padded by zeroes from left and the following checks
|
||||
+ * do not pass.
|
||||
+ */
|
||||
+ len = data_len;
|
||||
+ for (data += len, msg += n, i = 0; i < n; i++) {
|
||||
+ mask = ~constant_time_is_zero(len);
|
||||
+ len -= 1 & mask;
|
||||
+ data -= 1 & mask;
|
||||
+ *--msg = *data & mask;
|
||||
+ }
|
||||
+ // check first byte to be 0x00
|
||||
+ good = constant_time_is_zero(msg[0]);
|
||||
+ // check second byte to be 0x02
|
||||
+ good &= constant_time_eq(msg[1], 2);
|
||||
+
|
||||
+ // find zero byte after random data in padding
|
||||
+ found_zero_byte = 0;
|
||||
+ for (i = 2; i < n; i++) {
|
||||
+ unsigned int equals0 = constant_time_is_zero(msg[i]);
|
||||
+ zero_index = constant_time_select(~found_zero_byte & equals0, i, zero_index);
|
||||
+ found_zero_byte |= equals0;
|
||||
}
|
||||
- if (data[0] != 0x02)
|
||||
- LOG_FUNC_RETURN(ctx, SC_ERROR_WRONG_PADDING);
|
||||
- /* skip over padding bytes */
|
||||
- for (n = 1; n < len && data[n]; n++)
|
||||
- ;
|
||||
- /* Must be at least 8 pad bytes */
|
||||
- if (n >= len || n < 9)
|
||||
- LOG_FUNC_RETURN(ctx, SC_ERROR_WRONG_PADDING);
|
||||
- n++;
|
||||
- if (out == NULL)
|
||||
- /* just check the padding */
|
||||
- LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
||||
|
||||
- /* Now move decrypted contents to head of buffer */
|
||||
- if (*out_len < len - n)
|
||||
- LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
|
||||
- *out_len = len - n;
|
||||
- memmove(out, data + n, *out_len);
|
||||
+ // zero_index stands for index of last found zero
|
||||
+ good &= constant_time_ge(zero_index, 2 + 8);
|
||||
+
|
||||
+ // start of the actual message in data
|
||||
+ msg_index = zero_index + 1;
|
||||
+
|
||||
+ // length of message
|
||||
+ mlen = data_len - msg_index;
|
||||
+
|
||||
+ // check that message fits into out buffer
|
||||
+ good &= constant_time_ge(*out_len, mlen);
|
||||
+
|
||||
+ // move the result in-place by |num|-SC_PKCS1_PADDING_MIN_SIZE-|mlen| bytes to the left.
|
||||
+ *out_len = constant_time_select(constant_time_lt(n - SC_PKCS1_PADDING_MIN_SIZE, *out_len),
|
||||
+ n - SC_PKCS1_PADDING_MIN_SIZE, *out_len);
|
||||
+ for (msg_index = 1; msg_index < n - SC_PKCS1_PADDING_MIN_SIZE; msg_index <<= 1) {
|
||||
+ mask = ~constant_time_eq(msg_index & (n - SC_PKCS1_PADDING_MIN_SIZE - mlen), 0);
|
||||
+ for (i = SC_PKCS1_PADDING_MIN_SIZE; i < n - msg_index; i++)
|
||||
+ msg[i] = constant_time_select_8(mask, msg[i + msg_index], msg[i]);
|
||||
+ }
|
||||
+ // move message into out buffer, if good
|
||||
+ for (i = 0; i < *out_len; i++) {
|
||||
+ unsigned int msg_index;
|
||||
+ // when out is longer than message in data, use some bogus index in msg
|
||||
+ mask = good & constant_time_lt(i, mlen);
|
||||
+ msg_index = constant_time_select(mask, i + SC_PKCS1_PADDING_MIN_SIZE, 0); // to now overflow msg buffer
|
||||
+ out[i] = constant_time_select_8(mask, msg[msg_index], out[i]);
|
||||
+ }
|
||||
|
||||
- sc_log(ctx, "stripped output(%"SC_FORMAT_LEN_SIZE_T"u): %s", len - n,
|
||||
- sc_dump_hex(out, len - n));
|
||||
- LOG_FUNC_RETURN(ctx, len - n);
|
||||
+ free(msg_orig);
|
||||
+ return constant_time_select(good, mlen, SC_ERROR_WRONG_PADDING);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_OPENSSL
|
||||
Index: opensc-0.24.0/src/libopensc/pkcs15-sec.c
|
||||
===================================================================
|
||||
--- opensc-0.24.0.orig/src/libopensc/pkcs15-sec.c
|
||||
+++ opensc-0.24.0/src/libopensc/pkcs15-sec.c
|
||||
@@ -308,9 +308,10 @@ int sc_pkcs15_decipher(struct sc_pkcs15_
|
||||
|
||||
/* Strip any padding */
|
||||
if (pad_flags & SC_ALGORITHM_RSA_PAD_PKCS1) {
|
||||
- size_t s = r;
|
||||
- r = sc_pkcs1_strip_02_padding(ctx, out, s, out, &s);
|
||||
- LOG_TEST_RET(ctx, r, "Invalid PKCS#1 padding");
|
||||
+ unsigned int s = r;
|
||||
+ unsigned int key_size = (unsigned int)alg_info->key_length;
|
||||
+ r = sc_pkcs1_strip_02_padding_constant_time(ctx, key_size / 8, out, s, out, &s);
|
||||
+ /* for keeping PKCS#1 v1.5 depadding constant-time, do not log error here */
|
||||
}
|
||||
#ifdef ENABLE_OPENSSL
|
||||
if (pad_flags & SC_ALGORITHM_RSA_PAD_OAEP)
|
||||
@@ -332,7 +333,8 @@ int sc_pkcs15_decipher(struct sc_pkcs15_
|
||||
LOG_TEST_RET(ctx, r, "Invalid OAEP padding");
|
||||
}
|
||||
#endif
|
||||
- LOG_FUNC_RETURN(ctx, r);
|
||||
+ /* do not log error code to prevent side channel attack */
|
||||
+ return r;
|
||||
}
|
||||
|
||||
/* derive one key from another. RSA can use decipher, so this is for only ECDH
|
||||
Index: opensc-0.24.0/src/minidriver/minidriver.c
|
||||
===================================================================
|
||||
--- opensc-0.24.0.orig/src/minidriver/minidriver.c
|
||||
+++ opensc-0.24.0/src/minidriver/minidriver.c
|
||||
@@ -44,6 +44,7 @@
|
||||
#endif
|
||||
|
||||
#include "common/compat_strlcpy.h"
|
||||
+#include "common/constant-time.h"
|
||||
#include "libopensc/asn1.h"
|
||||
#include "libopensc/cardctl.h"
|
||||
#include "libopensc/opensc.h"
|
||||
@@ -4534,13 +4535,15 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_D
|
||||
|
||||
{
|
||||
DWORD dwret;
|
||||
- int r, opt_crypt_flags = 0;
|
||||
+ int r, opt_crypt_flags = 0, good = 0;
|
||||
unsigned ui;
|
||||
VENDOR_SPECIFIC *vs;
|
||||
struct sc_pkcs15_prkey_info *prkey_info;
|
||||
BYTE *pbuf = NULL, *pbuf2 = NULL;
|
||||
struct sc_pkcs15_object *pkey = NULL;
|
||||
struct sc_algorithm_info *alg_info = NULL;
|
||||
+ unsigned int wrong_padding = 0;
|
||||
+ unsigned int pbufLen = 0;
|
||||
|
||||
MD_FUNC_CALLED(pCardData, 1);
|
||||
|
||||
@@ -4641,11 +4644,11 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_D
|
||||
goto err;
|
||||
}
|
||||
|
||||
+ pbufLen = pInfo->cbData;
|
||||
if (alg_info->flags & SC_ALGORITHM_RSA_RAW) {
|
||||
logprintf(pCardData, 2, "sc_pkcs15_decipher: using RSA-RAW mechanism\n");
|
||||
r = sc_pkcs15_decipher(vs->p15card, pkey, opt_crypt_flags | SC_ALGORITHM_RSA_RAW, pbuf, pInfo->cbData, pbuf2, pInfo->cbData, NULL);
|
||||
- logprintf(pCardData, 2, "sc_pkcs15_decipher returned %d\n", r);
|
||||
-
|
||||
+ /* do not log return value to not leak it */
|
||||
if (r > 0) {
|
||||
/* Need to handle padding */
|
||||
if (pInfo->dwVersion >= CARD_RSA_KEY_DECRYPT_INFO_VERSION_TWO) {
|
||||
@@ -4653,17 +4656,13 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_D
|
||||
"sc_pkcs15_decipher: DECRYPT-INFO dwVersion=%lu\n",
|
||||
(unsigned long)pInfo->dwVersion);
|
||||
if (pInfo->dwPaddingType == CARD_PADDING_PKCS1) {
|
||||
- size_t temp = pInfo->cbData;
|
||||
+ unsigned int temp = pInfo->cbData;
|
||||
logprintf(pCardData, 2, "sc_pkcs15_decipher: stripping PKCS1 padding\n");
|
||||
- r = sc_pkcs1_strip_02_padding(vs->ctx, pbuf2, pInfo->cbData, pbuf2, &temp);
|
||||
+ r = sc_pkcs1_strip_02_padding_constant_time(vs->ctx, prkey_info->modulus_length / 8, pbuf2, pInfo->cbData, pbuf2, &temp);
|
||||
pInfo->cbData = (DWORD) temp;
|
||||
- if (r < 0) {
|
||||
- logprintf(pCardData, 2, "Cannot strip PKCS1 padding: %i\n", r);
|
||||
- pCardData->pfnCspFree(pbuf);
|
||||
- pCardData->pfnCspFree(pbuf2);
|
||||
- dwret = SCARD_F_INTERNAL_ERROR;
|
||||
- goto err;
|
||||
- }
|
||||
+ wrong_padding = constant_time_eq_s(r, SC_ERROR_WRONG_PADDING);
|
||||
+ /* continue without returning error to not leak that padding is wrong
|
||||
+ to prevent time side-channel leak for Marvin attack*/
|
||||
}
|
||||
else if (pInfo->dwPaddingType == CARD_PADDING_OAEP) {
|
||||
/* TODO: Handle OAEP padding if present - can call PFN_CSP_UNPAD_DATA */
|
||||
@@ -4711,28 +4710,38 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_D
|
||||
goto err;
|
||||
}
|
||||
|
||||
- if ( r < 0) {
|
||||
+ good = constant_time_eq_s(r, 0);
|
||||
+ /* if no error or padding error, do not return here to prevent Marvin attack */
|
||||
+ if (!(good | wrong_padding) && r < 0) {
|
||||
logprintf(pCardData, 2, "sc_pkcs15_decipher error(%i): %s\n", r, sc_strerror(r));
|
||||
pCardData->pfnCspFree(pbuf);
|
||||
pCardData->pfnCspFree(pbuf2);
|
||||
dwret = md_translate_OpenSC_to_Windows_error(r, SCARD_E_INVALID_VALUE);
|
||||
goto err;
|
||||
}
|
||||
+ dwret = constant_time_select_s(good, SCARD_S_SUCCESS, SCARD_F_INTERNAL_ERROR);
|
||||
|
||||
logprintf(pCardData, 2, "decrypted data(%lu):\n",
|
||||
(unsigned long)pInfo->cbData);
|
||||
loghex(pCardData, 7, pbuf2, pInfo->cbData);
|
||||
|
||||
/*inversion donnees */
|
||||
- for(ui = 0; ui < pInfo->cbData; ui++)
|
||||
- pInfo->pbData[ui] = pbuf2[pInfo->cbData-ui-1];
|
||||
+ /* copy data in constant-time way to prevent leak */
|
||||
+ for (ui = 0; ui < pbufLen; ui++) {
|
||||
+ unsigned int mask, msg_index, inv_ui;
|
||||
+ mask = good & constant_time_lt_s(ui, pInfo->cbData); /* ui should be in the bounds of pbuf2 */
|
||||
+ inv_ui = pInfo->cbData - ui - 1;
|
||||
+ msg_index = constant_time_select_s(mask, inv_ui, 0);
|
||||
+ pInfo->pbData[ui] = constant_time_select_8(mask, pbuf2[msg_index], pInfo->pbData[ui]);
|
||||
+ }
|
||||
|
||||
pCardData->pfnCspFree(pbuf);
|
||||
pCardData->pfnCspFree(pbuf2);
|
||||
|
||||
err:
|
||||
unlock(pCardData);
|
||||
- MD_FUNC_RETURN(pCardData, 1, dwret);
|
||||
+ /* do not log return value to not leak it */
|
||||
+ return dwret;
|
||||
}
|
||||
|
||||
|
||||
Index: opensc-0.24.0/src/tests/unittests/Makefile.am
|
||||
===================================================================
|
||||
--- opensc-0.24.0.orig/src/tests/unittests/Makefile.am
|
||||
+++ opensc-0.24.0/src/tests/unittests/Makefile.am
|
||||
@@ -14,8 +14,10 @@ VALGRIND_FLAGS = --num-callers=30 -q --k
|
||||
TESTS_ENVIRONMENT = LD_PRELOAD='/usr/lib/x86_64-linux-gnu/libpcsclite.so.1'
|
||||
endif
|
||||
|
||||
-noinst_PROGRAMS = asn1 simpletlv cachedir pkcs15filter openpgp-tool hextobin decode_ecdsa_signature check_macro_reference_loop
|
||||
-TESTS = asn1 simpletlv cachedir pkcs15filter openpgp-tool hextobin decode_ecdsa_signature check_macro_reference_loop
|
||||
+noinst_PROGRAMS = asn1 simpletlv cachedir pkcs15filter openpgp-tool hextobin \
|
||||
+ decode_ecdsa_signature check_macro_reference_loop strip_pkcs1_2_padding
|
||||
+TESTS = asn1 simpletlv cachedir pkcs15filter openpgp-tool hextobin \
|
||||
+ decode_ecdsa_signature check_macro_reference_loop strip_pkcs1_2_padding
|
||||
|
||||
noinst_HEADERS = torture.h
|
||||
|
||||
@@ -37,6 +39,7 @@ openpgp_tool_SOURCES = openpgp-tool.c $(
|
||||
hextobin_SOURCES = hextobin.c
|
||||
decode_ecdsa_signature_SOURCES = decode_ecdsa_signature.c
|
||||
check_macro_reference_loop = check_macro_reference_loop.c
|
||||
+strip_pkcs1_2_padding = strip_pkcs1_2_padding.c
|
||||
|
||||
if ENABLE_ZLIB
|
||||
noinst_PROGRAMS += compression
|
||||
Index: opensc-0.24.0/src/tests/unittests/Makefile.mak
|
||||
===================================================================
|
||||
--- opensc-0.24.0.orig/src/tests/unittests/Makefile.mak
|
||||
+++ opensc-0.24.0/src/tests/unittests/Makefile.mak
|
||||
@@ -1,11 +1,12 @@
|
||||
TOPDIR = ..\..\..
|
||||
|
||||
-TARGETS = asn1 compression pkcs15filter check_macro_reference_loop
|
||||
+TARGETS = asn1 compression pkcs15filter check_macro_reference_loop strip_pkcs1_2_padding
|
||||
|
||||
OBJECTS = asn1.obj \
|
||||
compression.obj \
|
||||
pkcs15-emulator-filter.obj \
|
||||
- check_macro_reference_loop.obj
|
||||
+ check_macro_reference_loop.obj \
|
||||
+ strip_pkcs1_2_padding.obj \
|
||||
$(TOPDIR)\win32\versioninfo.res
|
||||
|
||||
all: $(TARGETS)
|
||||
Index: opensc-0.24.0/src/tests/unittests/strip_pkcs1_2_padding.c
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ opensc-0.24.0/src/tests/unittests/strip_pkcs1_2_padding.c
|
||||
@@ -0,0 +1,204 @@
|
||||
+#include "common/compat_strlcpy.c"
|
||||
+#include "libopensc/log.c"
|
||||
+#include "libopensc/padding.c"
|
||||
+#include "torture.h"
|
||||
+#include <cmocka.h>
|
||||
+
|
||||
+static void
|
||||
+torture_long_output_buffer(void **state)
|
||||
+{
|
||||
+ unsigned int n = 14;
|
||||
+ unsigned int in_len = 14;
|
||||
+ unsigned char in[] = {0x00, 0x02,
|
||||
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
|
||||
+ 0x00,
|
||||
+ 'm', 's', 'g'};
|
||||
+ unsigned int out_len = 3;
|
||||
+ unsigned char *out = malloc(out_len * sizeof(unsigned char));
|
||||
+ unsigned char result_msg[] = {'m', 's', 'g'};
|
||||
+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
|
||||
+ assert_int_equal(r, 3);
|
||||
+ assert_memory_equal(out, result_msg, r);
|
||||
+ free(out);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+torture_short_output_buffer(void **state)
|
||||
+{
|
||||
+ unsigned int n = 14;
|
||||
+ unsigned int in_len = 14;
|
||||
+ unsigned char in[] = {0x00, 0x02,
|
||||
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
|
||||
+ 0x00,
|
||||
+ 'm', 's', 'g'};
|
||||
+ unsigned int out_len = 1;
|
||||
+ unsigned char *out = malloc(out_len * sizeof(unsigned char));
|
||||
+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
|
||||
+ assert_int_equal(r, SC_ERROR_WRONG_PADDING);
|
||||
+ free(out);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+torture_short_message_correct_padding(void **state)
|
||||
+{
|
||||
+ unsigned int n = 14;
|
||||
+ unsigned int in_len = 14;
|
||||
+ unsigned char in[] = {0x00, 0x02,
|
||||
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
|
||||
+ 0x00,
|
||||
+ 'm', 's', 'g'};
|
||||
+ unsigned int out_len = 3;
|
||||
+ unsigned char *out = malloc(out_len * sizeof(unsigned char));
|
||||
+ unsigned char result_msg[] = {'m', 's', 'g'};
|
||||
+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
|
||||
+ assert_int_equal(r, 3);
|
||||
+ assert_memory_equal(out, result_msg, r);
|
||||
+ free(out);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+torture_missing_first_zero(void **state)
|
||||
+{
|
||||
+ unsigned int n = 13;
|
||||
+ unsigned int in_len = 13;
|
||||
+ unsigned char in[] = {0x02,
|
||||
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
|
||||
+ 0x00,
|
||||
+ 'm', 's', 'g'};
|
||||
+ unsigned int out_len = 10;
|
||||
+ unsigned char *out = malloc(out_len * sizeof(unsigned char));
|
||||
+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
|
||||
+ assert_int_equal(r, SC_ERROR_WRONG_PADDING);
|
||||
+ free(out);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+torture_missing_two(void **state)
|
||||
+{
|
||||
+ unsigned int n = 13;
|
||||
+ unsigned int in_len = 13;
|
||||
+ unsigned char in[] = {0x00,
|
||||
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
|
||||
+ 0x00,
|
||||
+ 'm', 's', 'g'};
|
||||
+ unsigned int out_len = 10;
|
||||
+ unsigned char *out = malloc(out_len * sizeof(unsigned char));
|
||||
+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
|
||||
+ assert_int_equal(r, SC_ERROR_WRONG_PADDING);
|
||||
+ free(out);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+torture_short_padding(void **state)
|
||||
+{
|
||||
+ unsigned int n = 13;
|
||||
+ unsigned int in_len = 13;
|
||||
+ unsigned char in[] = {0x00, 0x02,
|
||||
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
+ 0x00,
|
||||
+ 'm', 's', 'g'};
|
||||
+ unsigned int out_len = 10;
|
||||
+ unsigned char *out = malloc(out_len * sizeof(unsigned char));
|
||||
+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
|
||||
+ assert_int_equal(r, SC_ERROR_WRONG_PADDING);
|
||||
+ free(out);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+torture_missing_second_zero(void **state)
|
||||
+{
|
||||
+ unsigned int n = 13;
|
||||
+ unsigned int in_len = 13;
|
||||
+ unsigned char in[] = {0x00, 0x02,
|
||||
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
|
||||
+ 'm', 's', 'g'};
|
||||
+ unsigned int out_len = 10;
|
||||
+ unsigned char *out = malloc(out_len * sizeof(unsigned char));
|
||||
+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
|
||||
+ assert_int_equal(r, SC_ERROR_WRONG_PADDING);
|
||||
+ free(out);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+torture_missing_message(void **state)
|
||||
+{
|
||||
+ unsigned int n = 20;
|
||||
+ unsigned int in_len = 11;
|
||||
+ unsigned char in[] = {0x00, 0x02,
|
||||
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
|
||||
+ 0x00};
|
||||
+ unsigned int out_len = 11;
|
||||
+ unsigned char *out = malloc(out_len * sizeof(unsigned char));
|
||||
+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
|
||||
+ assert_int_equal(r, SC_ERROR_WRONG_PADDING);
|
||||
+ free(out);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+torture_one_byte_message(void **state)
|
||||
+{
|
||||
+ unsigned int n = 12;
|
||||
+ unsigned int in_len = 12;
|
||||
+ unsigned char in[] = {0x00, 0x02,
|
||||
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
|
||||
+ 0x00,
|
||||
+ 'm'};
|
||||
+ unsigned int out_len = 1;
|
||||
+ unsigned char *out = malloc(out_len * sizeof(unsigned char));
|
||||
+ unsigned char result_msg[] = {'m'};
|
||||
+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
|
||||
+ assert_int_equal(r, 1);
|
||||
+ assert_memory_equal(out, result_msg, r);
|
||||
+ free(out);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+torture_longer_padding(void **state)
|
||||
+{
|
||||
+ unsigned int n = 26;
|
||||
+ unsigned int in_len = 26;
|
||||
+ unsigned char in[] = {0x00, 0x02,
|
||||
+ 0x0e, 0x38, 0x97, 0x18, 0x16, 0x57, 0x9e, 0x30, 0xb6, 0xa5, 0x78, 0x13, 0x20, 0xca, 0x11,
|
||||
+ 0x00,
|
||||
+ 0x9d, 0x98, 0x3d, 0xca, 0xa9, 0xa7, 0x11, 0x0a};
|
||||
+ unsigned int out_len = 8;
|
||||
+ unsigned char *out = malloc(out_len * sizeof(unsigned char));
|
||||
+ unsigned char result_msg[] = {0x9d, 0x98, 0x3d, 0xca, 0xa9, 0xa7, 0x11, 0x0a};
|
||||
+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
|
||||
+ assert_int_equal(r, 8);
|
||||
+ assert_memory_equal(out, result_msg, r);
|
||||
+ free(out);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+torture_empty_message(void **state)
|
||||
+{
|
||||
+ unsigned int n = 18;
|
||||
+ unsigned int in_len = 18;
|
||||
+ unsigned char in[] = {0x00, 0x02,
|
||||
+ 0x0e, 0x38, 0x97, 0x18, 0x16, 0x57, 0x9e, 0x30, 0xb6, 0xa5, 0x78, 0x13, 0x20, 0xca, 0x11,
|
||||
+ 0x00};
|
||||
+ unsigned int out_len = 8;
|
||||
+ unsigned char *out = malloc(out_len * sizeof(unsigned char));
|
||||
+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
|
||||
+ assert_int_equal(r, 0);
|
||||
+ free(out);
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+main(void)
|
||||
+{
|
||||
+ const struct CMUnitTest tests[] = {
|
||||
+ cmocka_unit_test(torture_long_output_buffer),
|
||||
+ cmocka_unit_test(torture_short_output_buffer),
|
||||
+ cmocka_unit_test(torture_short_message_correct_padding),
|
||||
+ cmocka_unit_test(torture_missing_first_zero),
|
||||
+ cmocka_unit_test(torture_missing_two),
|
||||
+ cmocka_unit_test(torture_short_padding),
|
||||
+ cmocka_unit_test(torture_missing_second_zero),
|
||||
+ cmocka_unit_test(torture_missing_message),
|
||||
+ cmocka_unit_test(torture_one_byte_message),
|
||||
+ cmocka_unit_test(torture_longer_padding),
|
||||
+ cmocka_unit_test(torture_empty_message)};
|
||||
+ return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
+}
|
||||
Index: opensc-0.24.0/src/pkcs11/framework-pkcs15.c
|
||||
===================================================================
|
||||
--- opensc-0.24.0.orig/src/pkcs11/framework-pkcs15.c
|
||||
+++ opensc-0.24.0/src/pkcs11/framework-pkcs15.c
|
||||
@@ -18,6 +18,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
+#include "common/constant-time.h"
|
||||
#include "config.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -4514,7 +4515,8 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_se
|
||||
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;
|
||||
|
||||
if (pulDataLen == NULL) {
|
||||
/* This is call from the C_DecyptInit function */
|
||||
@@ -4603,27 +4605,53 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_se
|
||||
rv = sc_pkcs15_decipher(fw_data->p15_card, prkey->prv_p15obj, flags,
|
||||
pEncryptedData, ulEncryptedDataLen, decrypted, sizeof(decrypted), pMechanism);
|
||||
|
||||
- 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), pMechanism);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
Index: opensc-0.24.0/src/pkcs11/mechanism.c
|
||||
===================================================================
|
||||
--- opensc-0.24.0.orig/src/pkcs11/mechanism.c
|
||||
+++ opensc-0.24.0/src/pkcs11/mechanism.c
|
||||
@@ -23,8 +23,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
-#include "sc-pkcs11.h"
|
||||
#include "common/compat_overflow.h"
|
||||
+#include "common/constant-time.h"
|
||||
+#include "sc-pkcs11.h"
|
||||
|
||||
/* Also used for verification data */
|
||||
struct hash_signature_info {
|
||||
@@ -1093,7 +1094,9 @@ sc_pkcs11_decr(struct sc_pkcs11_session
|
||||
rv = op->type->decrypt(op, pEncryptedData, ulEncryptedDataLen,
|
||||
pData, pulDataLen);
|
||||
|
||||
- if (rv != CKR_BUFFER_TOO_SMALL && pData != NULL)
|
||||
+ /* terminate session for any return value except CKR_BUFFER_TOO_SMALL,
|
||||
+ * perform check in time side-channel free way to prevent Marvin attack */
|
||||
+ if (!constant_time_eq_s(rv, CKR_BUFFER_TOO_SMALL) && pData != NULL)
|
||||
session_stop_operation(session, SC_PKCS11_OPERATION_DECRYPT);
|
||||
|
||||
return rv;
|
||||
@@ -1114,10 +1117,12 @@ sc_pkcs11_decr_update(struct sc_pkcs11_s
|
||||
rv = op->type->decrypt_update(op, pEncryptedData, ulEncryptedDataLen,
|
||||
pData, pulDataLen);
|
||||
|
||||
- /* terminate session for any error except CKR_BUFFER_TOO_SMALL */
|
||||
- if (rv != CKR_OK && rv != CKR_BUFFER_TOO_SMALL)
|
||||
+ /* terminate session for any return value except CKR_BUFFER_TOO_SMALL,
|
||||
+ * perform check in time side-channel free way to prevent Marvin attack */
|
||||
+ if (~constant_time_eq_s(rv, CKR_OK) & ~constant_time_eq_s(rv, CKR_BUFFER_TOO_SMALL))
|
||||
session_stop_operation(session, SC_PKCS11_OPERATION_DECRYPT);
|
||||
- LOG_FUNC_RETURN(context, (int)rv);
|
||||
+ /* do not log error code to prevent side channel attack */
|
||||
+ return rv;
|
||||
}
|
||||
|
||||
CK_RV
|
||||
@@ -1536,6 +1541,10 @@ sc_pkcs11_decrypt(sc_pkcs11_operation_t
|
||||
if (pulDataLen)
|
||||
*pulDataLen = ulDataLen;
|
||||
|
||||
+ /* Skip DecryptFinalize for PKCS#1 v1.5 padding to prevent time side-channel leakage */
|
||||
+ if (((CK_MECHANISM_PTR)&operation->mechanism)->mechanism == CKM_RSA_PKCS)
|
||||
+ return rv;
|
||||
+
|
||||
if (rv != CKR_OK)
|
||||
return rv;
|
||||
|
||||
Index: opensc-0.24.0/src/pkcs11/pkcs11-object.c
|
||||
===================================================================
|
||||
--- opensc-0.24.0.orig/src/pkcs11/pkcs11-object.c
|
||||
+++ opensc-0.24.0/src/pkcs11/pkcs11-object.c
|
||||
@@ -1034,7 +1034,8 @@ C_Decrypt(CK_SESSION_HANDLE hSession,
|
||||
rv = reset_login_state(session->slot, rv);
|
||||
}
|
||||
|
||||
- SC_LOG_RV("C_Decrypt() = %s", rv);
|
||||
+ /* do not log error code to prevent side channel attack */
|
||||
+ SC_LOG("C_Decrypt()");
|
||||
sc_pkcs11_unlock();
|
||||
return rv;
|
||||
}
|
||||
@@ -1058,7 +1059,8 @@ C_DecryptUpdate(CK_SESSION_HANDLE hSessi
|
||||
rv = sc_pkcs11_decr_update(session, pEncryptedPart, ulEncryptedPartLen,
|
||||
pPart, pulPartLen);
|
||||
|
||||
- SC_LOG_RV("C_DecryptUpdate() = %s", rv);
|
||||
+ /* do not log error code to prevent side channel attack */
|
||||
+ SC_LOG("C_DecryptUpdate()");
|
||||
sc_pkcs11_unlock();
|
||||
return rv;
|
||||
}
|
||||
@@ -1086,7 +1088,8 @@ C_DecryptFinal(CK_SESSION_HANDLE hSessio
|
||||
rv = reset_login_state(session->slot, rv);
|
||||
}
|
||||
|
||||
- SC_LOG_RV("C_DecryptFinal() = %s", rv);
|
||||
+ /* do not log error code to prevent side channel attack */
|
||||
+ SC_LOG("C_DecryptFinal()");
|
||||
sc_pkcs11_unlock();
|
||||
return rv;
|
||||
}
|
||||
Index: opensc-0.24.0/src/pkcs11/sc-pkcs11.h
|
||||
===================================================================
|
||||
--- opensc-0.24.0.orig/src/pkcs11/sc-pkcs11.h
|
||||
+++ opensc-0.24.0/src/pkcs11/sc-pkcs11.h
|
||||
@@ -246,6 +246,11 @@ do {\
|
||||
}\
|
||||
} while(0)
|
||||
|
||||
+#define SC_LOG(fmt) \
|
||||
+ do { \
|
||||
+ sc_log(context, (fmt)); \
|
||||
+ } while (0)
|
||||
+
|
||||
/* Debug virtual slots. S is slot to be highlighted or NULL
|
||||
* C is a comment format string and args It will be preceded by "VSS " */
|
||||
#define DEBUG_VSS(S, ...) do { sc_log(context,"VSS " __VA_ARGS__); _debug_virtual_slots(S); } while (0)
|
||||
Index: opensc-0.24.0/src/pkcs11/misc.c
|
||||
===================================================================
|
||||
--- opensc-0.24.0.orig/src/pkcs11/misc.c
|
||||
+++ opensc-0.24.0/src/pkcs11/misc.c
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
+#include "common/constant-time.h"
|
||||
#include "sc-pkcs11.h"
|
||||
|
||||
#define DUMP_TEMPLATE_MAX 32
|
||||
@@ -174,7 +175,7 @@ CK_RV reset_login_state(struct sc_pkcs11
|
||||
slot->p11card->framework->logout(slot);
|
||||
}
|
||||
|
||||
- if (rv == CKR_USER_NOT_LOGGED_IN) {
|
||||
+ if (constant_time_eq_s(rv, CKR_USER_NOT_LOGGED_IN)) {
|
||||
slot->login_user = -1;
|
||||
pop_all_login_states(slot);
|
||||
}
|
||||
@@ -9,10 +9,10 @@ Date: Thu Jul 11 15:27:19 2024 +0200
|
||||
|
||||
fuzz_card/2
|
||||
|
||||
Index: opensc-0.22.0/src/libopensc/card-cardos.c
|
||||
Index: opensc-0.24.0/src/libopensc/card-cardos.c
|
||||
===================================================================
|
||||
--- opensc-0.22.0.orig/src/libopensc/card-cardos.c
|
||||
+++ opensc-0.22.0/src/libopensc/card-cardos.c
|
||||
--- opensc-0.24.0.orig/src/libopensc/card-cardos.c
|
||||
+++ opensc-0.24.0/src/libopensc/card-cardos.c
|
||||
@@ -94,14 +94,14 @@ static void fixup_transceive_length(cons
|
||||
|
||||
static int cardos_match_card(sc_card_t *card)
|
||||
@@ -50,11 +50,11 @@ Index: opensc-0.22.0/src/libopensc/card-cardos.c
|
||||
return 0;
|
||||
if (apdu.resp[0] != atr[10] ||
|
||||
apdu.resp[1] != atr[11])
|
||||
Index: opensc-0.22.0/src/libopensc/card-cac1.c
|
||||
Index: opensc-0.24.0/src/libopensc/card-cac1.c
|
||||
===================================================================
|
||||
--- opensc-0.22.0.orig/src/libopensc/card-cac1.c
|
||||
+++ opensc-0.22.0/src/libopensc/card-cac1.c
|
||||
@@ -95,12 +95,12 @@ static int cac_cac1_get_certificate(sc_c
|
||||
--- opensc-0.24.0.orig/src/libopensc/card-cac1.c
|
||||
+++ opensc-0.24.0/src/libopensc/card-cac1.c
|
||||
@@ -92,12 +92,12 @@ static int cac_cac1_get_certificate(sc_c
|
||||
if (apdu.sw1 != 0x63 || apdu.sw2 < 1) {
|
||||
/* we've either finished reading, or hit an error, break */
|
||||
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||
@@ -70,10 +70,10 @@ Index: opensc-0.22.0/src/libopensc/card-cac1.c
|
||||
len = MIN(left, apdu.sw2);
|
||||
}
|
||||
if (r < 0) {
|
||||
Index: opensc-0.22.0/src/libopensc/card-oberthur.c
|
||||
Index: opensc-0.24.0/src/libopensc/card-oberthur.c
|
||||
===================================================================
|
||||
--- opensc-0.22.0.orig/src/libopensc/card-oberthur.c
|
||||
+++ opensc-0.22.0/src/libopensc/card-oberthur.c
|
||||
--- opensc-0.24.0.orig/src/libopensc/card-oberthur.c
|
||||
+++ opensc-0.24.0/src/libopensc/card-oberthur.c
|
||||
@@ -148,7 +148,7 @@ auth_select_aid(struct sc_card *card)
|
||||
{
|
||||
struct sc_apdu apdu;
|
||||
@@ -93,10 +93,10 @@ Index: opensc-0.22.0/src/libopensc/card-oberthur.c
|
||||
card->serialnr.len = 4;
|
||||
memcpy(card->serialnr.value, apdu.resp+15, 4);
|
||||
|
||||
Index: opensc-0.22.0/src/libopensc/card-gids.c
|
||||
Index: opensc-0.24.0/src/libopensc/card-gids.c
|
||||
===================================================================
|
||||
--- opensc-0.22.0.orig/src/libopensc/card-gids.c
|
||||
+++ opensc-0.22.0/src/libopensc/card-gids.c
|
||||
--- opensc-0.24.0.orig/src/libopensc/card-gids.c
|
||||
+++ opensc-0.24.0/src/libopensc/card-gids.c
|
||||
@@ -231,6 +231,7 @@ static int gids_get_DO(sc_card_t* card,
|
||||
size_t datasize = 0;
|
||||
const u8* p;
|
||||
@@ -123,53 +123,10 @@ Index: opensc-0.22.0/src/libopensc/card-gids.c
|
||||
if (!p) {
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
Index: opensc-0.22.0/src/libopensc/card-mcrd.c
|
||||
Index: opensc-0.24.0/src/libopensc/asn1.c
|
||||
===================================================================
|
||||
--- opensc-0.22.0.orig/src/libopensc/card-mcrd.c
|
||||
+++ opensc-0.22.0/src/libopensc/card-mcrd.c
|
||||
@@ -634,23 +634,25 @@ do_select(sc_card_t * card, u8 kind,
|
||||
}
|
||||
}
|
||||
|
||||
- if (p2 == 0x04 && apdu.resp[0] == 0x62) {
|
||||
- *file = sc_file_new();
|
||||
- if (!*file)
|
||||
- LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||
- /* EstEID v3.0 cards are buggy and sometimes return a double 0x62 tag */
|
||||
- if (card->type == SC_CARD_TYPE_MCRD_ESTEID_V30 && apdu.resp[2] == 0x62)
|
||||
- process_fcp(card, *file, apdu.resp + 4, apdu.resp[3]);
|
||||
- else
|
||||
- process_fcp(card, *file, apdu.resp + 2, apdu.resp[1]);
|
||||
- return SC_SUCCESS;
|
||||
- }
|
||||
+ if (p2 == 0x04 && apdu.resplen > 2 && apdu.resp[0] == 0x62) {
|
||||
+ *file = sc_file_new();
|
||||
+ if (!*file)
|
||||
+ LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||
+ if (apdu.resp[1] > apdu.resplen - 2)
|
||||
+ LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_DATA);
|
||||
+ /* EstEID v3.0 cards are buggy and sometimes return a double 0x62 tag */
|
||||
+ if (card->type == SC_CARD_TYPE_MCRD_ESTEID_V30 && apdu.resp[2] == 0x62)
|
||||
+ process_fcp(card, *file, apdu.resp + 4, apdu.resp[3]);
|
||||
+ else
|
||||
+ process_fcp(card, *file, apdu.resp + 2, apdu.resp[1]);
|
||||
+ return SC_SUCCESS;
|
||||
+ }
|
||||
|
||||
- if (p2 != 0x0C && apdu.resp[0] == 0x6F) {
|
||||
+ if (p2 != 0x0C && apdu.resplen > 2 && apdu.resp[0] == 0x6F) {
|
||||
*file = sc_file_new();
|
||||
if (!*file)
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||
- if (apdu.resp[1] <= apdu.resplen)
|
||||
+ if (apdu.resp[1] > apdu.resplen - 2)
|
||||
process_fcp(card, *file, apdu.resp + 2, apdu.resp[1]);
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
Index: opensc-0.22.0/src/libopensc/asn1.c
|
||||
===================================================================
|
||||
--- opensc-0.22.0.orig/src/libopensc/asn1.c
|
||||
+++ opensc-0.22.0/src/libopensc/asn1.c
|
||||
--- opensc-0.24.0.orig/src/libopensc/asn1.c
|
||||
+++ opensc-0.24.0/src/libopensc/asn1.c
|
||||
@@ -68,7 +68,7 @@ int sc_asn1_read_tag(const u8 ** buf, si
|
||||
|
||||
*buf = NULL;
|
||||
@@ -188,11 +145,11 @@ Index: opensc-0.22.0/src/libopensc/asn1.c
|
||||
p++;
|
||||
left--;
|
||||
if (tag == SC_ASN1_TAG_PRIMITIVE) {
|
||||
Index: opensc-0.22.0/src/libopensc/card-dnie.c
|
||||
Index: opensc-0.24.0/src/libopensc/card-dnie.c
|
||||
===================================================================
|
||||
--- opensc-0.22.0.orig/src/libopensc/card-dnie.c
|
||||
+++ opensc-0.22.0/src/libopensc/card-dnie.c
|
||||
@@ -1185,12 +1185,16 @@ static int dnie_compose_and_send_apdu(sc
|
||||
--- opensc-0.24.0.orig/src/libopensc/card-dnie.c
|
||||
+++ opensc-0.24.0/src/libopensc/card-dnie.c
|
||||
@@ -1171,12 +1171,16 @@ static int dnie_compose_and_send_apdu(sc
|
||||
|
||||
if (file_out) {
|
||||
/* finally process FCI response */
|
||||
@@ -210,7 +167,7 @@ Index: opensc-0.22.0/src/libopensc/card-dnie.c
|
||||
}
|
||||
LOG_FUNC_RETURN(ctx, res);
|
||||
}
|
||||
@@ -1949,7 +1953,7 @@ static int dnie_process_fci(struct sc_ca
|
||||
@@ -1934,7 +1938,7 @@ static int dnie_process_fci(struct sc_ca
|
||||
int *op = df_acl;
|
||||
int n = 0;
|
||||
sc_context_t *ctx = NULL;
|
||||
@@ -219,40 +176,11 @@ Index: opensc-0.22.0/src/libopensc/card-dnie.c
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
ctx = card->ctx;
|
||||
LOG_FUNC_CALLED(ctx);
|
||||
Index: opensc-0.22.0/src/libopensc/muscle.c
|
||||
Index: opensc-0.24.0/src/libopensc/muscle.c
|
||||
===================================================================
|
||||
--- opensc-0.22.0.orig/src/libopensc/muscle.c
|
||||
+++ opensc-0.22.0/src/libopensc/muscle.c
|
||||
@@ -94,33 +94,35 @@ int msc_partial_read_object(sc_card_t *c
|
||||
apdu.resp = data;
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||
- if(apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
|
||||
- return dataLength;
|
||||
- if(apdu.sw1 == 0x9C) {
|
||||
- if(apdu.sw2 == 0x07) {
|
||||
+ if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00 && dataLength <= apdu.resplen)
|
||||
+ return dataLength;
|
||||
+ if (apdu.sw1 == 0x9C) {
|
||||
+ if (apdu.sw2 == 0x07) {
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_FILE_NOT_FOUND);
|
||||
- } else if(apdu.sw2 == 0x06) {
|
||||
+ } else if (apdu.sw2 == 0x06) {
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_ALLOWED);
|
||||
- } else if(apdu.sw2 == 0x0F) {
|
||||
+ } else if (apdu.sw2 == 0x0F) {
|
||||
/* GUESSED */
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
|
||||
}
|
||||
}
|
||||
sc_log(card->ctx,
|
||||
"got strange SWs: 0x%02X 0x%02X\n", apdu.sw1, apdu.sw2);
|
||||
- return dataLength;
|
||||
-
|
||||
-}
|
||||
+
|
||||
+ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_UNKNOWN_DATA_RECEIVED);
|
||||
+ }
|
||||
--- opensc-0.24.0.orig/src/libopensc/muscle.c
|
||||
+++ opensc-0.24.0/src/libopensc/muscle.c
|
||||
@@ -112,13 +112,15 @@ int msc_partial_read_object(sc_card_t *c
|
||||
|
||||
int msc_read_object(sc_card_t *card, msc_id objectId, int offset, u8 *data, size_t dataLength)
|
||||
{
|
||||
@@ -265,16 +193,25 @@ Index: opensc-0.22.0/src/libopensc/muscle.c
|
||||
+ for(i = 0; i < dataLength; i += r) {
|
||||
r = msc_partial_read_object(card, objectId, offset + i, data + i, MIN(dataLength - i, max_read_unit));
|
||||
LOG_TEST_RET(card->ctx, r, "Error in partial object read");
|
||||
+ if (r==0)
|
||||
+ if (r == 0)
|
||||
+ break;
|
||||
}
|
||||
return dataLength;
|
||||
}
|
||||
Index: opensc-0.22.0/src/libopensc/card-entersafe.c
|
||||
@@ -171,7 +173,7 @@ int msc_create_object(sc_card_t *card, m
|
||||
apdu.sw1, apdu.sw2);
|
||||
}
|
||||
msc_zero_object(card, objectId, objectSize);
|
||||
- return objectSize;
|
||||
+ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_UNKNOWN_DATA_RECEIVED);
|
||||
}
|
||||
|
||||
/* Update up to MSC_MAX_READ - 9 bytes */
|
||||
Index: opensc-0.24.0/src/libopensc/card-entersafe.c
|
||||
===================================================================
|
||||
--- opensc-0.22.0.orig/src/libopensc/card-entersafe.c
|
||||
+++ opensc-0.22.0/src/libopensc/card-entersafe.c
|
||||
@@ -1453,7 +1453,9 @@ static int entersafe_get_serialnr(sc_car
|
||||
--- opensc-0.24.0.orig/src/libopensc/card-entersafe.c
|
||||
+++ opensc-0.24.0/src/libopensc/card-entersafe.c
|
||||
@@ -1482,7 +1482,9 @@ static int entersafe_get_serialnr(sc_car
|
||||
r=entersafe_transmit_apdu(card, &apdu,0,0,0,0);
|
||||
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||
LOG_TEST_RET(card->ctx, sc_check_sw(card,apdu.sw1,apdu.sw2),"EnterSafe get SN failed");
|
||||
|
||||
@@ -9,11 +9,11 @@ Date: Tue Jul 16 14:05:36 2024 +0200
|
||||
|
||||
fuzz_pkcs11/14
|
||||
|
||||
Index: opensc-0.22.0/src/libopensc/card-cac.c
|
||||
Index: opensc-0.24.0/src/libopensc/card-cac.c
|
||||
===================================================================
|
||||
--- opensc-0.22.0.orig/src/libopensc/card-cac.c
|
||||
+++ opensc-0.22.0/src/libopensc/card-cac.c
|
||||
@@ -1302,10 +1302,10 @@ static int cac_parse_aid(sc_card_t *card
|
||||
--- opensc-0.24.0.orig/src/libopensc/card-cac.c
|
||||
+++ opensc-0.24.0/src/libopensc/card-cac.c
|
||||
@@ -1292,10 +1292,10 @@ static int cac_parse_aid(sc_card_t *card
|
||||
/* Call without OID set will just select the AID without subsequent
|
||||
* OID selection, which we need to figure out just now
|
||||
*/
|
||||
@@ -27,11 +27,11 @@ Index: opensc-0.22.0/src/libopensc/card-cac.c
|
||||
|
||||
for (i = 0; i < prop.num_objects; i++) {
|
||||
/* don't fail just because we have more certs than we can support */
|
||||
Index: opensc-0.22.0/src/libopensc/card-cardos.c
|
||||
Index: opensc-0.24.0/src/libopensc/card-cardos.c
|
||||
===================================================================
|
||||
--- opensc-0.22.0.orig/src/libopensc/card-cardos.c
|
||||
+++ opensc-0.22.0/src/libopensc/card-cardos.c
|
||||
@@ -1277,7 +1277,7 @@ cardos_lifecycle_get(sc_card_t *card, in
|
||||
--- opensc-0.24.0.orig/src/libopensc/card-cardos.c
|
||||
+++ opensc-0.24.0/src/libopensc/card-cardos.c
|
||||
@@ -1278,7 +1278,7 @@ cardos_lifecycle_get(sc_card_t *card, in
|
||||
LOG_TEST_RET(card->ctx, r, "Card returned error");
|
||||
|
||||
if (apdu.resplen < 1) {
|
||||
@@ -40,10 +40,10 @@ Index: opensc-0.22.0/src/libopensc/card-cardos.c
|
||||
}
|
||||
|
||||
r = SC_SUCCESS;
|
||||
Index: opensc-0.22.0/src/libopensc/card-jpki.c
|
||||
Index: opensc-0.24.0/src/libopensc/card-jpki.c
|
||||
===================================================================
|
||||
--- opensc-0.22.0.orig/src/libopensc/card-jpki.c
|
||||
+++ opensc-0.22.0/src/libopensc/card-jpki.c
|
||||
--- opensc-0.24.0.orig/src/libopensc/card-jpki.c
|
||||
+++ opensc-0.24.0/src/libopensc/card-jpki.c
|
||||
@@ -195,6 +195,8 @@ jpki_select_file(struct sc_card *card,
|
||||
u8 buf[4];
|
||||
rc = sc_read_binary(card, 0, buf, 4, 0);
|
||||
|
||||
@@ -9,11 +9,11 @@ Date: Wed Jul 17 11:18:52 2024 +0200
|
||||
|
||||
fuzz_pkcs15_encode/21
|
||||
|
||||
diff --git a/src/libopensc/pkcs15-tcos.c b/src/libopensc/pkcs15-tcos.c
|
||||
index 4d02a98ee..2bd275c4f 100644
|
||||
--- a/src/libopensc/pkcs15-tcos.c
|
||||
+++ b/src/libopensc/pkcs15-tcos.c
|
||||
@@ -531,10 +531,15 @@ int sc_pkcs15emu_tcos_init_ex(
|
||||
Index: opensc-0.24.0/src/libopensc/pkcs15-tcos.c
|
||||
===================================================================
|
||||
--- opensc-0.24.0.orig/src/libopensc/pkcs15-tcos.c
|
||||
+++ opensc-0.24.0/src/libopensc/pkcs15-tcos.c
|
||||
@@ -530,10 +530,15 @@ int sc_pkcs15emu_tcos_init_ex(
|
||||
/* get the card serial number */
|
||||
r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serialnr);
|
||||
if (r < 0) {
|
||||
@@ -31,23 +31,11 @@ index 4d02a98ee..2bd275c4f 100644
|
||||
serial[19] = '\0';
|
||||
set_string(&p15card->tokeninfo->serial_number, serial);
|
||||
|
||||
|
||||
commit f9d68660f032ad4d7803431d5fc7577ea8792ac3
|
||||
Author: Veronika Hanulíková <vhanulik@redhat.com>
|
||||
Date: Wed Jul 17 14:56:22 2024 +0200
|
||||
|
||||
pkcs15-lib: Report transport key error
|
||||
|
||||
Thanks Matteo Marini for report
|
||||
https://github.com/OpenSC/OpenSC/security/advisories/GHSA-p3mx-7472-h3j8
|
||||
|
||||
fuzz_pkcs15init/17, fuzz_pkcs15init/18
|
||||
|
||||
diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c
|
||||
index 6574e8025..943d53e98 100644
|
||||
--- a/src/pkcs15init/pkcs15-lib.c
|
||||
+++ b/src/pkcs15init/pkcs15-lib.c
|
||||
@@ -3831,13 +3831,15 @@ sc_pkcs15init_get_transport_key(struct sc_profile *profile, struct sc_pkcs15_car
|
||||
Index: opensc-0.24.0/src/pkcs15init/pkcs15-lib.c
|
||||
===================================================================
|
||||
--- opensc-0.24.0.orig/src/pkcs15init/pkcs15-lib.c
|
||||
+++ opensc-0.24.0/src/pkcs15init/pkcs15-lib.c
|
||||
@@ -3805,13 +3805,15 @@ sc_pkcs15init_get_transport_key(struct s
|
||||
if (callbacks.get_key) {
|
||||
rv = callbacks.get_key(profile, type, reference, defbuf, defsize, pinbuf, pinsize);
|
||||
LOG_TEST_RET(ctx, rv, "Cannot get key");
|
||||
|
||||
@@ -154,15 +154,6 @@ Index: opensc-0.24.0/src/pkcs15init/pkcs15-setcos.c
|
||||
keybits = ((raw_pubkey[0] * 256) + raw_pubkey[1]); /* modulus bit length */
|
||||
if (keybits != key_info->modulus_length) {
|
||||
sc_log(ctx,
|
||||
@@ -505,7 +508,7 @@ setcos_generate_key(struct sc_profile *p
|
||||
keybits, key_info->modulus_length);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_PKCS15INIT, "Failed to generate key");
|
||||
}
|
||||
- memcpy (pubkey->u.rsa.modulus.data, &raw_pubkey[2], pubkey->u.rsa.modulus.len);
|
||||
+ memcpy(pubkey->u.rsa.modulus.data, &raw_pubkey[2], pubkey->u.rsa.modulus.len);
|
||||
}
|
||||
|
||||
sc_file_free(file);
|
||||
Index: opensc-0.24.0/src/pkcs15init/pkcs15-sc-hsm.c
|
||||
===================================================================
|
||||
--- opensc-0.24.0.orig/src/pkcs15init/pkcs15-sc-hsm.c
|
||||
|
||||
@@ -40,14 +40,14 @@ Index: opensc-0.24.0/src/libopensc/iasecc-sdo.c
|
||||
LOG_FUNC_CALLED(ctx);
|
||||
|
||||
+ if (data_len < 1)
|
||||
+ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
|
||||
+ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
|
||||
+
|
||||
if (*data == IASECC_SDO_TEMPLATE_TAG) {
|
||||
size_size = iasecc_parse_size(data + 1, data_len - 1, &size);
|
||||
LOG_TEST_RET(ctx, size_size, "parse error: invalid size data of IASECC_SDO_TEMPLATE");
|
||||
|
||||
+ if (data_len - 1 < size)
|
||||
+ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
|
||||
+ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
|
||||
+
|
||||
data += size_size + 1;
|
||||
data_len = size;
|
||||
|
||||
@@ -14,11 +14,11 @@ Date: Mon Aug 12 19:02:14 2024 +0200
|
||||
|
||||
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
|
||||
|
||||
Index: opensc-0.22.0/src/libopensc/card-openpgp.c
|
||||
Index: opensc-0.24.0/src/libopensc/card-openpgp.c
|
||||
===================================================================
|
||||
--- opensc-0.22.0.orig/src/libopensc/card-openpgp.c
|
||||
+++ opensc-0.22.0/src/libopensc/card-openpgp.c
|
||||
@@ -2657,14 +2657,21 @@ pgp_calculate_and_store_fingerprint(sc_c
|
||||
--- opensc-0.24.0.orig/src/libopensc/card-openpgp.c
|
||||
+++ opensc-0.24.0/src/libopensc/card-openpgp.c
|
||||
@@ -2769,14 +2769,21 @@ pgp_calculate_and_store_fingerprint(sc_c
|
||||
/* update the blob containing fingerprints (00C5) */
|
||||
sc_log(card->ctx, "Updating fingerprint blob 00C5.");
|
||||
fpseq_blob = pgp_find_blob(card, 0x00C5);
|
||||
@@ -45,7 +45,7 @@ Index: opensc-0.22.0/src/libopensc/card-openpgp.c
|
||||
|
||||
memcpy(newdata, fpseq_blob->data, fpseq_blob->len);
|
||||
/* move p to the portion holding the fingerprint of the current key */
|
||||
@@ -2778,6 +2785,9 @@ pgp_parse_and_set_pubkey_output(sc_card_
|
||||
@@ -2891,6 +2898,9 @@ pgp_parse_and_set_pubkey_output(sc_card_
|
||||
|
||||
/* RSA modulus */
|
||||
if (tag == 0x0081) {
|
||||
@@ -55,7 +55,7 @@ Index: opensc-0.22.0/src/libopensc/card-openpgp.c
|
||||
if ((BYTES4BITS(key_info->u.rsa.modulus_len) < len) /* modulus_len is in bits */
|
||||
|| key_info->u.rsa.modulus == NULL) {
|
||||
|
||||
@@ -2793,6 +2803,9 @@ pgp_parse_and_set_pubkey_output(sc_card_
|
||||
@@ -2906,6 +2916,9 @@ pgp_parse_and_set_pubkey_output(sc_card_
|
||||
}
|
||||
/* RSA public exponent */
|
||||
else if (tag == 0x0082) {
|
||||
@@ -65,7 +65,7 @@ Index: opensc-0.22.0/src/libopensc/card-openpgp.c
|
||||
if ((BYTES4BITS(key_info->u.rsa.exponent_len) < len) /* exponent_len is in bits */
|
||||
|| key_info->u.rsa.exponent == NULL) {
|
||||
|
||||
@@ -2808,6 +2821,10 @@ pgp_parse_and_set_pubkey_output(sc_card_
|
||||
@@ -2921,6 +2934,10 @@ pgp_parse_and_set_pubkey_output(sc_card_
|
||||
}
|
||||
/* ECC public key */
|
||||
else if (tag == 0x0086) {
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
-------------------------------------------------------------------
|
||||
Tue Jun 24 17:04:42 UTC 2025 - Martin Schreiner <martin.schreiner@suse.com>
|
||||
|
||||
- Security fix: [CVE-2023-5992, bsc#1219386]
|
||||
* Add patch:
|
||||
- opensc-CVE-2023-5992.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Tue Oct 1 06:30:06 UTC 2024 - Angel Yankov <angel.yankov@suse.com>
|
||||
|
||||
@@ -27,7 +34,7 @@ Tue Oct 1 06:27:05 UTC 2024 - Angel Yankov <angel.yankov@suse.com>
|
||||
- opensc-CVE-2024-45618.patch
|
||||
- opensc-CVE-2024-45619.patch
|
||||
- opensc-CVE-2024-45620.patch
|
||||
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Sun Feb 25 20:35:05 UTC 2024 - Martin Schreiner <martin.schreiner@suse.com>
|
||||
|
||||
|
||||
27
opensc.spec
27
opensc.spec
@@ -31,22 +31,24 @@ Source2: %{name}-rpmlintrc
|
||||
# https://web.archive.org/web/20111225073733/http://www.opensc-project.org/opensc/ticket/390
|
||||
Source3: opensc.module
|
||||
Patch0: opensc-gcc11.patch
|
||||
# PATCH-FIX-UPSTREAM: bsc#1219386 CVE-2023-5992: Side-channel leaks while stripping encryption PKCS#1 padding
|
||||
Patch1: opensc-CVE-2023-5992.patch
|
||||
# PATCH-FIX-UPSTREAM martin.schreiner@suse.com CVE-2024-1454 bsc#1219868
|
||||
Patch1: CVE-2024-1454.patch
|
||||
# PATCH-FIX-UPSTREAM: bsc#1230364 CVE-2024-8443: heap buffer overflow in OpenPGP driver when generating key
|
||||
Patch2: opensc-CVE-2024-8443.patch
|
||||
Patch2: CVE-2024-1454.patch
|
||||
# PATCH-FIX-UPSTREAM bsc#1230364 opensc: heap buffer overflow in OpenPGP driver when generating key
|
||||
Patch3: opensc-CVE-2024-8443.patch
|
||||
# PATCH-FIX-UPSTREAM: bsc#1230071 CVE-2024-45615: opensc: pkcs15init: Usage of uninitialized values in libopensc and pkcs15init
|
||||
Patch3: opensc-CVE-2024-45615.patch
|
||||
# PATCH-FIX-UPSTREAM: bsc#1230072 CVE-2024-45616: opensc: Uninitialized values after incorrect check or usage of APDU response values in libopensc
|
||||
Patch4: opensc-CVE-2024-45616.patch
|
||||
Patch4: opensc-CVE-2024-45615.patch
|
||||
# PATCH-FIX-UPSTREAM: bsc#1230072 CVE-2024-45616: opensc: Uninitialized values after incorrect check or usage of APDU response values in libopensc
|
||||
Patch5: opensc-CVE-2024-45616.patch
|
||||
# PATCH-FIX-UPSTREAM: bsc#1230073 CVE-2024-45617: opensc: Uninitialized values after incorrect or missing checking return values of functions in libopensc
|
||||
Patch5: opensc-CVE-2024-45617.patch
|
||||
Patch6: opensc-CVE-2024-45617.patch
|
||||
# PATCH-FIX-UPSTREAM: bsc#1230074 CVE-2024-45618: opensc: Uninitialized values after incorrect or missing checking return values of functions in pkcs15init
|
||||
Patch6: opensc-CVE-2024-45618.patch
|
||||
Patch7: opensc-CVE-2024-45618.patch
|
||||
# PATCH-FIX-UPSTREAM: bsc#1230075 CVE-2024-45619: opensc: Incorrect handling length of buffers or files in libopensc
|
||||
Patch7: opensc-CVE-2024-45619.patch
|
||||
# PATCH-FIX-UPSTREAM: bsc#1230076 CVE-2024-45620: opensc: Incorrect handling of the length of buffers or files in pkcs15init
|
||||
Patch8: opensc-CVE-2024-45620.patch
|
||||
Patch8: opensc-CVE-2024-45619.patch
|
||||
# PATCH-FIX-UPSTREAM: bsc#1230076 CVE-2024-45620: opensc: Incorrect handling of the length of buffers or files in pkcs15init
|
||||
Patch9: opensc-CVE-2024-45620.patch
|
||||
|
||||
BuildRequires: docbook-xsl-stylesheets
|
||||
BuildRequires: libxslt
|
||||
@@ -56,6 +58,7 @@ BuildRequires: zlib-devel
|
||||
BuildRequires: pkgconfig(bash-completion)
|
||||
BuildRequires: pkgconfig(libpcsclite) >= 1.8.22
|
||||
BuildRequires: pkgconfig(openssl) >= 1.0.1
|
||||
BuildRequires: automake
|
||||
Requires: pcsc-lite
|
||||
# There is no more devel package.
|
||||
Obsoletes: opensc-devel < %{version}
|
||||
@@ -79,6 +82,8 @@ may require third party proprietary software.
|
||||
%autosetup -p1
|
||||
|
||||
%build
|
||||
aclocal
|
||||
automake
|
||||
%configure \
|
||||
--docdir=%{_docdir}/%{name} \
|
||||
--disable-static \
|
||||
|
||||
Reference in New Issue
Block a user