Embedded SDK
Embedded SDK
Loading...
Searching...
No Matches
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
24WARN_UNUSED_RESULT cx_err_t
25bip32_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
52end:
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
63WARN_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
92end:
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
103WARN_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
128end:
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
139WARN_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
164end:
165 explicit_bzero(&privkey, sizeof(privkey));
166
167 return error;
168}
169
170WARN_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
201end:
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