Embedded SDK
Embedded SDK
Loading...
Searching...
No Matches
cx_pkcs1.c
Go to the documentation of this file.
1
2/*******************************************************************************
3 * Ledger Nano S - Secure firmware
4 * (c) 2022 Ledger
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 ********************************************************************************/
18
19#ifdef HAVE_RSA
20
21#include "cx_rsa.h"
22#include "cx_ram.h"
23#include "cx_utils.h"
24#include "errors.h"
25#include "exceptions.h"
26#include "lcx_rng.h"
27
28#include <string.h>
29
30#ifdef HAVE_RSA
31
32/* ----------------------------------------------------------------------- */
33/* */
34/* ----------------------------------------------------------------------- */
35
36// clang-format off
37#if defined(HAVE_SHA224)
38/* sha224 OID */
39const uint8_t C_cx_oid_sha224[CX_OID_SHA224_LENGTH] = {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
40 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c};
41#endif // HAVE_SHA224
42
43#if defined(HAVE_SHA256)
44/* sha256 OID */
45const uint8_t C_cx_oid_sha256[CX_OID_SHA256_LENGTH] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
46 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
47#endif // HAVE_SHA256
48
49#if defined(HAVE_SHA384)
50/* sha384 OID */
51const uint8_t C_cx_oid_sha384[CX_OID_SHA384_LENGTH] = {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
52 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30};
53#endif // HAVE_SHA384
54
55#if defined(HAVE_SHA512)
56/* sha512 OID */
57const uint8_t C_cx_oid_sha512[CX_OID_SHA512_LENGTH] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
58 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40};
59#endif // HAVE_SHA512
60
61#if defined(HAVE_SHA3)
62/* sha3-256 OID */
63const uint8_t C_cx_oid_sha3_256[CX_OID_SHA3_256_LENGTH]
64 = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
65 0x65, 0x03, 0x04, 0x02, 0x08, 0x05, 0x00, 0x04, 0x20};
66
67/* sha3-512 OID */
68const uint8_t C_cx_oid_sha3_512[CX_OID_SHA3_512_LENGTH]
69 = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
70 0x65, 0x03, 0x04, 0x02, 0x0a, 0x05, 0x00, 0x04, 0x40};
71#endif // HAVE_SHA3
72// clang-format on
73
74size_t cx_pkcs1_get_hash_len(cx_md_t hID)
75{
76 switch (hID) {
77#if defined(HAVE_SHA224)
78 case CX_SHA224:
79 return 224 / 8;
80#endif // HAVE_SHA224
81
82#if defined(HAVE_SHA256)
83 case CX_SHA256:
84 return 256 / 8;
85#endif // HAVE_SHA256
86
87#if defined(HAVE_SHA384)
88 case CX_SHA384:
89 return 384 / 8;
90#endif // HAVE_SHA384
91
92#if defined(HAVE_SHA512)
93 case CX_SHA512:
94 return 512 / 8;
95#endif // HAVE_SHA512
96
97#if defined(HAVE_SHA3)
98 case CX_SHA3_256:
99 return 256 / 8;
100
101 case CX_SHA3_512:
102 return 512 / 8;
103#endif // HAVE_SHA3
104
105 default:
106 break;
107 }
108 return 0;
109}
110
111static const uint8_t *cx_pkcs1_get_hash_oid(cx_md_t hID, size_t *len)
112{
113 switch (hID) {
114#if defined(HAVE_SHA224)
115 case CX_SHA224:
116 *len = sizeof(C_cx_oid_sha224);
117 return C_cx_oid_sha224;
118#endif // HAVE_SHA224
119
120#if defined(HAVE_SHA256)
121 case CX_SHA256:
122 *len = sizeof(C_cx_oid_sha256);
123 return C_cx_oid_sha256;
124#endif // HAVE_SHA256
125
126#if defined(HAVE_SHA384)
127 case CX_SHA384:
128 *len = sizeof(C_cx_oid_sha384);
129 return C_cx_oid_sha384;
130#endif // HAVE_SHA384
131
132#if defined(HAVE_SHA512)
133 case CX_SHA512:
134 *len = sizeof(C_cx_oid_sha512);
135 return C_cx_oid_sha512;
136#endif // HAVE_SHA512
137
138#if defined(HAVE_SHA3)
139 case CX_SHA3_256:
140 *len = sizeof(C_cx_oid_sha3_256);
141 return C_cx_oid_sha3_256;
142
143 case CX_SHA3_512:
144 *len = sizeof(C_cx_oid_sha3_512);
145 return C_cx_oid_sha3_512;
146#endif // HAVE_SHA3
147
148 default:
149 break;
150 }
151 *len = 0;
152 return NULL;
153}
154
155#ifdef _CX_PKCS1_CONST_SEED_SALT
156static const uint8_t C_cx_pkcs_salt[]
157 = {'T', 'h', 'e', 'S', 'a', 'l', 't', ' ', 'T', 'h', 'e', 'S', 'a', 'l', 't', ' ',
158 'T', 'h', 'e', 'S', 'a', 'l', 't', ' ', 'T', 'h', 'e', 'S', 'a', 'l', 't', ' '};
159#endif
160
161static const uint8_t C_cx_pss_zeros[] = {0, 0, 0, 0, 0, 0, 0, 0};
162
163// We only support the empty string label, defined as default.
164// The following arrays are the corresponding hash applied to this empty string label.
165#if defined(HAVE_SHA224)
166static const uint8_t C_cx_oeap_sha224_[]
167 = {0xd1, 0x4a, 0x02, 0x8c, 0x2a, 0x3a, 0x2b, 0xc9, 0x47, 0x61, 0x02, 0xbb, 0x28, 0x82,
168 0x34, 0xc4, 0x15, 0xa2, 0xb0, 0x1f, 0x82, 0x8e, 0xa6, 0x2a, 0xc5, 0xb3, 0xe4, 0x2f};
169#endif // HAVE_SHA224
170
171#if defined(HAVE_SHA256)
172static const uint8_t C_cx_oeap_sha256_[] = {
173 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
174 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55,
175};
176#endif // HAVE_SHA256
177
178#if defined(HAVE_SHA384)
179static const uint8_t C_cx_oeap_sha384_[] = {
180 0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, 0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a,
181 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43, 0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda,
182 0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb, 0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b};
183#endif // HAVE_SHA384
184
185#if defined(HAVE_SHA512)
186static const uint8_t C_cx_oeap_sha512_[] = {
187 0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd, 0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07,
188 0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc, 0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce,
189 0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0, 0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f,
190 0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81, 0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e};
191#endif // HAVE_SHA512
192
193static const uint8_t *cx_pkcs1_get_hash_oeap(cx_md_t hID, size_t *len)
194{
195 switch (hID) {
196#if defined(HAVE_SHA224)
197 case CX_SHA224:
198 *len = sizeof(C_cx_oeap_sha224_);
199 return C_cx_oeap_sha224_;
200#endif // HAVE_SHA224
201
202#if defined(HAVE_SHA256)
203 case CX_SHA256:
204 *len = sizeof(C_cx_oeap_sha256_);
205 return C_cx_oeap_sha256_;
206#endif // HAVE_SHA256
207
208#if defined(HAVE_SHA384)
209 case CX_SHA384:
210 *len = sizeof(C_cx_oeap_sha384_);
211 return C_cx_oeap_sha384_;
212#endif // HAVE_SHA384
213
214#if defined(HAVE_SHA512)
215 case CX_SHA512:
216 *len = sizeof(C_cx_oeap_sha512_);
217 return C_cx_oeap_sha512_;
218#endif // HAVE_SHA512
219
220 default:
221 break;
222 }
223 *len = 0;
224 return NULL;
225}
226
227static cx_err_t cx_pkcs1_MGF1(cx_md_t hID,
228 uint8_t *seed,
229 size_t seed_len,
230 uint8_t *out,
231 size_t out_len)
232{
233 size_t hLen;
234 size_t round_len;
235 uint8_t counter[4] = {0};
236 cx_hash_t *hash_ctx = &G_cx.pkcs1.hash_ctx.hash;
237 cx_err_t error = CX_OK;
238
239 if (hID != CX_SHA224 && hID != CX_SHA256 && hID != CX_SHA384 && hID != CX_SHA512
240 && hID != CX_SHA3_256 && hID != CX_SHA3_512) {
241 return CX_INVALID_PARAMETER;
242 }
243 hLen = cx_pkcs1_get_hash_len(hID);
244
245 while (out_len) {
246 round_len = (out_len < hLen) ? out_len : hLen;
247
248 CX_CHECK(cx_hash_init_ex(hash_ctx, hID, hLen));
249 CX_CHECK(cx_hash_update(hash_ctx, seed, seed_len));
250 CX_CHECK(cx_hash_update(hash_ctx, counter, 4));
251 CX_CHECK(cx_hash_final(hash_ctx, G_cx.pkcs1.digest));
252
253 memcpy(out, G_cx.pkcs1.digest, round_len);
254 out_len -= round_len;
255 out += round_len;
256 counter[3]++;
257 if (counter[3] == 0) {
258 counter[2]++;
259 }
260 }
261end:
262 return error;
263}
264
265/* ----------------------------------------------------------------------- */
266/* EMSA: pkcs1 V1.5 */
267/* ----------------------------------------------------------------------- */
268
269/*
270 * message: at ptr+size-msg_size
271 */
272cx_err_t cx_pkcs1_emsa_v1o5_encode(cx_md_t hID,
273 uint8_t *em,
274 size_t emLen,
275 const uint8_t *mHash,
276 size_t mHashLen)
277{
278 size_t PSLen;
279 size_t oid_len;
280 const uint8_t *oid;
281
282 oid = cx_pkcs1_get_hash_oid(hID, &oid_len);
283 if (oid == NULL) {
284 return CX_INVALID_PARAMETER;
285 }
286
287 if ((3 + oid_len + mHashLen) >= emLen) {
288 return CX_INVALID_PARAMETER;
289 }
290 PSLen = emLen - (3 + oid_len + mHashLen);
291
292 memcpy(em + 2 + PSLen + 1 + oid_len, mHash, mHashLen);
293 memcpy(em + 2 + PSLen + 1, oid, oid_len);
294 em[0] = 0;
295 em[1] = 1;
296 memset(em + 2, 0xFF, PSLen);
297 em[2 + PSLen] = 0;
298
299 return CX_OK;
300}
301
307bool cx_pkcs1_emsa_v1o5_verify(cx_md_t hID,
308 uint8_t *em,
309 size_t emLen,
310 const uint8_t *mHash,
311 size_t mHashLen)
312{
313 size_t PSLen;
314 size_t i;
315 size_t oid_len;
316 const uint8_t *oid;
317
318 oid = cx_pkcs1_get_hash_oid(hID, &oid_len);
319 if (oid == NULL) {
320 return false;
321 }
322
323 if ((3 + oid_len + mHashLen) >= emLen) {
324 return false;
325 }
326 PSLen = emLen - (3 + oid_len + mHashLen);
327
328 // -> check 00 01 ... 00
329 if ((em[0]) || (em[1] != 1) || (em[2 + PSLen] != 0)) {
330 return 0;
331 }
332 // -> check .. .. FFFFFF ..
333 for (i = 2 + PSLen - 1; i >= 2; i--) {
334 if (em[i] != 0xFF) {
335 return false;
336 }
337 }
338 // check OID / hash
339 if (memcmp(em + 2 + PSLen + 1, oid, oid_len) != 0
340 || memcmp(em + 2 + PSLen + 1 + oid_len, mHash, mHashLen) != 0) {
341 return false;
342 }
343
344 // OKAY
345 return true;
346}
347
348/* ----------------------------------------------------------------------- */
349/* EMSA: pkcs1 PSS */
350/* ----------------------------------------------------------------------- */
351static uint8_t const CX_PSS_MASK[] = {0, 0x7F, 0x3F, 0x1F, 0xF, 0x7, 0x3, 0x1};
352
353cx_err_t cx_pkcs1_emsa_pss_encode_with_salt_len(cx_md_t hID,
354 uint8_t *em,
355 size_t emBits,
356 const uint8_t *mHash,
357 size_t mHashLen,
358 size_t mSaltLen,
359 size_t *size)
360{
361 uint8_t salt[64];
362 size_t hLen;
363 size_t mDBlen;
364 size_t PSLen;
365 size_t emLen;
366 cx_hash_t *hash_ctx = &G_cx.pkcs1.hash_ctx.hash;
367 cx_err_t error;
368
369 if (hID != CX_SHA224 && hID != CX_SHA256 && hID != CX_SHA384 && hID != CX_SHA512) {
370 return CX_INVALID_PARAMETER;
371 }
372
373 hLen = cx_pkcs1_get_hash_len(hID);
374 emLen = (emBits + 7) / 8;
375
376 if ((1 + hLen) >= emLen) {
377 return CX_INVALID_PARAMETER;
378 }
379 mDBlen = emLen - (1 + hLen);
380
381 if ((hLen + mSaltLen + 2) >= emLen) {
382 return CX_INVALID_PARAMETER;
383 }
384 PSLen = emLen - (mSaltLen + hLen + 2);
385
386#ifndef _CX_PKCS1_CONST_SEED_SALT
387 cx_rng_no_throw(salt, mSaltLen);
388#endif
389
390 CX_CHECK(cx_hash_init_ex(hash_ctx, hID, hLen));
391 CX_CHECK(cx_hash_update(hash_ctx, C_cx_pss_zeros, 8));
392 CX_CHECK(cx_hash_update(hash_ctx, mHash, mHashLen));
393 CX_CHECK(cx_hash_update(hash_ctx, salt, mSaltLen));
394 CX_CHECK(cx_hash_final(hash_ctx, em + mDBlen));
395
396 em[emLen - 1] = 0xbc;
397 CX_CHECK(cx_pkcs1_MGF1(hID, em + mDBlen, hLen, em, mDBlen));
398 em[PSLen] ^= 1;
399 cx_memxor(em + PSLen + 1, salt, mSaltLen);
400 em[0] &= CX_PSS_MASK[8 * emLen - emBits];
401 *size = emLen;
402 explicit_bzero(&G_cx.pkcs1, sizeof(cx_pkcs1_t));
403end:
404 return error;
405}
406
407cx_err_t cx_pkcs1_emsa_pss_encode(cx_md_t hID,
408 uint8_t *em,
409 size_t emBits,
410 const uint8_t *mHash,
411 size_t mHashLen,
412 size_t *size)
413{
414 size_t hLen = cx_pkcs1_get_hash_len(hID);
415 return cx_pkcs1_emsa_pss_encode_with_salt_len(hID, em, emBits, mHash, mHashLen, hLen, size);
416}
417
418bool cx_pkcs1_emsa_pss_verify_with_salt_len(cx_md_t hID,
419 uint8_t *em,
420 size_t emBits,
421 const uint8_t *mHash,
422 size_t mHashLen,
423 size_t mSaltLen)
424{
425 size_t mDBlen;
426 size_t PSLen;
427 size_t i;
428 size_t emLen;
429 size_t hLen;
430 cx_hash_t *hash_ctx = &G_cx.pkcs1.hash_ctx.hash;
431
432 if (hID != CX_SHA224 && hID != CX_SHA256 && hID != CX_SHA384 && hID != CX_SHA512) {
433 return false;
434 }
435
436 hLen = cx_pkcs1_get_hash_len(hID);
437 emLen = (emBits + 7) / 8;
438
439 if ((1 + hLen) >= emLen) {
440 return false;
441 }
442 mDBlen = emLen - (1 + hLen);
443
444 if ((mSaltLen + hLen + 2) >= emLen) {
445 return false;
446 }
447 PSLen = emLen - (mSaltLen + hLen + 2);
448
449 if (em[emLen - 1] != 0xbc) {
450 return false;
451 }
452 if (em[0] & ~CX_PSS_MASK[8 * emLen - emBits]) {
453 return false;
454 }
455 if (cx_pkcs1_MGF1(hID, em + mDBlen, hLen, G_cx.pkcs1.MGF1, mDBlen) != CX_OK) {
456 return false;
457 }
458 cx_memxor(em, G_cx.pkcs1.MGF1, mDBlen);
459 em[0] &= CX_PSS_MASK[8 * emLen - emBits];
460 for (i = 0; i < PSLen; i++) {
461 if (em[i] != 0) {
462 return false;
463 }
464 }
465 if (em[PSLen] != 0x01) {
466 return false;
467 }
468
469 if (cx_hash_init_ex(hash_ctx, hID, hLen) != CX_OK
470 || cx_hash_update(hash_ctx, C_cx_pss_zeros, 8) != CX_OK
471 || cx_hash_update(hash_ctx, mHash, mHashLen) != CX_OK
472 || cx_hash_update(hash_ctx, em + PSLen + 1, mSaltLen) != CX_OK
473 || cx_hash_final(hash_ctx, G_cx.pkcs1.digest) != CX_OK) {
474 return false;
475 }
476
477 return memcmp(G_cx.pkcs1.digest, em + mDBlen, hLen) == 0;
478}
479
480bool cx_pkcs1_emsa_pss_verify(cx_md_t hID,
481 uint8_t *em,
482 size_t emBits,
483 const uint8_t *mHash,
484 size_t mHashLen)
485{
486 // By default and by convention, the salt length is the hash length.
487 // In order to verify a RSA PSS signature with a variable salt length,
488 // the 'cx_pkcs1_emsa_pss_verify_with_salt_len' function must be
489 // used directly.
490 size_t hLen = cx_pkcs1_get_hash_len(hID);
491 return cx_pkcs1_emsa_pss_verify_with_salt_len(hID, em, emBits, mHash, mHashLen, hLen);
492}
493
494/* ----------------------------------------------------------------------- */
495/* EME: pkcs1 V1.5 */
496/* ----------------------------------------------------------------------- */
497cx_err_t cx_pkcs1_eme_v1o5_encode(cx_md_t hID,
498 uint8_t *em,
499 size_t emLen,
500 const uint8_t *m,
501 size_t mLen)
502{
503 size_t PSLen;
504 size_t offset;
505 (void) hID;
506
507 if ((3 + mLen) >= emLen) {
508 return CX_INVALID_PARAMETER;
509 }
510 PSLen = emLen - (3 + mLen);
511
512 memcpy(em + 2 + PSLen + 1, m, mLen);
513 em[0] = 0;
514 em[1] = 2;
515 cx_rng_no_throw(em + 2, PSLen);
516 for (offset = 2 + PSLen - 1; offset >= 2; offset--) {
517 if (em[offset] == 0) {
518 em[offset] = 0x24;
519 }
520 }
521 em[2 + PSLen] = 0;
522 return CX_OK;
523}
524
525size_t cx_pkcs1_eme_v1o5_decode(cx_md_t hID, uint8_t *em, size_t emLen, uint8_t *m, size_t mLen)
526{
527 size_t offset;
528 (void) hID;
529 // -> check 00 02 ... 00
530 if ((em[0]) || (em[1] != 2)) {
531 return -1;
532 }
533 // -> check .. .. FFFFFF ..
534 offset = 2;
535 while (offset < emLen) {
536 if (em[offset] == 0) {
537 break;
538 }
539 offset++;
540 }
541 if (offset == emLen) {
542 return -1;
543 }
544 offset++;
545 // copy M
546 if (mLen < emLen - offset) {
547 return -1;
548 }
549 mLen = emLen - offset;
550 memmove(m, em + offset, mLen);
551 return mLen;
552}
553
554/* ----------------------------------------------------------------------- */
555/* EME: pkcs1 OAEP */
556/* ----------------------------------------------------------------------- */
557cx_err_t cx_pkcs1_eme_oaep_encode(cx_md_t hID,
558 uint8_t *em,
559 size_t emLen,
560 const uint8_t *m,
561 size_t mLen)
562{
563 size_t mDBlen;
564 size_t psLen;
565 size_t offset;
566 uint8_t seed[64];
567 size_t hLen;
568 const uint8_t *lHash;
569 size_t lHashLen;
570 cx_err_t error;
571
572 hLen = cx_pkcs1_get_hash_len(hID);
573 lHash = cx_pkcs1_get_hash_oeap(hID, &lHashLen);
574 if (hLen == 0 || lHash == NULL) {
575 return CX_INVALID_PARAMETER;
576 }
577
578 if ((hLen + 1) >= emLen) {
579 return CX_INVALID_PARAMETER;
580 }
581 mDBlen = emLen - (hLen + 1);
582 if ((mLen + 2 * hLen + 2) >= emLen) {
583 return CX_INVALID_PARAMETER;
584 }
585 psLen = emLen - (mLen + 2 * hLen + 2);
586
587 // random seed
588 cx_rng_no_throw(seed, hLen);
589
590 // DB = lHash || PS || 01 || M
591 offset = 1 + hLen;
592 memcpy(em + offset, lHash, lHashLen);
593 offset += lHashLen;
594 memset(em + offset, 0, psLen);
595 offset += psLen;
596 em[offset] = 0x01;
597 offset++;
598 memcpy(em + offset, m, mLen);
599
600 // 00 | masked seed || maskedDB
601 em[0] = 0x00;
602
603 CX_CHECK(cx_pkcs1_MGF1(hID, seed, hLen, G_cx.pkcs1.MGF1, mDBlen));
604 cx_memxor(em + 1 + hLen, G_cx.pkcs1.MGF1, mDBlen);
605
606 CX_CHECK(cx_pkcs1_MGF1(hID, em + 1 + hLen, mDBlen, G_cx.pkcs1.MGF1, hLen));
607 memcpy(em + 1, seed, hLen);
608 cx_memxor(em + 1, G_cx.pkcs1.MGF1, hLen);
609
610end:
611 return error;
612}
613
614cx_err_t cx_pkcs1_eme_oaep_decode(cx_md_t hID, uint8_t *em, size_t emLen, uint8_t *m, size_t *mLen)
615{
616 size_t mDBlen;
617 size_t offset;
618 size_t hLen;
619 const uint8_t *lHash;
620 size_t lHashLen;
621 cx_err_t error;
622
623 hLen = cx_pkcs1_get_hash_len(hID);
624 lHash = cx_pkcs1_get_hash_oeap(hID, &lHashLen);
625 if (hLen == 0 || lHash == NULL) {
626 return CX_INVALID_PARAMETER;
627 }
628 if ((hLen + 1) >= emLen) {
629 return CX_INVALID_PARAMETER;
630 }
631 mDBlen = emLen - (hLen + 1);
632
633 // unmask all
634 CX_CHECK(cx_pkcs1_MGF1(hID, em + 1 + hLen, mDBlen, G_cx.pkcs1.MGF1, hLen));
635 cx_memxor(em + 1, G_cx.pkcs1.MGF1, hLen);
636 CX_CHECK(cx_pkcs1_MGF1(hID, em + 1, hLen, G_cx.pkcs1.MGF1, mDBlen));
637 cx_memxor(em + 1 + hLen, G_cx.pkcs1.MGF1, mDBlen);
638
639 // Y||seed||lHash||PS||01||M
640 if (em[0] != 0x00) {
641 return CX_INVALID_PARAMETER;
642 }
643 if (memcmp(em + 1 + hLen, lHash, hLen) != 0) {
644 return CX_INVALID_PARAMETER;
645 }
646
647 for (offset = 1 + hLen + lHashLen; offset < emLen; offset++) {
648 if (em[offset] != 0) {
649 break;
650 }
651 }
652 if ((offset == emLen) || (em[offset] != 0x01)) {
653 return CX_INVALID_PARAMETER;
654 }
655 offset++;
656
657 // copy M
658 if (*mLen < emLen - offset) {
659 return CX_INVALID_PARAMETER;
660 }
661
662 *mLen = emLen - offset;
663 memmove(m, em + offset, *mLen);
664
665end:
666 return error;
667}
668
669#endif
670
671#endif // HAVE_RSA
union cx_u G_cx
Definition cx_ram.c:21
void cx_memxor(uint8_t *buf1, const uint8_t *buf2, size_t len)
Definition cx_utils.c:173
Random Number Generation.
unsigned char uint8_t
Definition usbd_conf.h:53