Embedded SDK
Embedded SDK
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 
31 static 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 
44 cx_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 
66 cx_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 
91 cx_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 
116 cx_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 
151 end:
152  return error;
153 }
154 
155 cx_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 
192 end:
193  return error;
194 }
195 
196 static const uint8_t C_default_e[] = {0x00, 0x01, 0x00, 0x01};
197 
198 cx_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 
277 end:
278  cx_bn_unlock();
279  return error;
280 }
281 
282 cx_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 
331 end:
332  cx_bn_unlock();
333  return error;
334 }
335 
336 cx_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 
349 bool 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 
398 end:
399  cx_bn_unlock();
400  return error == CX_OK && ok;
401 }
402 
403 bool 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 
416 cx_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;
443  case CX_PAD_PKCS1_OAEP:
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 
465 end:
466  cx_bn_unlock();
467  return error;
468 }
469 cx_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;
514  case CX_PAD_PKCS1_OAEP:
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 
525 end:
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