Line data Source code
1 : /**
2 : * The MIT License (MIT)
3 : *
4 : * Copyright (c) 2021 RSK Labs Ltd
5 : *
6 : * Permission is hereby granted, free of charge, to any person obtaining a copy
7 : * of this software and associated documentation files (the "Software"), to
8 : * deal in the Software without restriction, including without limitation the
9 : * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 : * sell copies of the Software, and to permit persons to whom the Software is
11 : * furnished to do so, subject to the following conditions:
12 : *
13 : * The above copyright notice and this permission notice shall be included in
14 : * all copies or substantial portions of the Software.
15 : *
16 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 : * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 : * IN THE SOFTWARE.
23 : */
24 :
25 : #include <string.h>
26 :
27 : #include "os.h"
28 : #include "cx.h"
29 : #include "hal/constants.h"
30 : #include "hal/seed.h"
31 :
32 2 : bool seed_available() {
33 2 : return os_perso_isonboarded() == 1;
34 : }
35 :
36 5 : bool seed_derive_pubkey(uint32_t* path,
37 : uint8_t path_length,
38 : uint8_t* pubkey_out,
39 : uint8_t* pubkey_out_length) {
40 :
41 : volatile unsigned char private_key_data[PRIVATE_KEY_LENGTH];
42 : volatile cx_ecfp_private_key_t private_key;
43 : volatile cx_ecfp_public_key_t public_key;
44 :
45 : BEGIN_TRY {
46 5 : TRY {
47 : // Derive and init private key
48 5 : os_perso_derive_node_bip32(CX_CURVE_256K1,
49 : path,
50 : path_length,
51 : (unsigned char*)private_key_data,
52 : NULL);
53 4 : cx_ecdsa_init_private_key(CX_CURVE_256K1,
54 : (unsigned char*)private_key_data,
55 : PRIVATE_KEY_LENGTH,
56 : (cx_ecfp_private_key_t*)&private_key);
57 : // Cleanup private key data
58 3 : explicit_bzero((void*)private_key_data, sizeof(private_key_data));
59 : // Derive public key
60 3 : cx_ecfp_generate_pair(CX_CURVE_256K1,
61 : (cx_ecfp_public_key_t*)&public_key,
62 : (cx_ecfp_private_key_t*)&private_key,
63 : 1);
64 : // Cleanup private key
65 2 : explicit_bzero((void*)&private_key, sizeof(private_key));
66 2 : if (*pubkey_out_length < public_key.W_len) {
67 1 : THROW(1);
68 : }
69 : // Output the public key
70 1 : *pubkey_out_length = public_key.W_len;
71 1 : os_memmove(
72 1 : (void*)pubkey_out, (const void*)public_key.W, public_key.W_len);
73 : // Cleanup public key
74 1 : explicit_bzero((void*)&public_key, sizeof(public_key));
75 : }
76 1 : CATCH_ALL {
77 : // Cleanup key data and fail
78 4 : explicit_bzero((void*)private_key_data, sizeof(private_key_data));
79 4 : explicit_bzero((void*)&private_key, sizeof(private_key));
80 4 : explicit_bzero((void*)&public_key, sizeof(public_key));
81 4 : return false;
82 : }
83 1 : FINALLY {
84 : }
85 : }
86 1 : END_TRY;
87 :
88 1 : return true;
89 : }
90 :
91 5 : bool seed_sign(uint32_t* path,
92 : uint8_t path_length,
93 : uint8_t* hash32,
94 : uint8_t* sig_out,
95 : uint8_t* sig_out_length) {
96 :
97 : volatile unsigned char private_key_data[PRIVATE_KEY_LENGTH];
98 : volatile cx_ecfp_private_key_t private_key;
99 :
100 : // Check the destination buffer won't be overflowed by the signature
101 5 : if (*sig_out_length < MAX_SIGNATURE_LENGTH) {
102 1 : return false;
103 : }
104 :
105 : BEGIN_TRY {
106 4 : TRY {
107 : // Derive and init private key
108 4 : os_perso_derive_node_bip32(CX_CURVE_256K1,
109 : path,
110 : path_length,
111 : (unsigned char*)private_key_data,
112 : NULL);
113 3 : cx_ecdsa_init_private_key(CX_CURVE_256K1,
114 : (unsigned char*)private_key_data,
115 : PRIVATE_KEY_LENGTH,
116 : (cx_ecfp_private_key_t*)&private_key);
117 : // Cleanup private key data
118 2 : explicit_bzero((void*)private_key_data, sizeof(private_key_data));
119 2 : *sig_out_length = (uint8_t)cx_ecdsa_sign((void*)&private_key,
120 : CX_RND_RFC6979 | CX_LAST,
121 : CX_SHA256,
122 : hash32,
123 : HASH_LENGTH,
124 : sig_out);
125 : // Cleanup private key
126 1 : explicit_bzero((void*)&private_key, sizeof(private_key));
127 : }
128 1 : CATCH_ALL {
129 : // Cleanup key data and fail
130 3 : explicit_bzero((void*)private_key_data, sizeof(private_key_data));
131 3 : explicit_bzero((void*)&private_key, sizeof(private_key));
132 3 : return false;
133 : }
134 1 : FINALLY {
135 : }
136 : }
137 1 : END_TRY;
138 :
139 1 : return true;
140 : }
|