diff options
| author | Zhang Peng <peng.zhang1.cn@windriver.com> | 2025-10-31 17:14:45 +0800 |
|---|---|---|
| committer | Gyorgy Sarvari <skandigraun@gmail.com> | 2025-11-02 15:09:01 +0100 |
| commit | 4cbf9d8d2c9fc3cae387c20d9d7f7c1fb622ee2d (patch) | |
| tree | 93988325dc978842afe389d6dd089f6f006f619b /meta-oe/recipes-support/opensc/files | |
| parent | 01b7c42dfd25f1308113a4de540cfc03a6ae94cb (diff) | |
| download | meta-openembedded-4cbf9d8d2c9fc3cae387c20d9d7f7c1fb622ee2d.tar.gz | |
opensc: fix CVE-2023-5992
CVE-2023-5992:
A vulnerability was found in OpenSC where PKCS#1 encryption padding removal is not
implemented as side-channel resistant. This issue may result in the potential leak
of private data.
Reference:
[https://nvd.nist.gov/vuln/detail/CVE-2023-5992]
[https://github.com/OpenSC/OpenSC/wiki/CVE-2023-5992]
Upstream patches:
[https://github.com/OpenSC/OpenSC/pull/2948]
[https://github.com/OpenSC/OpenSC/pull/3016]
Signed-off-by: Zhang Peng <peng.zhang1.cn@windriver.com>
Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com>
Diffstat (limited to 'meta-oe/recipes-support/opensc/files')
10 files changed, 1244 insertions, 0 deletions
diff --git a/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0001.patch b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0001.patch new file mode 100644 index 0000000000..4798ab56ae --- /dev/null +++ b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0001.patch | |||
| @@ -0,0 +1,359 @@ | |||
| 1 | From 9c14d6d996e526ebfda75de7b577255acf7ad86d Mon Sep 17 00:00:00 2001 | ||
| 2 | From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= <vhanulik@redhat.com> | ||
| 3 | Date: Mon, 13 Nov 2023 13:54:54 +0100 | ||
| 4 | Subject: [PATCH 01/10] Reimplement removing of PKCS#1 v1.5 padding to be time | ||
| 5 | constant | ||
| 6 | |||
| 7 | CVE: CVE-2023-5992 | ||
| 8 | Upstream-Status: Backport [https://github.com/OpenSC/OpenSC/pull/2948] | ||
| 9 | |||
| 10 | Signed-off-by: Zhang Peng <peng.zhang1.cn@windriver.com> | ||
| 11 | --- | ||
| 12 | src/common/Makefile.am | 5 +- | ||
| 13 | src/common/constant-time.h | 128 ++++++++++++++++++++++++++++++++++++ | ||
| 14 | src/libopensc/internal.h | 4 +- | ||
| 15 | src/libopensc/padding.c | 102 +++++++++++++++++++--------- | ||
| 16 | src/libopensc/pkcs15-sec.c | 5 +- | ||
| 17 | src/minidriver/minidriver.c | 4 +- | ||
| 18 | 6 files changed, 209 insertions(+), 39 deletions(-) | ||
| 19 | create mode 100644 src/common/constant-time.h | ||
| 20 | |||
| 21 | diff --git a/src/common/Makefile.am b/src/common/Makefile.am | ||
| 22 | index 83a40e1c2..c4cfff185 100644 | ||
| 23 | --- a/src/common/Makefile.am | ||
| 24 | +++ b/src/common/Makefile.am | ||
| 25 | @@ -8,7 +8,7 @@ dist_noinst_DATA = \ | ||
| 26 | LICENSE.compat_getopt compat_getopt.txt \ | ||
| 27 | compat_getopt_main.c \ | ||
| 28 | README.compat_strlcpy compat_strlcpy.3 | ||
| 29 | -noinst_HEADERS = compat_strlcat.h compat_strlcpy.h compat_strnlen.h compat_getpass.h compat_getopt.h simclist.h libpkcs11.h libscdl.h | ||
| 30 | +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 | ||
| 31 | |||
| 32 | AM_CPPFLAGS = -I$(top_srcdir)/src | ||
| 33 | |||
| 34 | @@ -40,7 +40,8 @@ TIDY_FILES = \ | ||
| 35 | compat_report_rangecheckfailure.c \ | ||
| 36 | compat___iob_func.c \ | ||
| 37 | simclist.c simclist.h \ | ||
| 38 | - libpkcs11.c libscdl.c | ||
| 39 | + libpkcs11.c libscdl.c \ | ||
| 40 | + constant-time.h | ||
| 41 | |||
| 42 | check-local: | ||
| 43 | if [ -x "$(CLANGTIDY)" ]; then clang-tidy -config='' --checks='$(TIDY_CHECKS)' -header-filter=.* $(addprefix $(srcdir)/,$(TIDY_FILES)) -- $(TIDY_FLAGS); fi | ||
| 44 | diff --git a/src/common/constant-time.h b/src/common/constant-time.h | ||
| 45 | new file mode 100644 | ||
| 46 | index 000000000..40c3e500c | ||
| 47 | --- /dev/null | ||
| 48 | +++ b/src/common/constant-time.h | ||
| 49 | @@ -0,0 +1,128 @@ | ||
| 50 | +/* Original source: https://github.com/openssl/openssl/blob/9890cc42daff5e2d0cad01ac4bf78c391f599a6e/include/internal/constant_time.h */ | ||
| 51 | + | ||
| 52 | +#ifndef CONSTANT_TIME_H | ||
| 53 | +#define CONSTANT_TIME_H | ||
| 54 | + | ||
| 55 | +#include <stdlib.h> | ||
| 56 | +#include <string.h> | ||
| 57 | + | ||
| 58 | +#if !defined(inline) | ||
| 59 | +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L | ||
| 60 | +#define constant_inline inline | ||
| 61 | +#elif defined(__GNUC__) && __GNUC__ >= 2 | ||
| 62 | +#elif defined(__GNUC__) && __GNUC__ >= 2 | ||
| 63 | +#elif defined(_MSC_VER) | ||
| 64 | +#define constant_inline __inline | ||
| 65 | +#else | ||
| 66 | +#define constant_inline | ||
| 67 | +#endif | ||
| 68 | +#else /* use what caller wants as inline may be from config.h */ | ||
| 69 | +#define constant_inline inline /* inline */ | ||
| 70 | +#endif | ||
| 71 | + | ||
| 72 | +/*- | ||
| 73 | + * The boolean methods return a bitmask of all ones (0xff...f) for true | ||
| 74 | + * and 0 for false. For example, | ||
| 75 | + * if (a < b) { | ||
| 76 | + * c = a; | ||
| 77 | + * } else { | ||
| 78 | + * c = b; | ||
| 79 | + * } | ||
| 80 | + * can be written as | ||
| 81 | + * unsigned int lt = constant_time_lt(a, b); | ||
| 82 | + * c = constant_time_select(lt, a, b); | ||
| 83 | + */ | ||
| 84 | + | ||
| 85 | +static constant_inline unsigned int | ||
| 86 | +value_barrier(unsigned int a) | ||
| 87 | +{ | ||
| 88 | + volatile unsigned int r = a; | ||
| 89 | + return r; | ||
| 90 | +} | ||
| 91 | + | ||
| 92 | +static constant_inline size_t | ||
| 93 | +value_barrier_s(size_t a) | ||
| 94 | +{ | ||
| 95 | + volatile size_t r = a; | ||
| 96 | + return r; | ||
| 97 | +} | ||
| 98 | + | ||
| 99 | +/* MSB */ | ||
| 100 | +static constant_inline size_t | ||
| 101 | +constant_time_msb_s(size_t a) | ||
| 102 | +{ | ||
| 103 | + return 0 - (a >> (sizeof(a) * 8 - 1)); | ||
| 104 | +} | ||
| 105 | + | ||
| 106 | +static constant_inline unsigned int | ||
| 107 | +constant_time_msb(unsigned int a) | ||
| 108 | +{ | ||
| 109 | + return 0 - (a >> (sizeof(a) * 8 - 1)); | ||
| 110 | +} | ||
| 111 | + | ||
| 112 | +/* Select */ | ||
| 113 | +static constant_inline unsigned int | ||
| 114 | +constant_time_select(unsigned int mask, unsigned int a, unsigned int b) | ||
| 115 | +{ | ||
| 116 | + return (value_barrier(mask) & a) | (value_barrier(~mask) & b); | ||
| 117 | +} | ||
| 118 | + | ||
| 119 | +static constant_inline unsigned char | ||
| 120 | +constant_time_select_8(unsigned char mask, unsigned char a, unsigned char b) | ||
| 121 | +{ | ||
| 122 | + return (unsigned char)constant_time_select(mask, a, b); | ||
| 123 | +} | ||
| 124 | + | ||
| 125 | +static constant_inline size_t | ||
| 126 | +constant_time_select_s(size_t mask, size_t a, size_t b) | ||
| 127 | +{ | ||
| 128 | + return (value_barrier_s(mask) & a) | (value_barrier_s(~mask) & b); | ||
| 129 | +} | ||
| 130 | + | ||
| 131 | +/* Zero */ | ||
| 132 | +static constant_inline unsigned int | ||
| 133 | +constant_time_is_zero(unsigned int a) | ||
| 134 | +{ | ||
| 135 | + return constant_time_msb(~a & (a - 1)); | ||
| 136 | +} | ||
| 137 | + | ||
| 138 | +static constant_inline size_t | ||
| 139 | +constant_time_is_zero_s(size_t a) | ||
| 140 | +{ | ||
| 141 | + return constant_time_msb_s(~a & (a - 1)); | ||
| 142 | +} | ||
| 143 | + | ||
| 144 | +/* Comparison*/ | ||
| 145 | +static constant_inline size_t | ||
| 146 | +constant_time_lt_s(size_t a, size_t b) | ||
| 147 | +{ | ||
| 148 | + return constant_time_msb_s(a ^ ((a ^ b) | ((a - b) ^ b))); | ||
| 149 | +} | ||
| 150 | + | ||
| 151 | +static constant_inline unsigned int | ||
| 152 | +constant_time_lt(unsigned int a, unsigned int b) | ||
| 153 | +{ | ||
| 154 | + return constant_time_msb(a ^ ((a ^ b) | ((a - b) ^ b))); | ||
| 155 | +} | ||
| 156 | + | ||
| 157 | +static constant_inline unsigned int | ||
| 158 | +constant_time_ge(unsigned int a, unsigned int b) | ||
| 159 | +{ | ||
| 160 | + return ~constant_time_lt(a, b); | ||
| 161 | +} | ||
| 162 | + | ||
| 163 | +/* Equality*/ | ||
| 164 | + | ||
| 165 | +static constant_inline unsigned int | ||
| 166 | +constant_time_eq(unsigned int a, unsigned int b) | ||
| 167 | +{ | ||
| 168 | + return constant_time_is_zero(a ^ b); | ||
| 169 | +} | ||
| 170 | + | ||
| 171 | +static constant_inline size_t | ||
| 172 | +constant_time_eq_s(size_t a, size_t b) | ||
| 173 | +{ | ||
| 174 | + return constant_time_is_zero_s(a ^ b); | ||
| 175 | +} | ||
| 176 | + | ||
| 177 | +#endif /* CONSTANT_TIME_H */ | ||
| 178 | diff --git a/src/libopensc/internal.h b/src/libopensc/internal.h | ||
| 179 | index e7ac63ccf..57568d311 100644 | ||
| 180 | --- a/src/libopensc/internal.h | ||
| 181 | +++ b/src/libopensc/internal.h | ||
| 182 | @@ -166,8 +166,8 @@ int _sc_card_add_xeddsa_alg(struct sc_card *card, unsigned int key_length, | ||
| 183 | |||
| 184 | int sc_pkcs1_strip_01_padding(struct sc_context *ctx, const u8 *in_dat, size_t in_len, | ||
| 185 | u8 *out_dat, size_t *out_len); | ||
| 186 | -int sc_pkcs1_strip_02_padding(struct sc_context *ctx, const u8 *data, size_t len, | ||
| 187 | - u8 *out_dat, size_t *out_len); | ||
| 188 | +int sc_pkcs1_strip_02_padding_constant_time(sc_context_t *ctx, unsigned int n, const u8 *data, | ||
| 189 | + unsigned int data_len, u8 *out, unsigned int *out_len); | ||
| 190 | int sc_pkcs1_strip_digest_info_prefix(unsigned int *algorithm, | ||
| 191 | const u8 *in_dat, size_t in_len, u8 *out_dat, size_t *out_len); | ||
| 192 | |||
| 193 | diff --git a/src/libopensc/padding.c b/src/libopensc/padding.c | ||
| 194 | index e4940ea2b..3a8b81c3f 100644 | ||
| 195 | --- a/src/libopensc/padding.c | ||
| 196 | +++ b/src/libopensc/padding.c | ||
| 197 | @@ -32,10 +32,13 @@ | ||
| 198 | #include <string.h> | ||
| 199 | #include <stdlib.h> | ||
| 200 | |||
| 201 | +#include "common/constant-time.h" | ||
| 202 | #include "internal.h" | ||
| 203 | |||
| 204 | /* TODO doxygen comments */ | ||
| 205 | |||
| 206 | +#define SC_PKCS1_PADDING_MIN_SIZE 11 | ||
| 207 | + | ||
| 208 | /* | ||
| 209 | * Prefixes for pkcs-v1 signatures | ||
| 210 | */ | ||
| 211 | @@ -143,45 +146,82 @@ sc_pkcs1_strip_01_padding(struct sc_context *ctx, const u8 *in_dat, size_t in_le | ||
| 212 | return SC_SUCCESS; | ||
| 213 | } | ||
| 214 | |||
| 215 | - | ||
| 216 | -/* remove pkcs1 BT02 padding (adding BT02 padding is currently not | ||
| 217 | - * needed/implemented) */ | ||
| 218 | +/* Remove pkcs1 BT02 padding (adding BT02 padding is currently not | ||
| 219 | + * needed/implemented) in constant-time. | ||
| 220 | + * Original source: https://github.com/openssl/openssl/blob/9890cc42daff5e2d0cad01ac4bf78c391f599a6e/crypto/rsa/rsa_pk1.c#L171 */ | ||
| 221 | int | ||
| 222 | -sc_pkcs1_strip_02_padding(sc_context_t *ctx, const u8 *data, size_t len, u8 *out, size_t *out_len) | ||
| 223 | +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) | ||
| 224 | { | ||
| 225 | - unsigned int n = 0; | ||
| 226 | - | ||
| 227 | + unsigned int i = 0; | ||
| 228 | + u8 *msg, *msg_orig = NULL; | ||
| 229 | + unsigned int good, found_zero_byte, mask; | ||
| 230 | + unsigned int zero_index = 0, msg_index, mlen = -1, len = 0; | ||
| 231 | LOG_FUNC_CALLED(ctx); | ||
| 232 | - if (data == NULL || len < 3) | ||
| 233 | + | ||
| 234 | + if (data == NULL || data_len <= 0 || data_len > n || n < SC_PKCS1_PADDING_MIN_SIZE) | ||
| 235 | LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL); | ||
| 236 | |||
| 237 | - /* skip leading zero byte */ | ||
| 238 | - if (*data == 0) { | ||
| 239 | - data++; | ||
| 240 | - len--; | ||
| 241 | + msg = msg_orig = calloc(n, sizeof(u8)); | ||
| 242 | + if (msg == NULL) | ||
| 243 | + LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL); | ||
| 244 | + | ||
| 245 | + /* | ||
| 246 | + * We can not check length of input data straight away and still we need to read | ||
| 247 | + * from input even when the input is not as long as needed to keep the time constant. | ||
| 248 | + * If data has wrong size, it is padded by zeroes from left and the following checks | ||
| 249 | + * do not pass. | ||
| 250 | + */ | ||
| 251 | + len = data_len; | ||
| 252 | + for (data += len, msg += n, i = 0; i < n; i++) { | ||
| 253 | + mask = ~constant_time_is_zero(len); | ||
| 254 | + len -= 1 & mask; | ||
| 255 | + data -= 1 & mask; | ||
| 256 | + *--msg = *data & mask; | ||
| 257 | + } | ||
| 258 | + // check first byte to be 0x00 | ||
| 259 | + good = constant_time_is_zero(msg[0]); | ||
| 260 | + // check second byte to be 0x02 | ||
| 261 | + good &= constant_time_eq(msg[1], 2); | ||
| 262 | + | ||
| 263 | + // find zero byte after random data in padding | ||
| 264 | + found_zero_byte = 0; | ||
| 265 | + for (i = 2; i < n; i++) { | ||
| 266 | + unsigned int equals0 = constant_time_is_zero(msg[i]); | ||
| 267 | + zero_index = constant_time_select(~found_zero_byte & equals0, i, zero_index); | ||
| 268 | + found_zero_byte |= equals0; | ||
| 269 | } | ||
| 270 | - if (data[0] != 0x02) | ||
| 271 | - LOG_FUNC_RETURN(ctx, SC_ERROR_WRONG_PADDING); | ||
| 272 | - /* skip over padding bytes */ | ||
| 273 | - for (n = 1; n < len && data[n]; n++) | ||
| 274 | - ; | ||
| 275 | - /* Must be at least 8 pad bytes */ | ||
| 276 | - if (n >= len || n < 9) | ||
| 277 | - LOG_FUNC_RETURN(ctx, SC_ERROR_WRONG_PADDING); | ||
| 278 | - n++; | ||
| 279 | - if (out == NULL) | ||
| 280 | - /* just check the padding */ | ||
| 281 | - LOG_FUNC_RETURN(ctx, SC_SUCCESS); | ||
| 282 | |||
| 283 | - /* Now move decrypted contents to head of buffer */ | ||
| 284 | - if (*out_len < len - n) | ||
| 285 | - LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL); | ||
| 286 | - *out_len = len - n; | ||
| 287 | - memmove(out, data + n, *out_len); | ||
| 288 | + // zero_index stands for index of last found zero | ||
| 289 | + good &= constant_time_ge(zero_index, 2 + 8); | ||
| 290 | + | ||
| 291 | + // start of the actual message in data | ||
| 292 | + msg_index = zero_index + 1; | ||
| 293 | + | ||
| 294 | + // length of message | ||
| 295 | + mlen = data_len - msg_index; | ||
| 296 | + | ||
| 297 | + // check that message fits into out buffer | ||
| 298 | + good &= constant_time_ge(*out_len, mlen); | ||
| 299 | + | ||
| 300 | + // move the result in-place by |num|-SC_PKCS1_PADDING_MIN_SIZE-|mlen| bytes to the left. | ||
| 301 | + *out_len = constant_time_select(constant_time_lt(n - SC_PKCS1_PADDING_MIN_SIZE, *out_len), | ||
| 302 | + n - SC_PKCS1_PADDING_MIN_SIZE, *out_len); | ||
| 303 | + for (msg_index = 1; msg_index < n - SC_PKCS1_PADDING_MIN_SIZE; msg_index <<= 1) { | ||
| 304 | + mask = ~constant_time_eq(msg_index & (n - SC_PKCS1_PADDING_MIN_SIZE - mlen), 0); | ||
| 305 | + for (i = SC_PKCS1_PADDING_MIN_SIZE; i < n - msg_index; i++) | ||
| 306 | + msg[i] = constant_time_select_8(mask, msg[i + msg_index], msg[i]); | ||
| 307 | + } | ||
| 308 | + // move message into out buffer, if good | ||
| 309 | + for (i = 0; i < *out_len; i++) { | ||
| 310 | + unsigned int msg_index; | ||
| 311 | + // when out is longer than message in data, use some bogus index in msg | ||
| 312 | + mask = good & constant_time_lt(i, mlen); | ||
| 313 | + msg_index = constant_time_select(mask, i + SC_PKCS1_PADDING_MIN_SIZE, 0); // to now overflow msg buffer | ||
| 314 | + out[i] = constant_time_select_8(mask, msg[msg_index], out[i]); | ||
| 315 | + } | ||
| 316 | |||
| 317 | - sc_log(ctx, "stripped output(%"SC_FORMAT_LEN_SIZE_T"u): %s", len - n, | ||
| 318 | - sc_dump_hex(out, len - n)); | ||
| 319 | - LOG_FUNC_RETURN(ctx, len - n); | ||
| 320 | + free(msg_orig); | ||
| 321 | + return constant_time_select(good, mlen, SC_ERROR_WRONG_PADDING); | ||
| 322 | } | ||
| 323 | |||
| 324 | /* add/remove DigestInfo prefix */ | ||
| 325 | diff --git a/src/libopensc/pkcs15-sec.c b/src/libopensc/pkcs15-sec.c | ||
| 326 | index b86cb77c3..cea46798a 100644 | ||
| 327 | --- a/src/libopensc/pkcs15-sec.c | ||
| 328 | +++ b/src/libopensc/pkcs15-sec.c | ||
| 329 | @@ -308,8 +308,9 @@ int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card, | ||
| 330 | |||
| 331 | /* Strip any padding */ | ||
| 332 | if (pad_flags & SC_ALGORITHM_RSA_PAD_PKCS1) { | ||
| 333 | - size_t s = r; | ||
| 334 | - r = sc_pkcs1_strip_02_padding(ctx, out, s, out, &s); | ||
| 335 | + int s = r; | ||
| 336 | + int key_size = alg_info->key_length; | ||
| 337 | + r = sc_pkcs1_strip_02_padding_constant_time(ctx, key_size / 8, out, s, out, &s); | ||
| 338 | LOG_TEST_RET(ctx, r, "Invalid PKCS#1 padding"); | ||
| 339 | } | ||
| 340 | |||
| 341 | diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c | ||
| 342 | index 0c089feab..e4d693a09 100644 | ||
| 343 | --- a/src/minidriver/minidriver.c | ||
| 344 | +++ b/src/minidriver/minidriver.c | ||
| 345 | @@ -4582,9 +4582,9 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData, | ||
| 346 | "sc_pkcs15_decipher: DECRYPT-INFO dwVersion=%lu\n", | ||
| 347 | (unsigned long)pInfo->dwVersion); | ||
| 348 | if (pInfo->dwPaddingType == CARD_PADDING_PKCS1) { | ||
| 349 | - size_t temp = pInfo->cbData; | ||
| 350 | + unsigned int temp = pInfo->cbData; | ||
| 351 | logprintf(pCardData, 2, "sc_pkcs15_decipher: stripping PKCS1 padding\n"); | ||
| 352 | - r = sc_pkcs1_strip_02_padding(vs->ctx, pbuf2, pInfo->cbData, pbuf2, &temp); | ||
| 353 | + r = sc_pkcs1_strip_02_padding_constant_time(vs->ctx, prkey_info->modulus_length / 8, pbuf2, pInfo->cbData, pbuf2, &temp); | ||
| 354 | pInfo->cbData = (DWORD) temp; | ||
| 355 | if (r < 0) { | ||
| 356 | logprintf(pCardData, 2, "Cannot strip PKCS1 padding: %i\n", r); | ||
| 357 | -- | ||
| 358 | 2.50.0 | ||
| 359 | |||
diff --git a/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0002.patch b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0002.patch new file mode 100644 index 0000000000..6f3ca502ee --- /dev/null +++ b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0002.patch | |||
| @@ -0,0 +1,269 @@ | |||
| 1 | From c5ffd28572765a957ecadc8593c0bf0a596f535f Mon Sep 17 00:00:00 2001 | ||
| 2 | From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= <vhanulik@redhat.com> | ||
| 3 | Date: Mon, 13 Nov 2023 14:31:08 +0100 | ||
| 4 | Subject: [PATCH 02/10] Add unit tests for PKCS#1 v1.5 de-padding | ||
| 5 | |||
| 6 | CVE: CVE-2023-5992 | ||
| 7 | Upstream-Status: Backport [https://github.com/OpenSC/OpenSC/pull/2948] | ||
| 8 | |||
| 9 | Signed-off-by: Zhang Peng <peng.zhang1.cn@windriver.com> | ||
| 10 | --- | ||
| 11 | src/tests/unittests/Makefile.am | 5 +- | ||
| 12 | src/tests/unittests/Makefile.mak | 5 +- | ||
| 13 | src/tests/unittests/strip_pkcs1_2_padding.c | 204 ++++++++++++++++++++ | ||
| 14 | 3 files changed, 210 insertions(+), 4 deletions(-) | ||
| 15 | create mode 100644 src/tests/unittests/strip_pkcs1_2_padding.c | ||
| 16 | |||
| 17 | diff --git a/src/tests/unittests/Makefile.am b/src/tests/unittests/Makefile.am | ||
| 18 | index 03019c324..4ef1c7206 100644 | ||
| 19 | --- a/src/tests/unittests/Makefile.am | ||
| 20 | +++ b/src/tests/unittests/Makefile.am | ||
| 21 | @@ -6,8 +6,8 @@ include $(top_srcdir)/aminclude_static.am | ||
| 22 | clean-local: code-coverage-clean | ||
| 23 | distclean-local: code-coverage-dist-clean | ||
| 24 | |||
| 25 | -noinst_PROGRAMS = asn1 simpletlv cachedir | ||
| 26 | -TESTS = asn1 simpletlv cachedir | ||
| 27 | +noinst_PROGRAMS = asn1 simpletlv cachedir strip_pkcs1_2_padding | ||
| 28 | +TESTS = asn1 simpletlv cachedir strip_pkcs1_2_padding | ||
| 29 | |||
| 30 | noinst_HEADERS = torture.h | ||
| 31 | |||
| 32 | @@ -23,6 +23,7 @@ LDADD = $(top_builddir)/src/libopensc/libopensc.la \ | ||
| 33 | asn1_SOURCES = asn1.c | ||
| 34 | simpletlv_SOURCES = simpletlv.c | ||
| 35 | cachedir_SOURCES = cachedir.c | ||
| 36 | +strip_pkcs1_2_padding = strip_pkcs1_2_padding.c | ||
| 37 | |||
| 38 | if ENABLE_ZLIB | ||
| 39 | noinst_PROGRAMS += compression | ||
| 40 | diff --git a/src/tests/unittests/Makefile.mak b/src/tests/unittests/Makefile.mak | ||
| 41 | index 41762fdbf..a04086a67 100644 | ||
| 42 | --- a/src/tests/unittests/Makefile.mak | ||
| 43 | +++ b/src/tests/unittests/Makefile.mak | ||
| 44 | @@ -1,9 +1,10 @@ | ||
| 45 | TOPDIR = ..\..\.. | ||
| 46 | |||
| 47 | -TARGETS = asn1 compression | ||
| 48 | +TARGETS = asn1 compression strip_pkcs1_2_padding | ||
| 49 | |||
| 50 | OBJECTS = asn1.obj \ | ||
| 51 | - compression.obj | ||
| 52 | + compression.obj \ | ||
| 53 | + strip_pkcs1_2_padding.obj \ | ||
| 54 | $(TOPDIR)\win32\versioninfo.res | ||
| 55 | |||
| 56 | all: $(TARGETS) | ||
| 57 | diff --git a/src/tests/unittests/strip_pkcs1_2_padding.c b/src/tests/unittests/strip_pkcs1_2_padding.c | ||
| 58 | new file mode 100644 | ||
| 59 | index 000000000..f9561b936 | ||
| 60 | --- /dev/null | ||
| 61 | +++ b/src/tests/unittests/strip_pkcs1_2_padding.c | ||
| 62 | @@ -0,0 +1,204 @@ | ||
| 63 | +#include "common/compat_strlcpy.c" | ||
| 64 | +#include "libopensc/log.c" | ||
| 65 | +#include "libopensc/padding.c" | ||
| 66 | +#include "torture.h" | ||
| 67 | +#include <cmocka.h> | ||
| 68 | + | ||
| 69 | +static void | ||
| 70 | +torture_long_output_buffer(void **state) | ||
| 71 | +{ | ||
| 72 | + unsigned int n = 14; | ||
| 73 | + unsigned int in_len = 14; | ||
| 74 | + unsigned char in[] = {0x00, 0x02, | ||
| 75 | + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, | ||
| 76 | + 0x00, | ||
| 77 | + 'm', 's', 'g'}; | ||
| 78 | + unsigned int out_len = 3; | ||
| 79 | + unsigned char *out = malloc(out_len * sizeof(unsigned char)); | ||
| 80 | + unsigned char result_msg[] = {'m', 's', 'g'}; | ||
| 81 | + int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); | ||
| 82 | + assert_int_equal(r, 3); | ||
| 83 | + assert_memory_equal(out, result_msg, r); | ||
| 84 | + free(out); | ||
| 85 | +} | ||
| 86 | + | ||
| 87 | +static void | ||
| 88 | +torture_short_output_buffer(void **state) | ||
| 89 | +{ | ||
| 90 | + unsigned int n = 14; | ||
| 91 | + unsigned int in_len = 14; | ||
| 92 | + unsigned char in[] = {0x00, 0x02, | ||
| 93 | + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, | ||
| 94 | + 0x00, | ||
| 95 | + 'm', 's', 'g'}; | ||
| 96 | + unsigned int out_len = 1; | ||
| 97 | + unsigned char *out = malloc(out_len * sizeof(unsigned char)); | ||
| 98 | + int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); | ||
| 99 | + assert_int_equal(r, SC_ERROR_WRONG_PADDING); | ||
| 100 | + free(out); | ||
| 101 | +} | ||
| 102 | + | ||
| 103 | +static void | ||
| 104 | +torture_short_message_correct_padding(void **state) | ||
| 105 | +{ | ||
| 106 | + unsigned int n = 14; | ||
| 107 | + unsigned int in_len = 14; | ||
| 108 | + unsigned char in[] = {0x00, 0x02, | ||
| 109 | + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, | ||
| 110 | + 0x00, | ||
| 111 | + 'm', 's', 'g'}; | ||
| 112 | + unsigned int out_len = 3; | ||
| 113 | + unsigned char *out = malloc(out_len * sizeof(unsigned char)); | ||
| 114 | + unsigned char result_msg[] = {'m', 's', 'g'}; | ||
| 115 | + int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); | ||
| 116 | + assert_int_equal(r, 3); | ||
| 117 | + assert_memory_equal(out, result_msg, r); | ||
| 118 | + free(out); | ||
| 119 | +} | ||
| 120 | + | ||
| 121 | +static void | ||
| 122 | +torture_missing_first_zero(void **state) | ||
| 123 | +{ | ||
| 124 | + unsigned int n = 13; | ||
| 125 | + unsigned int in_len = 13; | ||
| 126 | + unsigned char in[] = {0x02, | ||
| 127 | + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, | ||
| 128 | + 0x00, | ||
| 129 | + 'm', 's', 'g'}; | ||
| 130 | + unsigned int out_len = 10; | ||
| 131 | + unsigned char *out = malloc(out_len * sizeof(unsigned char)); | ||
| 132 | + int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); | ||
| 133 | + assert_int_equal(r, SC_ERROR_WRONG_PADDING); | ||
| 134 | + free(out); | ||
| 135 | +} | ||
| 136 | + | ||
| 137 | +static void | ||
| 138 | +torture_missing_two(void **state) | ||
| 139 | +{ | ||
| 140 | + unsigned int n = 13; | ||
| 141 | + unsigned int in_len = 13; | ||
| 142 | + unsigned char in[] = {0x00, | ||
| 143 | + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, | ||
| 144 | + 0x00, | ||
| 145 | + 'm', 's', 'g'}; | ||
| 146 | + unsigned int out_len = 10; | ||
| 147 | + unsigned char *out = malloc(out_len * sizeof(unsigned char)); | ||
| 148 | + int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); | ||
| 149 | + assert_int_equal(r, SC_ERROR_WRONG_PADDING); | ||
| 150 | + free(out); | ||
| 151 | +} | ||
| 152 | + | ||
| 153 | +static void | ||
| 154 | +torture_short_padding(void **state) | ||
| 155 | +{ | ||
| 156 | + unsigned int n = 13; | ||
| 157 | + unsigned int in_len = 13; | ||
| 158 | + unsigned char in[] = {0x00, 0x02, | ||
| 159 | + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, | ||
| 160 | + 0x00, | ||
| 161 | + 'm', 's', 'g'}; | ||
| 162 | + unsigned int out_len = 10; | ||
| 163 | + unsigned char *out = malloc(out_len * sizeof(unsigned char)); | ||
| 164 | + int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); | ||
| 165 | + assert_int_equal(r, SC_ERROR_WRONG_PADDING); | ||
| 166 | + free(out); | ||
| 167 | +} | ||
| 168 | + | ||
| 169 | +static void | ||
| 170 | +torture_missing_second_zero(void **state) | ||
| 171 | +{ | ||
| 172 | + unsigned int n = 13; | ||
| 173 | + unsigned int in_len = 13; | ||
| 174 | + unsigned char in[] = {0x00, 0x02, | ||
| 175 | + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, | ||
| 176 | + 'm', 's', 'g'}; | ||
| 177 | + unsigned int out_len = 10; | ||
| 178 | + unsigned char *out = malloc(out_len * sizeof(unsigned char)); | ||
| 179 | + int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); | ||
| 180 | + assert_int_equal(r, SC_ERROR_WRONG_PADDING); | ||
| 181 | + free(out); | ||
| 182 | +} | ||
| 183 | + | ||
| 184 | +static void | ||
| 185 | +torture_missing_message(void **state) | ||
| 186 | +{ | ||
| 187 | + unsigned int n = 20; | ||
| 188 | + unsigned int in_len = 11; | ||
| 189 | + unsigned char in[] = {0x00, 0x02, | ||
| 190 | + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, | ||
| 191 | + 0x00}; | ||
| 192 | + unsigned int out_len = 11; | ||
| 193 | + unsigned char *out = malloc(out_len * sizeof(unsigned char)); | ||
| 194 | + int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); | ||
| 195 | + assert_int_equal(r, SC_ERROR_WRONG_PADDING); | ||
| 196 | + free(out); | ||
| 197 | +} | ||
| 198 | + | ||
| 199 | +static void | ||
| 200 | +torture_one_byte_message(void **state) | ||
| 201 | +{ | ||
| 202 | + unsigned int n = 12; | ||
| 203 | + unsigned int in_len = 12; | ||
| 204 | + unsigned char in[] = {0x00, 0x02, | ||
| 205 | + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, | ||
| 206 | + 0x00, | ||
| 207 | + 'm'}; | ||
| 208 | + unsigned int out_len = 1; | ||
| 209 | + unsigned char *out = malloc(out_len * sizeof(unsigned char)); | ||
| 210 | + unsigned char result_msg[] = {'m'}; | ||
| 211 | + int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); | ||
| 212 | + assert_int_equal(r, 1); | ||
| 213 | + assert_memory_equal(out, result_msg, r); | ||
| 214 | + free(out); | ||
| 215 | +} | ||
| 216 | + | ||
| 217 | +static void | ||
| 218 | +torture_longer_padding(void **state) | ||
| 219 | +{ | ||
| 220 | + unsigned int n = 26; | ||
| 221 | + unsigned int in_len = 26; | ||
| 222 | + unsigned char in[] = {0x00, 0x02, | ||
| 223 | + 0x0e, 0x38, 0x97, 0x18, 0x16, 0x57, 0x9e, 0x30, 0xb6, 0xa5, 0x78, 0x13, 0x20, 0xca, 0x11, | ||
| 224 | + 0x00, | ||
| 225 | + 0x9d, 0x98, 0x3d, 0xca, 0xa9, 0xa7, 0x11, 0x0a}; | ||
| 226 | + unsigned int out_len = 8; | ||
| 227 | + unsigned char *out = malloc(out_len * sizeof(unsigned char)); | ||
| 228 | + unsigned char result_msg[] = {0x9d, 0x98, 0x3d, 0xca, 0xa9, 0xa7, 0x11, 0x0a}; | ||
| 229 | + int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); | ||
| 230 | + assert_int_equal(r, 8); | ||
| 231 | + assert_memory_equal(out, result_msg, r); | ||
| 232 | + free(out); | ||
| 233 | +} | ||
| 234 | + | ||
| 235 | +static void | ||
| 236 | +torture_empty_message(void **state) | ||
| 237 | +{ | ||
| 238 | + unsigned int n = 18; | ||
| 239 | + unsigned int in_len = 18; | ||
| 240 | + unsigned char in[] = {0x00, 0x02, | ||
| 241 | + 0x0e, 0x38, 0x97, 0x18, 0x16, 0x57, 0x9e, 0x30, 0xb6, 0xa5, 0x78, 0x13, 0x20, 0xca, 0x11, | ||
| 242 | + 0x00}; | ||
| 243 | + unsigned int out_len = 8; | ||
| 244 | + unsigned char *out = malloc(out_len * sizeof(unsigned char)); | ||
| 245 | + int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); | ||
| 246 | + assert_int_equal(r, 0); | ||
| 247 | + free(out); | ||
| 248 | +} | ||
| 249 | + | ||
| 250 | +int | ||
| 251 | +main(void) | ||
| 252 | +{ | ||
| 253 | + const struct CMUnitTest tests[] = { | ||
| 254 | + cmocka_unit_test(torture_long_output_buffer), | ||
| 255 | + cmocka_unit_test(torture_short_output_buffer), | ||
| 256 | + cmocka_unit_test(torture_short_message_correct_padding), | ||
| 257 | + cmocka_unit_test(torture_missing_first_zero), | ||
| 258 | + cmocka_unit_test(torture_missing_two), | ||
| 259 | + cmocka_unit_test(torture_short_padding), | ||
| 260 | + cmocka_unit_test(torture_missing_second_zero), | ||
| 261 | + cmocka_unit_test(torture_missing_message), | ||
| 262 | + cmocka_unit_test(torture_one_byte_message), | ||
| 263 | + cmocka_unit_test(torture_longer_padding), | ||
| 264 | + cmocka_unit_test(torture_empty_message)}; | ||
| 265 | + return cmocka_run_group_tests(tests, NULL, NULL); | ||
| 266 | +} | ||
| 267 | -- | ||
| 268 | 2.50.0 | ||
| 269 | |||
diff --git a/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0003.patch b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0003.patch new file mode 100644 index 0000000000..52a73064dc --- /dev/null +++ b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0003.patch | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | From 7266f151bb5896b9213d4cf0a298859a53cfb750 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= <vhanulik@redhat.com> | ||
| 3 | Date: Thu, 16 Nov 2023 10:38:12 +0100 | ||
| 4 | Subject: [PATCH 03/10] pkcs15-sec: Remove logging after PKCS#1 v1.5 depadding | ||
| 5 | |||
| 6 | To prevent Marvin attack on RSA PKCS#1 v1.5 padding | ||
| 7 | when logging the return value, signaling the padding error. | ||
| 8 | |||
| 9 | CVE: CVE-2023-5992 | ||
| 10 | Upstream-Status: Backport [https://github.com/OpenSC/OpenSC/pull/2948] | ||
| 11 | |||
| 12 | Signed-off-by: Zhang Peng <peng.zhang1.cn@windriver.com> | ||
| 13 | --- | ||
| 14 | src/libopensc/pkcs15-sec.c | 8 ++++---- | ||
| 15 | 1 file changed, 4 insertions(+), 4 deletions(-) | ||
| 16 | |||
| 17 | diff --git a/src/libopensc/pkcs15-sec.c b/src/libopensc/pkcs15-sec.c | ||
| 18 | index cea46798a..b04856b4d 100644 | ||
| 19 | --- a/src/libopensc/pkcs15-sec.c | ||
| 20 | +++ b/src/libopensc/pkcs15-sec.c | ||
| 21 | @@ -308,13 +308,13 @@ int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card, | ||
| 22 | |||
| 23 | /* Strip any padding */ | ||
| 24 | if (pad_flags & SC_ALGORITHM_RSA_PAD_PKCS1) { | ||
| 25 | - int s = r; | ||
| 26 | - int key_size = alg_info->key_length; | ||
| 27 | + unsigned int s = r; | ||
| 28 | + unsigned int key_size = (unsigned int)alg_info->key_length; | ||
| 29 | r = sc_pkcs1_strip_02_padding_constant_time(ctx, key_size / 8, out, s, out, &s); | ||
| 30 | - LOG_TEST_RET(ctx, r, "Invalid PKCS#1 padding"); | ||
| 31 | + /* for keeping PKCS#1 v1.5 depadding constant-time, do not log error here */ | ||
| 32 | } | ||
| 33 | |||
| 34 | - LOG_FUNC_RETURN(ctx, r); | ||
| 35 | + return r; | ||
| 36 | } | ||
| 37 | |||
| 38 | /* derive one key from another. RSA can use decipher, so this is for only ECDH | ||
| 39 | -- | ||
| 40 | 2.50.0 | ||
| 41 | |||
diff --git a/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0004.patch b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0004.patch new file mode 100644 index 0000000000..459e1d2a61 --- /dev/null +++ b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0004.patch | |||
| @@ -0,0 +1,109 @@ | |||
| 1 | From 663dcbae0d92a05eba28ca56b80346b2fbe5a6d5 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= <vhanulik@redhat.com> | ||
| 3 | Date: Thu, 16 Nov 2023 15:49:15 +0100 | ||
| 4 | Subject: [PATCH 04/10] framework-pkcs15.c: Handle PKCS#1 v1.5 depadding | ||
| 5 | constant-time | ||
| 6 | |||
| 7 | In order to not disclose time side-channel when the depadding | ||
| 8 | fails, do the same operations as for case when depadding ends | ||
| 9 | with success. | ||
| 10 | |||
| 11 | CVE: CVE-2023-5992 | ||
| 12 | Upstream-Status: Backport [https://github.com/OpenSC/OpenSC/pull/2948] | ||
| 13 | |||
| 14 | Signed-off-by: Zhang Peng <peng.zhang1.cn@windriver.com> | ||
| 15 | --- | ||
| 16 | src/pkcs11/framework-pkcs15.c | 54 ++++++++++++++++++++++++++--------- | ||
| 17 | 1 file changed, 41 insertions(+), 13 deletions(-) | ||
| 18 | |||
| 19 | diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c | ||
| 20 | index 4fc8f13ab..8376057ea 100644 | ||
| 21 | --- a/src/pkcs11/framework-pkcs15.c | ||
| 22 | +++ b/src/pkcs11/framework-pkcs15.c | ||
| 23 | @@ -18,6 +18,7 @@ | ||
| 24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 25 | */ | ||
| 26 | |||
| 27 | +#include "common/constant-time.h" | ||
| 28 | #include "config.h" | ||
| 29 | #include <stdlib.h> | ||
| 30 | #include <string.h> | ||
| 31 | @@ -4341,7 +4342,8 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_session *session, void *obj, | ||
| 32 | struct pkcs15_fw_data *fw_data = NULL; | ||
| 33 | struct pkcs15_prkey_object *prkey; | ||
| 34 | unsigned char decrypted[512]; /* FIXME: Will not work for keys above 4096 bits */ | ||
| 35 | - int buff_too_small, rv, flags = 0, prkey_has_path = 0; | ||
| 36 | + int rv, flags = 0, prkey_has_path = 0; | ||
| 37 | + CK_ULONG mask, good, rv_pkcs11; | ||
| 38 | |||
| 39 | sc_log(context, "Initiating decryption."); | ||
| 40 | |||
| 41 | @@ -4415,27 +4417,53 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_session *session, void *obj, | ||
| 42 | rv = sc_pkcs15_decipher(fw_data->p15_card, prkey->prv_p15obj, flags, | ||
| 43 | pEncryptedData, ulEncryptedDataLen, decrypted, sizeof(decrypted)); | ||
| 44 | |||
| 45 | - if (rv < 0 && !sc_pkcs11_conf.lock_login && !prkey_has_path) | ||
| 46 | + /* skip for PKCS#1 v1.5 padding prevent side channel attack */ | ||
| 47 | + if (!(flags & SC_ALGORITHM_RSA_PAD_PKCS1) && | ||
| 48 | + rv < 0 && !sc_pkcs11_conf.lock_login && !prkey_has_path) | ||
| 49 | if (reselect_app_df(fw_data->p15_card) == SC_SUCCESS) | ||
| 50 | rv = sc_pkcs15_decipher(fw_data->p15_card, prkey->prv_p15obj, flags, | ||
| 51 | pEncryptedData, ulEncryptedDataLen, decrypted, sizeof(decrypted)); | ||
| 52 | |||
| 53 | sc_unlock(p11card->card); | ||
| 54 | |||
| 55 | - sc_log(context, "Decryption complete. Result %d.", rv); | ||
| 56 | + sc_log(context, "Decryption complete."); | ||
| 57 | |||
| 58 | - if (rv < 0) | ||
| 59 | - return sc_to_cryptoki_error(rv, "C_Decrypt"); | ||
| 60 | + /* Handle following code in constant-time | ||
| 61 | + * to prevent Marvin attack for PKCS#1 v1.5 padding. */ | ||
| 62 | |||
| 63 | - buff_too_small = (*pulDataLen < (CK_ULONG)rv); | ||
| 64 | - *pulDataLen = rv; | ||
| 65 | - if (pData == NULL_PTR) | ||
| 66 | - return CKR_OK; | ||
| 67 | - if (buff_too_small) | ||
| 68 | - return CKR_BUFFER_TOO_SMALL; | ||
| 69 | - memcpy(pData, decrypted, *pulDataLen); | ||
| 70 | + /* only padding error must be handled in constant-time way, | ||
| 71 | + * other error can be returned straight away */ | ||
| 72 | + if ((~constant_time_eq_s(rv, SC_ERROR_WRONG_PADDING) & constant_time_lt_s(sizeof(decrypted), rv))) | ||
| 73 | + return sc_to_cryptoki_error(rv, "C_Decrypt"); | ||
| 74 | |||
| 75 | - return CKR_OK; | ||
| 76 | + /* check rv for padding error */ | ||
| 77 | + good = ~constant_time_eq_s(rv, SC_ERROR_WRONG_PADDING); | ||
| 78 | + rv_pkcs11 = sc_to_cryptoki_error(SC_ERROR_WRONG_PADDING, "C_Decrypt"); | ||
| 79 | + rv_pkcs11 = constant_time_select_s(good, CKR_OK, rv_pkcs11); | ||
| 80 | + | ||
| 81 | + if (pData == NULL_PTR) { | ||
| 82 | + /* set length only if no error */ | ||
| 83 | + *pulDataLen = constant_time_select_s(good, rv, *pulDataLen); | ||
| 84 | + /* return error only if original rv < 0 */ | ||
| 85 | + return rv_pkcs11; | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | + /* check whether *pulDataLen < rv and set return value for small output buffer */ | ||
| 89 | + mask = good & constant_time_lt_s(*pulDataLen, rv); | ||
| 90 | + rv_pkcs11 = constant_time_select_s(mask, CKR_BUFFER_TOO_SMALL, rv_pkcs11); | ||
| 91 | + good &= ~mask; | ||
| 92 | + | ||
| 93 | + /* move everything from decrypted into out buffer constant-time, if rv is ok */ | ||
| 94 | + for (CK_ULONG i = 0; i < *pulDataLen; i++) { /* iterate over whole pData to not disclose real depadded length */ | ||
| 95 | + CK_ULONG msg_index; | ||
| 96 | + mask = good & constant_time_lt_s(i, sizeof(decrypted)); /* i should be in the bounds of decrypted */ | ||
| 97 | + mask &= constant_time_lt_s(i, constant_time_select_s(good, rv, 0)); /* check that is in bounds of depadded message */ | ||
| 98 | + msg_index = constant_time_select_s(mask, i, 0); | ||
| 99 | + pData[i] = constant_time_select_8(mask, decrypted[msg_index], pData[i]); | ||
| 100 | + } | ||
| 101 | + *pulDataLen = constant_time_select_s(good, rv, *pulDataLen); | ||
| 102 | + /* do not log error code to prevent side channel attack */ | ||
| 103 | + return rv_pkcs11; | ||
| 104 | } | ||
| 105 | |||
| 106 | |||
| 107 | -- | ||
| 108 | 2.50.0 | ||
| 109 | |||
diff --git a/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0005.patch b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0005.patch new file mode 100644 index 0000000000..a52b964306 --- /dev/null +++ b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0005.patch | |||
| @@ -0,0 +1,63 @@ | |||
| 1 | From f7fc30b02090d657b9ba64cbb5168cb5a94592ef Mon Sep 17 00:00:00 2001 | ||
| 2 | From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= <vhanulik@redhat.com> | ||
| 3 | Date: Mon, 8 Jan 2024 14:59:22 +0100 | ||
| 4 | Subject: [PATCH 05/10] mechanism: Handle PKCS#1 v1.5 depadding constant-time | ||
| 5 | |||
| 6 | CVE: CVE-2023-5992 | ||
| 7 | Upstream-Status: Backport [https://github.com/OpenSC/OpenSC/pull/2948] | ||
| 8 | |||
| 9 | Signed-off-by: Zhang Peng <peng.zhang1.cn@windriver.com> | ||
| 10 | --- | ||
| 11 | src/pkcs11/mechanism.c | 15 +++++++++++++-- | ||
| 12 | 1 file changed, 13 insertions(+), 2 deletions(-) | ||
| 13 | |||
| 14 | diff --git a/src/pkcs11/mechanism.c b/src/pkcs11/mechanism.c | ||
| 15 | index c5959b36b..b3fce1714 100644 | ||
| 16 | --- a/src/pkcs11/mechanism.c | ||
| 17 | +++ b/src/pkcs11/mechanism.c | ||
| 18 | @@ -23,6 +23,7 @@ | ||
| 19 | #include <stdlib.h> | ||
| 20 | #include <string.h> | ||
| 21 | |||
| 22 | +#include "common/constant-time.h" | ||
| 23 | #include "sc-pkcs11.h" | ||
| 24 | |||
| 25 | /* Also used for verification data */ | ||
| 26 | @@ -844,7 +845,9 @@ sc_pkcs11_decr(struct sc_pkcs11_session *session, | ||
| 27 | rv = op->type->decrypt(op, pEncryptedData, ulEncryptedDataLen, | ||
| 28 | pData, pulDataLen); | ||
| 29 | |||
| 30 | - if (rv != CKR_BUFFER_TOO_SMALL && pData != NULL) | ||
| 31 | + /* terminate session for any return value except CKR_BUFFER_TOO_SMALL, | ||
| 32 | + * perform check in time side-channel free way to prevent Marvin attack */ | ||
| 33 | + if (!constant_time_eq_s(rv, CKR_BUFFER_TOO_SMALL) && pData != NULL) | ||
| 34 | session_stop_operation(session, SC_PKCS11_OPERATION_DECRYPT); | ||
| 35 | |||
| 36 | return rv; | ||
| 37 | @@ -1084,14 +1087,22 @@ sc_pkcs11_decrypt(sc_pkcs11_operation_t *operation, | ||
| 38 | { | ||
| 39 | struct signature_data *data; | ||
| 40 | struct sc_pkcs11_object *key; | ||
| 41 | + CK_RV rv; | ||
| 42 | |||
| 43 | data = (struct signature_data*) operation->priv_data; | ||
| 44 | |||
| 45 | key = data->key; | ||
| 46 | - return key->ops->decrypt(operation->session, | ||
| 47 | + rv = key->ops->decrypt(operation->session, | ||
| 48 | key, &operation->mechanism, | ||
| 49 | pEncryptedData, ulEncryptedDataLen, | ||
| 50 | pData, pulDataLen); | ||
| 51 | + | ||
| 52 | + /* Skip DecryptFinalize for PKCS#1 v1.5 padding to prevent time side-channel leakage */ | ||
| 53 | + if (((CK_MECHANISM_PTR)&operation->mechanism)->mechanism == CKM_RSA_PKCS) | ||
| 54 | + return rv; | ||
| 55 | + | ||
| 56 | + if (rv != CKR_OK) | ||
| 57 | + return rv; | ||
| 58 | } | ||
| 59 | |||
| 60 | static CK_RV | ||
| 61 | -- | ||
| 62 | 2.50.0 | ||
| 63 | |||
diff --git a/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0006.patch b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0006.patch new file mode 100644 index 0000000000..b9c1f8ce3e --- /dev/null +++ b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0006.patch | |||
| @@ -0,0 +1,118 @@ | |||
| 1 | From 224a5a9bb32a8eb575dc30f18004c069c62fc8b1 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= <vhanulik@redhat.com> | ||
| 3 | Date: Wed, 22 Nov 2023 15:02:57 +0100 | ||
| 4 | Subject: [PATCH 06/10] minidriver: Make CardRSADecrypt constant-time | ||
| 5 | |||
| 6 | CVE: CVE-2023-5992 | ||
| 7 | Upstream-Status: Backport [https://github.com/OpenSC/OpenSC/pull/2948] | ||
| 8 | |||
| 9 | Signed-off-by: Zhang Peng <peng.zhang1.cn@windriver.com> | ||
| 10 | --- | ||
| 11 | src/minidriver/minidriver.c | 36 +++++++++++++++++++++++------------- | ||
| 12 | 1 file changed, 23 insertions(+), 13 deletions(-) | ||
| 13 | |||
| 14 | diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c | ||
| 15 | index e4d693a09..37e576ba2 100644 | ||
| 16 | --- a/src/minidriver/minidriver.c | ||
| 17 | +++ b/src/minidriver/minidriver.c | ||
| 18 | @@ -41,6 +41,7 @@ | ||
| 19 | #include "cardmod.h" | ||
| 20 | |||
| 21 | #include "common/compat_strlcpy.h" | ||
| 22 | +#include "common/constant-time.h" | ||
| 23 | #include "libopensc/asn1.h" | ||
| 24 | #include "libopensc/cardctl.h" | ||
| 25 | #include "libopensc/opensc.h" | ||
| 26 | @@ -4463,13 +4464,15 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData, | ||
| 27 | |||
| 28 | { | ||
| 29 | DWORD dwret; | ||
| 30 | - int r, opt_crypt_flags = 0; | ||
| 31 | + int r, opt_crypt_flags = 0, good = 0; | ||
| 32 | unsigned ui; | ||
| 33 | VENDOR_SPECIFIC *vs; | ||
| 34 | struct sc_pkcs15_prkey_info *prkey_info; | ||
| 35 | BYTE *pbuf = NULL, *pbuf2 = NULL; | ||
| 36 | struct sc_pkcs15_object *pkey = NULL; | ||
| 37 | struct sc_algorithm_info *alg_info = NULL; | ||
| 38 | + unsigned int wrong_padding = 0; | ||
| 39 | + unsigned int pbufLen = 0; | ||
| 40 | |||
| 41 | MD_FUNC_CALLED(pCardData, 1); | ||
| 42 | |||
| 43 | @@ -4570,10 +4573,11 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData, | ||
| 44 | goto err; | ||
| 45 | } | ||
| 46 | |||
| 47 | + pbufLen = pInfo->cbData; | ||
| 48 | if (alg_info->flags & SC_ALGORITHM_RSA_RAW) { | ||
| 49 | logprintf(pCardData, 2, "sc_pkcs15_decipher: using RSA-RAW mechanism\n"); | ||
| 50 | r = sc_pkcs15_decipher(vs->p15card, pkey, opt_crypt_flags, pbuf, pInfo->cbData, pbuf2, pInfo->cbData); | ||
| 51 | - logprintf(pCardData, 2, "sc_pkcs15_decipher returned %d\n", r); | ||
| 52 | + /* do not log return value to not leak it */ | ||
| 53 | |||
| 54 | if (r > 0) { | ||
| 55 | /* Need to handle padding */ | ||
| 56 | @@ -4586,13 +4590,9 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData, | ||
| 57 | logprintf(pCardData, 2, "sc_pkcs15_decipher: stripping PKCS1 padding\n"); | ||
| 58 | r = sc_pkcs1_strip_02_padding_constant_time(vs->ctx, prkey_info->modulus_length / 8, pbuf2, pInfo->cbData, pbuf2, &temp); | ||
| 59 | pInfo->cbData = (DWORD) temp; | ||
| 60 | - if (r < 0) { | ||
| 61 | - logprintf(pCardData, 2, "Cannot strip PKCS1 padding: %i\n", r); | ||
| 62 | - pCardData->pfnCspFree(pbuf); | ||
| 63 | - pCardData->pfnCspFree(pbuf2); | ||
| 64 | - dwret = SCARD_F_INTERNAL_ERROR; | ||
| 65 | - goto err; | ||
| 66 | - } | ||
| 67 | + wrong_padding = constant_time_eq_s(r, SC_ERROR_WRONG_PADDING); | ||
| 68 | + /* continue without returning error to not leak that padding is wrong | ||
| 69 | + to prevent time side-channel leak for Marvin attack*/ | ||
| 70 | } | ||
| 71 | else if (pInfo->dwPaddingType == CARD_PADDING_OAEP) { | ||
| 72 | /* TODO: Handle OAEP padding if present - can call PFN_CSP_UNPAD_DATA */ | ||
| 73 | @@ -4640,28 +4640,38 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData, | ||
| 74 | goto err; | ||
| 75 | } | ||
| 76 | |||
| 77 | - if ( r < 0) { | ||
| 78 | + good = constant_time_eq_s(r, 0); | ||
| 79 | + /* if no error or padding error, do not return here to prevent Marvin attack */ | ||
| 80 | + if (!(good | wrong_padding) && r < 0) { | ||
| 81 | logprintf(pCardData, 2, "sc_pkcs15_decipher error(%i): %s\n", r, sc_strerror(r)); | ||
| 82 | pCardData->pfnCspFree(pbuf); | ||
| 83 | pCardData->pfnCspFree(pbuf2); | ||
| 84 | dwret = md_translate_OpenSC_to_Windows_error(r, SCARD_E_INVALID_VALUE); | ||
| 85 | goto err; | ||
| 86 | } | ||
| 87 | + dwret = constant_time_select_s(good, SCARD_S_SUCCESS, SCARD_F_INTERNAL_ERROR); | ||
| 88 | |||
| 89 | logprintf(pCardData, 2, "decrypted data(%lu):\n", | ||
| 90 | (unsigned long)pInfo->cbData); | ||
| 91 | loghex(pCardData, 7, pbuf2, pInfo->cbData); | ||
| 92 | |||
| 93 | /*inversion donnees */ | ||
| 94 | - for(ui = 0; ui < pInfo->cbData; ui++) | ||
| 95 | - pInfo->pbData[ui] = pbuf2[pInfo->cbData-ui-1]; | ||
| 96 | + /* copy data in constant-time way to prevent leak */ | ||
| 97 | + for (ui = 0; ui < pbufLen; ui++) { | ||
| 98 | + unsigned int mask, msg_index, inv_ui; | ||
| 99 | + mask = good & constant_time_lt_s(ui, pInfo->cbData); /* ui should be in the bounds of pbuf2 */ | ||
| 100 | + inv_ui = pInfo->cbData - ui - 1; | ||
| 101 | + msg_index = constant_time_select_s(mask, inv_ui, 0); | ||
| 102 | + pInfo->pbData[ui] = constant_time_select_8(mask, pbuf2[msg_index], pInfo->pbData[ui]); | ||
| 103 | + } | ||
| 104 | |||
| 105 | pCardData->pfnCspFree(pbuf); | ||
| 106 | pCardData->pfnCspFree(pbuf2); | ||
| 107 | |||
| 108 | err: | ||
| 109 | unlock(pCardData); | ||
| 110 | - MD_FUNC_RETURN(pCardData, 1, dwret); | ||
| 111 | + /* do not log return value to not leak it */ | ||
| 112 | + return dwret; | ||
| 113 | } | ||
| 114 | |||
| 115 | |||
| 116 | -- | ||
| 117 | 2.50.0 | ||
| 118 | |||
diff --git a/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0007.patch b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0007.patch new file mode 100644 index 0000000000..ccd44833fa --- /dev/null +++ b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0007.patch | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | From 65f81aa8cdb8fa7e3c54165c9c800e6dae5591c7 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= <vhanulik@redhat.com> | ||
| 3 | Date: Fri, 24 Nov 2023 20:59:07 +0100 | ||
| 4 | Subject: [PATCH 07/10] pkcs11-object: Remove return value logging | ||
| 5 | |||
| 6 | To prevent Marvin attack on RSA PKCS#1 v1.5 padding | ||
| 7 | when logging the return value, signaling the padding error. | ||
| 8 | |||
| 9 | CVE: CVE-2023-5992 | ||
| 10 | Upstream-Status: Backport [https://github.com/OpenSC/OpenSC/pull/2948] | ||
| 11 | |||
| 12 | Signed-off-by: Zhang Peng <peng.zhang1.cn@windriver.com> | ||
| 13 | --- | ||
| 14 | src/pkcs11/pkcs11-object.c | 3 ++- | ||
| 15 | src/pkcs11/sc-pkcs11.h | 5 +++++ | ||
| 16 | 2 files changed, 7 insertions(+), 1 deletion(-) | ||
| 17 | |||
| 18 | diff --git a/src/pkcs11/pkcs11-object.c b/src/pkcs11/pkcs11-object.c | ||
| 19 | index c5cf78a2b..aae149b86 100644 | ||
| 20 | --- a/src/pkcs11/pkcs11-object.c | ||
| 21 | +++ b/src/pkcs11/pkcs11-object.c | ||
| 22 | @@ -930,7 +930,8 @@ CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, /* the session's handle */ | ||
| 23 | rv = reset_login_state(session->slot, rv); | ||
| 24 | } | ||
| 25 | |||
| 26 | - sc_log(context, "C_Decrypt() = %s", lookup_enum ( RV_T, rv )); | ||
| 27 | + /* do not log error code to prevent side channel attack */ | ||
| 28 | + SC_LOG("C_Decrypt()"); | ||
| 29 | sc_pkcs11_unlock(); | ||
| 30 | return rv; | ||
| 31 | } | ||
| 32 | diff --git a/src/pkcs11/sc-pkcs11.h b/src/pkcs11/sc-pkcs11.h | ||
| 33 | index 3c6b92ba4..35c8d5eb3 100644 | ||
| 34 | --- a/src/pkcs11/sc-pkcs11.h | ||
| 35 | +++ b/src/pkcs11/sc-pkcs11.h | ||
| 36 | @@ -226,6 +226,11 @@ struct sc_pkcs11_slot { | ||
| 37 | }; | ||
| 38 | typedef struct sc_pkcs11_slot sc_pkcs11_slot_t; | ||
| 39 | |||
| 40 | +#define SC_LOG(fmt) \ | ||
| 41 | + do { \ | ||
| 42 | + sc_log(context, (fmt)); \ | ||
| 43 | + } while (0) | ||
| 44 | + | ||
| 45 | /* Debug virtual slots. S is slot to be highlighted or NULL | ||
| 46 | * C is a comment format string and args It will be preceded by "VSS " */ | ||
| 47 | #define DEBUG_VSS(S, ...) do { sc_log(context,"VSS " __VA_ARGS__); _debug_virtual_slots(S); } while (0) | ||
| 48 | -- | ||
| 49 | 2.50.0 | ||
| 50 | |||
diff --git a/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0008.patch b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0008.patch new file mode 100644 index 0000000000..d50337902d --- /dev/null +++ b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0008.patch | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | From 60f1966c06ed5fbe9e9e1edeefa2d280f5341484 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= <vhanulik@redhat.com> | ||
| 3 | Date: Fri, 24 Nov 2023 21:00:23 +0100 | ||
| 4 | Subject: [PATCH 08/10] misc: Compare return value constant-time | ||
| 5 | |||
| 6 | CVE: CVE-2023-5992 | ||
| 7 | Upstream-Status: Backport [https://github.com/OpenSC/OpenSC/pull/2948] | ||
| 8 | |||
| 9 | Signed-off-by: Zhang Peng <peng.zhang1.cn@windriver.com> | ||
| 10 | --- | ||
| 11 | src/pkcs11/misc.c | 3 ++- | ||
| 12 | 1 file changed, 2 insertions(+), 1 deletion(-) | ||
| 13 | |||
| 14 | diff --git a/src/pkcs11/misc.c b/src/pkcs11/misc.c | ||
| 15 | index c3f5bb4e1..c0fd07240 100644 | ||
| 16 | --- a/src/pkcs11/misc.c | ||
| 17 | +++ b/src/pkcs11/misc.c | ||
| 18 | @@ -23,6 +23,7 @@ | ||
| 19 | #include <stdlib.h> | ||
| 20 | #include <string.h> | ||
| 21 | |||
| 22 | +#include "common/constant-time.h" | ||
| 23 | #include "sc-pkcs11.h" | ||
| 24 | |||
| 25 | #define DUMP_TEMPLATE_MAX 32 | ||
| 26 | @@ -172,7 +173,7 @@ CK_RV reset_login_state(struct sc_pkcs11_slot *slot, CK_RV rv) | ||
| 27 | slot->p11card->framework->logout(slot); | ||
| 28 | } | ||
| 29 | |||
| 30 | - if (rv == CKR_USER_NOT_LOGGED_IN) { | ||
| 31 | + if (constant_time_eq_s(rv, CKR_USER_NOT_LOGGED_IN)) { | ||
| 32 | slot->login_user = -1; | ||
| 33 | pop_all_login_states(slot); | ||
| 34 | } | ||
| 35 | -- | ||
| 36 | 2.50.0 | ||
| 37 | |||
diff --git a/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0009.patch b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0009.patch new file mode 100644 index 0000000000..d65555bca9 --- /dev/null +++ b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0009.patch | |||
| @@ -0,0 +1,123 @@ | |||
| 1 | From e5f77a60bf22d76f695e360cc5c13c5c9ea8ba0c Mon Sep 17 00:00:00 2001 | ||
| 2 | From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= <vhanulik@redhat.com> | ||
| 3 | Date: Mon, 5 Feb 2024 11:30:11 +0100 | ||
| 4 | Subject: [PATCH 09/10] unittests: Do not use uninitialized memory | ||
| 5 | |||
| 6 | Thanks Coverity CID 414676, 414677, 414678, | ||
| 7 | 414679, 414680, 414681, 414682, 414683, 414684, | ||
| 8 | 414685, 414686 | ||
| 9 | |||
| 10 | CVE: CVE-2023-5992 | ||
| 11 | Upstream-Status: Backport [https://github.com/OpenSC/OpenSC/pull/3016] | ||
| 12 | |||
| 13 | Signed-off-by: Zhang Peng <peng.zhang1.cn@windriver.com> | ||
| 14 | --- | ||
| 15 | src/tests/unittests/strip_pkcs1_2_padding.c | 22 ++++++++++----------- | ||
| 16 | 1 file changed, 11 insertions(+), 11 deletions(-) | ||
| 17 | |||
| 18 | diff --git a/src/tests/unittests/strip_pkcs1_2_padding.c b/src/tests/unittests/strip_pkcs1_2_padding.c | ||
| 19 | index f9561b936..990e94a38 100644 | ||
| 20 | --- a/src/tests/unittests/strip_pkcs1_2_padding.c | ||
| 21 | +++ b/src/tests/unittests/strip_pkcs1_2_padding.c | ||
| 22 | @@ -14,7 +14,7 @@ torture_long_output_buffer(void **state) | ||
| 23 | 0x00, | ||
| 24 | 'm', 's', 'g'}; | ||
| 25 | unsigned int out_len = 3; | ||
| 26 | - unsigned char *out = malloc(out_len * sizeof(unsigned char)); | ||
| 27 | + unsigned char *out = calloc(out_len, sizeof(unsigned char)); | ||
| 28 | unsigned char result_msg[] = {'m', 's', 'g'}; | ||
| 29 | int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); | ||
| 30 | assert_int_equal(r, 3); | ||
| 31 | @@ -32,7 +32,7 @@ torture_short_output_buffer(void **state) | ||
| 32 | 0x00, | ||
| 33 | 'm', 's', 'g'}; | ||
| 34 | unsigned int out_len = 1; | ||
| 35 | - unsigned char *out = malloc(out_len * sizeof(unsigned char)); | ||
| 36 | + unsigned char *out = calloc(out_len, sizeof(unsigned char)); | ||
| 37 | int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); | ||
| 38 | assert_int_equal(r, SC_ERROR_WRONG_PADDING); | ||
| 39 | free(out); | ||
| 40 | @@ -48,7 +48,7 @@ torture_short_message_correct_padding(void **state) | ||
| 41 | 0x00, | ||
| 42 | 'm', 's', 'g'}; | ||
| 43 | unsigned int out_len = 3; | ||
| 44 | - unsigned char *out = malloc(out_len * sizeof(unsigned char)); | ||
| 45 | + unsigned char *out = calloc(out_len, sizeof(unsigned char)); | ||
| 46 | unsigned char result_msg[] = {'m', 's', 'g'}; | ||
| 47 | int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); | ||
| 48 | assert_int_equal(r, 3); | ||
| 49 | @@ -66,7 +66,7 @@ torture_missing_first_zero(void **state) | ||
| 50 | 0x00, | ||
| 51 | 'm', 's', 'g'}; | ||
| 52 | unsigned int out_len = 10; | ||
| 53 | - unsigned char *out = malloc(out_len * sizeof(unsigned char)); | ||
| 54 | + unsigned char *out = calloc(out_len, sizeof(unsigned char)); | ||
| 55 | int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); | ||
| 56 | assert_int_equal(r, SC_ERROR_WRONG_PADDING); | ||
| 57 | free(out); | ||
| 58 | @@ -82,7 +82,7 @@ torture_missing_two(void **state) | ||
| 59 | 0x00, | ||
| 60 | 'm', 's', 'g'}; | ||
| 61 | unsigned int out_len = 10; | ||
| 62 | - unsigned char *out = malloc(out_len * sizeof(unsigned char)); | ||
| 63 | + unsigned char *out = calloc(out_len, sizeof(unsigned char)); | ||
| 64 | int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); | ||
| 65 | assert_int_equal(r, SC_ERROR_WRONG_PADDING); | ||
| 66 | free(out); | ||
| 67 | @@ -98,7 +98,7 @@ torture_short_padding(void **state) | ||
| 68 | 0x00, | ||
| 69 | 'm', 's', 'g'}; | ||
| 70 | unsigned int out_len = 10; | ||
| 71 | - unsigned char *out = malloc(out_len * sizeof(unsigned char)); | ||
| 72 | + unsigned char *out = calloc(out_len, sizeof(unsigned char)); | ||
| 73 | int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); | ||
| 74 | assert_int_equal(r, SC_ERROR_WRONG_PADDING); | ||
| 75 | free(out); | ||
| 76 | @@ -113,7 +113,7 @@ torture_missing_second_zero(void **state) | ||
| 77 | 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, | ||
| 78 | 'm', 's', 'g'}; | ||
| 79 | unsigned int out_len = 10; | ||
| 80 | - unsigned char *out = malloc(out_len * sizeof(unsigned char)); | ||
| 81 | + unsigned char *out = calloc(out_len, sizeof(unsigned char)); | ||
| 82 | int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); | ||
| 83 | assert_int_equal(r, SC_ERROR_WRONG_PADDING); | ||
| 84 | free(out); | ||
| 85 | @@ -128,7 +128,7 @@ torture_missing_message(void **state) | ||
| 86 | 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, | ||
| 87 | 0x00}; | ||
| 88 | unsigned int out_len = 11; | ||
| 89 | - unsigned char *out = malloc(out_len * sizeof(unsigned char)); | ||
| 90 | + unsigned char *out = calloc(out_len, sizeof(unsigned char)); | ||
| 91 | int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); | ||
| 92 | assert_int_equal(r, SC_ERROR_WRONG_PADDING); | ||
| 93 | free(out); | ||
| 94 | @@ -144,7 +144,7 @@ torture_one_byte_message(void **state) | ||
| 95 | 0x00, | ||
| 96 | 'm'}; | ||
| 97 | unsigned int out_len = 1; | ||
| 98 | - unsigned char *out = malloc(out_len * sizeof(unsigned char)); | ||
| 99 | + unsigned char *out = calloc(out_len, sizeof(unsigned char)); | ||
| 100 | unsigned char result_msg[] = {'m'}; | ||
| 101 | int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); | ||
| 102 | assert_int_equal(r, 1); | ||
| 103 | @@ -162,7 +162,7 @@ torture_longer_padding(void **state) | ||
| 104 | 0x00, | ||
| 105 | 0x9d, 0x98, 0x3d, 0xca, 0xa9, 0xa7, 0x11, 0x0a}; | ||
| 106 | unsigned int out_len = 8; | ||
| 107 | - unsigned char *out = malloc(out_len * sizeof(unsigned char)); | ||
| 108 | + unsigned char *out = calloc(out_len, sizeof(unsigned char)); | ||
| 109 | unsigned char result_msg[] = {0x9d, 0x98, 0x3d, 0xca, 0xa9, 0xa7, 0x11, 0x0a}; | ||
| 110 | int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); | ||
| 111 | assert_int_equal(r, 8); | ||
| 112 | @@ -179,7 +179,7 @@ torture_empty_message(void **state) | ||
| 113 | 0x0e, 0x38, 0x97, 0x18, 0x16, 0x57, 0x9e, 0x30, 0xb6, 0xa5, 0x78, 0x13, 0x20, 0xca, 0x11, | ||
| 114 | 0x00}; | ||
| 115 | unsigned int out_len = 8; | ||
| 116 | - unsigned char *out = malloc(out_len * sizeof(unsigned char)); | ||
| 117 | + unsigned char *out = calloc(out_len, sizeof(unsigned char)); | ||
| 118 | int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); | ||
| 119 | assert_int_equal(r, 0); | ||
| 120 | free(out); | ||
| 121 | -- | ||
| 122 | 2.50.0 | ||
| 123 | |||
diff --git a/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0010.patch b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0010.patch new file mode 100644 index 0000000000..2585406b56 --- /dev/null +++ b/meta-oe/recipes-support/opensc/files/CVE-2023-5992-0010.patch | |||
| @@ -0,0 +1,75 @@ | |||
| 1 | From 0039fe386c996faffaa2cf2d728c176cc239468b Mon Sep 17 00:00:00 2001 | ||
| 2 | From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= <vhanulik@redhat.com> | ||
| 3 | Date: Mon, 5 Feb 2024 13:33:05 +0100 | ||
| 4 | Subject: [PATCH 10/10] Fix constant-time comparison of negative values | ||
| 5 | |||
| 6 | Thanks Coverity CID 414687 | ||
| 7 | |||
| 8 | CVE: CVE-2023-5992 | ||
| 9 | Upstream-Status: Backport [https://github.com/OpenSC/OpenSC/pull/3016] | ||
| 10 | |||
| 11 | Signed-off-by: Zhang Peng <peng.zhang1.cn@windriver.com> | ||
| 12 | --- | ||
| 13 | src/common/constant-time.h | 6 ++++++ | ||
| 14 | src/minidriver/minidriver.c | 4 ++-- | ||
| 15 | src/pkcs11/framework-pkcs15.c | 4 ++-- | ||
| 16 | 3 files changed, 10 insertions(+), 4 deletions(-) | ||
| 17 | |||
| 18 | diff --git a/src/common/constant-time.h b/src/common/constant-time.h | ||
| 19 | index 40c3e500c..3f4446d4d 100644 | ||
| 20 | --- a/src/common/constant-time.h | ||
| 21 | +++ b/src/common/constant-time.h | ||
| 22 | @@ -125,4 +125,10 @@ constant_time_eq_s(size_t a, size_t b) | ||
| 23 | return constant_time_is_zero_s(a ^ b); | ||
| 24 | } | ||
| 25 | |||
| 26 | +static constant_inline unsigned int | ||
| 27 | +constant_time_eq_i(int a, int b) | ||
| 28 | +{ | ||
| 29 | + return constant_time_eq((unsigned int)a, (unsigned int)b); | ||
| 30 | +} | ||
| 31 | + | ||
| 32 | #endif /* CONSTANT_TIME_H */ | ||
| 33 | diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c | ||
| 34 | index 37e576ba2..e2be9e53d 100644 | ||
| 35 | --- a/src/minidriver/minidriver.c | ||
| 36 | +++ b/src/minidriver/minidriver.c | ||
| 37 | @@ -4590,7 +4590,7 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData, | ||
| 38 | logprintf(pCardData, 2, "sc_pkcs15_decipher: stripping PKCS1 padding\n"); | ||
| 39 | r = sc_pkcs1_strip_02_padding_constant_time(vs->ctx, prkey_info->modulus_length / 8, pbuf2, pInfo->cbData, pbuf2, &temp); | ||
| 40 | pInfo->cbData = (DWORD) temp; | ||
| 41 | - wrong_padding = constant_time_eq_s(r, SC_ERROR_WRONG_PADDING); | ||
| 42 | + wrong_padding = constant_time_eq_i(r, SC_ERROR_WRONG_PADDING); | ||
| 43 | /* continue without returning error to not leak that padding is wrong | ||
| 44 | to prevent time side-channel leak for Marvin attack*/ | ||
| 45 | } | ||
| 46 | @@ -4640,7 +4640,7 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData, | ||
| 47 | goto err; | ||
| 48 | } | ||
| 49 | |||
| 50 | - good = constant_time_eq_s(r, 0); | ||
| 51 | + good = constant_time_eq_i(r, 0); | ||
| 52 | /* if no error or padding error, do not return here to prevent Marvin attack */ | ||
| 53 | if (!(good | wrong_padding) && r < 0) { | ||
| 54 | logprintf(pCardData, 2, "sc_pkcs15_decipher error(%i): %s\n", r, sc_strerror(r)); | ||
| 55 | diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c | ||
| 56 | index 8376057ea..8b0a63b10 100644 | ||
| 57 | --- a/src/pkcs11/framework-pkcs15.c | ||
| 58 | +++ b/src/pkcs11/framework-pkcs15.c | ||
| 59 | @@ -4433,11 +4433,11 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_session *session, void *obj, | ||
| 60 | |||
| 61 | /* only padding error must be handled in constant-time way, | ||
| 62 | * other error can be returned straight away */ | ||
| 63 | - if ((~constant_time_eq_s(rv, SC_ERROR_WRONG_PADDING) & constant_time_lt_s(sizeof(decrypted), rv))) | ||
| 64 | + if ((~constant_time_eq_i(rv, SC_ERROR_WRONG_PADDING) & constant_time_lt_s(sizeof(decrypted), (size_t)rv))) | ||
| 65 | return sc_to_cryptoki_error(rv, "C_Decrypt"); | ||
| 66 | |||
| 67 | /* check rv for padding error */ | ||
| 68 | - good = ~constant_time_eq_s(rv, SC_ERROR_WRONG_PADDING); | ||
| 69 | + good = ~constant_time_eq_i(rv, SC_ERROR_WRONG_PADDING); | ||
| 70 | rv_pkcs11 = sc_to_cryptoki_error(SC_ERROR_WRONG_PADDING, "C_Decrypt"); | ||
| 71 | rv_pkcs11 = constant_time_select_s(good, CKR_OK, rv_pkcs11); | ||
| 72 | |||
| 73 | -- | ||
| 74 | 2.50.0 | ||
| 75 | |||
