Compare commits

...

No commits in common. "c8" and "c8-beta" have entirely different histories.
c8 ... c8-beta

5 changed files with 2 additions and 1584 deletions

View File

@ -1,96 +0,0 @@
From bff98ff078a99e6864ba1a598fd7dc9af4a9476b Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@redhat.com>
Date: Thu, 7 Sep 2023 13:23:04 +0200
Subject: [PATCH] cache: Honor the file offset when writing cache
When the reads are not consecutive, avoid caching anything after the gaps.
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
---
src/libopensc/pkcs15-cache.c | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/src/libopensc/pkcs15-cache.c b/src/libopensc/pkcs15-cache.c
index 6ebe35a8af..61af35fc5a 100644
--- a/src/libopensc/pkcs15-cache.c
+++ b/src/libopensc/pkcs15-cache.c
@@ -195,6 +195,7 @@ int sc_pkcs15_cache_file(struct sc_pkcs15_card *p15card,
{
char fname[PATH_MAX];
int r;
+ long len;
FILE *f;
size_t c;
@@ -202,22 +203,33 @@ int sc_pkcs15_cache_file(struct sc_pkcs15_card *p15card,
if (r != 0)
return r;
- f = fopen(fname, "wb");
+ f = fopen(fname, "ab");
/* If the open failed because the cache directory does
* not exist, create it and a re-try the fopen() call.
*/
if (f == NULL && errno == ENOENT) {
if ((r = sc_make_cache_dir(p15card->card->ctx)) < 0)
return r;
- f = fopen(fname, "wb");
+ f = fopen(fname, "ab");
}
if (f == NULL)
return 0;
+ /* we opened the file for appending so we should be at the end of file.
+ * The ftell() will give use the length of the file */
+ len = ftell(f);
+ if (len > path->index) {
+ /* override previous cache records on this location */
+ fseek(f, path->index, SEEK_SET);
+ } else if (path->index > len) {
+ /* We miss some bytes so we will not cache this chunk */
+ return 0;
+ }
+
c = fwrite(buf, 1, bufsize, f);
fclose(f);
if (c != bufsize) {
- sc_log(p15card->card->ctx,
+ sc_log(p15card->card->ctx,
"fwrite() wrote only %"SC_FORMAT_LEN_SIZE_T"u bytes",
c);
unlink(fname);
From 0875c69295ef28b45fb682b37cede58fc36b7a1a Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@redhat.com>
Date: Fri, 15 Sep 2023 19:17:53 +0200
Subject: [PATCH] pkcs15-cache: Avoid fd leaks and check return values
CID 401725
CID 401726
Thanks coverity
---
src/libopensc/pkcs15-cache.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/libopensc/pkcs15-cache.c b/src/libopensc/pkcs15-cache.c
index 61af35fc5a..bae5797fe2 100644
--- a/src/libopensc/pkcs15-cache.c
+++ b/src/libopensc/pkcs15-cache.c
@@ -220,9 +220,14 @@ int sc_pkcs15_cache_file(struct sc_pkcs15_card *p15card,
len = ftell(f);
if (len > path->index) {
/* override previous cache records on this location */
- fseek(f, path->index, SEEK_SET);
+ r = fseek(f, path->index, SEEK_SET);
+ if (r != 0) {
+ fclose(f);
+ return 0;
+ }
} else if (path->index > len) {
/* We miss some bytes so we will not cache this chunk */
+ fclose(f);
return 0;
}

View File

@ -1,485 +0,0 @@
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 5153428dc..9ecbffe8f 100644
--- a/src/common/Makefile.am
+++ b/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
+noinst_HEADERS = compat_strlcat.h compat_strlcpy.h compat_strnlen.h compat_getpass.h \
+ compat_getopt.h simclist.h libpkcs11.h libscdl.h constant-time.h
AM_CPPFLAGS = -I$(top_srcdir)/src
@@ -43,7 +44,8 @@ TIDY_FILES = \
compat_report_rangecheckfailure.c \
compat___iob_func.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='' -header-filter=.* $(TIDY_FILES) -- $(TIDY_FLAGS); fi
diff --git a/src/common/constant-time.h b/src/common/constant-time.h
new file mode 100644
index 0000000000..40c3e500c2
--- /dev/null
+++ b/src/common/constant-time.h
@@ -0,0 +1,134 @@
+/* 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);
+}
+
+static constant_inline unsigned int
+constant_time_eq_i(int a, int b)
+{
+ return constant_time_eq((unsigned int)a, (unsigned int)b);
+}
+
+#endif /* CONSTANT_TIME_H */
diff --git a/src/libopensc/internal.h b/src/libopensc/internal.h
index 74014235a..13eccfa1a 100644
--- a/src/libopensc/internal.h
+++ b/src/libopensc/internal.h
@@ -168,6 +168,8 @@ int sc_pkcs1_strip_01_padding(struct sc_context *ctx, const u8 *in_dat, size_t i
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);
diff --git a/src/libopensc/padding.c b/src/libopensc/padding.c
index ca47733a4e..ddb3061134 100644
--- a/src/libopensc/padding.c
+++ b/src/libopensc/padding.c
@@ -32,10 +32,13 @@
#include <string.h>
#include <stdlib.h>
+#include "common/constant-time.h"
#include "internal.h"
/* TODO doxygen comments */
+#define SC_PKCS1_PADDING_MIN_SIZE 11
+
/*
* Prefixes for pkcs-v1 signatures
*/
@@ -144,44 +147,82 @@ sc_pkcs1_strip_01_padding(struct sc_cont
}
-/* 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);
}
/* add/remove DigestInfo prefix */
diff --git a/src/libopensc/pkcs15-sec.c b/src/libopensc/pkcs15-sec.c
index a019af460f..f7ee819d65 100644
--- a/src/libopensc/pkcs15-sec.c
+++ b/src/libopensc/pkcs15-sec.c
@@ -286,12 +286,14 @@ 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 */
}
- 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
diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c
index f75a3dbaec..632681df63 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>
@@ -4174,7 +4175,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;
sc_log(context, "Initiating decryption.");
@@ -4246,27 +4248,54 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_se
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)
+ /* Handle following code in constant-time
return sc_to_cryptoki_error(rv, "C_Decrypt");
+ * 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);
-
- return CKR_OK;
+ /* only padding error must be handled in constant-time way,
+ * other error can be returned straight away */
+ if ((~constant_time_eq_i(rv, SC_ERROR_WRONG_PADDING) & constant_time_lt_s(sizeof(decrypted), (size_t)rv)))
+ return sc_to_cryptoki_error(rv, "C_Decrypt");
+
+ /* check rv for padding error */
+ good = ~constant_time_eq_i(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;
}
diff --git a/src/pkcs11/mechanism.c b/src/pkcs11/mechanism.c
index 03495265a4..d3f0434231 100644
--- a/src/pkcs11/mechanism.c
+++ b/src/pkcs11/mechanism.c
@@ -23,6 +23,7 @@
#include <stdlib.h>
#include <string.h>
+#include "common/constant-time.h"
#include "sc-pkcs11.h"
/* Also used for verification data */
@@ -1089,7 +1090,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;
diff --git a/src/pkcs11/pkcs11-object.c b/src/pkcs11/pkcs11-object.c
index f04c0b4c56..b023911213 100644
--- a/src/pkcs11/pkcs11-object.c
+++ b/src/pkcs11/pkcs11-object.c
@@ -926,7 +926,8 @@ CK_RV C_Decrypt(CK_SESSION_HANDLE hSessi
rv = reset_login_state(session->slot, rv);
}
- sc_log(context, "C_Decrypt() = %s", lookup_enum ( RV_T, rv ));
+ /* do not log error code to prevent side channel attack */
+ sc_log(context, "C_Decrypt() finished");
sc_pkcs11_unlock();
return rv;
}
diff --git a/src/pkcs11/misc.c b/src/pkcs11/misc.c
index 5ca1176b1d..1d893d6181 100644
--- a/src/pkcs11/misc.c
+++ b/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 *slot, CK_RV rv)
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);
}

View File

@ -1,107 +0,0 @@
From 868f76fb31255fd3fdacfc3e476452efeb61c3e7 Mon Sep 17 00:00:00 2001
From: Frank Morgner <frankmorgner@gmail.com>
Date: Wed, 21 Jun 2023 12:27:23 +0200
Subject: [PATCH] Fixed PIN authentication bypass
If two processes are accessing a token, then one process may leave the
card usable with an authenticated PIN so that a key may sign/decrypt any
data. This is especially the case if the token does not support a way of
resetting the authentication status (logout).
We have some tracking of the authentication status in software via
PKCS#11, Minidriver (os-wise) and CryptoTokenKit, which is why a
PIN-prompt will appear even though the card may technically be unlocked
as described in the above example. However, before this change, an empty
PIN was not verified (likely yielding an error during PIN-verification),
but it was just checked whether the PIN is authenticated. This defeats
the purpose of the PIN verification, because an empty PIN is not the
correct one. Especially during OS Logon, we don't want that kind of
shortcut, but we want the user to verify the correct PIN (even though
the token was left unattended and authentication at the computer).
This essentially reverts commit e6f7373ef066cfab6e3162e8b5f692683db23864.
---
src/libopensc/pkcs15-pin.c | 13 -------------
1 file changed, 13 deletions(-)
diff --git a/src/libopensc/pkcs15-pin.c b/src/libopensc/pkcs15-pin.c
index 80a185fecd..393234efe4 100644
--- a/src/libopensc/pkcs15-pin.c
+++ b/src/libopensc/pkcs15-pin.c
@@ -307,19 +307,6 @@ sc_pkcs15_verify_pin(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *pi
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_PIN_REFERENCE);
auth_info = (struct sc_pkcs15_auth_info *)pin_obj->data;
- /*
- * if pin cache is disabled, we can get here with no PIN data.
- * in this case, to avoid error or unnecessary pin prompting on pinpad,
- * check if the PIN has been already verified and the access condition
- * is still open on card.
- */
- if (pinlen == 0) {
- r = sc_pkcs15_get_pin_info(p15card, pin_obj);
-
- if (r == SC_SUCCESS && auth_info->logged_in == SC_PIN_STATE_LOGGED_IN)
- LOG_FUNC_RETURN(ctx, r);
- }
-
r = _validate_pin(p15card, auth_info, pinlen);
if (r)
From 80cc5d30635f0d2c92b5099c0f9dc680d0ffce2f Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@redhat.com>
Date: Tue, 24 Oct 2023 11:13:08 +0200
Subject: [PATCH] pkcs15init: Check login status before asking for a pin
The original code block from e6f7373 is still needed when pkcs15init
layer checks ACLs for PKCS#15 objects, but it should be kept out of
the libopensc, which is used for more authentication code paths
and can be used for PIN bypass.
---
src/libopensc/pkcs15-pin.c | 1 +
src/pkcs15init/pkcs15-lib.c | 16 ++++++++++++++++
2 files changed, 17 insertions(+)
diff --git a/src/libopensc/pkcs15-pin.c b/src/libopensc/pkcs15-pin.c
index 393234efe..b26e57236 100644
--- a/src/libopensc/pkcs15-pin.c
+++ b/src/libopensc/pkcs15-pin.c
@@ -307,6 +307,7 @@ sc_pkcs15_verify_pin(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *pi
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_PIN_REFERENCE);
auth_info = (struct sc_pkcs15_auth_info *)pin_obj->data;
+ /* Check the provided pin matches pin requirements */
r = _validate_pin(p15card, auth_info, pinlen);
if (r)
diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c
index 9148b83b5..cca11d1f1 100644
--- a/src/pkcs15init/pkcs15-lib.c
+++ b/src/pkcs15init/pkcs15-lib.c
@@ -3958,6 +3958,22 @@ sc_pkcs15init_verify_secret(struct sc_profile *profile, struct sc_pkcs15_card *p
found:
if (pin_obj) {
+ /*
+ * If pin cache is disabled or the reader is using pinpad, we can get here
+ * with no PIN data. This is ok as we can not asynchronously invoke the prompt
+ * (unless the pinpad is in use).
+ * In this case, check if the PIN has been already verified and
+ * the access condition is still open on card.
+ */
+ if (pinsize == 0) {
+ r = sc_pkcs15_get_pin_info(p15card, pin_obj);
+ /* update local copy of auth info */
+ memcpy(&auth_info, pin_obj->data, sizeof(auth_info));
+
+ if (r == SC_SUCCESS && auth_info.logged_in == SC_PIN_STATE_LOGGED_IN)
+ LOG_FUNC_RETURN(ctx, r);
+ }
+
r = sc_pkcs15_verify_pin(p15card, pin_obj, use_pinpad || pinsize == 0 ? NULL : pinbuf, use_pinpad ? 0 : pinsize);
LOG_TEST_RET(ctx, r, "Cannot validate pkcs15 PIN");
}
--
2.43.0

View File

@ -1,855 +0,0 @@
From 245efe608d083fd4e4ec96793fdefd218e26fde7 Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@redhat.com>
Date: Thu, 17 Aug 2023 13:54:42 +0200
Subject: [PATCH] pkcs15: Avoid buffer overflow when getting last update
Thanks oss-fuzz
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=60769
---
src/libopensc/pkcs15.c | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c
index eb7fc6afc..4215b733a 100644
--- a/src/libopensc/pkcs15.c
+++ b/src/libopensc/pkcs15.c
@@ -532,7 +532,7 @@ sc_pkcs15_get_lastupdate(struct sc_pkcs15_card *p15card)
struct sc_context *ctx = p15card->card->ctx;
struct sc_file *file = NULL;
struct sc_asn1_entry asn1_last_update[C_ASN1_LAST_UPDATE_SIZE];
- unsigned char *content, last_update[32];
+ unsigned char *content, last_update[32] = {0};
size_t lupdate_len = sizeof(last_update) - 1;
int r, content_len;
size_t size;
@@ -569,9 +569,11 @@ sc_pkcs15_get_lastupdate(struct sc_pkcs15_card *p15card)
if (r < 0)
return NULL;
- p15card->tokeninfo->last_update.gtime = strdup((char *)last_update);
- if (!p15card->tokeninfo->last_update.gtime)
- return NULL;
+ if (asn1_last_update[0].flags & SC_ASN1_PRESENT) {
+ p15card->tokeninfo->last_update.gtime = strdup((char *)last_update);
+ if (!p15card->tokeninfo->last_update.gtime)
+ return NULL;
+ }
done:
sc_log(ctx, "lastUpdate.gtime '%s'", p15card->tokeninfo->last_update.gtime);
return p15card->tokeninfo->last_update.gtime;
2.41.0
From 440ca666eff10cc7011901252d20f3fc4ea23651 Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@redhat.com>
Date: Thu, 17 Aug 2023 13:41:36 +0200
Subject: [PATCH] setcos: Avoid buffer underflow
Thanks oss-fuzz
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=60672
---
src/pkcs15init/pkcs15-setcos.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/pkcs15init/pkcs15-setcos.c b/src/pkcs15init/pkcs15-setcos.c
index 1b56afe6d..1907b47f9 100644
--- a/src/pkcs15init/pkcs15-setcos.c
+++ b/src/pkcs15init/pkcs15-setcos.c
@@ -349,6 +349,10 @@ setcos_create_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
/* Replace the path of instantiated key template by the path from the object data. */
memcpy(&file->path, &key_info->path, sizeof(file->path));
+ if (file->path.len < 2) {
+ sc_file_free(file);
+ LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "Invalid path");
+ }
file->id = file->path.value[file->path.len - 2] * 0x100
+ file->path.value[file->path.len - 1];
--
2.41.0
From 41d61da8481582e12710b5858f8b635e0a71ab5e Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@redhat.com>
Date: Wed, 20 Sep 2023 10:13:57 +0200
Subject: [PATCH] oberthur: Avoid buffer overflow
Thanks oss-fuzz
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=60650
---
src/pkcs15init/pkcs15-oberthur.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/pkcs15init/pkcs15-oberthur.c b/src/pkcs15init/pkcs15-oberthur.c
index ad2cabd53..c441ab1e7 100644
--- a/src/pkcs15init/pkcs15-oberthur.c
+++ b/src/pkcs15init/pkcs15-oberthur.c
@@ -715,6 +715,9 @@ cosm_create_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
if (object->type != SC_PKCS15_TYPE_PRKEY_RSA)
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Create key failed: RSA only supported");
+ if (key_info->path.len < 2)
+ LOG_TEST_RET(ctx, SC_ERROR_OBJECT_NOT_VALID, "The path needs to be at least to bytes long");
+
sc_log(ctx, "create private key ID:%s", sc_pkcs15_print_id(&key_info->id));
/* Here, the path of private key file should be defined.
* Nevertheless, we need to instantiate private key to get the ACLs. */
--
2.41.0
From 88880db0307a07e33cf2e1592bb029e9c170dfea Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= <vhanulik@redhat.com>
Date: Wed, 21 Jun 2023 15:48:27 +0200
Subject: [PATCH] pkcs15-pubkey: free DER value when parsing public key fails
The der value might be allocated in asn1_decode_entry()
but it is not released when errror occurs.
Thanks OSS-Fuzz
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=59615
---
src/libopensc/pkcs15-pubkey.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c
index 4a0ddffbe..7107c47cb 100644
--- a/src/libopensc/pkcs15-pubkey.c
+++ b/src/libopensc/pkcs15-pubkey.c
@@ -351,6 +351,8 @@ int sc_pkcs15_decode_pukdf_entry(struct sc_pkcs15_card *p15card,
err:
if (r < 0) {
sc_pkcs15_free_pubkey_info(info);
+ if (der->len)
+ free(der->value);
}
LOG_FUNC_RETURN(ctx, r);
--
2.41.0
From 638a5007a5d240d6fa901aa822cfeef94fe36e85 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= <vhanulik@redhat.com>
Date: Thu, 10 Aug 2023 12:20:33 +0200
Subject: [PATCH] pkcs15-pubkey.c: Avoid double-free
Thanks OSS-Fuzz
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=60616
---
src/libopensc/pkcs15-pubkey.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c
index 7107c47cb..49b514968 100644
--- a/src/libopensc/pkcs15-pubkey.c
+++ b/src/libopensc/pkcs15-pubkey.c
@@ -351,8 +351,12 @@ int sc_pkcs15_decode_pukdf_entry(struct sc_pkcs15_card *p15card,
err:
if (r < 0) {
sc_pkcs15_free_pubkey_info(info);
- if (der->len)
+ if (der->len) {
free(der->value);
+ /* der points to obj->content */
+ obj->content.value = NULL;
+ obj->content.len = 0;
+ }
}
LOG_FUNC_RETURN(ctx, r);
--
2.41.0
From c449a181a6988cc1e8dc8764d23574e48cdc3fa6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= <vhanulik@redhat.com>
Date: Mon, 19 Jun 2023 16:14:51 +0200
Subject: [PATCH] pkcs15-cflex: check path length to prevent underflow
Thanks OSS-Fuzz
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=58932
---
src/pkcs15init/pkcs15-cflex.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/pkcs15init/pkcs15-cflex.c b/src/pkcs15init/pkcs15-cflex.c
index d06568073..ce1d48e62 100644
--- a/src/pkcs15init/pkcs15-cflex.c
+++ b/src/pkcs15init/pkcs15-cflex.c
@@ -56,6 +56,9 @@ cflex_delete_file(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t *d
int r = 0;
/* Select the parent DF */
path = df->path;
+ if (path.len < 2) {
+ return SC_ERROR_INVALID_ARGUMENTS;
+ }
path.len -= 2;
r = sc_select_file(p15card->card, &path, &parent);
if (r < 0)
--
2.41.0
From 5631e9843c832a99769def85b7b9b68b4e3e3959 Mon Sep 17 00:00:00 2001
From: Veronika Hanulikova <xhanulik@fi.muni.cz>
Date: Fri, 3 Mar 2023 16:07:38 +0100
Subject: [PATCH] Check length of string before making copy
Thanks OSS-Fuzz
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=55851
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=55998
---
src/pkcs15init/profile.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/pkcs15init/profile.c b/src/pkcs15init/profile.c
index 2b793b028..3bad1e853 100644
--- a/src/pkcs15init/profile.c
+++ b/src/pkcs15init/profile.c
@@ -1575,7 +1575,10 @@ do_acl(struct state *cur, int argc, char **argv)
while (argc--) {
unsigned int op, method, id;
+ if (strlen(*argv) >= sizeof(oper))
+ goto bad;
strlcpy(oper, *argv++, sizeof(oper));
+
if ((what = strchr(oper, '=')) == NULL)
goto bad;
*what++ = '\0';
@@ -2288,6 +2291,9 @@ get_authid(struct state *cur, const char *value,
return get_uint(cur, value, type);
}
+ if (strlen(value) >= sizeof(temp))
+ return 1;
+
n = strcspn(value, "0123456789x");
strlcpy(temp, value, (sizeof(temp) > n) ? n + 1 : sizeof(temp));
--
2.41.0
From e7f81d86dcdc751f4737f4b29a99bfc54d29c5c9 Mon Sep 17 00:00:00 2001
From: Frank Morgner <frankmorgner@gmail.com>
Date: Thu, 8 Dec 2022 00:45:31 +0100
Subject: [PATCH] muscle: prevent out of bounds write
fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=53631
---
src/libopensc/muscle.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/libopensc/muscle.c b/src/libopensc/muscle.c
index 7af279a0a..61a4ec24d 100644
--- a/src/libopensc/muscle.c
+++ b/src/libopensc/muscle.c
@@ -127,7 +127,7 @@ int msc_zero_object(sc_card_t *card, msc_id objectId, size_t dataLength)
{
u8 zeroBuffer[MSC_MAX_APDU];
size_t i;
- size_t max_write_unit = MSC_MAX_SEND - 9; /* - 9 for object ID+length */
+ size_t max_write_unit = MIN(MSC_MAX_APDU, MSC_MAX_SEND - 9); /* - 9 for object ID+length */
memset(zeroBuffer, 0, max_write_unit);
for(i = 0; i < dataLength; i += max_write_unit) {
--
2.41.0
From df5a176bfdf8c52ba89c7fef1f82f6f3b9312bc1 Mon Sep 17 00:00:00 2001
From: Veronika Hanulikova <xhanulik@fi.muni.cz>
Date: Fri, 10 Feb 2023 11:47:34 +0100
Subject: [PATCH] Check array bounds
Thanks OSS-Fuzz
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=54312
---
src/libopensc/muscle.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/libopensc/muscle.c b/src/libopensc/muscle.c
index 61a4ec24d..9d01e0c11 100644
--- a/src/libopensc/muscle.c
+++ b/src/libopensc/muscle.c
@@ -181,6 +181,9 @@ int msc_partial_update_object(sc_card_t *card, msc_id objectId, int offset, cons
sc_apdu_t apdu;
int r;
+ if (dataLength + 9 > MSC_MAX_APDU)
+ return SC_ERROR_INVALID_ARGUMENTS;
+
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x54, 0x00, 0x00);
apdu.lc = dataLength + 9;
if (card->ctx->debug >= 2)
--
2.41.0
From 578aed8391ef117ca64a9e0cba8e5c264368a0ec Mon Sep 17 00:00:00 2001
From: Frank Morgner <frankmorgner@gmail.com>
Date: Thu, 8 Dec 2022 00:27:18 +0100
Subject: [PATCH] sc_pkcs15init_rmdir: prevent out of bounds write
fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=53927
---
src/pkcs15init/pkcs15-lib.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c
index 91cee3731..3df03c6e1 100644
--- a/src/pkcs15init/pkcs15-lib.c
+++ b/src/pkcs15init/pkcs15-lib.c
@@ -685,6 +685,8 @@ sc_pkcs15init_rmdir(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
path = df->path;
path.len += 2;
+ if (path.len > SC_MAX_PATH_SIZE)
+ return SC_ERROR_INTERNAL;
nfids = r / 2;
while (r >= 0 && nfids--) {
--
2.41.0
From 4013a807492568bf9907cfb3df41f130ac83c7b9 Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@redhat.com>
Date: Wed, 15 Nov 2023 10:53:46 +0100
Subject: [PATCH] setcos: Avoid writing behind the path buffer end
The path->value buffer is fixed to 16 bytes so it is not always possible
to append 2 more bytes. Doing so overruns the buffer, writing into the
ACL block, crashing during the cleanup.
Thanks oss-fuzz
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=64181
---
src/pkcs15init/pkcs15-setcos.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/pkcs15init/pkcs15-setcos.c b/src/pkcs15init/pkcs15-setcos.c
index 70a28048b..1eeeda064 100644
--- a/src/pkcs15init/pkcs15-setcos.c
+++ b/src/pkcs15init/pkcs15-setcos.c
@@ -287,6 +287,10 @@ setcos_new_file(sc_profile_t *profile, sc_card_t *card,
file->id += num;
p = &file->path;
*p = profile->df_info->file->path;
+ if (p->len + 2 > SC_MAX_PATH_SIZE) {
+ sc_file_free(file);
+ return SC_ERROR_INVALID_DATA;
+ }
p->value[p->len++] = (u8) (file->id / 256);
p->value[p->len++] = (u8) (file->id % 256);
--
2.42.0
From 8fc2c20c3f895569eeb58328bb882aec07325d3b Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@redhat.com>
Date: Tue, 7 Nov 2023 17:48:27 +0100
Subject: [PATCH] iasecc: Avoid another buffer overflow
thanks oss-fuzz
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=63949
---
src/libopensc/iasecc-sdo.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/libopensc/iasecc-sdo.c b/src/libopensc/iasecc-sdo.c
index a41c3c2d3..86032f5a8 100644
--- a/src/libopensc/iasecc-sdo.c
+++ b/src/libopensc/iasecc-sdo.c
@@ -44,7 +44,8 @@ iasecc_parse_acls(struct sc_card *card, struct iasecc_sdo_docp *docp, int flags)
{
struct sc_context *ctx = card->ctx;
struct iasecc_extended_tlv *acls = &docp->acls_contact;
- int ii, offs;
+ int ii;
+ size_t offs;
unsigned char mask = 0x40;
if (flags)
@@ -56,8 +57,12 @@ iasecc_parse_acls(struct sc_card *card, struct iasecc_sdo_docp *docp, int flags)
docp->amb = *(acls->value + 0);
memset(docp->scbs, 0xFF, sizeof(docp->scbs));
for (ii=0, offs = 1; ii<7; ii++, mask >>= 1)
- if (mask & docp->amb)
+ if (mask & docp->amb) {
+ if (offs >= acls->size) {
+ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
+ }
docp->scbs[ii] = *(acls->value + offs++);
+ }
sc_log(ctx, "iasecc_parse_docp() SCBs %02X:%02X:%02X:%02X:%02X:%02X:%02X",
docp->scbs[0],docp->scbs[1],docp->scbs[2],docp->scbs[3],
--
2.42.0
From 83b9129bd3cfc6ac57d5554e015c3df85f5076dc Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@redhat.com>
Date: Wed, 11 Oct 2023 08:57:45 +0200
Subject: [PATCH] iassecc: Verify buffer lengths before use
Thanks oss-fuzz
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=63163
---
src/libopensc/iasecc-sdo.c | 55 +++++++++++++++++++++-----------------
1 file changed, 31 insertions(+), 24 deletions(-)
diff --git a/src/libopensc/iasecc-sdo.c b/src/libopensc/iasecc-sdo.c
index 3eeb03b91..a6e6c2677 100644
--- a/src/libopensc/iasecc-sdo.c
+++ b/src/libopensc/iasecc-sdo.c
@@ -36,7 +36,7 @@
#include "iasecc.h"
#include "iasecc-sdo.h"
-static int iasecc_parse_size(unsigned char *data, size_t *out);
+static int iasecc_parse_size(unsigned char *data, size_t data_len, size_t *out);
static int
@@ -330,7 +330,7 @@ iasecc_se_parse(struct sc_card *card, unsigned char *data, size_t data_len, stru
LOG_FUNC_CALLED(ctx);
if (*data == IASECC_SDO_TEMPLATE_TAG) {
- size_size = iasecc_parse_size(data + 1, &size);
+ 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");
data += size_size + 1;
@@ -345,7 +345,7 @@ iasecc_se_parse(struct sc_card *card, unsigned char *data, size_t data_len, stru
if ((*(data + 1) & 0x7F) != IASECC_SDO_CLASS_SE)
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
- size_size = iasecc_parse_size(data + 3, &size);
+ size_size = iasecc_parse_size(data + 3, data_len - 3, &size);
LOG_TEST_RET(ctx, size_size, "parse error: invalid SDO SE data size");
if (data_len != size + size_size + 3)
@@ -365,7 +365,7 @@ iasecc_se_parse(struct sc_card *card, unsigned char *data, size_t data_len, stru
LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
}
- size_size = iasecc_parse_size(data + 1, &size);
+ size_size = iasecc_parse_size(data + 1, data_len - 1, &size);
LOG_TEST_RET(ctx, size_size, "parse error: invalid size data");
if (data_len != size + size_size + 1)
@@ -387,17 +387,17 @@ iasecc_se_parse(struct sc_card *card, unsigned char *data, size_t data_len, stru
static int
-iasecc_parse_size(unsigned char *data, size_t *out)
+iasecc_parse_size(unsigned char *data, size_t data_len, size_t *out)
{
- if (*data < 0x80) {
+ if (*data < 0x80 && data_len > 0) {
*out = *data;
return 1;
}
- else if (*data == 0x81) {
+ else if (*data == 0x81 && data_len > 1) {
*out = *(data + 1);
return 2;
}
- else if (*data == 0x82) {
+ else if (*data == 0x82 && data_len > 2) {
*out = *(data + 1) * 0x100 + *(data + 2);
return 3;
}
@@ -407,14 +407,18 @@ iasecc_parse_size(unsigned char *data, size_t *out)
static int
-iasecc_parse_get_tlv(struct sc_card *card, unsigned char *data, struct iasecc_extended_tlv *tlv)
+iasecc_parse_get_tlv(struct sc_card *card, unsigned char *data, size_t data_len, struct iasecc_extended_tlv *tlv)
{
struct sc_context *ctx = card->ctx;
size_t size_len, tag_len;
memset(tlv, 0, sizeof(*tlv));
sc_log(ctx, "iasecc_parse_get_tlv() called for tag 0x%X", *data);
+ if (data_len < 1)
+ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
if ((*data == 0x7F) || (*data == 0x5F)) {
+ if (data_len < 2)
+ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
tlv->tag = *data * 0x100 + *(data + 1);
tag_len = 2;
}
@@ -424,8 +428,11 @@ iasecc_parse_get_tlv(struct sc_card *card, unsigned char *data, struct iasecc_ex
}
sc_log(ctx, "iasecc_parse_get_tlv() tlv->tag 0x%X", tlv->tag);
- size_len = iasecc_parse_size(data + tag_len, &tlv->size);
+ size_len = iasecc_parse_size(data + tag_len, data_len - tag_len, &tlv->size);
LOG_TEST_RET(ctx, size_len, "parse error: invalid size data");
+ if (tag_len + size_len + tlv->size > data_len) {
+ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
+ }
tlv->value = calloc(1, tlv->size);
if (!tlv->value)
@@ -452,7 +459,7 @@ iasecc_parse_chv(struct sc_card *card, unsigned char *data, size_t data_len, str
while(offs < data_len) {
struct iasecc_extended_tlv tlv;
- rv = iasecc_parse_get_tlv(card, data + offs, &tlv);
+ rv = iasecc_parse_get_tlv(card, data + offs, data_len - offs, &tlv);
LOG_TEST_RET(ctx, rv, "iasecc_parse_chv() get and parse TLV error");
sc_log(ctx,
@@ -486,7 +493,7 @@ iasecc_parse_prvkey(struct sc_card *card, unsigned char *data, size_t data_len,
while(offs < data_len) {
struct iasecc_extended_tlv tlv;
- rv = iasecc_parse_get_tlv(card, data + offs, &tlv);
+ rv = iasecc_parse_get_tlv(card, data + offs, data_len - offs, &tlv);
LOG_TEST_RET(ctx, rv, "iasecc_parse_prvkey() get and parse TLV error");
sc_log(ctx,
@@ -516,7 +523,7 @@ iasecc_parse_pubkey(struct sc_card *card, unsigned char *data, size_t data_len,
while(offs < data_len) {
struct iasecc_extended_tlv tlv;
- rv = iasecc_parse_get_tlv(card, data + offs, &tlv);
+ rv = iasecc_parse_get_tlv(card, data + offs, data_len - offs, &tlv);
LOG_TEST_RET(ctx, rv, "iasecc_parse_pubkey() get and parse TLV error");
sc_log(ctx,
@@ -554,7 +561,7 @@ iasecc_parse_keyset(struct sc_card *card, unsigned char *data, size_t data_len,
while(offs < data_len) {
struct iasecc_extended_tlv tlv;
- rv = iasecc_parse_get_tlv(card, data + offs, &tlv);
+ rv = iasecc_parse_get_tlv(card, data + offs, data_len - offs, &tlv);
LOG_TEST_RET(ctx, rv, "iasecc_parse_keyset() get and parse TLV error");
sc_log(ctx,
@@ -586,7 +593,7 @@ iasecc_parse_docp(struct sc_card *card, unsigned char *data, size_t data_len, st
while(offs < data_len) {
struct iasecc_extended_tlv tlv;
- rv = iasecc_parse_get_tlv(card, data + offs, &tlv);
+ rv = iasecc_parse_get_tlv(card, data + offs, data_len - offs, &tlv);
LOG_TEST_RET(ctx, rv, "iasecc_parse_get_tlv() get and parse TLV error");
sc_log(ctx,
@@ -641,7 +648,7 @@ iasecc_parse_docp(struct sc_card *card, unsigned char *data, size_t data_len, st
static int
-iasecc_sdo_parse_data(struct sc_card *card, unsigned char *data, struct iasecc_sdo *sdo)
+iasecc_sdo_parse_data(struct sc_card *card, unsigned char *data, size_t data_len, struct iasecc_sdo *sdo)
{
struct sc_context *ctx = card->ctx;
struct iasecc_extended_tlv tlv;
@@ -650,7 +657,7 @@ iasecc_sdo_parse_data(struct sc_card *card, unsigned char *data, struct iasecc_s
LOG_FUNC_CALLED(ctx);
sc_log(ctx, "iasecc_sdo_parse_data() class %X; ref %X", sdo->sdo_class, sdo->sdo_ref);
- tlv_size = iasecc_parse_get_tlv(card, data, &tlv);
+ tlv_size = iasecc_parse_get_tlv(card, data, data_len, &tlv);
LOG_TEST_RET(ctx, tlv_size, "parse error: get TLV");
sc_log(ctx, "iasecc_sdo_parse_data() tlv.tag 0x%X", tlv.tag);
@@ -735,7 +742,7 @@ iasecc_sdo_parse(struct sc_card *card, unsigned char *data, size_t data_len, str
LOG_FUNC_CALLED(ctx);
if (*data == IASECC_SDO_TEMPLATE_TAG) {
- size_size = iasecc_parse_size(data + 1, &size);
+ 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");
data += size_size + 1;
@@ -754,7 +761,7 @@ iasecc_sdo_parse(struct sc_card *card, unsigned char *data, size_t data_len, str
if (sdo->sdo_ref != (*(data + 2) & 0x3F))
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
- size_size = iasecc_parse_size(data + 3, &size);
+ size_size = iasecc_parse_size(data + 3, data_len - 3, &size);
LOG_TEST_RET(ctx, size_size, "parse error: invalid size data");
if (data_len != size + size_size + 3)
@@ -766,7 +773,7 @@ iasecc_sdo_parse(struct sc_card *card, unsigned char *data, size_t data_len, str
offs = 3 + size_size;
for (; offs < data_len;) {
- rv = iasecc_sdo_parse_data(card, data + offs, sdo);
+ rv = iasecc_sdo_parse_data(card, data + offs, data_len - offs, sdo);
LOG_TEST_RET(ctx, rv, "parse error: invalid SDO data");
offs += rv;
@@ -812,7 +819,7 @@ iasecc_sdo_allocate_and_parse(struct sc_card *card, unsigned char *data, size_t
if (data_len == 3)
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
- size_size = iasecc_parse_size(data + 3, &size);
+ size_size = iasecc_parse_size(data + 3, data_len - 3, &size);
LOG_TEST_RET(ctx, size_size, "parse error: invalid size data");
if (data_len != size + size_size + 3)
@@ -824,7 +831,7 @@ iasecc_sdo_allocate_and_parse(struct sc_card *card, unsigned char *data, size_t
offs = 3 + size_size;
for (; offs < data_len;) {
- rv = iasecc_sdo_parse_data(card, data + offs, sdo);
+ rv = iasecc_sdo_parse_data(card, data + offs, data_len - offs, sdo);
LOG_TEST_RET(ctx, rv, "parse error: invalid SDO data");
offs += rv;
@@ -1222,7 +1229,7 @@ iasecc_sdo_parse_card_answer(struct sc_context *ctx, unsigned char *data, size_t
memset(out, 0, sizeof(*out));
for (offs=0; offs<data_len; ) {
- size_size = iasecc_parse_size(data + 1, &size);
+ size_size = iasecc_parse_size(data + 1, data_len - 1, &size);
if (*(data + offs) == IASECC_CARD_ANSWER_TAG_DATA ) {
if (size > sizeof(out->data))
@@ -1293,7 +1300,7 @@ iasecc_docp_copy(struct sc_context *ctx, struct iasecc_sdo_docp *in, struct iase
int rv;
LOG_FUNC_CALLED(ctx);
- if (!in || !out)
+ if (!in || !out)
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
memset(out, 0, sizeof(struct iasecc_sdo_docp));
--
2.42.0
From fbda61d0d276dc98b9d1d1e6810bbd21d19e3859 Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@redhat.com>
Date: Fri, 27 Oct 2023 13:23:18 +0200
Subject: [PATCH] iasecc: Avoid buffer overflow with invalid data
Thanks oss-fuzz
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=63587
---
src/libopensc/iasecc-sdo.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/libopensc/iasecc-sdo.c b/src/libopensc/iasecc-sdo.c
index 1e01c0df5..479b3c23b 100644
--- a/src/libopensc/iasecc-sdo.c
+++ b/src/libopensc/iasecc-sdo.c
@@ -371,15 +371,15 @@ iasecc_se_parse(struct sc_card *card, unsigned char *data, size_t data_len, stru
static int
iasecc_parse_size(unsigned char *data, size_t data_len, size_t *out)
{
- if (*data < 0x80 && data_len > 0) {
+ if (data_len > 0 && *data < 0x80) {
*out = *data;
return 1;
}
- else if (*data == 0x81 && data_len > 1) {
+ else if (data_len > 1 && *data == 0x81) {
*out = *(data + 1);
return 2;
}
- else if (*data == 0x82 && data_len > 2) {
+ else if (data_len > 2 && *data == 0x82) {
*out = *(data + 1) * 0x100 + *(data + 2);
return 3;
}
--
2.42.0
From 2a4921ab23fd0853f327517636c50de947548161 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= <vhanulik@redhat.com>
Date: Tue, 29 Aug 2023 14:40:21 +0200
Subject: [PATCH] iasecc: Check length of data when parsing crt
Thanks OSS-Fuzz
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=61797
---
src/libopensc/iasecc-sdo.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/libopensc/iasecc-sdo.c b/src/libopensc/iasecc-sdo.c
index b3e567dd5..3eeb03b91 100644
--- a/src/libopensc/iasecc-sdo.c
+++ b/src/libopensc/iasecc-sdo.c
@@ -204,7 +204,7 @@ iasecc_sdo_free(struct sc_card *card, struct iasecc_sdo *sdo)
static int
-iasecc_crt_parse(struct sc_card *card, unsigned char *data, struct iasecc_se_info *se)
+iasecc_crt_parse(struct sc_card *card, unsigned char *data, size_t data_len, struct iasecc_se_info *se)
{
struct sc_context *ctx = card->ctx;
struct sc_crt crt;
@@ -212,11 +212,16 @@ iasecc_crt_parse(struct sc_card *card, unsigned char *data, struct iasecc_se_inf
sc_log(ctx, "iasecc_crt_parse(0x%X) called", *data);
+ if (data_len < 2)
+ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
+
memset(&crt, 0, sizeof(crt));
crt.tag = *(data + 0);
len = *(data + 1);
for(offs = 2; offs < len + 2; offs += 3) {
+ if ((size_t) offs + 2 >= data_len)
+ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
sc_log(ctx, "iasecc_crt_parse(0x%X) CRT %X -> %X", *data, *(data + offs), *(data + offs + 2));
if (*(data + offs) == IASECC_CRT_TAG_USAGE) {
crt.usage = *(data + offs + 2);
@@ -368,7 +373,7 @@ iasecc_se_parse(struct sc_card *card, unsigned char *data, size_t data_len, stru
offs = 1 + size_size;
for (; offs < data_len;) {
- rv = iasecc_crt_parse(card, data + offs, se);
+ rv = iasecc_crt_parse(card, data + offs, data_len - offs, se);
LOG_TEST_RET(ctx, rv, "parse error: invalid SE data");
offs += rv;
--
2.42.0
From 6085994384a7171c5c68f6718d9db10ed77c5af1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= <vhanulik@redhat.com>
Date: Thu, 10 Aug 2023 13:56:24 +0200
Subject: [PATCH] card-entersafe.c: Free modulus buffer in case of error
Thanks OSS-Fuzz
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=60680
---
src/libopensc/card-entersafe.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/src/libopensc/card-entersafe.c b/src/libopensc/card-entersafe.c
index eb31f7146..168894abd 100644
--- a/src/libopensc/card-entersafe.c
+++ b/src/libopensc/card-entersafe.c
@@ -1423,12 +1423,18 @@ static int entersafe_gen_key(sc_card_t *card, sc_entersafe_gen_key_data *data)
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_OUT_OF_MEMORY);
p=rbuf;
- if (*p!='E')
+ if (*p!='E') {
+ free(data->modulus);
+ data->modulus = NULL;
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA);
+ }
p+=2+p[1];
/* N */
- if (*p!='N')
+ if (*p!='N') {
+ free(data->modulus);
+ data->modulus = NULL;
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA);
+ }
++p;
if(*p++>0x80)
{
--
2.42.0
From 50f0985f6343eeac4044661d56807ee9286db42c Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@redhat.com>
Date: Sun, 8 Oct 2023 19:08:39 +0200
Subject: [PATCH] entersafe: Avoid buffer overflow during keygen
Thanks oss-fuzz
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=63104
---
src/libopensc/card-entersafe.c | 54 ++++++++++++++++++++--------------
1 file changed, 32 insertions(+), 22 deletions(-)
diff --git a/src/libopensc/card-entersafe.c b/src/libopensc/card-entersafe.c
index 168894abd..feb9ebe18 100644
--- a/src/libopensc/card-entersafe.c
+++ b/src/libopensc/card-entersafe.c
@@ -1374,8 +1374,9 @@ static int entersafe_gen_key(sc_card_t *card, sc_entersafe_gen_key_data *data)
int r;
size_t len = data->key_length >> 3;
sc_apdu_t apdu;
- u8 rbuf[300];
+ u8 rbuf[300] = {0};
u8 sbuf[4],*p;
+ size_t plen = 0;
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
@@ -1418,40 +1419,49 @@ static int entersafe_gen_key(sc_card_t *card, sc_entersafe_gen_key_data *data)
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
LOG_TEST_RET(card->ctx, sc_check_sw(card,apdu.sw1,apdu.sw2),"EnterSafe get pukey failed");
- data->modulus = malloc(len);
- if (!data->modulus)
- SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_OUT_OF_MEMORY);
-
- p=rbuf;
- if (*p!='E') {
- free(data->modulus);
- data->modulus = NULL;
+ p = rbuf;
+ plen = apdu.resplen;
+ if (*p != 'E') {
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA);
}
- p+=2+p[1];
+ if ((size_t)(p - rbuf) + 2 + p[1] >= plen) {
+ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA);
+ }
+ p += 2 + p[1];
/* N */
- if (*p!='N') {
- free(data->modulus);
- data->modulus = NULL;
+ if (*p != 'N') {
+ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA);
+ }
+ if ((size_t)(p - rbuf) + 2 >= plen) {
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA);
}
++p;
- if(*p++>0x80)
+ if (*p++ > 0x80)
{
- u8 len_bytes=(*(p-1))&0x0f;
- size_t module_len=0;
- while(len_bytes!=0)
+ u8 len_bytes = (*(p - 1)) & 0x0f;
+ size_t module_len = 0;
+ if ((size_t)(p - rbuf) + len_bytes >= plen) {
+ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA);
+ }
+ while (len_bytes != 0)
{
- module_len=module_len<<8;
- module_len+=*p++;
+ module_len = module_len << 8;
+ module_len += *p++;
--len_bytes;
}
}
- entersafe_reverse_buffer(p,len);
- memcpy(data->modulus,p,len);
+ if ((p - rbuf) + len >= plen) {
+ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA);
+ }
- SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_SUCCESS);
+ data->modulus = malloc(len);
+ if (!data->modulus)
+ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_OUT_OF_MEMORY);
+ entersafe_reverse_buffer(p, len);
+ memcpy(data->modulus, p, len);
+
+ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS);
}
static int entersafe_get_serialnr(sc_card_t *card, sc_serial_number_t *serial)
--
2.42.0

View File

@ -3,7 +3,7 @@
Name: opensc
Version: 0.20.0
Release: 8%{?dist}
Release: 6%{?dist}
Summary: Smart card library and applications
Group: System Environment/Libraries
@ -54,33 +54,7 @@ Patch18: opensc-0.20.0-CVE-2023-2977.patch
# 295f399304644e6b0acde267ac410d0aae4a1aee
# ca01aa7a8edc8280a5ceadebb472c2e3c198d8c2
Patch19: opensc-0.20.0-reader-removal.patch
# https://github.com/OpenSC/OpenSC/commit/bff98ff078a99e6864ba1a598fd7dc9af4a9476b
# https://github.com/OpenSC/OpenSC/commit/0875c69295ef28b45fb682b37cede58fc36b7a1a
Patch20: %{name}-0.23.0-cache-offsets.patch
# https://github.com/OpenSC/OpenSC/commit/868f76fb31255fd3fdacfc3e476452efeb61c3e7
# https://github.com/OpenSC/OpenSC/commit/80cc5d30635f0d2c92b5099c0f9dc680d0ffce2f
Patch21: %{name}-0.23.0-pin-bypass.patch
# https://github.com/OpenSC/OpenSC/commit/245efe608d083fd4e4ec96793fdefd218e26fde7
# https://github.com/OpenSC/OpenSC/commit/440ca666eff10cc7011901252d20f3fc4ea23651
# https://github.com/OpenSC/OpenSC/commit/41d61da8481582e12710b5858f8b635e0a71ab5e
# https://github.com/OpenSC/OpenSC/commit/88880db0307a07e33cf2e1592bb029e9c170dfea
# https://github.com/OpenSC/OpenSC/commit/638a5007a5d240d6fa901aa822cfeef94fe36e85
# https://github.com/OpenSC/OpenSC/commit/c449a181a6988cc1e8dc8764d23574e48cdc3fa6
# https://github.com/OpenSC/OpenSC/commit/5631e9843c832a99769def85b7b9b68b4e3e3959
# https://github.com/OpenSC/OpenSC/commit/e7f81d86dcdc751f4737f4b29a99bfc54d29c5c9
# https://github.com/OpenSC/OpenSC/commit/df5a176bfdf8c52ba89c7fef1f82f6f3b9312bc1
# https://github.com/OpenSC/OpenSC/commit/578aed8391ef117ca64a9e0cba8e5c264368a0ec
# https://github.com/OpenSC/OpenSC/commit/013a807492568bf9907cfb3df41f130ac83c7b9
# https://github.com/OpenSC/OpenSC/commit/fc2c20c3f895569eeb58328bb882aec07325d3b
# https://github.com/OpenSC/OpenSC/commit/3b9129bd3cfc6ac57d5554e015c3df85f5076dc
# https://github.com/OpenSC/OpenSC/commit/bda61d0d276dc98b9d1d1e6810bbd21d19e3859
# https://github.com/OpenSC/OpenSC/commit/a4921ab23fd0853f327517636c50de947548161
# https://github.com/OpenSC/OpenSC/commit/085994384a7171c5c68f6718d9db10ed77c5af1
# https://github.com/OpenSC/OpenSC/commit/0f0985f6343eeac4044661d56807ee9286db42c
Patch22: %{name}-0.23.0-pkcs15init.patch
# https://github.com/OpenSC/OpenSC/pull/2948
# https://github.com/OpenSC/OpenSC/pull/3016
Patch23: %{name}-0.23.0-constant-time-pkcs1.patch
BuildRequires: pcsc-lite-devel
BuildRequires: readline-devel
@ -122,10 +96,6 @@ every software/card that does so, too.
%patch17 -p1 -b .idprime
%patch18 -p1 -b .CVE-2023-2977
%patch19 -p1 -b .reader-removal
%patch20 -p1 -b .cache-offsets
%patch21 -p1 -b .pin-bypass
%patch22 -p1 -b .pkcs15init
%patch23 -p1 -b .constant-time-pkcs1.5
cp -p src/pkcs15init/README ./README.pkcs15init
cp -p src/scconf/README.scconf .
@ -284,15 +254,6 @@ fi
%changelog
* Thu Feb 08 2024 Veronika Hanulikova <vhanulik@redhat.com> - 0.20.0-8
- Fix CVE-2023-5992: Side-channel leaks while stripping encryption PKCS#1.5 padding
* Thu Nov 30 2023 Jakub Jelen <jjelen@redhat.com> - 0.20.0-7
- Fix file caching with different offsets (RHEL-4077)
- Fix CVE-2023-40660: Potential PIN bypass
- Fix CVE-2023-40661: Dynamic analyzers reports in pkcs15init
- Fix CVE-2023-5992: Marvin: Side-channel leaks while stripping encryption PKCS#1.5 padding
* Tue Jul 11 2023 Jakub Jelen <jjelen@redhat.com> - 0.20.0-6
- Fix introduced issues tagged by coverity (RHEL-765)