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 : #include <stdlib.h>
27 : #include "os.h"
28 : #include "cx.h"
29 : #include "signer_authorization.h"
30 : #include "defs.h"
31 : #include "ui_err.h"
32 : #include "memutil.h"
33 : #include "ints.h"
34 : #include "compiletime.h"
35 : #include "runtime.h"
36 :
37 : // Initial signer hash taken from an external definition (see Makefile for
38 : // details)
39 : #ifdef PARAM_INITIAL_SIGNER_HASH
40 : static const uint8_t INITIAL_SIGNER_HASH[] = PARAM_INITIAL_SIGNER_HASH;
41 : #else
42 : #error "Initial signer hash not defined!"
43 : #endif
44 :
45 : // Initial signer iteration taken from an external definition (see Makefile for
46 : // details)
47 : #ifdef PARAM_INITIAL_SIGNER_ITERATION
48 : static const uint16_t INITIAL_SIGNER_ITERATION = PARAM_INITIAL_SIGNER_ITERATION;
49 : #else
50 : #error "Initial signer iteration not defined!"
51 : #endif
52 :
53 : // Authorized signers
54 : static const uint8_t authorizers_pubkeys[][AUTHORIZED_SIGNER_PUBKEY_LENGTH] =
55 : AUTHORIZERS_PUBKEYS;
56 :
57 : // Total number of authorizers
58 : #define TOTAL_AUTHORIZERS \
59 : (sizeof(authorizers_pubkeys) / sizeof(authorizers_pubkeys[0]))
60 :
61 : // Minimum number of authorizers required to authorize a signer
62 : #define THRESHOLD_AUTHORIZERS (TOTAL_AUTHORIZERS / 2 + 1)
63 :
64 : /*
65 : * Sanity check the status of the signer authorization
66 : * component
67 : */
68 10 : static void sanity_check() {
69 10 : if (!N_current_signer_status.initialized)
70 0 : THROW(ERR_UI_INTERNAL);
71 10 : }
72 :
73 : /*
74 : * Check that the SM for the signer authorization
75 : * matches the expected state.
76 : *
77 : * Reset the state and throw a protocol error
78 : * otherwise.
79 : */
80 9 : static void check_state(sigaut_t* sigaut_ctx, sigaut_state_t expected) {
81 9 : sanity_check();
82 :
83 9 : if (sigaut_ctx->state != expected) {
84 0 : reset_signer_authorization(sigaut_ctx);
85 0 : THROW(ERR_UI_PROT_INVALID);
86 : }
87 9 : }
88 :
89 1 : static void generate_message_to_sign(sigaut_t* sigaut_ctx) {
90 : uint8_t message_size;
91 :
92 1 : cx_keccak_init(&sigaut_ctx->auth_hash_ctx, 256);
93 :
94 : // Hash eth prefix
95 1 : cx_hash((cx_hash_t*)&sigaut_ctx->auth_hash_ctx,
96 : 0,
97 : (unsigned char*)ETHEREUM_MSG_PREFIX,
98 : ETHEREUM_MSG_PREFIX_LENGTH,
99 : 0);
100 :
101 : // Compute total message size
102 3 : UINT_TO_DECSTR(sigaut_ctx->buf, sigaut_ctx->signer.iteration);
103 1 : message_size = RSK_SIGNER_VERSION_MSG_P1_LENGTH +
104 : sizeof(sigaut_ctx->signer.hash) * 2 + // Hexa
105 1 : RSK_SIGNER_VERSION_MSG_P2_LENGTH +
106 1 : strlen((const char*)sigaut_ctx->buf);
107 :
108 : // Hash message size
109 5 : UINT_TO_DECSTR(sigaut_ctx->buf, message_size);
110 1 : cx_hash((cx_hash_t*)&sigaut_ctx->auth_hash_ctx,
111 : 0,
112 1 : sigaut_ctx->buf,
113 1 : strlen((const char*)sigaut_ctx->buf),
114 : 0);
115 :
116 : // Hash message
117 1 : cx_hash((cx_hash_t*)&sigaut_ctx->auth_hash_ctx,
118 : 0,
119 : (unsigned char*)RSK_SIGNER_VERSION_MSG_P1,
120 : RSK_SIGNER_VERSION_MSG_P1_LENGTH,
121 : 0);
122 33 : for (unsigned int i = 0; i < sizeof(sigaut_ctx->signer.hash); i++) {
123 32 : BYTE_TO_HEXSTR(sigaut_ctx->buf, sigaut_ctx->signer.hash[i]);
124 32 : cx_hash(
125 32 : (cx_hash_t*)&sigaut_ctx->auth_hash_ctx, 0, sigaut_ctx->buf, 2, 0);
126 : }
127 1 : cx_hash((cx_hash_t*)&sigaut_ctx->auth_hash_ctx,
128 : 0,
129 : (unsigned char*)RSK_SIGNER_VERSION_MSG_P2,
130 : RSK_SIGNER_VERSION_MSG_P2_LENGTH,
131 : 0);
132 3 : UINT_TO_DECSTR(sigaut_ctx->buf, sigaut_ctx->signer.iteration);
133 1 : cx_hash((cx_hash_t*)&sigaut_ctx->auth_hash_ctx,
134 : CX_LAST,
135 1 : sigaut_ctx->buf,
136 1 : strlen((const char*)sigaut_ctx->buf),
137 1 : sigaut_ctx->auth_hash);
138 1 : }
139 :
140 : // -----------------------------------------------------------------------
141 : // Protocol implementation
142 : // -----------------------------------------------------------------------
143 :
144 : /*
145 : * Initialize the signer authorization
146 : */
147 1 : void init_signer_authorization() {
148 : // Build should fail when more authorizers than supported are provided
149 : COMPILE_TIME_ASSERT(TOTAL_AUTHORIZERS <= MAX_AUTHORIZERS);
150 :
151 1 : const bool t = true;
152 : // Make sure NVM signer status is initialized
153 1 : if (!N_current_signer_status.initialized) {
154 1 : nvm_write(N_current_signer_status.signer.hash,
155 : (void*)INITIAL_SIGNER_HASH,
156 : sizeof(N_current_signer_status.signer.hash));
157 1 : nvm_write(&N_current_signer_status.signer.iteration,
158 : (void*)&INITIAL_SIGNER_ITERATION,
159 : sizeof(N_current_signer_status.signer.iteration));
160 1 : nvm_write(&N_current_signer_status.initialized,
161 : (void*)&t,
162 : sizeof(N_current_signer_status.initialized));
163 : }
164 1 : }
165 :
166 : /*
167 : * Reset the given signer authorization context
168 : *
169 : * @arg[in] sigaut_ctx signer authorization context
170 : */
171 12 : void reset_signer_authorization(sigaut_t* sigaut_ctx) {
172 12 : explicit_bzero(sigaut_ctx, sizeof(sigaut_t));
173 12 : sigaut_ctx->state = sigaut_state_wait_signer_version;
174 12 : }
175 :
176 : /*
177 : * Implement the signer authorization protocol.
178 : *
179 : * @arg[in] rx number of received bytes from the Host
180 : * @arg[in] sigaut_ctx signer authorization context
181 : * @ret number of transmited bytes to the host
182 : */
183 14 : unsigned int do_authorize_signer(volatile unsigned int rx,
184 : sigaut_t* sigaut_ctx) {
185 : uint8_t signature_valid, valid_count, auth_index;
186 :
187 14 : switch (APDU_OP()) {
188 1 : case OP_SIGAUT_GET_CURRENT:
189 1 : sanity_check();
190 :
191 2 : SAFE_MEMMOVE(APDU_DATA_PTR,
192 : APDU_TOTAL_DATA_SIZE_OUT,
193 : MEMMOVE_ZERO_OFFSET,
194 : N_current_signer_status.signer.hash,
195 : sizeof(N_current_signer_status.signer.hash),
196 : MEMMOVE_ZERO_OFFSET,
197 : sizeof(N_current_signer_status.signer.hash),
198 : THROW(ERR_UI_INTERNAL));
199 :
200 : if (APDU_TOTAL_DATA_SIZE_OUT <
201 : sizeof(N_current_signer_status.signer.hash) +
202 : sizeof(N_current_signer_status.signer.iteration))
203 : THROW(ERR_UI_INTERNAL);
204 :
205 3 : VAR_BIGENDIAN_TO(APDU_DATA_PTR +
206 : sizeof(N_current_signer_status.signer.hash),
207 : N_current_signer_status.signer.iteration,
208 : sizeof(N_current_signer_status.signer.iteration));
209 :
210 1 : return TX_FOR_DATA_SIZE(
211 : sizeof(N_current_signer_status.signer.hash) +
212 : sizeof(N_current_signer_status.signer.iteration));
213 3 : case OP_SIGAUT_SIGVER:
214 3 : check_state(sigaut_ctx, sigaut_state_wait_signer_version);
215 :
216 : // Should receive a signer hash followed by a signer iteration
217 3 : if (APDU_DATA_SIZE(rx) != (sizeof(sigaut_ctx->signer.hash) +
218 : sizeof(sigaut_ctx->signer.iteration)))
219 1 : THROW(ERR_UI_PROT_INVALID);
220 :
221 : // Set the signer version
222 4 : SAFE_MEMMOVE(sigaut_ctx->signer.hash,
223 : sizeof(sigaut_ctx->signer.hash),
224 : MEMMOVE_ZERO_OFFSET,
225 : APDU_DATA_PTR,
226 : APDU_TOTAL_DATA_SIZE,
227 : MEMMOVE_ZERO_OFFSET,
228 : sizeof(sigaut_ctx->signer.hash),
229 : THROW(ERR_UI_INTERNAL));
230 :
231 6 : BIGENDIAN_FROM(APDU_DATA_PTR + sizeof(sigaut_ctx->signer.hash),
232 : sigaut_ctx->signer.iteration);
233 :
234 : // Make sure the intended iteration is strictly greater than the current
235 : // iteration
236 2 : if (sigaut_ctx->signer.iteration <=
237 2 : N_current_signer_status.signer.iteration) {
238 1 : reset_signer_authorization(sigaut_ctx);
239 1 : THROW(ERR_SIGAUT_INVALID_ITERATION);
240 : }
241 :
242 : // Compute the hash that should be signed for this signer version
243 : // to be authorized
244 1 : generate_message_to_sign(sigaut_ctx);
245 :
246 1 : sigaut_ctx->state = sigaut_state_wait_signature;
247 :
248 1 : return TX_FOR_DATA_SIZE(0);
249 6 : case OP_SIGAUT_SIGN:
250 6 : check_state(sigaut_ctx, sigaut_state_wait_signature);
251 :
252 : // Check to see whether we find a matching authorized signer
253 6 : signature_valid = 0;
254 15 : for (unsigned int i = 0; i < TOTAL_AUTHORIZERS && !signature_valid;
255 9 : i++) {
256 : // Clear public key memory region first just in case initialization
257 : // fails
258 9 : explicit_bzero(&sigaut_ctx->pubkey, sizeof(sigaut_ctx->pubkey));
259 : // Init public key
260 9 : cx_ecfp_init_public_key(CX_CURVE_256K1,
261 9 : (unsigned char*)authorizers_pubkeys[i],
262 : sizeof(authorizers_pubkeys[i]),
263 : &sigaut_ctx->pubkey);
264 0 : signature_valid = cx_ecdsa_verify(&sigaut_ctx->pubkey,
265 : 0,
266 : CX_NONE,
267 9 : sigaut_ctx->auth_hash,
268 : HASH_LENGTH,
269 : APDU_DATA_PTR,
270 9 : APDU_DATA_SIZE(rx));
271 : // Cleanup
272 9 : explicit_bzero(&sigaut_ctx->pubkey, sizeof(sigaut_ctx->pubkey));
273 :
274 : // Found a valid signature?
275 9 : if (signature_valid) {
276 5 : sigaut_ctx->authorized_signer_verified[i] = true;
277 : }
278 : }
279 :
280 : // Reached the threshold?
281 6 : valid_count = 0;
282 24 : for (unsigned int i = 0; i < TOTAL_AUTHORIZERS; i++)
283 18 : if (sigaut_ctx->authorized_signer_verified[i])
284 7 : valid_count++;
285 :
286 6 : if (valid_count >= THRESHOLD_AUTHORIZERS) {
287 : // Write the new authorized signer version and iteration to NVM,
288 : // reset the operation and signal success
289 1 : nvm_write(N_current_signer_status.signer.hash,
290 1 : sigaut_ctx->signer.hash,
291 : sizeof(N_current_signer_status.signer.hash));
292 1 : nvm_write(&N_current_signer_status.signer.iteration,
293 1 : &sigaut_ctx->signer.iteration,
294 : sizeof(N_current_signer_status.signer.iteration));
295 1 : reset_signer_authorization(sigaut_ctx);
296 1 : APDU_DATA_PTR[0] = RES_SIGAUT_SUCCESS;
297 : } else {
298 5 : APDU_DATA_PTR[0] = RES_SIGAUT_MORE;
299 : }
300 6 : return TX_FOR_DATA_SIZE(1);
301 1 : case OP_SIGAUT_GET_AUTH_COUNT:
302 1 : APDU_DATA_PTR[0] = (unsigned char)TOTAL_AUTHORIZERS;
303 1 : return TX_FOR_DATA_SIZE(1);
304 3 : case OP_SIGAUT_GET_AUTH_AT:
305 3 : if (APDU_DATA_SIZE(rx) != 1)
306 0 : THROW(ERR_UI_PROT_INVALID);
307 :
308 3 : auth_index = APDU_DATA_PTR[0];
309 3 : if (auth_index >= (uint8_t)TOTAL_AUTHORIZERS)
310 0 : THROW(ERR_SIGAUT_INVALID_AUTH_INVALID_INDEX);
311 :
312 6 : SAFE_MEMMOVE(APDU_DATA_PTR,
313 : APDU_TOTAL_DATA_SIZE_OUT,
314 : MEMMOVE_ZERO_OFFSET,
315 : authorizers_pubkeys[auth_index],
316 : sizeof(authorizers_pubkeys[auth_index]),
317 : MEMMOVE_ZERO_OFFSET,
318 : sizeof(authorizers_pubkeys[auth_index]),
319 : THROW(ERR_UI_INTERNAL));
320 :
321 3 : return TX_FOR_DATA_SIZE(sizeof(authorizers_pubkeys[auth_index]));
322 0 : default:
323 0 : reset_signer_authorization(sigaut_ctx);
324 0 : THROW(ERR_UI_PROT_INVALID);
325 : break;
326 : }
327 : }
328 :
329 : /*
330 : * Tell whether the given signer hash is authorized to run
331 : * as per the current signer authorization status.
332 : *
333 : * @arg[in] signer_hash the signer hash
334 : */
335 2 : bool is_authorized_signer(unsigned char* signer_hash) {
336 : #ifdef DEBUG_BUILD
337 : return true;
338 : #else
339 2 : return !memcmp(N_current_signer_status.signer.hash,
340 : signer_hash,
341 : sizeof(N_current_signer_status.signer.hash));
342 : #endif
343 : }
|