Embedded SDK
Embedded SDK
crypto_helpers.c
Go to the documentation of this file.
1 /*****************************************************************************
2  * Ledger SDK.
3  * (c) 2023 Ledger SAS.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *****************************************************************************/
17 #include <stdint.h> // uint*_t
18 #include <string.h> // memset, explicit_bzero
19 #include <stdbool.h> // bool
20 
21 #include "cx.h"
22 #include "os.h"
23 
24 WARN_UNUSED_RESULT cx_err_t
25 bip32_derive_with_seed_init_privkey_256(unsigned int derivation_mode,
26  cx_curve_t curve,
27  const uint32_t *path,
28  size_t path_len,
29  cx_ecfp_256_private_key_t *privkey,
30  uint8_t *chain_code,
31  unsigned char *seed,
32  size_t seed_len)
33 {
34  cx_err_t error = CX_OK;
35  uint8_t raw_privkey[64]; // Allocate 64 bytes to respect Syscall API but only 32 will be used
36  size_t length;
37 
38  // Check curve key length
39  CX_CHECK(cx_ecdomain_parameters_length(curve, &length));
40  if (length != 32) {
41  error = CX_EC_INVALID_CURVE;
42  goto end;
43  }
44 
45  // Derive private key according to BIP32 path
46  CX_CHECK(os_derive_bip32_with_seed_no_throw(
47  derivation_mode, curve, path, path_len, raw_privkey, chain_code, seed, seed_len));
48 
49  // Init privkey from raw
50  CX_CHECK(cx_ecfp_init_private_key_no_throw(curve, raw_privkey, length, privkey));
51 
52 end:
53  explicit_bzero(raw_privkey, sizeof(raw_privkey));
54 
55  if (error != CX_OK) {
56  // Make sure the caller doesn't use uninitialized data in case
57  // the return code is not checked.
58  explicit_bzero(privkey, sizeof(cx_ecfp_256_private_key_t));
59  }
60  return error;
61 }
62 
63 WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_get_pubkey_256(unsigned int derivation_mode,
64  cx_curve_t curve,
65  const uint32_t *path,
66  size_t path_len,
67  uint8_t raw_pubkey[static 65],
68  uint8_t *chain_code,
69  cx_md_t hashID,
70  unsigned char *seed,
71  size_t seed_len)
72 {
73  cx_err_t error = CX_OK;
74 
75  cx_ecfp_256_private_key_t privkey;
76  cx_ecfp_256_public_key_t pubkey;
77 
78  // Derive private key according to BIP32 path
80  derivation_mode, curve, path, path_len, &privkey, chain_code, seed, seed_len));
81 
82  // Generate associated pubkey
83  CX_CHECK(cx_ecfp_generate_pair2_no_throw(curve, &pubkey, &privkey, true, hashID));
84 
85  // Check pubkey length then copy it to raw_pubkey
86  if (pubkey.W_len != 65) {
87  error = CX_EC_INVALID_CURVE;
88  goto end;
89  }
90  memmove(raw_pubkey, pubkey.W, pubkey.W_len);
91 
92 end:
93  explicit_bzero(&privkey, sizeof(privkey));
94 
95  if (error != CX_OK) {
96  // Make sure the caller doesn't use uninitialized data in case
97  // the return code is not checked.
98  explicit_bzero(raw_pubkey, 65);
99  }
100  return error;
101 }
102 
103 WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_ecdsa_sign_hash_256(unsigned int derivation_mode,
104  cx_curve_t curve,
105  const uint32_t *path,
106  size_t path_len,
107  uint32_t sign_mode,
108  cx_md_t hashID,
109  const uint8_t *hash,
110  size_t hash_len,
111  uint8_t *sig,
112  size_t *sig_len,
113  uint32_t *info,
114  unsigned char *seed,
115  size_t seed_len)
116 {
117  cx_err_t error = CX_OK;
118  cx_ecfp_256_private_key_t privkey;
119  size_t buf_len = *sig_len;
120 
121  // Derive private key according to BIP32 path
123  derivation_mode, curve, path, path_len, &privkey, NULL, seed, seed_len));
124 
125  CX_CHECK(
126  cx_ecdsa_sign_no_throw(&privkey, sign_mode, hashID, hash, hash_len, sig, sig_len, info));
127 
128 end:
129  explicit_bzero(&privkey, sizeof(privkey));
130 
131  if (error != CX_OK) {
132  // Make sure the caller doesn't use uninitialized data in case
133  // the return code is not checked.
134  explicit_bzero(sig, buf_len);
135  }
136  return error;
137 }
138 
139 WARN_UNUSED_RESULT cx_err_t
141  cx_curve_t curve,
142  const uint32_t *path,
143  size_t path_len,
144  uint32_t sign_mode,
145  cx_md_t hashID,
146  const uint8_t *hash,
147  size_t hash_len,
148  uint8_t sig_r[static 32],
149  uint8_t sig_s[static 32],
150  uint32_t *info,
151  unsigned char *seed,
152  size_t seed_len)
153 {
154  cx_err_t error = CX_OK;
155  cx_ecfp_256_private_key_t privkey;
156 
157  // Derive private key according to BIP32 path
159  derivation_mode, curve, path, path_len, &privkey, NULL, seed, seed_len));
160 
161  CX_CHECK(cx_ecdsa_sign_rs_no_throw(
162  &privkey, sign_mode, hashID, hash, hash_len, 32, sig_r, sig_s, info));
163 
164 end:
165  explicit_bzero(&privkey, sizeof(privkey));
166 
167  return error;
168 }
169 
170 WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_eddsa_sign_hash_256(unsigned int derivation_mode,
171  cx_curve_t curve,
172  const uint32_t *path,
173  size_t path_len,
174  cx_md_t hashID,
175  const uint8_t *hash,
176  size_t hash_len,
177  uint8_t *sig,
178  size_t *sig_len,
179  unsigned char *seed,
180  size_t seed_len)
181 {
182  cx_err_t error = CX_OK;
183  cx_ecfp_256_private_key_t privkey;
184  size_t size;
185  size_t buf_len = *sig_len;
186 
187  if (sig_len == NULL) {
188  error = CX_INVALID_PARAMETER_VALUE;
189  goto end;
190  }
191 
192  // Derive private key according to BIP32 path
194  derivation_mode, curve, path, path_len, &privkey, NULL, seed, seed_len));
195 
196  CX_CHECK(cx_eddsa_sign_no_throw(&privkey, hashID, hash, hash_len, sig, *sig_len));
197 
198  CX_CHECK(cx_ecdomain_parameters_length(curve, &size));
199  *sig_len = size * 2;
200 
201 end:
202  explicit_bzero(&privkey, sizeof(privkey));
203 
204  if (error != CX_OK) {
205  // Make sure the caller doesn't use uninitialized data in case
206  // the return code is not checked.
207  explicit_bzero(sig, buf_len);
208  }
209  return error;
210 }
WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_ecdsa_sign_hash_256(unsigned int derivation_mode, cx_curve_t curve, const uint32_t *path, size_t path_len, uint32_t sign_mode, cx_md_t hashID, const uint8_t *hash, size_t hash_len, uint8_t *sig, size_t *sig_len, uint32_t *info, unsigned char *seed, size_t seed_len)
Sign a hash with ecdsa using the device seed derived from the specified bip32 path and seed key.
WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_init_privkey_256(unsigned int derivation_mode, cx_curve_t curve, const uint32_t *path, size_t path_len, cx_ecfp_256_private_key_t *privkey, uint8_t *chain_code, unsigned char *seed, size_t seed_len)
Gets the private key from the device seed using the specified bip32 path and seed key.
WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_eddsa_sign_hash_256(unsigned int derivation_mode, cx_curve_t curve, const uint32_t *path, size_t path_len, cx_md_t hashID, const uint8_t *hash, size_t hash_len, uint8_t *sig, size_t *sig_len, unsigned char *seed, size_t seed_len)
Sign a hash with eddsa using the device seed derived from the specified bip32 path and seed key.
WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_ecdsa_sign_rs_hash_256(unsigned int derivation_mode, cx_curve_t curve, const uint32_t *path, size_t path_len, uint32_t sign_mode, cx_md_t hashID, const uint8_t *hash, size_t hash_len, uint8_t sig_r[static 32], uint8_t sig_s[static 32], uint32_t *info, unsigned char *seed, size_t seed_len)
Sign a hash with ecdsa using the device seed derived from the specified bip32 path and seed key.
WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_get_pubkey_256(unsigned int derivation_mode, cx_curve_t curve, const uint32_t *path, size_t path_len, uint8_t raw_pubkey[static 65], uint8_t *chain_code, cx_md_t hashID, unsigned char *seed, size_t seed_len)
Gets the public key from the device seed using the specified bip32 path and seed key.
unsigned char uint8_t
Definition: usbd_conf.h:53