Embedded SDK
Embedded SDK
cx_ecdh.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 #if defined(HAVE_ECDH) || defined(HAVE_X25519) || defined(HAVE_X448)
20 
21 #include "cx_ecfp.h"
22 #include "cx_utils.h"
23 #include "cx_ram.h"
24 
25 #include <string.h>
26 
27 #if defined(HAVE_ECDH)
28 cx_err_t cx_ecdh_no_throw(const cx_ecfp_private_key_t *key,
29  uint32_t mode,
30  const uint8_t *public_point,
31  size_t P_len,
32  uint8_t *secret,
33  size_t secret_len)
34 {
35  size_t sz;
36  cx_curve_t curve;
37  cx_err_t error;
38  cx_ecpoint_t W;
39 
40  curve = key->curve;
41  CX_CHECK(cx_ecdomain_parameters_length(curve, &sz));
42 
43  if (false
44 #ifdef HAVE_ECC_WEIERSTRASS
45  || CX_CURVE_RANGE(curve, WEIERSTRASS)
46 #endif
47 #ifdef HAVE_ECC_MONTGOMERY
48  || CX_CURVE_RANGE(curve, MONTGOMERY)
49 #endif
50  ) {
51  if (P_len != (1 + sz * 2)) {
52  error = CX_INVALID_PARAMETER;
53  goto end;
54  }
55  if (!(((mode & CX_MASK_EC) == CX_ECDH_X) || ((mode & CX_MASK_EC) == CX_ECDH_POINT))) {
56  error = CX_INVALID_PARAMETER;
57  goto end;
58  }
59  }
60  else {
61  error = INVALID_PARAMETER;
62  goto end;
63  }
64 
65  switch (mode & CX_MASK_EC) {
66  case CX_ECDH_POINT:
67  if (secret_len < P_len) {
68  error = INVALID_PARAMETER;
69  goto end;
70  }
71  break;
72  case CX_ECDH_X:
73  if (secret_len < sz) {
74  error = INVALID_PARAMETER;
75  goto end;
76  }
77  break;
78  default:
79  error = INVALID_PARAMETER;
80  goto end;
81  break;
82  }
83 
84  CX_CHECK(cx_bn_lock(sz, 0));
85  CX_CHECK(cx_ecpoint_alloc(&W, curve));
86  CX_CHECK(cx_ecpoint_init(&W, public_point + 1, sz, public_point + 1 + sz, sz));
87  // Scalar multiplication with random projective coordinates and additive splitting
88  if (CX_CURVE_RANGE(curve, WEIERSTRASS)) {
89  CX_CHECK(cx_ecpoint_rnd_fixed_scalarmul(&W, key->d, key->d_len));
90  }
91  else {
92  CX_CHECK(cx_ecpoint_rnd_scalarmul(&W, key->d, key->d_len));
93  }
94  switch (mode & CX_MASK_EC) {
95  case CX_ECDH_POINT:
96  secret[0] = 0x04;
97  CX_CHECK(cx_ecpoint_export(&W, secret + 1, sz, secret + 1 + sz, sz));
98  break;
99  case CX_ECDH_X:
100  CX_CHECK(cx_ecpoint_export(&W, secret, sz, NULL, 0));
101  break;
102  }
103 
104 end:
105  cx_bn_unlock();
106  return error;
107 }
108 
109 #endif // HAVE_ECDH
110 
111 #if defined(HAVE_X25519)
112 cx_err_t cx_x25519(uint8_t *u, const uint8_t *k, size_t k_len)
113 {
114  cx_bn_t bn_u;
115  size_t domain_length;
116  cx_err_t error;
117 
118  CX_CHECK(cx_ecdomain_parameters_length(CX_CURVE_Curve25519, &domain_length));
119  CX_CHECK(cx_bn_lock(domain_length, 0));
120  CX_CHECK(cx_bn_alloc(&bn_u, domain_length));
121  CX_CHECK(cx_bn_init(bn_u, u, domain_length));
122  CX_CHECK(cx_ecpoint_x25519(bn_u, k, k_len));
123  CX_CHECK(cx_bn_export(bn_u, u, domain_length));
124 
125 end:
126  cx_bn_unlock();
127  return error;
128 }
129 #endif // HAVE_X25519
130 
131 #if defined(HAVE_X448)
132 cx_err_t cx_x448(uint8_t *u, const uint8_t *k, size_t k_len)
133 {
134  cx_bn_t bn_u;
135  size_t domain_length;
136  cx_err_t error;
137 
138  CX_CHECK(cx_ecdomain_parameters_length(CX_CURVE_Curve448, &domain_length));
139  CX_CHECK(cx_bn_lock(domain_length, 0));
140  CX_CHECK(cx_bn_alloc(&bn_u, domain_length));
141  CX_CHECK(cx_bn_init(bn_u, u, domain_length));
142  CX_CHECK(cx_ecpoint_x448(bn_u, k, k_len));
143  CX_CHECK(cx_bn_export(bn_u, u, domain_length));
144 
145 end:
146  cx_bn_unlock();
147  return error;
148 }
149 #endif // HAVE_X448
150 
151 #endif // HAVE_ECDH || HAVE_X25519 || HAVE_X448
#define CX_ECDH_X
Definition: lcx_common.h:173
#define CX_ECDH_POINT
Definition: lcx_common.h:172
#define CX_MASK_EC
Definition: lcx_common.h:170
unsigned char uint8_t
Definition: usbd_conf.h:53