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 (mSaltLen > sizeof(salt)) {
382 return CX_INVALID_PARAMETER;
383 }
384 if ((hLen + mSaltLen + 2) >= emLen) {
385 return CX_INVALID_PARAMETER;
386 }
387 PSLen = emLen - (mSaltLen + hLen + 2);
388
389#ifndef _CX_PKCS1_CONST_SEED_SALT
390 cx_rng_no_throw(salt, mSaltLen);
391#endif
392
393 CX_CHECK(cx_hash_init_ex(hash_ctx, hID, hLen));
394 CX_CHECK(cx_hash_update(hash_ctx, C_cx_pss_zeros, 8));
395 CX_CHECK(cx_hash_update(hash_ctx, mHash, mHashLen));
396 CX_CHECK(cx_hash_update(hash_ctx, salt, mSaltLen));
397 CX_CHECK(cx_hash_final(hash_ctx, em + mDBlen));
398
399 em[emLen - 1] = 0xbc;
400 CX_CHECK(cx_pkcs1_MGF1(hID, em + mDBlen, hLen, em, mDBlen));
401 em[PSLen] ^= 1;
402 cx_memxor(em + PSLen + 1, salt, mSaltLen);
403 em[0] &= CX_PSS_MASK[8 * emLen - emBits];
404 *size = emLen;
405 explicit_bzero(&G_cx.pkcs1, sizeof(cx_pkcs1_t));
406end:
407 return error;
408}
409
410cx_err_t cx_pkcs1_emsa_pss_encode(cx_md_t hID,
411 uint8_t *em,
412 size_t emBits,
413 const uint8_t *mHash,
414 size_t mHashLen,
415 size_t *size)
416{
417 size_t hLen = cx_pkcs1_get_hash_len(hID);
418 return cx_pkcs1_emsa_pss_encode_with_salt_len(hID, em, emBits, mHash, mHashLen, hLen, size);
419}
420
421bool cx_pkcs1_emsa_pss_verify_with_salt_len(cx_md_t hID,
422 uint8_t *em,
423 size_t emBits,
424 const uint8_t *mHash,
425 size_t mHashLen,
426 size_t mSaltLen)
427{
428 size_t mDBlen;
429 size_t PSLen;
430 size_t i;
431 size_t emLen;
432 size_t hLen;
433 cx_hash_t *hash_ctx = &G_cx.pkcs1.hash_ctx.hash;
434
435 if (hID != CX_SHA224 && hID != CX_SHA256 && hID != CX_SHA384 && hID != CX_SHA512) {
436 return false;
437 }
438
439 hLen = cx_pkcs1_get_hash_len(hID);
440 emLen = (emBits + 7) / 8;
441
442 if ((1 + hLen) >= emLen) {
443 return false;
444 }
445 mDBlen = emLen - (1 + hLen);
446
447 if ((mSaltLen + hLen + 2) >= emLen) {
448 return false;
449 }
450 PSLen = emLen - (mSaltLen + hLen + 2);
451
452 if (em[emLen - 1] != 0xbc) {
453 return false;
454 }
455 if (em[0] & ~CX_PSS_MASK[8 * emLen - emBits]) {
456 return false;
457 }
458 if (cx_pkcs1_MGF1(hID, em + mDBlen, hLen, G_cx.pkcs1.MGF1, mDBlen) != CX_OK) {
459 return false;
460 }
461 cx_memxor(em, G_cx.pkcs1.MGF1, mDBlen);
462 em[0] &= CX_PSS_MASK[8 * emLen - emBits];
463 for (i = 0; i < PSLen; i++) {
464 if (em[i] != 0) {
465 return false;
466 }
467 }
468 if (em[PSLen] != 0x01) {
469 return false;
470 }
471
472 if (cx_hash_init_ex(hash_ctx, hID, hLen) != CX_OK
473 || cx_hash_update(hash_ctx, C_cx_pss_zeros, 8) != CX_OK
474 || cx_hash_update(hash_ctx, mHash, mHashLen) != CX_OK
475 || cx_hash_update(hash_ctx, em + PSLen + 1, mSaltLen) != CX_OK
476 || cx_hash_final(hash_ctx, G_cx.pkcs1.digest) != CX_OK) {
477 return false;
478 }
479
480 return memcmp(G_cx.pkcs1.digest, em + mDBlen, hLen) == 0;
481}
482
483bool cx_pkcs1_emsa_pss_verify(cx_md_t hID,
484 uint8_t *em,
485 size_t emBits,
486 const uint8_t *mHash,
487 size_t mHashLen)
488{
489 // By default and by convention, the salt length is the hash length.
490 // In order to verify a RSA PSS signature with a variable salt length,
491 // the 'cx_pkcs1_emsa_pss_verify_with_salt_len' function must be
492 // used directly.
493 size_t hLen = cx_pkcs1_get_hash_len(hID);
494 return cx_pkcs1_emsa_pss_verify_with_salt_len(hID, em, emBits, mHash, mHashLen, hLen);
495}
496
497/* ----------------------------------------------------------------------- */
498/* EME: pkcs1 V1.5 */
499/* ----------------------------------------------------------------------- */
500cx_err_t cx_pkcs1_eme_v1o5_encode(cx_md_t hID,
501 uint8_t *em,
502 size_t emLen,
503 const uint8_t *m,
504 size_t mLen)
505{
506 size_t PSLen;
507 size_t offset;
508 (void) hID;
509
510 if ((3 + mLen) >= emLen) {
511 return CX_INVALID_PARAMETER;
512 }
513 PSLen = emLen - (3 + mLen);
514
515 memcpy(em + 2 + PSLen + 1, m, mLen);
516 em[0] = 0;
517 em[1] = 2;
518 cx_rng_no_throw(em + 2, PSLen);
519 for (offset = 2 + PSLen - 1; offset >= 2; offset--) {
520 if (em[offset] == 0) {
521 em[offset] = 0x24;
522 }
523 }
524 em[2 + PSLen] = 0;
525 return CX_OK;
526}
527
528size_t cx_pkcs1_eme_v1o5_decode(cx_md_t hID, uint8_t *em, size_t emLen, uint8_t *m, size_t mLen)
529{
530 size_t offset;
531 (void) hID;
532 // -> check 00 02 ... 00
533 if ((em[0]) || (em[1] != 2)) {
534 return -1;
535 }
536 // -> check .. .. FFFFFF ..
537 offset = 2;
538 while (offset < emLen) {
539 if (em[offset] == 0) {
540 break;
541 }
542 offset++;
543 }
544 if (offset == emLen) {
545 return -1;
546 }
547 offset++;
548 // copy M
549 if (mLen < emLen - offset) {
550 return -1;
551 }
552 mLen = emLen - offset;
553 memmove(m, em + offset, mLen);
554 return mLen;
555}
556
557/* ----------------------------------------------------------------------- */
558/* EME: pkcs1 OAEP */
559/* ----------------------------------------------------------------------- */
560cx_err_t cx_pkcs1_eme_oaep_encode(cx_md_t hID,
561 uint8_t *em,
562 size_t emLen,
563 const uint8_t *m,
564 size_t mLen)
565{
566 size_t mDBlen;
567 size_t psLen;
568 size_t offset;
569 uint8_t seed[64];
570 size_t hLen;
571 const uint8_t *lHash;
572 size_t lHashLen;
573 cx_err_t error;
574
575 hLen = cx_pkcs1_get_hash_len(hID);
576 lHash = cx_pkcs1_get_hash_oeap(hID, &lHashLen);
577 if (hLen == 0 || lHash == NULL) {
578 return CX_INVALID_PARAMETER;
579 }
580
581 if ((hLen + 1) >= emLen) {
582 return CX_INVALID_PARAMETER;
583 }
584 mDBlen = emLen - (hLen + 1);
585 if ((mLen + 2 * hLen + 2) >= emLen) {
586 return CX_INVALID_PARAMETER;
587 }
588 psLen = emLen - (mLen + 2 * hLen + 2);
589
590 // random seed
591 cx_rng_no_throw(seed, hLen);
592
593 // DB = lHash || PS || 01 || M
594 offset = 1 + hLen;
595 memcpy(em + offset, lHash, lHashLen);
596 offset += lHashLen;
597 memset(em + offset, 0, psLen);
598 offset += psLen;
599 em[offset] = 0x01;
600 offset++;
601 memcpy(em + offset, m, mLen);
602
603 // 00 | masked seed || maskedDB
604 em[0] = 0x00;
605
606 CX_CHECK(cx_pkcs1_MGF1(hID, seed, hLen, G_cx.pkcs1.MGF1, mDBlen));
607 cx_memxor(em + 1 + hLen, G_cx.pkcs1.MGF1, mDBlen);
608
609 CX_CHECK(cx_pkcs1_MGF1(hID, em + 1 + hLen, mDBlen, G_cx.pkcs1.MGF1, hLen));
610 memcpy(em + 1, seed, hLen);
611 cx_memxor(em + 1, G_cx.pkcs1.MGF1, hLen);
612
613end:
614 return error;
615}
616
617cx_err_t cx_pkcs1_eme_oaep_decode(cx_md_t hID, uint8_t *em, size_t emLen, uint8_t *m, size_t *mLen)
618{
619 size_t mDBlen;
620 size_t offset;
621 size_t hLen;
622 const uint8_t *lHash;
623 size_t lHashLen;
624 cx_err_t error;
625
626 hLen = cx_pkcs1_get_hash_len(hID);
627 lHash = cx_pkcs1_get_hash_oeap(hID, &lHashLen);
628 if (hLen == 0 || lHash == NULL) {
629 return CX_INVALID_PARAMETER;
630 }
631 if ((hLen + 1) >= emLen) {
632 return CX_INVALID_PARAMETER;
633 }
634 mDBlen = emLen - (hLen + 1);
635
636 // unmask all
637 CX_CHECK(cx_pkcs1_MGF1(hID, em + 1 + hLen, mDBlen, G_cx.pkcs1.MGF1, hLen));
638 cx_memxor(em + 1, G_cx.pkcs1.MGF1, hLen);
639 CX_CHECK(cx_pkcs1_MGF1(hID, em + 1, hLen, G_cx.pkcs1.MGF1, mDBlen));
640 cx_memxor(em + 1 + hLen, G_cx.pkcs1.MGF1, mDBlen);
641
642 // Y||seed||lHash||PS||01||M
643 if (em[0] != 0x00) {
644 return CX_INVALID_PARAMETER;
645 }
646 if (memcmp(em + 1 + hLen, lHash, hLen) != 0) {
647 return CX_INVALID_PARAMETER;
648 }
649
650 for (offset = 1 + hLen + lHashLen; offset < emLen; offset++) {
651 if (em[offset] != 0) {
652 break;
653 }
654 }
655 if ((offset == emLen) || (em[offset] != 0x01)) {
656 return CX_INVALID_PARAMETER;
657 }
658 offset++;
659
660 // copy M
661 if (*mLen < emLen - offset) {
662 return CX_INVALID_PARAMETER;
663 }
664
665 *mLen = emLen - offset;
666 memmove(m, em + offset, *mLen);
667
668end:
669 return error;
670}
671
672#endif
673
674#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.