Embedded SDK
Embedded SDK
Loading...
Searching...
No Matches
cx_rsa.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_utils.h"
23#include "cx_ram.h"
24#include "ox.h"
25
26#include <string.h>
27
28#pragma GCC diagnostic push
29#pragma GCC diagnostic ignored "-Wcast-qual"
30
31static cx_err_t modulus_valid(size_t modulus_len)
32{
33 switch (modulus_len) {
34 case 128:
35 case 256:
36 case 384:
37 case 512:
38 return CX_OK;
39 default:
40 return CX_INVALID_PARAMETER;
41 }
42}
43
44cx_err_t cx_rsa_private_key_ctx_size(const cx_rsa_private_key_t *key, size_t *size)
45{
46 switch (key->size) {
47 case 128:
48 *size = sizeof(cx_rsa_1024_private_key_t);
49 break;
50 case 256:
51 *size = sizeof(cx_rsa_2048_private_key_t);
52 break;
53 case 384:
54 *size = sizeof(cx_rsa_3072_private_key_t);
55 break;
56 case 512:
57 *size = sizeof(cx_rsa_4096_private_key_t);
58 break;
59 default:
60 return CX_INVALID_PARAMETER;
61 }
62
63 return CX_OK;
64}
65
66cx_err_t cx_rsa_get_public_components(const cx_rsa_public_key_t *key, uint8_t **e, uint8_t **n)
67{
68 switch (key->size) {
69 case 128:
70 *e = ((cx_rsa_1024_public_key_t *) key)->e;
71 *n = ((cx_rsa_1024_public_key_t *) key)->n;
72 break;
73 case 256:
74 *e = ((cx_rsa_2048_public_key_t *) key)->e;
75 *n = ((cx_rsa_2048_public_key_t *) key)->n;
76 break;
77 case 384:
78 *e = ((cx_rsa_3072_public_key_t *) key)->e;
79 *n = ((cx_rsa_3072_public_key_t *) key)->n;
80 break;
81 case 512:
82 *e = ((cx_rsa_4096_public_key_t *) key)->e;
83 *n = ((cx_rsa_4096_public_key_t *) key)->n;
84 break;
85 default:
86 return CX_INVALID_PARAMETER;
87 }
88 return CX_OK;
89}
90
91cx_err_t cx_rsa_get_private_components(const cx_rsa_private_key_t *key, uint8_t **d, uint8_t **n)
92{
93 switch (key->size) {
94 case 128:
95 *d = ((cx_rsa_1024_private_key_t *) key)->d;
96 *n = ((cx_rsa_1024_private_key_t *) key)->n;
97 break;
98 case 256:
99 *d = ((cx_rsa_2048_private_key_t *) key)->d;
100 *n = ((cx_rsa_2048_private_key_t *) key)->n;
101 break;
102 case 384:
103 *d = ((cx_rsa_3072_private_key_t *) key)->d;
104 *n = ((cx_rsa_3072_private_key_t *) key)->n;
105 break;
106 case 512:
107 *d = ((cx_rsa_4096_private_key_t *) key)->d;
108 *n = ((cx_rsa_4096_private_key_t *) key)->n;
109 break;
110 default:
111 return CX_INVALID_PARAMETER;
112 }
113 return CX_OK;
114}
115
116cx_err_t cx_rsa_init_public_key_no_throw(const uint8_t *exponent,
117 size_t exponent_len,
118 const uint8_t *modulus,
119 size_t modulus_len,
120 cx_rsa_public_key_t *key)
121{
122 cx_err_t error;
123 uint8_t *e;
124 uint8_t *n;
125
126 if (!(((exponent == NULL) && (exponent_len == 0)) || ((exponent) && (exponent_len <= 4)))) {
127 return CX_INVALID_PARAMETER;
128 }
129 if (!(((modulus == NULL) && (modulus_len == 0)) || (modulus))) {
130 return CX_INVALID_PARAMETER;
131 }
132 if (key == NULL) {
133 return CX_INVALID_PARAMETER;
134 }
135
136 CX_CHECK(modulus_valid(modulus_len));
137 key->size = modulus_len;
138
139 CX_CHECK(cx_rsa_get_public_components(key, &e, &n));
140
141 if (modulus && exponent) {
142 memset(e, 0, 4);
143 memmove(e + (4 - exponent_len), exponent, exponent_len);
144 memmove(n, modulus, modulus_len);
145 }
146 else {
147 memset(n, 0, modulus_len);
148 memset(e, 0, 4);
149 }
150
151end:
152 return error;
153}
154
155cx_err_t cx_rsa_init_private_key_no_throw(const uint8_t *exponent,
156 size_t exponent_len,
157 const uint8_t *modulus,
158 size_t modulus_len,
159 cx_rsa_private_key_t *key)
160{
161 cx_err_t error;
162 uint8_t *d;
163 uint8_t *n;
164
165 if (!(((exponent == NULL) && (exponent_len == 0)) || (exponent))) {
166 return CX_INVALID_PARAMETER;
167 }
168 if (!(((modulus == NULL) && (modulus_len == 0)) || (modulus))) {
169 return CX_INVALID_PARAMETER;
170 }
171 if (exponent_len != modulus_len) {
172 return CX_INVALID_PARAMETER;
173 }
174 if (key == NULL) {
175 return CX_INVALID_PARAMETER;
176 }
177
178 CX_CHECK(modulus_valid(modulus_len));
179 key->size = modulus_len;
180
181 CX_CHECK(cx_rsa_get_private_components(key, &d, &n));
182
183 if (modulus && exponent) {
184 memmove(d, exponent, modulus_len);
185 memmove(n, modulus, modulus_len);
186 }
187 else {
188 memset(d, 0, modulus_len);
189 memset(n, 0, modulus_len);
190 }
191
192end:
193 return error;
194}
195
196static const uint8_t C_default_e[] = {0x00, 0x01, 0x00, 0x01};
197
198cx_err_t cx_rsa_generate_pair_no_throw(size_t modulus_len,
199 cx_rsa_public_key_t *public_key,
200 cx_rsa_private_key_t *private_key,
201 const uint8_t *exponent,
202 size_t exponent_len,
203 const uint8_t *externalPQ)
204{
205 cx_bn_t bn_p, bn_q, bn_n;
206 cx_err_t error;
207 uint8_t *pv_d;
208 uint8_t *pv_n;
209 uint8_t *pu_e;
210 uint8_t *pu_n;
211 size_t size;
212
213 if (!(((exponent == NULL) && (exponent_len == 0)) || ((exponent) && (exponent_len <= 4)))) {
214 return CX_INVALID_PARAMETER;
215 }
216 if (!((public_key != NULL) && (private_key != NULL))) {
217 return CX_INVALID_PARAMETER;
218 }
219
220 CX_CHECK(modulus_valid(modulus_len));
221
222 private_key->size = modulus_len;
223 public_key->size = modulus_len;
224 CX_CHECK(cx_rsa_get_private_components(private_key, &pv_d, &pv_n));
225 CX_CHECK(cx_rsa_get_public_components(public_key, &pu_e, &pu_n));
226
227 size = modulus_len / 2;
228
229 CX_CHECK(cx_bn_lock(size, 0));
230 CX_CHECK(cx_bn_alloc(&bn_p, size));
231 CX_CHECK(cx_bn_alloc(&bn_q, size));
232 // gen prime
233 if (externalPQ) {
234 CX_CHECK(cx_bn_init(bn_p, externalPQ, size));
235 CX_CHECK(cx_bn_init(bn_q, externalPQ + size, size));
236 }
237 else {
238 CX_CHECK(cx_bn_rand(bn_p));
239 CX_CHECK(cx_bn_set_bit(bn_p, size * 8 - 1));
240 CX_CHECK(cx_bn_set_bit(bn_p, size * 8 - 2));
241 CX_CHECK(cx_bn_rand(bn_q));
242 CX_CHECK(cx_bn_set_bit(bn_q, size * 8 - 1));
243 CX_CHECK(cx_bn_set_bit(bn_q, size * 8 - 2));
244 CX_CHECK(cx_bn_next_prime(bn_p));
245 CX_CHECK(cx_bn_next_prime(bn_q));
246 }
247
248 // public key:
249 CX_CHECK(cx_bn_alloc(&bn_n, modulus_len));
250 CX_CHECK(cx_bn_mul(bn_n, bn_p, bn_q));
251 CX_CHECK(cx_bn_export(bn_n, pu_n, modulus_len));
252 if (exponent == NULL) {
253 exponent = C_default_e;
254 exponent_len = sizeof(C_default_e);
255 }
256 memmove(pu_e + (4 - exponent_len), exponent, exponent_len);
257 CX_CHECK(cx_bn_destroy(&bn_n));
258
259 // private key:
260 // - n=(p-1)(q-1)
261 CX_CHECK(cx_bn_alloc(&bn_n, size));
262 CX_CHECK(cx_bn_set_u32(bn_n, 1));
263 CX_CHECK_IGNORE_CARRY(cx_bn_sub(bn_p, bn_p, bn_n));
264 CX_CHECK_IGNORE_CARRY(cx_bn_sub(bn_q, bn_q, bn_n));
265 CX_CHECK(cx_bn_destroy(&bn_n));
266 CX_CHECK(cx_bn_alloc(&bn_n, modulus_len));
267 CX_CHECK(cx_bn_mul(bn_n, bn_p, bn_q));
268 CX_CHECK(cx_bn_destroy(&bn_p));
269 CX_CHECK(cx_bn_destroy(&bn_q));
270 // - d = inv(e) mod n
271 CX_CHECK(cx_bn_alloc(&bn_p, modulus_len));
272 CX_CHECK(cx_bn_mod_u32_invert(
273 bn_p, (pu_e[0] << 24) | (pu_e[1] << 16) | (pu_e[2] << 8) | (pu_e[3] << 0), bn_n));
274 CX_CHECK(cx_bn_export(bn_p, pv_d, modulus_len));
275 memmove(pv_n, pu_n, modulus_len);
276
277end:
278 cx_bn_unlock();
279 return error;
280}
281
282cx_err_t cx_rsa_sign_with_salt_len(const cx_rsa_private_key_t *key,
283 uint32_t mode,
284 cx_md_t hashID,
285 const uint8_t *hash,
286 size_t hash_len,
287 uint8_t *sig,
288 size_t sig_len,
289 size_t salt_len)
290{
291 uint8_t *key_d;
292 uint8_t *key_n;
293 cx_bn_t bn_n, bn_msg, bn_r;
294 uint32_t nbits;
295 cx_err_t error;
296
297 // cx_scc_struct_check_rsa_privkey(key);
298 if (!(hash && (hash_len <= key->size))) {
299 return CX_INVALID_PARAMETER;
300 }
301 if (!(sig && (sig_len >= key->size))) {
302 return CX_INVALID_PARAMETER;
303 }
304
305 CX_CHECK(cx_rsa_get_private_components(key, &key_d, &key_n));
306 CX_CHECK(cx_bn_lock(key->size, 0));
307 CX_CHECK(cx_bn_alloc(&bn_r, key->size));
308 CX_CHECK(cx_bn_alloc_init(&bn_n, key->size, key_n, key->size));
309
310 // encode
311 switch (mode & CX_MASK_PAD) {
312 case CX_PAD_PKCS1_1o5:
313 sig_len = key->size;
314 CX_CHECK(cx_pkcs1_emsa_v1o5_encode(hashID, sig, sig_len, hash, hash_len));
315 break;
316 case CX_PAD_PKCS1_PSS:
317 CX_CHECK(cx_bn_cnt_bits(bn_n, &nbits));
318 CX_CHECK(cx_pkcs1_emsa_pss_encode_with_salt_len(
319 hashID, sig, nbits - 1, hash, hash_len, salt_len, &sig_len));
320 break;
321 default:
322 error = CX_INVALID_PARAMETER;
323 goto end;
324 }
325
326 // encrypt
327 CX_CHECK(cx_bn_alloc_init(&bn_msg, key->size, sig, sig_len));
328 CX_CHECK(cx_bn_mod_pow2(bn_r, bn_msg, key_d, key->size, bn_n));
329 CX_CHECK(cx_bn_export(bn_r, sig, key->size));
330
331end:
332 cx_bn_unlock();
333 return error;
334}
335
336cx_err_t cx_rsa_sign_no_throw(const cx_rsa_private_key_t *key,
337 uint32_t mode,
338 cx_md_t hashID,
339 const uint8_t *hash,
340 size_t hash_len,
341 uint8_t *sig,
342 size_t sig_len)
343{
344 size_t output_hash_len = cx_pkcs1_get_hash_len(hashID);
345 return cx_rsa_sign_with_salt_len(
346 key, mode, hashID, hash, hash_len, sig, sig_len, output_hash_len);
347}
348
349bool cx_rsa_verify_with_salt_len(const cx_rsa_public_key_t *key,
350 uint32_t mode,
351 cx_md_t hashID,
352 const uint8_t *hash,
353 size_t hash_len,
354 uint8_t *sig,
355 size_t sig_len,
356 size_t salt_len)
357{
358 size_t ok;
359 uint8_t *key_n;
360 uint8_t *key_e;
361 cx_bn_t bn_n, bn_msg, bn_r;
362 uint32_t nbits;
363 cx_err_t error;
364
365 if (hash == NULL || hash_len > key->size) {
366 return false;
367 }
368 if (sig == NULL || sig_len != key->size) {
369 return false;
370 }
371
372 ok = false;
373
374 // decrypt sig
375 CX_CHECK(cx_rsa_get_public_components(key, &key_e, &key_n));
376 CX_CHECK(cx_bn_lock(key->size, 0));
377 CX_CHECK(cx_bn_alloc(&bn_r, key->size));
378 CX_CHECK(cx_bn_alloc_init(&bn_n, key->size, key_n, key->size));
379 CX_CHECK(cx_bn_alloc_init(&bn_msg, key->size, sig, sig_len));
380 CX_CHECK(cx_bn_mod_pow2(bn_r, bn_msg, key_e, 4, bn_n));
381 CX_CHECK(cx_bn_export(bn_r, sig, sig_len));
382
383 // verify sig
384 switch (mode & CX_MASK_PAD) {
385 case CX_PAD_PKCS1_1o5:
386 ok = cx_pkcs1_emsa_v1o5_verify(hashID, sig, sig_len, hash, hash_len);
387 break;
388 case CX_PAD_PKCS1_PSS:
389 CX_CHECK(cx_bn_cnt_bits(bn_n, &nbits));
390 ok = cx_pkcs1_emsa_pss_verify_with_salt_len(
391 hashID, sig, nbits - 1, hash, hash_len, salt_len);
392 break;
393 default:
394 error = CX_INVALID_PARAMETER;
395 goto end;
396 }
397
398end:
399 cx_bn_unlock();
400 return error == CX_OK && ok;
401}
402
403bool cx_rsa_verify(const cx_rsa_public_key_t *key,
404 uint32_t mode,
405 cx_md_t hashID,
406 const uint8_t *hash,
407 size_t hash_len,
408 uint8_t *sig,
409 size_t sig_len)
410{
411 size_t output_hash_len = cx_pkcs1_get_hash_len(hashID);
412 return cx_rsa_verify_with_salt_len(
413 key, mode, hashID, hash, hash_len, sig, sig_len, output_hash_len);
414}
415
416cx_err_t cx_rsa_encrypt_no_throw(const cx_rsa_public_key_t *key,
417 uint32_t mode,
418 cx_md_t hashID,
419 const uint8_t *mesg,
420 size_t mesg_len,
421 uint8_t *enc,
422 size_t enc_len)
423{
424 uint8_t *key_n;
425 uint8_t *key_e;
426 cx_bn_t bn_n, bn_msg, bn_r;
427 cx_err_t error;
428
429 // cx_scc_struct_check_rsa_pubkey(key);
430 if (!(mesg && (mesg_len <= key->size))) {
431 return CX_INVALID_PARAMETER;
432 }
433 if (!(enc && (enc_len >= key->size))) {
434 return CX_INVALID_PARAMETER;
435 }
436
437 // encode
438 switch (mode & CX_MASK_PAD) {
439 case CX_PAD_PKCS1_1o5:
440 enc_len = key->size;
441 CX_CHECK(cx_pkcs1_eme_v1o5_encode(hashID, enc, enc_len, mesg, mesg_len));
442 break;
444 enc_len = key->size;
445 CX_CHECK(cx_pkcs1_eme_oaep_encode(hashID, enc, enc_len, mesg, mesg_len));
446 break;
447 case CX_PAD_NONE:
448 memmove(enc, mesg, mesg_len);
449 enc_len = mesg_len;
450 break;
451 default:
452 error = CX_INVALID_PARAMETER;
453 goto end;
454 }
455
456 // encrypt
457 CX_CHECK(cx_rsa_get_public_components(key, &key_e, &key_n));
458 CX_CHECK(cx_bn_lock(key->size, 0));
459 CX_CHECK(cx_bn_alloc(&bn_r, key->size));
460 CX_CHECK(cx_bn_alloc_init(&bn_n, key->size, key_n, key->size));
461 CX_CHECK(cx_bn_alloc_init(&bn_msg, key->size, enc, enc_len));
462 CX_CHECK(cx_bn_mod_pow2(bn_r, bn_msg, key_e, 4, bn_n));
463 CX_CHECK(cx_bn_export(bn_r, enc, key->size));
464
465end:
466 cx_bn_unlock();
467 return error;
468}
469cx_err_t cx_rsa_decrypt_no_throw(const cx_rsa_private_key_t *key,
470 uint32_t mode,
471 cx_md_t hashID,
472 const uint8_t *mesg,
473 size_t mesg_len,
474 uint8_t *dec,
475 size_t *dec_len)
476{
477 uint8_t *key_n;
478 uint8_t *key_d;
479 cx_bn_t bn_n, bn_msg, bn_r;
480 cx_err_t error;
481 int diff;
482
483 // cx_scc_struct_check_rsa_privkey(key);
484 if (!(mesg && (mesg_len == key->size))) {
485 return CX_INVALID_PARAMETER;
486 }
487 if (!(dec && (*dec_len >= key->size))) {
488 return CX_INVALID_PARAMETER;
489 }
490
491 // decrypt
492 CX_CHECK(cx_rsa_get_private_components(key, &key_d, &key_n));
493 CX_CHECK(cx_bn_lock(key->size, 0));
494 CX_CHECK(cx_bn_alloc(&bn_r, key->size));
495 CX_CHECK(cx_bn_alloc_init(&bn_n, key->size, key_n, key->size));
496 CX_CHECK(cx_bn_alloc_init(&bn_msg, key->size, mesg, mesg_len));
497
498 // If the encrypted message is greater than the modulus,
499 // we consider the encrypted message as incorrect.
500 CX_CHECK(cx_bn_cmp(bn_msg, bn_n, &diff));
501 if (diff > 0) {
502 error = CX_INVALID_PARAMETER;
503 goto end;
504 }
505 else {
506 CX_CHECK(cx_bn_mod_pow2(bn_r, bn_msg, key_d, key->size, bn_n));
507 CX_CHECK(cx_bn_export(bn_r, dec, key->size));
508 }
509
510 switch (mode & CX_MASK_PAD) {
511 case CX_PAD_PKCS1_1o5:
512 *dec_len = cx_pkcs1_eme_v1o5_decode(hashID, dec, key->size, dec, *dec_len);
513 break;
515 CX_CHECK(cx_pkcs1_eme_oaep_decode(hashID, dec, key->size, dec, dec_len));
516 break;
517 case CX_PAD_NONE:
518 *dec_len = key->size;
519 break;
520 default:
521 error = CX_INVALID_PARAMETER;
522 goto end;
523 }
524
525end:
526 cx_bn_unlock();
527 return error;
528}
529
530#pragma GCC diagnostic pop
531
532#endif // HAVE_RSA
#define CX_PAD_NONE
Definition lcx_common.h:135
#define CX_PAD_PKCS1_OAEP
Definition lcx_common.h:140
#define CX_PAD_PKCS1_PSS
Definition lcx_common.h:139
#define CX_MASK_PAD
Definition lcx_common.h:134
#define CX_PAD_PKCS1_1o5
Definition lcx_common.h:138
unsigned char uint8_t
Definition usbd_conf.h:53