diff options
| author | Narpat Mali <narpat.mali@windriver.com> | 2024-02-09 15:43:55 +0000 |
|---|---|---|
| committer | Steve Sakoman <steve@sakoman.com> | 2024-02-15 03:51:57 -1000 |
| commit | e17cf6a549c53c48629d9454ec744fd2c824a83f (patch) | |
| tree | f6323003aea6761ec845b25b014f91bbbba34894 | |
| parent | d83cb2d0e584f92762bf3ad6d32fd8d96d5c8471 (diff) | |
| download | poky-e17cf6a549c53c48629d9454ec744fd2c824a83f.tar.gz | |
python3-pycryptodome: Fix CVE-2023-52323
PyCryptodome and pycryptodomex before 3.19.1 allow side-channel
leakage for OAEP decryption, exploitable for a Manger attack.
References:
https://security-tracker.debian.org/tracker/CVE-2023-52323
https://github.com/Legrandin/pycryptodome/blob/master/Changelog.rst
(From OE-Core rev: 04c9b6b081914005209bac8eeb9f417e7b989cca)
Signed-off-by: Narpat Mali <narpat.mali@windriver.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
4 files changed, 875 insertions, 0 deletions
diff --git a/meta/recipes-devtools/python/python3-pycryptodome/CVE-2023-52323.patch b/meta/recipes-devtools/python/python3-pycryptodome/CVE-2023-52323.patch new file mode 100644 index 0000000000..be3090eb8d --- /dev/null +++ b/meta/recipes-devtools/python/python3-pycryptodome/CVE-2023-52323.patch | |||
| @@ -0,0 +1,436 @@ | |||
| 1 | From 73bbed822fadddf3c0ab4a945ee6ab16bbca6961 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Helder Eijs <helderijs@gmail.com> | ||
| 3 | Date: Thu, 1 Feb 2024 13:43:44 +0000 | ||
| 4 | Subject: [PATCH] Use constant-time (faster) padding decoding also for OAEP | ||
| 5 | |||
| 6 | CVE: CVE-2023-52323 | ||
| 7 | |||
| 8 | Upstream-Status: Backport [https://github.com/Legrandin/pycryptodome/commit/0deea1bfe1489e8c80d2053bbb06a1aa0b181ebd] | ||
| 9 | |||
| 10 | Signed-off-by: Narpat Mali <narpat.mali@windriver.com> | ||
| 11 | --- | ||
| 12 | lib/Crypto/Cipher/PKCS1_OAEP.py | 38 +++++------- | ||
| 13 | lib/Crypto/Cipher/PKCS1_v1_5.py | 31 +--------- | ||
| 14 | lib/Crypto/Cipher/_pkcs1_oaep_decode.py | 41 +++++++++++++ | ||
| 15 | src/pkcs1_decode.c | 79 +++++++++++++++++++++++-- | ||
| 16 | src/test/test_pkcs1.c | 22 +++---- | ||
| 17 | 5 files changed, 145 insertions(+), 66 deletions(-) | ||
| 18 | create mode 100644 lib/Crypto/Cipher/_pkcs1_oaep_decode.py | ||
| 19 | |||
| 20 | diff --git a/lib/Crypto/Cipher/PKCS1_OAEP.py b/lib/Crypto/Cipher/PKCS1_OAEP.py | ||
| 21 | index 57a982b..6974584 100644 | ||
| 22 | --- a/lib/Crypto/Cipher/PKCS1_OAEP.py | ||
| 23 | +++ b/lib/Crypto/Cipher/PKCS1_OAEP.py | ||
| 24 | @@ -23,11 +23,13 @@ | ||
| 25 | from Crypto.Signature.pss import MGF1 | ||
| 26 | import Crypto.Hash.SHA1 | ||
| 27 | |||
| 28 | -from Crypto.Util.py3compat import bord, _copy_bytes | ||
| 29 | +from Crypto.Util.py3compat import _copy_bytes | ||
| 30 | import Crypto.Util.number | ||
| 31 | -from Crypto.Util.number import ceil_div, bytes_to_long, long_to_bytes | ||
| 32 | -from Crypto.Util.strxor import strxor | ||
| 33 | +from Crypto.Util.number import ceil_div, bytes_to_long, long_to_bytes | ||
| 34 | +from Crypto.Util.strxor import strxor | ||
| 35 | from Crypto import Random | ||
| 36 | +from ._pkcs1_oaep_decode import oaep_decode | ||
| 37 | + | ||
| 38 | |||
| 39 | class PKCS1OAEP_Cipher: | ||
| 40 | """Cipher object for PKCS#1 v1.5 OAEP. | ||
| 41 | @@ -68,7 +70,7 @@ class PKCS1OAEP_Cipher: | ||
| 42 | if mgfunc: | ||
| 43 | self._mgf = mgfunc | ||
| 44 | else: | ||
| 45 | - self._mgf = lambda x,y: MGF1(x,y,self._hashObj) | ||
| 46 | + self._mgf = lambda x, y: MGF1(x, y, self._hashObj) | ||
| 47 | |||
| 48 | self._label = _copy_bytes(None, None, label) | ||
| 49 | self._randfunc = randfunc | ||
| 50 | @@ -105,7 +107,7 @@ class PKCS1OAEP_Cipher: | ||
| 51 | |||
| 52 | # See 7.1.1 in RFC3447 | ||
| 53 | modBits = Crypto.Util.number.size(self._key.n) | ||
| 54 | - k = ceil_div(modBits, 8) # Convert from bits to bytes | ||
| 55 | + k = ceil_div(modBits, 8) # Convert from bits to bytes | ||
| 56 | hLen = self._hashObj.digest_size | ||
| 57 | mLen = len(message) | ||
| 58 | |||
| 59 | @@ -159,11 +161,11 @@ class PKCS1OAEP_Cipher: | ||
| 60 | |||
| 61 | # See 7.1.2 in RFC3447 | ||
| 62 | modBits = Crypto.Util.number.size(self._key.n) | ||
| 63 | - k = ceil_div(modBits,8) # Convert from bits to bytes | ||
| 64 | + k = ceil_div(modBits, 8) # Convert from bits to bytes | ||
| 65 | hLen = self._hashObj.digest_size | ||
| 66 | |||
| 67 | # Step 1b and 1c | ||
| 68 | - if len(ciphertext) != k or k<hLen+2: | ||
| 69 | + if len(ciphertext) != k or k < hLen+2: | ||
| 70 | raise ValueError("Ciphertext with incorrect length.") | ||
| 71 | # Step 2a (O2SIP) | ||
| 72 | ct_int = bytes_to_long(ciphertext) | ||
| 73 | @@ -173,8 +175,6 @@ class PKCS1OAEP_Cipher: | ||
| 74 | em = long_to_bytes(m_int, k) | ||
| 75 | # Step 3a | ||
| 76 | lHash = self._hashObj.new(self._label).digest() | ||
| 77 | - # Step 3b | ||
| 78 | - y = em[0] | ||
| 79 | # y must be 0, but we MUST NOT check it here in order not to | ||
| 80 | # allow attacks like Manger's (http://dl.acm.org/citation.cfm?id=704143) | ||
| 81 | maskedSeed = em[1:hLen+1] | ||
| 82 | @@ -187,22 +187,17 @@ class PKCS1OAEP_Cipher: | ||
| 83 | dbMask = self._mgf(seed, k-hLen-1) | ||
| 84 | # Step 3f | ||
| 85 | db = strxor(maskedDB, dbMask) | ||
| 86 | - # Step 3g | ||
| 87 | - one_pos = hLen + db[hLen:].find(b'\x01') | ||
| 88 | - lHash1 = db[:hLen] | ||
| 89 | - invalid = bord(y) | int(one_pos < hLen) | ||
| 90 | - hash_compare = strxor(lHash1, lHash) | ||
| 91 | - for x in hash_compare: | ||
| 92 | - invalid |= bord(x) | ||
| 93 | - for x in db[hLen:one_pos]: | ||
| 94 | - invalid |= bord(x) | ||
| 95 | - if invalid != 0: | ||
| 96 | + # Step 3b + 3g | ||
| 97 | + res = oaep_decode(em, lHash, db) | ||
| 98 | + if res <= 0: | ||
| 99 | raise ValueError("Incorrect decryption.") | ||
| 100 | # Step 4 | ||
| 101 | - return db[one_pos + 1:] | ||
| 102 | + return db[res:] | ||
| 103 | + | ||
| 104 | |||
| 105 | def new(key, hashAlgo=None, mgfunc=None, label=b'', randfunc=None): | ||
| 106 | - """Return a cipher object :class:`PKCS1OAEP_Cipher` that can be used to perform PKCS#1 OAEP encryption or decryption. | ||
| 107 | + """Return a cipher object :class:`PKCS1OAEP_Cipher` | ||
| 108 | + that can be used to perform PKCS#1 OAEP encryption or decryption. | ||
| 109 | |||
| 110 | :param key: | ||
| 111 | The key object to use to encrypt or decrypt the message. | ||
| 112 | @@ -236,4 +231,3 @@ def new(key, hashAlgo=None, mgfunc=None, label=b'', randfunc=None): | ||
| 113 | if randfunc is None: | ||
| 114 | randfunc = Random.get_random_bytes | ||
| 115 | return PKCS1OAEP_Cipher(key, hashAlgo, mgfunc, label, randfunc) | ||
| 116 | - | ||
| 117 | diff --git a/lib/Crypto/Cipher/PKCS1_v1_5.py b/lib/Crypto/Cipher/PKCS1_v1_5.py | ||
| 118 | index d0d474a..94e99cf 100644 | ||
| 119 | --- a/lib/Crypto/Cipher/PKCS1_v1_5.py | ||
| 120 | +++ b/lib/Crypto/Cipher/PKCS1_v1_5.py | ||
| 121 | @@ -25,31 +25,7 @@ __all__ = ['new', 'PKCS115_Cipher'] | ||
| 122 | from Crypto import Random | ||
| 123 | from Crypto.Util.number import bytes_to_long, long_to_bytes | ||
| 124 | from Crypto.Util.py3compat import bord, is_bytes, _copy_bytes | ||
| 125 | - | ||
| 126 | -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, c_size_t, | ||
| 127 | - c_uint8_ptr) | ||
| 128 | - | ||
| 129 | - | ||
| 130 | -_raw_pkcs1_decode = load_pycryptodome_raw_lib("Crypto.Cipher._pkcs1_decode", | ||
| 131 | - """ | ||
| 132 | - int pkcs1_decode(const uint8_t *em, size_t len_em, | ||
| 133 | - const uint8_t *sentinel, size_t len_sentinel, | ||
| 134 | - size_t expected_pt_len, | ||
| 135 | - uint8_t *output); | ||
| 136 | - """) | ||
| 137 | - | ||
| 138 | - | ||
| 139 | -def _pkcs1_decode(em, sentinel, expected_pt_len, output): | ||
| 140 | - if len(em) != len(output): | ||
| 141 | - raise ValueError("Incorrect output length") | ||
| 142 | - | ||
| 143 | - ret = _raw_pkcs1_decode.pkcs1_decode(c_uint8_ptr(em), | ||
| 144 | - c_size_t(len(em)), | ||
| 145 | - c_uint8_ptr(sentinel), | ||
| 146 | - c_size_t(len(sentinel)), | ||
| 147 | - c_size_t(expected_pt_len), | ||
| 148 | - c_uint8_ptr(output)) | ||
| 149 | - return ret | ||
| 150 | +from ._pkcs1_oaep_decode import pkcs1_decode | ||
| 151 | |||
| 152 | |||
| 153 | class PKCS115_Cipher: | ||
| 154 | @@ -113,7 +89,6 @@ class PKCS115_Cipher: | ||
| 155 | continue | ||
| 156 | ps.append(new_byte) | ||
| 157 | ps = b"".join(ps) | ||
| 158 | - assert(len(ps) == k - mLen - 3) | ||
| 159 | # Step 2b | ||
| 160 | em = b'\x00\x02' + ps + b'\x00' + _copy_bytes(None, None, message) | ||
| 161 | # Step 3a (OS2IP) | ||
| 162 | @@ -185,14 +160,14 @@ class PKCS115_Cipher: | ||
| 163 | # Step 3 (not constant time when the sentinel is not a byte string) | ||
| 164 | output = bytes(bytearray(k)) | ||
| 165 | if not is_bytes(sentinel) or len(sentinel) > k: | ||
| 166 | - size = _pkcs1_decode(em, b'', expected_pt_len, output) | ||
| 167 | + size = pkcs1_decode(em, b'', expected_pt_len, output) | ||
| 168 | if size < 0: | ||
| 169 | return sentinel | ||
| 170 | else: | ||
| 171 | return output[size:] | ||
| 172 | |||
| 173 | # Step 3 (somewhat constant time) | ||
| 174 | - size = _pkcs1_decode(em, sentinel, expected_pt_len, output) | ||
| 175 | + size = pkcs1_decode(em, sentinel, expected_pt_len, output) | ||
| 176 | return output[size:] | ||
| 177 | |||
| 178 | |||
| 179 | diff --git a/lib/Crypto/Cipher/_pkcs1_oaep_decode.py b/lib/Crypto/Cipher/_pkcs1_oaep_decode.py | ||
| 180 | new file mode 100644 | ||
| 181 | index 0000000..fc07528 | ||
| 182 | --- /dev/null | ||
| 183 | +++ b/lib/Crypto/Cipher/_pkcs1_oaep_decode.py | ||
| 184 | @@ -0,0 +1,41 @@ | ||
| 185 | +from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, c_size_t, | ||
| 186 | + c_uint8_ptr) | ||
| 187 | + | ||
| 188 | + | ||
| 189 | +_raw_pkcs1_decode = load_pycryptodome_raw_lib("Crypto.Cipher._pkcs1_decode", | ||
| 190 | + """ | ||
| 191 | + int pkcs1_decode(const uint8_t *em, size_t len_em, | ||
| 192 | + const uint8_t *sentinel, size_t len_sentinel, | ||
| 193 | + size_t expected_pt_len, | ||
| 194 | + uint8_t *output); | ||
| 195 | + | ||
| 196 | + int oaep_decode(const uint8_t *em, | ||
| 197 | + size_t em_len, | ||
| 198 | + const uint8_t *lHash, | ||
| 199 | + size_t hLen, | ||
| 200 | + const uint8_t *db, | ||
| 201 | + size_t db_len); | ||
| 202 | + """) | ||
| 203 | + | ||
| 204 | + | ||
| 205 | +def pkcs1_decode(em, sentinel, expected_pt_len, output): | ||
| 206 | + if len(em) != len(output): | ||
| 207 | + raise ValueError("Incorrect output length") | ||
| 208 | + | ||
| 209 | + ret = _raw_pkcs1_decode.pkcs1_decode(c_uint8_ptr(em), | ||
| 210 | + c_size_t(len(em)), | ||
| 211 | + c_uint8_ptr(sentinel), | ||
| 212 | + c_size_t(len(sentinel)), | ||
| 213 | + c_size_t(expected_pt_len), | ||
| 214 | + c_uint8_ptr(output)) | ||
| 215 | + return ret | ||
| 216 | + | ||
| 217 | + | ||
| 218 | +def oaep_decode(em, lHash, db): | ||
| 219 | + ret = _raw_pkcs1_decode.oaep_decode(c_uint8_ptr(em), | ||
| 220 | + c_size_t(len(em)), | ||
| 221 | + c_uint8_ptr(lHash), | ||
| 222 | + c_size_t(len(lHash)), | ||
| 223 | + c_uint8_ptr(db), | ||
| 224 | + c_size_t(len(db))) | ||
| 225 | + return ret | ||
| 226 | diff --git a/src/pkcs1_decode.c b/src/pkcs1_decode.c | ||
| 227 | index 207b198..74cb4a2 100644 | ||
| 228 | --- a/src/pkcs1_decode.c | ||
| 229 | +++ b/src/pkcs1_decode.c | ||
| 230 | @@ -130,7 +130,7 @@ STATIC size_t safe_select_idx(size_t in1, size_t in2, uint8_t choice) | ||
| 231 | * - in1[] is NOT equal to in2[] where neq_mask[] is 0xFF. | ||
| 232 | * Return non-zero otherwise. | ||
| 233 | */ | ||
| 234 | -STATIC uint8_t safe_cmp(const uint8_t *in1, const uint8_t *in2, | ||
| 235 | +STATIC uint8_t safe_cmp_masks(const uint8_t *in1, const uint8_t *in2, | ||
| 236 | const uint8_t *eq_mask, const uint8_t *neq_mask, | ||
| 237 | size_t len) | ||
| 238 | { | ||
| 239 | @@ -187,7 +187,7 @@ STATIC size_t safe_search(const uint8_t *in1, uint8_t c, size_t len) | ||
| 240 | return result; | ||
| 241 | } | ||
| 242 | |||
| 243 | -#define EM_PREFIX_LEN 10 | ||
| 244 | +#define PKCS1_PREFIX_LEN 10 | ||
| 245 | |||
| 246 | /* | ||
| 247 | * Decode and verify the PKCS#1 padding, then put either the plaintext | ||
| 248 | @@ -222,13 +222,13 @@ EXPORT_SYM int pkcs1_decode(const uint8_t *em, size_t len_em_output, | ||
| 249 | if (NULL == em || NULL == output || NULL == sentinel) { | ||
| 250 | return -1; | ||
| 251 | } | ||
| 252 | - if (len_em_output < (EM_PREFIX_LEN + 2)) { | ||
| 253 | + if (len_em_output < (PKCS1_PREFIX_LEN + 2)) { | ||
| 254 | return -1; | ||
| 255 | } | ||
| 256 | if (len_sentinel > len_em_output) { | ||
| 257 | return -1; | ||
| 258 | } | ||
| 259 | - if (expected_pt_len > 0 && expected_pt_len > (len_em_output - EM_PREFIX_LEN - 1)) { | ||
| 260 | + if (expected_pt_len > 0 && expected_pt_len > (len_em_output - PKCS1_PREFIX_LEN - 1)) { | ||
| 261 | return -1; | ||
| 262 | } | ||
| 263 | |||
| 264 | @@ -240,7 +240,7 @@ EXPORT_SYM int pkcs1_decode(const uint8_t *em, size_t len_em_output, | ||
| 265 | memcpy(padded_sentinel + (len_em_output - len_sentinel), sentinel, len_sentinel); | ||
| 266 | |||
| 267 | /** The first 10 bytes must follow the pattern **/ | ||
| 268 | - match = safe_cmp(em, | ||
| 269 | + match = safe_cmp_masks(em, | ||
| 270 | (const uint8_t*)"\x00\x02" "\x00\x00\x00\x00\x00\x00\x00\x00", | ||
| 271 | (const uint8_t*)"\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00", | ||
| 272 | (const uint8_t*)"\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", | ||
| 273 | @@ -283,3 +283,72 @@ end: | ||
| 274 | free(padded_sentinel); | ||
| 275 | return result; | ||
| 276 | } | ||
| 277 | + | ||
| 278 | +/* | ||
| 279 | + * Decode and verify the OAEP padding in constant time. | ||
| 280 | + * | ||
| 281 | + * The function returns the number of bytes to ignore at the beginning | ||
| 282 | + * of db (the rest is the plaintext), or -1 in case of problems. | ||
| 283 | + */ | ||
| 284 | + | ||
| 285 | +EXPORT_SYM int oaep_decode(const uint8_t *em, | ||
| 286 | + size_t em_len, | ||
| 287 | + const uint8_t *lHash, | ||
| 288 | + size_t hLen, | ||
| 289 | + const uint8_t *db, | ||
| 290 | + size_t db_len) /* em_len - 1 - hLen */ | ||
| 291 | +{ | ||
| 292 | + int result; | ||
| 293 | + size_t one_pos, search_len, i; | ||
| 294 | + uint8_t wrong_padding; | ||
| 295 | + uint8_t *eq_mask = NULL; | ||
| 296 | + uint8_t *neq_mask = NULL; | ||
| 297 | + uint8_t *target_db = NULL; | ||
| 298 | + | ||
| 299 | + if (NULL == em || NULL == lHash || NULL == db) { | ||
| 300 | + return -1; | ||
| 301 | + } | ||
| 302 | + | ||
| 303 | + if (em_len < 2*hLen+2 || db_len != em_len-1-hLen) { | ||
| 304 | + return -1; | ||
| 305 | + } | ||
| 306 | + | ||
| 307 | + /* Allocate */ | ||
| 308 | + eq_mask = (uint8_t*) calloc(1, db_len); | ||
| 309 | + neq_mask = (uint8_t*) calloc(1, db_len); | ||
| 310 | + target_db = (uint8_t*) calloc(1, db_len); | ||
| 311 | + if (NULL == eq_mask || NULL == neq_mask || NULL == target_db) { | ||
| 312 | + result = -1; | ||
| 313 | + goto cleanup; | ||
| 314 | + } | ||
| 315 | + | ||
| 316 | + /* Step 3g */ | ||
| 317 | + search_len = db_len - hLen; | ||
| 318 | + | ||
| 319 | + one_pos = safe_search(db + hLen, 0x01, search_len); | ||
| 320 | + if (SIZE_T_MAX == one_pos) { | ||
| 321 | + result = -1; | ||
| 322 | + goto cleanup; | ||
| 323 | + } | ||
| 324 | + | ||
| 325 | + memset(eq_mask, 0xAA, db_len); | ||
| 326 | + memcpy(target_db, lHash, hLen); | ||
| 327 | + memset(eq_mask, 0xFF, hLen); | ||
| 328 | + | ||
| 329 | + for (i=0; i<search_len; i++) { | ||
| 330 | + eq_mask[hLen + i] = propagate_ones(i < one_pos); | ||
| 331 | + } | ||
| 332 | + | ||
| 333 | + wrong_padding = em[0]; | ||
| 334 | + wrong_padding |= safe_cmp_masks(db, target_db, eq_mask, neq_mask, db_len); | ||
| 335 | + set_if_match(&wrong_padding, one_pos, search_len); | ||
| 336 | + | ||
| 337 | + result = wrong_padding ? -1 : (int)(hLen + 1 + one_pos); | ||
| 338 | + | ||
| 339 | +cleanup: | ||
| 340 | + free(eq_mask); | ||
| 341 | + free(neq_mask); | ||
| 342 | + free(target_db); | ||
| 343 | + | ||
| 344 | + return result; | ||
| 345 | +} | ||
| 346 | diff --git a/src/test/test_pkcs1.c b/src/test/test_pkcs1.c | ||
| 347 | index 6ef63cb..69aaac5 100644 | ||
| 348 | --- a/src/test/test_pkcs1.c | ||
| 349 | +++ b/src/test/test_pkcs1.c | ||
| 350 | @@ -5,7 +5,7 @@ void set_if_match(uint8_t *flag, size_t term1, size_t term2); | ||
| 351 | void set_if_no_match(uint8_t *flag, size_t term1, size_t term2); | ||
| 352 | void safe_select(const uint8_t *in1, const uint8_t *in2, uint8_t *out, uint8_t choice, size_t len); | ||
| 353 | size_t safe_select_idx(size_t in1, size_t in2, uint8_t choice); | ||
| 354 | -uint8_t safe_cmp(const uint8_t *in1, const uint8_t *in2, | ||
| 355 | +uint8_t safe_cmp_masks(const uint8_t *in1, const uint8_t *in2, | ||
| 356 | const uint8_t *eq_mask, const uint8_t *neq_mask, | ||
| 357 | size_t len); | ||
| 358 | size_t safe_search(const uint8_t *in1, uint8_t c, size_t len); | ||
| 359 | @@ -80,29 +80,29 @@ void test_safe_select_idx() | ||
| 360 | assert(safe_select_idx(0x100004, 0x223344, 1) == 0x223344); | ||
| 361 | } | ||
| 362 | |||
| 363 | -void test_safe_cmp() | ||
| 364 | +void test_safe_cmp_masks(void) | ||
| 365 | { | ||
| 366 | uint8_t res; | ||
| 367 | |||
| 368 | - res = safe_cmp(onezero, onezero, | ||
| 369 | + res = safe_cmp_masks(onezero, onezero, | ||
| 370 | (uint8_t*)"\xFF\xFF", | ||
| 371 | (uint8_t*)"\x00\x00", | ||
| 372 | 2); | ||
| 373 | assert(res == 0); | ||
| 374 | |||
| 375 | - res = safe_cmp(onezero, zerozero, | ||
| 376 | + res = safe_cmp_masks(onezero, zerozero, | ||
| 377 | (uint8_t*)"\xFF\xFF", | ||
| 378 | (uint8_t*)"\x00\x00", | ||
| 379 | 2); | ||
| 380 | assert(res != 0); | ||
| 381 | |||
| 382 | - res = safe_cmp(onezero, oneone, | ||
| 383 | + res = safe_cmp_masks(onezero, oneone, | ||
| 384 | (uint8_t*)"\xFF\xFF", | ||
| 385 | (uint8_t*)"\x00\x00", | ||
| 386 | 2); | ||
| 387 | assert(res != 0); | ||
| 388 | |||
| 389 | - res = safe_cmp(onezero, oneone, | ||
| 390 | + res = safe_cmp_masks(onezero, oneone, | ||
| 391 | (uint8_t*)"\xFF\x00", | ||
| 392 | (uint8_t*)"\x00\x00", | ||
| 393 | 2); | ||
| 394 | @@ -110,19 +110,19 @@ void test_safe_cmp() | ||
| 395 | |||
| 396 | /** -- **/ | ||
| 397 | |||
| 398 | - res = safe_cmp(onezero, onezero, | ||
| 399 | + res = safe_cmp_masks(onezero, onezero, | ||
| 400 | (uint8_t*)"\x00\x00", | ||
| 401 | (uint8_t*)"\xFF\xFF", | ||
| 402 | 2); | ||
| 403 | assert(res != 0); | ||
| 404 | |||
| 405 | - res = safe_cmp(oneone, zerozero, | ||
| 406 | + res = safe_cmp_masks(oneone, zerozero, | ||
| 407 | (uint8_t*)"\x00\x00", | ||
| 408 | (uint8_t*)"\xFF\xFF", | ||
| 409 | 2); | ||
| 410 | assert(res == 0); | ||
| 411 | |||
| 412 | - res = safe_cmp(onezero, oneone, | ||
| 413 | + res = safe_cmp_masks(onezero, oneone, | ||
| 414 | (uint8_t*)"\x00\x00", | ||
| 415 | (uint8_t*)"\x00\xFF", | ||
| 416 | 2); | ||
| 417 | @@ -130,7 +130,7 @@ void test_safe_cmp() | ||
| 418 | |||
| 419 | /** -- **/ | ||
| 420 | |||
| 421 | - res = safe_cmp(onezero, oneone, | ||
| 422 | + res = safe_cmp_masks(onezero, oneone, | ||
| 423 | (uint8_t*)"\xFF\x00", | ||
| 424 | (uint8_t*)"\x00\xFF", | ||
| 425 | 2); | ||
| 426 | @@ -158,7 +158,7 @@ int main(void) | ||
| 427 | test_set_if_no_match(); | ||
| 428 | test_safe_select(); | ||
| 429 | test_safe_select_idx(); | ||
| 430 | - test_safe_cmp(); | ||
| 431 | + test_safe_cmp_masks(); | ||
| 432 | test_safe_search(); | ||
| 433 | return 0; | ||
| 434 | } | ||
| 435 | -- | ||
| 436 | 2.40.0 | ||
diff --git a/meta/recipes-devtools/python/python3-pycryptodome_3.14.1.bb b/meta/recipes-devtools/python/python3-pycryptodome_3.14.1.bb index c0324590c2..1e6c514224 100644 --- a/meta/recipes-devtools/python/python3-pycryptodome_3.14.1.bb +++ b/meta/recipes-devtools/python/python3-pycryptodome_3.14.1.bb | |||
| @@ -3,3 +3,4 @@ inherit setuptools3 | |||
| 3 | 3 | ||
| 4 | SRC_URI[sha256sum] = "e04e40a7f8c1669195536a37979dd87da2c32dbdc73d6fe35f0077b0c17c803b" | 4 | SRC_URI[sha256sum] = "e04e40a7f8c1669195536a37979dd87da2c32dbdc73d6fe35f0077b0c17c803b" |
| 5 | 5 | ||
| 6 | SRC_URI += "file://CVE-2023-52323.patch" | ||
diff --git a/meta/recipes-devtools/python/python3-pycryptodomex/CVE-2023-52323.patch b/meta/recipes-devtools/python/python3-pycryptodomex/CVE-2023-52323.patch new file mode 100644 index 0000000000..56000b996e --- /dev/null +++ b/meta/recipes-devtools/python/python3-pycryptodomex/CVE-2023-52323.patch | |||
| @@ -0,0 +1,436 @@ | |||
| 1 | From 8ed5cf533be298d40ec9f75a188738ad4c3a8417 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Narpat Mali <narpat.mali@windriver.com> | ||
| 3 | Date: Thu, 8 Feb 2024 09:09:35 +0000 | ||
| 4 | Subject: [PATCH] Use constant-time (faster) padding decoding also for OAEP | ||
| 5 | |||
| 6 | CVE: CVE-2023-52323 | ||
| 7 | |||
| 8 | Upstream-Status: Backport [https://github.com/Legrandin/pycryptodome/commit/0deea1bfe1489e8c80d2053bbb06a1aa0b181ebd] | ||
| 9 | |||
| 10 | Signed-off-by: Narpat Mali <narpat.mali@windriver.com> | ||
| 11 | --- | ||
| 12 | lib/Cryptodome/Cipher/PKCS1_OAEP.py | 38 +++++----- | ||
| 13 | lib/Cryptodome/Cipher/PKCS1_v1_5.py | 31 +------- | ||
| 14 | lib/Cryptodome/Cipher/_pkcs1_oaep_decode.py | 41 +++++++++++ | ||
| 15 | src/pkcs1_decode.c | 79 +++++++++++++++++++-- | ||
| 16 | src/test/test_pkcs1.c | 22 +++--- | ||
| 17 | 5 files changed, 145 insertions(+), 66 deletions(-) | ||
| 18 | create mode 100644 lib/Cryptodome/Cipher/_pkcs1_oaep_decode.py | ||
| 19 | |||
| 20 | diff --git a/lib/Cryptodome/Cipher/PKCS1_OAEP.py b/lib/Cryptodome/Cipher/PKCS1_OAEP.py | ||
| 21 | index 7525c5d..653df04 100644 | ||
| 22 | --- a/lib/Cryptodome/Cipher/PKCS1_OAEP.py | ||
| 23 | +++ b/lib/Cryptodome/Cipher/PKCS1_OAEP.py | ||
| 24 | @@ -23,11 +23,13 @@ | ||
| 25 | from Cryptodome.Signature.pss import MGF1 | ||
| 26 | import Cryptodome.Hash.SHA1 | ||
| 27 | |||
| 28 | -from Cryptodome.Util.py3compat import bord, _copy_bytes | ||
| 29 | +from Crypto.Util.py3compat import _copy_bytes | ||
| 30 | import Cryptodome.Util.number | ||
| 31 | -from Cryptodome.Util.number import ceil_div, bytes_to_long, long_to_bytes | ||
| 32 | -from Cryptodome.Util.strxor import strxor | ||
| 33 | +from Crypto.Util.number import ceil_div, bytes_to_long, long_to_bytes | ||
| 34 | +from Crypto.Util.strxor import strxor | ||
| 35 | from Cryptodome import Random | ||
| 36 | +from ._pkcs1_oaep_decode import oaep_decode | ||
| 37 | + | ||
| 38 | |||
| 39 | class PKCS1OAEP_Cipher: | ||
| 40 | """Cipher object for PKCS#1 v1.5 OAEP. | ||
| 41 | @@ -68,7 +70,7 @@ class PKCS1OAEP_Cipher: | ||
| 42 | if mgfunc: | ||
| 43 | self._mgf = mgfunc | ||
| 44 | else: | ||
| 45 | - self._mgf = lambda x,y: MGF1(x,y,self._hashObj) | ||
| 46 | + self._mgf = lambda x, y: MGF1(x, y, self._hashObj) | ||
| 47 | |||
| 48 | self._label = _copy_bytes(None, None, label) | ||
| 49 | self._randfunc = randfunc | ||
| 50 | @@ -105,7 +107,7 @@ class PKCS1OAEP_Cipher: | ||
| 51 | |||
| 52 | # See 7.1.1 in RFC3447 | ||
| 53 | modBits = Cryptodome.Util.number.size(self._key.n) | ||
| 54 | - k = ceil_div(modBits, 8) # Convert from bits to bytes | ||
| 55 | + k = ceil_div(modBits, 8) # Convert from bits to bytes | ||
| 56 | hLen = self._hashObj.digest_size | ||
| 57 | mLen = len(message) | ||
| 58 | |||
| 59 | @@ -159,11 +161,11 @@ class PKCS1OAEP_Cipher: | ||
| 60 | |||
| 61 | # See 7.1.2 in RFC3447 | ||
| 62 | modBits = Cryptodome.Util.number.size(self._key.n) | ||
| 63 | - k = ceil_div(modBits,8) # Convert from bits to bytes | ||
| 64 | + k = ceil_div(modBits, 8) # Convert from bits to bytes | ||
| 65 | hLen = self._hashObj.digest_size | ||
| 66 | |||
| 67 | # Step 1b and 1c | ||
| 68 | - if len(ciphertext) != k or k<hLen+2: | ||
| 69 | + if len(ciphertext) != k or k < hLen+2: | ||
| 70 | raise ValueError("Ciphertext with incorrect length.") | ||
| 71 | # Step 2a (O2SIP) | ||
| 72 | ct_int = bytes_to_long(ciphertext) | ||
| 73 | @@ -173,8 +175,6 @@ class PKCS1OAEP_Cipher: | ||
| 74 | em = long_to_bytes(m_int, k) | ||
| 75 | # Step 3a | ||
| 76 | lHash = self._hashObj.new(self._label).digest() | ||
| 77 | - # Step 3b | ||
| 78 | - y = em[0] | ||
| 79 | # y must be 0, but we MUST NOT check it here in order not to | ||
| 80 | # allow attacks like Manger's (http://dl.acm.org/citation.cfm?id=704143) | ||
| 81 | maskedSeed = em[1:hLen+1] | ||
| 82 | @@ -187,22 +187,17 @@ class PKCS1OAEP_Cipher: | ||
| 83 | dbMask = self._mgf(seed, k-hLen-1) | ||
| 84 | # Step 3f | ||
| 85 | db = strxor(maskedDB, dbMask) | ||
| 86 | - # Step 3g | ||
| 87 | - one_pos = hLen + db[hLen:].find(b'\x01') | ||
| 88 | - lHash1 = db[:hLen] | ||
| 89 | - invalid = bord(y) | int(one_pos < hLen) | ||
| 90 | - hash_compare = strxor(lHash1, lHash) | ||
| 91 | - for x in hash_compare: | ||
| 92 | - invalid |= bord(x) | ||
| 93 | - for x in db[hLen:one_pos]: | ||
| 94 | - invalid |= bord(x) | ||
| 95 | - if invalid != 0: | ||
| 96 | + # Step 3b + 3g | ||
| 97 | + res = oaep_decode(em, lHash, db) | ||
| 98 | + if res <= 0: | ||
| 99 | raise ValueError("Incorrect decryption.") | ||
| 100 | # Step 4 | ||
| 101 | - return db[one_pos + 1:] | ||
| 102 | + return db[res:] | ||
| 103 | + | ||
| 104 | |||
| 105 | def new(key, hashAlgo=None, mgfunc=None, label=b'', randfunc=None): | ||
| 106 | - """Return a cipher object :class:`PKCS1OAEP_Cipher` that can be used to perform PKCS#1 OAEP encryption or decryption. | ||
| 107 | + """Return a cipher object :class:`PKCS1OAEP_Cipher` | ||
| 108 | + that can be used to perform PKCS#1 OAEP encryption or decryption. | ||
| 109 | |||
| 110 | :param key: | ||
| 111 | The key object to use to encrypt or decrypt the message. | ||
| 112 | @@ -236,4 +231,3 @@ def new(key, hashAlgo=None, mgfunc=None, label=b'', randfunc=None): | ||
| 113 | if randfunc is None: | ||
| 114 | randfunc = Random.get_random_bytes | ||
| 115 | return PKCS1OAEP_Cipher(key, hashAlgo, mgfunc, label, randfunc) | ||
| 116 | - | ||
| 117 | diff --git a/lib/Cryptodome/Cipher/PKCS1_v1_5.py b/lib/Cryptodome/Cipher/PKCS1_v1_5.py | ||
| 118 | index 17ef9eb..f20a7ce 100644 | ||
| 119 | --- a/lib/Cryptodome/Cipher/PKCS1_v1_5.py | ||
| 120 | +++ b/lib/Cryptodome/Cipher/PKCS1_v1_5.py | ||
| 121 | @@ -25,31 +25,7 @@ __all__ = ['new', 'PKCS115_Cipher'] | ||
| 122 | from Cryptodome import Random | ||
| 123 | from Cryptodome.Util.number import bytes_to_long, long_to_bytes | ||
| 124 | from Cryptodome.Util.py3compat import bord, is_bytes, _copy_bytes | ||
| 125 | - | ||
| 126 | -from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, c_size_t, | ||
| 127 | - c_uint8_ptr) | ||
| 128 | - | ||
| 129 | - | ||
| 130 | -_raw_pkcs1_decode = load_pycryptodome_raw_lib("Cryptodome.Cipher._pkcs1_decode", | ||
| 131 | - """ | ||
| 132 | - int pkcs1_decode(const uint8_t *em, size_t len_em, | ||
| 133 | - const uint8_t *sentinel, size_t len_sentinel, | ||
| 134 | - size_t expected_pt_len, | ||
| 135 | - uint8_t *output); | ||
| 136 | - """) | ||
| 137 | - | ||
| 138 | - | ||
| 139 | -def _pkcs1_decode(em, sentinel, expected_pt_len, output): | ||
| 140 | - if len(em) != len(output): | ||
| 141 | - raise ValueError("Incorrect output length") | ||
| 142 | - | ||
| 143 | - ret = _raw_pkcs1_decode.pkcs1_decode(c_uint8_ptr(em), | ||
| 144 | - c_size_t(len(em)), | ||
| 145 | - c_uint8_ptr(sentinel), | ||
| 146 | - c_size_t(len(sentinel)), | ||
| 147 | - c_size_t(expected_pt_len), | ||
| 148 | - c_uint8_ptr(output)) | ||
| 149 | - return ret | ||
| 150 | +from ._pkcs1_oaep_decode import pkcs1_decode | ||
| 151 | |||
| 152 | |||
| 153 | class PKCS115_Cipher: | ||
| 154 | @@ -113,7 +89,6 @@ class PKCS115_Cipher: | ||
| 155 | continue | ||
| 156 | ps.append(new_byte) | ||
| 157 | ps = b"".join(ps) | ||
| 158 | - assert(len(ps) == k - mLen - 3) | ||
| 159 | # Step 2b | ||
| 160 | em = b'\x00\x02' + ps + b'\x00' + _copy_bytes(None, None, message) | ||
| 161 | # Step 3a (OS2IP) | ||
| 162 | @@ -185,14 +160,14 @@ class PKCS115_Cipher: | ||
| 163 | # Step 3 (not constant time when the sentinel is not a byte string) | ||
| 164 | output = bytes(bytearray(k)) | ||
| 165 | if not is_bytes(sentinel) or len(sentinel) > k: | ||
| 166 | - size = _pkcs1_decode(em, b'', expected_pt_len, output) | ||
| 167 | + size = pkcs1_decode(em, b'', expected_pt_len, output) | ||
| 168 | if size < 0: | ||
| 169 | return sentinel | ||
| 170 | else: | ||
| 171 | return output[size:] | ||
| 172 | |||
| 173 | # Step 3 (somewhat constant time) | ||
| 174 | - size = _pkcs1_decode(em, sentinel, expected_pt_len, output) | ||
| 175 | + size = pkcs1_decode(em, sentinel, expected_pt_len, output) | ||
| 176 | return output[size:] | ||
| 177 | |||
| 178 | |||
| 179 | diff --git a/lib/Cryptodome/Cipher/_pkcs1_oaep_decode.py b/lib/Cryptodome/Cipher/_pkcs1_oaep_decode.py | ||
| 180 | new file mode 100644 | ||
| 181 | index 0000000..fc07528 | ||
| 182 | --- /dev/null | ||
| 183 | +++ b/lib/Cryptodome/Cipher/_pkcs1_oaep_decode.py | ||
| 184 | @@ -0,0 +1,41 @@ | ||
| 185 | +from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, c_size_t, | ||
| 186 | + c_uint8_ptr) | ||
| 187 | + | ||
| 188 | + | ||
| 189 | +_raw_pkcs1_decode = load_pycryptodome_raw_lib("Crypto.Cipher._pkcs1_decode", | ||
| 190 | + """ | ||
| 191 | + int pkcs1_decode(const uint8_t *em, size_t len_em, | ||
| 192 | + const uint8_t *sentinel, size_t len_sentinel, | ||
| 193 | + size_t expected_pt_len, | ||
| 194 | + uint8_t *output); | ||
| 195 | + | ||
| 196 | + int oaep_decode(const uint8_t *em, | ||
| 197 | + size_t em_len, | ||
| 198 | + const uint8_t *lHash, | ||
| 199 | + size_t hLen, | ||
| 200 | + const uint8_t *db, | ||
| 201 | + size_t db_len); | ||
| 202 | + """) | ||
| 203 | + | ||
| 204 | + | ||
| 205 | +def pkcs1_decode(em, sentinel, expected_pt_len, output): | ||
| 206 | + if len(em) != len(output): | ||
| 207 | + raise ValueError("Incorrect output length") | ||
| 208 | + | ||
| 209 | + ret = _raw_pkcs1_decode.pkcs1_decode(c_uint8_ptr(em), | ||
| 210 | + c_size_t(len(em)), | ||
| 211 | + c_uint8_ptr(sentinel), | ||
| 212 | + c_size_t(len(sentinel)), | ||
| 213 | + c_size_t(expected_pt_len), | ||
| 214 | + c_uint8_ptr(output)) | ||
| 215 | + return ret | ||
| 216 | + | ||
| 217 | + | ||
| 218 | +def oaep_decode(em, lHash, db): | ||
| 219 | + ret = _raw_pkcs1_decode.oaep_decode(c_uint8_ptr(em), | ||
| 220 | + c_size_t(len(em)), | ||
| 221 | + c_uint8_ptr(lHash), | ||
| 222 | + c_size_t(len(lHash)), | ||
| 223 | + c_uint8_ptr(db), | ||
| 224 | + c_size_t(len(db))) | ||
| 225 | + return ret | ||
| 226 | diff --git a/src/pkcs1_decode.c b/src/pkcs1_decode.c | ||
| 227 | index 207b198..74cb4a2 100644 | ||
| 228 | --- a/src/pkcs1_decode.c | ||
| 229 | +++ b/src/pkcs1_decode.c | ||
| 230 | @@ -130,7 +130,7 @@ STATIC size_t safe_select_idx(size_t in1, size_t in2, uint8_t choice) | ||
| 231 | * - in1[] is NOT equal to in2[] where neq_mask[] is 0xFF. | ||
| 232 | * Return non-zero otherwise. | ||
| 233 | */ | ||
| 234 | -STATIC uint8_t safe_cmp(const uint8_t *in1, const uint8_t *in2, | ||
| 235 | +STATIC uint8_t safe_cmp_masks(const uint8_t *in1, const uint8_t *in2, | ||
| 236 | const uint8_t *eq_mask, const uint8_t *neq_mask, | ||
| 237 | size_t len) | ||
| 238 | { | ||
| 239 | @@ -187,7 +187,7 @@ STATIC size_t safe_search(const uint8_t *in1, uint8_t c, size_t len) | ||
| 240 | return result; | ||
| 241 | } | ||
| 242 | |||
| 243 | -#define EM_PREFIX_LEN 10 | ||
| 244 | +#define PKCS1_PREFIX_LEN 10 | ||
| 245 | |||
| 246 | /* | ||
| 247 | * Decode and verify the PKCS#1 padding, then put either the plaintext | ||
| 248 | @@ -222,13 +222,13 @@ EXPORT_SYM int pkcs1_decode(const uint8_t *em, size_t len_em_output, | ||
| 249 | if (NULL == em || NULL == output || NULL == sentinel) { | ||
| 250 | return -1; | ||
| 251 | } | ||
| 252 | - if (len_em_output < (EM_PREFIX_LEN + 2)) { | ||
| 253 | + if (len_em_output < (PKCS1_PREFIX_LEN + 2)) { | ||
| 254 | return -1; | ||
| 255 | } | ||
| 256 | if (len_sentinel > len_em_output) { | ||
| 257 | return -1; | ||
| 258 | } | ||
| 259 | - if (expected_pt_len > 0 && expected_pt_len > (len_em_output - EM_PREFIX_LEN - 1)) { | ||
| 260 | + if (expected_pt_len > 0 && expected_pt_len > (len_em_output - PKCS1_PREFIX_LEN - 1)) { | ||
| 261 | return -1; | ||
| 262 | } | ||
| 263 | |||
| 264 | @@ -240,7 +240,7 @@ EXPORT_SYM int pkcs1_decode(const uint8_t *em, size_t len_em_output, | ||
| 265 | memcpy(padded_sentinel + (len_em_output - len_sentinel), sentinel, len_sentinel); | ||
| 266 | |||
| 267 | /** The first 10 bytes must follow the pattern **/ | ||
| 268 | - match = safe_cmp(em, | ||
| 269 | + match = safe_cmp_masks(em, | ||
| 270 | (const uint8_t*)"\x00\x02" "\x00\x00\x00\x00\x00\x00\x00\x00", | ||
| 271 | (const uint8_t*)"\xFF\xFF" "\x00\x00\x00\x00\x00\x00\x00\x00", | ||
| 272 | (const uint8_t*)"\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", | ||
| 273 | @@ -283,3 +283,72 @@ end: | ||
| 274 | free(padded_sentinel); | ||
| 275 | return result; | ||
| 276 | } | ||
| 277 | + | ||
| 278 | +/* | ||
| 279 | + * Decode and verify the OAEP padding in constant time. | ||
| 280 | + * | ||
| 281 | + * The function returns the number of bytes to ignore at the beginning | ||
| 282 | + * of db (the rest is the plaintext), or -1 in case of problems. | ||
| 283 | + */ | ||
| 284 | + | ||
| 285 | +EXPORT_SYM int oaep_decode(const uint8_t *em, | ||
| 286 | + size_t em_len, | ||
| 287 | + const uint8_t *lHash, | ||
| 288 | + size_t hLen, | ||
| 289 | + const uint8_t *db, | ||
| 290 | + size_t db_len) /* em_len - 1 - hLen */ | ||
| 291 | +{ | ||
| 292 | + int result; | ||
| 293 | + size_t one_pos, search_len, i; | ||
| 294 | + uint8_t wrong_padding; | ||
| 295 | + uint8_t *eq_mask = NULL; | ||
| 296 | + uint8_t *neq_mask = NULL; | ||
| 297 | + uint8_t *target_db = NULL; | ||
| 298 | + | ||
| 299 | + if (NULL == em || NULL == lHash || NULL == db) { | ||
| 300 | + return -1; | ||
| 301 | + } | ||
| 302 | + | ||
| 303 | + if (em_len < 2*hLen+2 || db_len != em_len-1-hLen) { | ||
| 304 | + return -1; | ||
| 305 | + } | ||
| 306 | + | ||
| 307 | + /* Allocate */ | ||
| 308 | + eq_mask = (uint8_t*) calloc(1, db_len); | ||
| 309 | + neq_mask = (uint8_t*) calloc(1, db_len); | ||
| 310 | + target_db = (uint8_t*) calloc(1, db_len); | ||
| 311 | + if (NULL == eq_mask || NULL == neq_mask || NULL == target_db) { | ||
| 312 | + result = -1; | ||
| 313 | + goto cleanup; | ||
| 314 | + } | ||
| 315 | + | ||
| 316 | + /* Step 3g */ | ||
| 317 | + search_len = db_len - hLen; | ||
| 318 | + | ||
| 319 | + one_pos = safe_search(db + hLen, 0x01, search_len); | ||
| 320 | + if (SIZE_T_MAX == one_pos) { | ||
| 321 | + result = -1; | ||
| 322 | + goto cleanup; | ||
| 323 | + } | ||
| 324 | + | ||
| 325 | + memset(eq_mask, 0xAA, db_len); | ||
| 326 | + memcpy(target_db, lHash, hLen); | ||
| 327 | + memset(eq_mask, 0xFF, hLen); | ||
| 328 | + | ||
| 329 | + for (i=0; i<search_len; i++) { | ||
| 330 | + eq_mask[hLen + i] = propagate_ones(i < one_pos); | ||
| 331 | + } | ||
| 332 | + | ||
| 333 | + wrong_padding = em[0]; | ||
| 334 | + wrong_padding |= safe_cmp_masks(db, target_db, eq_mask, neq_mask, db_len); | ||
| 335 | + set_if_match(&wrong_padding, one_pos, search_len); | ||
| 336 | + | ||
| 337 | + result = wrong_padding ? -1 : (int)(hLen + 1 + one_pos); | ||
| 338 | + | ||
| 339 | +cleanup: | ||
| 340 | + free(eq_mask); | ||
| 341 | + free(neq_mask); | ||
| 342 | + free(target_db); | ||
| 343 | + | ||
| 344 | + return result; | ||
| 345 | +} | ||
| 346 | diff --git a/src/test/test_pkcs1.c b/src/test/test_pkcs1.c | ||
| 347 | index 6ef63cb..69aaac5 100644 | ||
| 348 | --- a/src/test/test_pkcs1.c | ||
| 349 | +++ b/src/test/test_pkcs1.c | ||
| 350 | @@ -5,7 +5,7 @@ void set_if_match(uint8_t *flag, size_t term1, size_t term2); | ||
| 351 | void set_if_no_match(uint8_t *flag, size_t term1, size_t term2); | ||
| 352 | void safe_select(const uint8_t *in1, const uint8_t *in2, uint8_t *out, uint8_t choice, size_t len); | ||
| 353 | size_t safe_select_idx(size_t in1, size_t in2, uint8_t choice); | ||
| 354 | -uint8_t safe_cmp(const uint8_t *in1, const uint8_t *in2, | ||
| 355 | +uint8_t safe_cmp_masks(const uint8_t *in1, const uint8_t *in2, | ||
| 356 | const uint8_t *eq_mask, const uint8_t *neq_mask, | ||
| 357 | size_t len); | ||
| 358 | size_t safe_search(const uint8_t *in1, uint8_t c, size_t len); | ||
| 359 | @@ -80,29 +80,29 @@ void test_safe_select_idx() | ||
| 360 | assert(safe_select_idx(0x100004, 0x223344, 1) == 0x223344); | ||
| 361 | } | ||
| 362 | |||
| 363 | -void test_safe_cmp() | ||
| 364 | +void test_safe_cmp_masks(void) | ||
| 365 | { | ||
| 366 | uint8_t res; | ||
| 367 | |||
| 368 | - res = safe_cmp(onezero, onezero, | ||
| 369 | + res = safe_cmp_masks(onezero, onezero, | ||
| 370 | (uint8_t*)"\xFF\xFF", | ||
| 371 | (uint8_t*)"\x00\x00", | ||
| 372 | 2); | ||
| 373 | assert(res == 0); | ||
| 374 | |||
| 375 | - res = safe_cmp(onezero, zerozero, | ||
| 376 | + res = safe_cmp_masks(onezero, zerozero, | ||
| 377 | (uint8_t*)"\xFF\xFF", | ||
| 378 | (uint8_t*)"\x00\x00", | ||
| 379 | 2); | ||
| 380 | assert(res != 0); | ||
| 381 | |||
| 382 | - res = safe_cmp(onezero, oneone, | ||
| 383 | + res = safe_cmp_masks(onezero, oneone, | ||
| 384 | (uint8_t*)"\xFF\xFF", | ||
| 385 | (uint8_t*)"\x00\x00", | ||
| 386 | 2); | ||
| 387 | assert(res != 0); | ||
| 388 | |||
| 389 | - res = safe_cmp(onezero, oneone, | ||
| 390 | + res = safe_cmp_masks(onezero, oneone, | ||
| 391 | (uint8_t*)"\xFF\x00", | ||
| 392 | (uint8_t*)"\x00\x00", | ||
| 393 | 2); | ||
| 394 | @@ -110,19 +110,19 @@ void test_safe_cmp() | ||
| 395 | |||
| 396 | /** -- **/ | ||
| 397 | |||
| 398 | - res = safe_cmp(onezero, onezero, | ||
| 399 | + res = safe_cmp_masks(onezero, onezero, | ||
| 400 | (uint8_t*)"\x00\x00", | ||
| 401 | (uint8_t*)"\xFF\xFF", | ||
| 402 | 2); | ||
| 403 | assert(res != 0); | ||
| 404 | |||
| 405 | - res = safe_cmp(oneone, zerozero, | ||
| 406 | + res = safe_cmp_masks(oneone, zerozero, | ||
| 407 | (uint8_t*)"\x00\x00", | ||
| 408 | (uint8_t*)"\xFF\xFF", | ||
| 409 | 2); | ||
| 410 | assert(res == 0); | ||
| 411 | |||
| 412 | - res = safe_cmp(onezero, oneone, | ||
| 413 | + res = safe_cmp_masks(onezero, oneone, | ||
| 414 | (uint8_t*)"\x00\x00", | ||
| 415 | (uint8_t*)"\x00\xFF", | ||
| 416 | 2); | ||
| 417 | @@ -130,7 +130,7 @@ void test_safe_cmp() | ||
| 418 | |||
| 419 | /** -- **/ | ||
| 420 | |||
| 421 | - res = safe_cmp(onezero, oneone, | ||
| 422 | + res = safe_cmp_masks(onezero, oneone, | ||
| 423 | (uint8_t*)"\xFF\x00", | ||
| 424 | (uint8_t*)"\x00\xFF", | ||
| 425 | 2); | ||
| 426 | @@ -158,7 +158,7 @@ int main(void) | ||
| 427 | test_set_if_no_match(); | ||
| 428 | test_safe_select(); | ||
| 429 | test_safe_select_idx(); | ||
| 430 | - test_safe_cmp(); | ||
| 431 | + test_safe_cmp_masks(); | ||
| 432 | test_safe_search(); | ||
| 433 | return 0; | ||
| 434 | } | ||
| 435 | -- | ||
| 436 | 2.40.0 | ||
diff --git a/meta/recipes-devtools/python/python3-pycryptodomex_3.14.1.bb b/meta/recipes-devtools/python/python3-pycryptodomex_3.14.1.bb index 79a3fee19c..31ad3fda5e 100644 --- a/meta/recipes-devtools/python/python3-pycryptodomex_3.14.1.bb +++ b/meta/recipes-devtools/python/python3-pycryptodomex_3.14.1.bb | |||
| @@ -3,6 +3,8 @@ inherit setuptools3 | |||
| 3 | 3 | ||
| 4 | SRC_URI[sha256sum] = "2ce76ed0081fd6ac8c74edc75b9d14eca2064173af79843c24fa62573263c1f2" | 4 | SRC_URI[sha256sum] = "2ce76ed0081fd6ac8c74edc75b9d14eca2064173af79843c24fa62573263c1f2" |
| 5 | 5 | ||
| 6 | SRC_URI += "file://CVE-2023-52323.patch" | ||
| 7 | |||
| 6 | FILES:${PN}-tests = " \ | 8 | FILES:${PN}-tests = " \ |
| 7 | ${PYTHON_SITEPACKAGES_DIR}/Cryptodome/SelfTest/ \ | 9 | ${PYTHON_SITEPACKAGES_DIR}/Cryptodome/SelfTest/ \ |
| 8 | ${PYTHON_SITEPACKAGES_DIR}/Cryptodome/SelfTest/__pycache__/ \ | 10 | ${PYTHON_SITEPACKAGES_DIR}/Cryptodome/SelfTest/__pycache__/ \ |
