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 "upgrade.h"
26 :
27 : #include <string.h>
28 : #include <secp256k1.h>
29 : #include <secp256k1_ecdh.h>
30 : #include <openenclave/corelibc/stdlib.h>
31 :
32 : #include "hal/exceptions.h"
33 : #include "hal/log.h"
34 : #include "hal/seed.h"
35 : #include "hal/hash.h"
36 :
37 : #include "defs.h"
38 : #include "apdu.h"
39 : #include "hsm.h"
40 : #include "migrate.h"
41 : #include "eth.h"
42 : #include "ints.h"
43 : #include "compiletime.h"
44 : #include "evidence.h"
45 : #include "util.h"
46 : #include "random.h"
47 : #include "aes_gcm.h"
48 :
49 : // Authorizers' public keys length (uncompressed format)
50 : #define AUTHORIZED_SIGNER_PUBKEY_LENGTH 65
51 :
52 : // Maximum number of authorizers (increase this if using a greater number)
53 : #define MAX_AUTHORIZERS 10
54 :
55 : // Maximum size for a peer data packet
56 : #define MAX_RECV_DATA_SIZE (8 * 1024) // 8Kbytes
57 :
58 : // Authorized signers
59 : #include "upgrade_signers.h"
60 : static const uint8_t authorizers_pubkeys[][AUTHORIZED_SIGNER_PUBKEY_LENGTH] =
61 : AUTHORIZERS_PUBKEYS;
62 :
63 : // Total number of authorizers
64 : #define TOTAL_AUTHORIZERS \
65 : (sizeof(authorizers_pubkeys) / sizeof(authorizers_pubkeys[0]))
66 :
67 : // Minimum number of authorizers required to authorize a signer
68 : #define THRESHOLD_AUTHORIZERS (TOTAL_AUTHORIZERS / 2 + 1)
69 :
70 : // SGX upgrade spec message parts
71 : #define SGX_UPG_SPEC_MSG_P1 "RSK_powHSM_SGX_upgrade_from_"
72 : #define SGX_UPG_SPEC_MSG_P1_LENGTH (sizeof(SGX_UPG_SPEC_MSG_P1) - sizeof(""))
73 :
74 : #define SGX_UPG_SPEC_MSG_P2 "_to_"
75 : #define SGX_UPG_SPEC_MSG_P2_LENGTH (sizeof(SGX_UPG_SPEC_MSG_P2) - sizeof(""))
76 :
77 : #define EVIDENCE_FORMAT EVIDENCE_FORMAT_SGX_LOCAL
78 :
79 : // Operation selectors
80 : typedef enum {
81 : OP_UPGRADE_START = 0x01,
82 : OP_UPGRADE_SPEC_SIG = 0x02,
83 : OP_UPGRADE_IDENTIFY_SELF = 0x03,
84 : OP_UPGRADE_IDENTIFY_PEER = 0x04,
85 : OP_UPGRADE_PROCESS_DATA = 0x05,
86 : } op_code_upgrade_t;
87 :
88 : // Error codes
89 : typedef enum {
90 : ERR_UPGRADE_PROTOCOL = 0x6A00,
91 : ERR_UPGRADE_SPEC = 0x6A01,
92 : ERR_UPGRADE_SIGNATURE = 0x6A02,
93 : ERR_UPGRADE_AUTH = 0x6A03,
94 : ERR_UPGRADE_DATA_PROCESSING = 0x6A04,
95 : ERR_UPGRADE_INTERNAL = 0x6A99,
96 : } err_code_upgrade_t;
97 :
98 : // MRENCLAVE size
99 : #define UPGRADE_MRENCLAVE_SIZE HASH_LENGTH
100 :
101 : // SGX upgrade spec
102 : typedef struct {
103 : uint8_t mrenclave_from[UPGRADE_MRENCLAVE_SIZE];
104 : uint8_t mrenclave_to[UPGRADE_MRENCLAVE_SIZE];
105 : } upgrade_spec_t;
106 :
107 : // SGX upgrade operations
108 : typedef enum {
109 : upgrade_operation_none = 0,
110 : upgrade_operation_export = 1,
111 : upgrade_operation_import = 2,
112 : } upgrade_operation_t;
113 :
114 : // SGX upgrade SM states
115 : typedef enum {
116 : upgrade_state_await_spec,
117 : upgrade_state_await_spec_sigs,
118 : upgrade_state_send_self_id,
119 : upgrade_state_await_peer_id,
120 : upgrade_state_ready_for_xchg,
121 : } upgrade_state_t;
122 :
123 : // SGX upgrade context
124 : typedef struct {
125 : upgrade_state_t state;
126 :
127 : upgrade_spec_t spec;
128 : upgrade_operation_t operation;
129 : uint8_t* my_mrenclave;
130 : uint8_t* their_mrenclave;
131 :
132 : uint8_t expected_message_hash[HASH_LENGTH];
133 : bool authorized_signer_verified[MAX_AUTHORIZERS];
134 :
135 : uint8_t* evidence;
136 : size_t evidence_size;
137 : bool evidence_external;
138 :
139 : uint8_t my_privkey[PRIVATE_KEY_LENGTH];
140 : uint8_t my_pubkey[PUBKEY_CMP_LENGTH];
141 : size_t my_pubkey_len;
142 : uint8_t their_pubkey[PUBKEY_CMP_LENGTH];
143 :
144 : size_t trx_offset;
145 : } upgrade_ctx_t;
146 :
147 : // SGX upgrade ctx
148 : static upgrade_ctx_t upgrade_ctx;
149 :
150 : /*
151 : * Free current evidence buffer, if any
152 : */
153 89 : static void free_evidence() {
154 89 : if (upgrade_ctx.evidence) {
155 43 : if (!upgrade_ctx.evidence_external)
156 34 : evidence_free(upgrade_ctx.evidence);
157 : else
158 9 : oe_free(upgrade_ctx.evidence);
159 : }
160 89 : upgrade_ctx.evidence = NULL;
161 89 : upgrade_ctx.evidence_size = 0;
162 89 : }
163 :
164 : /*
165 : * Reset the upgrade context
166 : */
167 57 : static void reset_upgrade() {
168 57 : free_evidence();
169 57 : explicit_bzero(&upgrade_ctx, sizeof(upgrade_ctx));
170 57 : }
171 :
172 : /*
173 : * Check that the context for the SGX upgrade
174 : * matches the expected state and is in a
175 : * consistent state.
176 : *
177 : * Reset the state and throw a protocol error
178 : * otherwise.
179 : */
180 87 : static void check_state(upgrade_state_t expected) {
181 : // Consistency check
182 87 : if (upgrade_ctx.state == upgrade_state_await_spec &&
183 30 : upgrade_ctx.operation != upgrade_operation_none) {
184 0 : reset_upgrade();
185 0 : THROW(ERR_UPGRADE_PROTOCOL);
186 87 : } else if (upgrade_ctx.state != upgrade_state_await_spec &&
187 57 : upgrade_ctx.operation == upgrade_operation_none) {
188 0 : reset_upgrade();
189 0 : THROW(ERR_UPGRADE_PROTOCOL);
190 : }
191 : // Expectation check
192 87 : if (upgrade_ctx.state != expected) {
193 2 : reset_upgrade();
194 2 : THROW(ERR_UPGRADE_PROTOCOL);
195 : }
196 85 : }
197 :
198 17 : static bool generate_message_to_verify() {
199 : uint8_t message_size;
200 : uint8_t aux_buf[4]; // Hold at most three digits plus a null terminator
201 : hash_keccak256_ctx_t hash_ctx;
202 :
203 17 : if (!hash_keccak256_init(&hash_ctx))
204 0 : goto generate_message_to_verify_error;
205 :
206 : // Hash eth prefix
207 17 : if (!hash_keccak256_update(&hash_ctx,
208 : (const uint8_t*)ETHEREUM_MSG_PREFIX,
209 : ETHEREUM_MSG_PREFIX_LENGTH))
210 0 : goto generate_message_to_verify_error;
211 :
212 : // Compute total message size
213 17 : message_size = SGX_UPG_SPEC_MSG_P1_LENGTH +
214 : sizeof(upgrade_ctx.spec.mrenclave_from) * 2 + // Hexa
215 : SGX_UPG_SPEC_MSG_P2_LENGTH +
216 : sizeof(upgrade_ctx.spec.mrenclave_to) * 2; // Hexa
217 :
218 : // Hash message size
219 119 : UINT_TO_DECSTR(aux_buf, message_size);
220 17 : if (!hash_keccak256_update(&hash_ctx, aux_buf, strlen((char*)aux_buf)))
221 0 : goto generate_message_to_verify_error;
222 :
223 : // Hash message
224 17 : if (!hash_keccak256_update(&hash_ctx,
225 : (uint8_t*)SGX_UPG_SPEC_MSG_P1,
226 : SGX_UPG_SPEC_MSG_P1_LENGTH))
227 0 : goto generate_message_to_verify_error;
228 :
229 561 : for (unsigned int i = 0; i < sizeof(upgrade_ctx.spec.mrenclave_from); i++) {
230 544 : BYTE_TO_HEXSTR(aux_buf, upgrade_ctx.spec.mrenclave_from[i]);
231 544 : if (!hash_keccak256_update(&hash_ctx, aux_buf, 2))
232 0 : goto generate_message_to_verify_error;
233 : }
234 :
235 17 : if (!hash_keccak256_update(&hash_ctx,
236 : (uint8_t*)SGX_UPG_SPEC_MSG_P2,
237 : SGX_UPG_SPEC_MSG_P2_LENGTH))
238 0 : goto generate_message_to_verify_error;
239 :
240 561 : for (unsigned int i = 0; i < sizeof(upgrade_ctx.spec.mrenclave_to); i++) {
241 544 : BYTE_TO_HEXSTR(aux_buf, upgrade_ctx.spec.mrenclave_to[i]);
242 544 : if (!hash_keccak256_update(&hash_ctx, aux_buf, 2))
243 0 : goto generate_message_to_verify_error;
244 : }
245 :
246 : // Output hash
247 17 : if (!hash_keccak256_final(&hash_ctx, upgrade_ctx.expected_message_hash))
248 0 : goto generate_message_to_verify_error;
249 17 : return true;
250 :
251 0 : generate_message_to_verify_error:
252 : LOG("Error generating message to verify\n");
253 0 : return false;
254 : }
255 :
256 11 : static size_t send_data(uint8_t* src,
257 : size_t src_size,
258 : size_t* src_offset,
259 : bool* more) {
260 11 : size_t tx = MIN(APDU_TOTAL_DATA_SIZE_OUT, src_size - *src_offset);
261 11 : memcpy(APDU_DATA_PTR, src + *src_offset, tx);
262 11 : *src_offset += tx;
263 11 : *more = *src_offset < src_size;
264 : LOG("Sending %lu bytes of data\n", tx);
265 11 : return tx;
266 : }
267 :
268 13 : static bool receive_data(volatile unsigned int rx,
269 : uint8_t** dest,
270 : size_t* dest_size,
271 : size_t* dest_offset) {
272 13 : size_t pl = !*dest ? 2 : 0; // Two bytes for payload length
273 13 : if (APDU_DATA_SIZE(rx) <= pl) {
274 1 : reset_upgrade();
275 1 : THROW(ERR_UPGRADE_PROTOCOL);
276 : }
277 12 : if (!*dest) {
278 30 : VAR_BIGENDIAN_FROM(APDU_DATA_PTR, *dest_size, pl);
279 : // We allow a maximum data size due to the nature of data
280 : // we need to process
281 10 : if (*dest_size > MAX_RECV_DATA_SIZE) {
282 : LOG("Data bigger than allowed max\n");
283 1 : reset_upgrade();
284 1 : THROW(ERR_UPGRADE_PROTOCOL);
285 : }
286 9 : *dest = oe_malloc(*dest_size);
287 9 : if (!*dest) {
288 : LOG("Unable to allocate memory\n");
289 0 : THROW(ERR_UPGRADE_INTERNAL);
290 : }
291 9 : *dest_offset = 0;
292 : LOG("Expecting %lu bytes of data\n", *dest_size);
293 : }
294 11 : if (APDU_DATA_SIZE(rx) - pl > *dest_size - *dest_offset) {
295 : LOG("Data buffer overflow\n");
296 1 : reset_upgrade();
297 1 : THROW(ERR_UPGRADE_PROTOCOL);
298 : }
299 10 : memcpy(*dest + *dest_offset, APDU_DATA_PTR + pl, APDU_DATA_SIZE(rx) - pl);
300 10 : *dest_offset += APDU_DATA_SIZE(rx) - pl;
301 : LOG("Received %lu bytes of data\n", APDU_DATA_SIZE(rx) - pl);
302 10 : return *dest_offset < *dest_size; // More?
303 : }
304 :
305 46 : static secp256k1_context* assert_secp256k1_context_create_and_randomize() {
306 : unsigned char randomize[32];
307 46 : secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
308 46 : if (!random_getrandom(randomize, sizeof(randomize))) {
309 : LOG("Error generating random seed for "
310 : "secp256k1 context randomisation\n");
311 1 : reset_upgrade();
312 1 : THROW(ERR_INTERNAL);
313 : }
314 45 : if (!secp256k1_context_randomize(ctx, randomize)) {
315 : LOG("Error randomising secp256k1 context\n");
316 0 : reset_upgrade();
317 0 : THROW(ERR_INTERNAL);
318 : }
319 45 : explicit_bzero(randomize, sizeof(randomize));
320 45 : return ctx;
321 : }
322 :
323 : // -----------------------------------------------------------------------
324 : // Protocol implementation
325 : // -----------------------------------------------------------------------
326 :
327 30 : void upgrade_init() {
328 : // Build should fail when more authorizers than supported are provided
329 : COMPILE_TIME_ASSERT(TOTAL_AUTHORIZERS <= MAX_AUTHORIZERS);
330 : // Build should fail if hash size size differs from expected key size
331 : COMPILE_TIME_ASSERT(HASH_LENGTH == AES_GCM_KEY_SIZE);
332 :
333 30 : reset_upgrade();
334 : LOG("Upgrade module initialized\n");
335 30 : }
336 :
337 1 : void upgrade_reset() {
338 1 : reset_upgrade();
339 1 : }
340 :
341 88 : unsigned int upgrade_process_apdu(volatile unsigned int rx) {
342 : uint8_t key[AES_GCM_KEY_SIZE];
343 88 : size_t sz = 0;
344 : unsigned int tx;
345 : bool baux;
346 : int signature_valid;
347 : long unsigned valid_count;
348 : secp256k1_context* secp_ctx;
349 : secp256k1_ecdsa_signature signature;
350 : secp256k1_pubkey pubkey;
351 88 : oe_claim_t* claims = NULL;
352 : size_t claims_size;
353 : oe_claim_t* claim;
354 : evidence_format_t format;
355 : uint16_t error;
356 :
357 88 : switch (APDU_OP()) {
358 31 : case OP_UPGRADE_START:
359 31 : check_state(upgrade_state_await_spec);
360 :
361 : // We expect a from/to upgrade spec plus an operation type byte
362 30 : if (APDU_DATA_SIZE(rx) != UPGRADE_MRENCLAVE_SIZE * 2 + 1) {
363 2 : reset_upgrade();
364 2 : THROW(ERR_UPGRADE_PROTOCOL);
365 : }
366 : // Operation validations
367 28 : switch (APDU_DATA_PTR[0]) {
368 20 : case upgrade_operation_export:
369 20 : REQUIRE_ONBOARDED();
370 19 : REQUIRE_UNLOCKED();
371 18 : break;
372 8 : case upgrade_operation_import:
373 8 : REQUIRE_NOT_ONBOARDED();
374 7 : break;
375 0 : default:
376 0 : reset_upgrade();
377 0 : THROW(ERR_UPGRADE_PROTOCOL);
378 : }
379 25 : upgrade_ctx.operation = APDU_DATA_PTR[0];
380 : // Spec
381 25 : memcpy(upgrade_ctx.spec.mrenclave_from,
382 25 : APDU_DATA_PTR + 1,
383 : UPGRADE_MRENCLAVE_SIZE);
384 25 : memcpy(upgrade_ctx.spec.mrenclave_to,
385 25 : APDU_DATA_PTR + 1 + UPGRADE_MRENCLAVE_SIZE,
386 : UPGRADE_MRENCLAVE_SIZE);
387 25 : upgrade_ctx.my_mrenclave =
388 25 : upgrade_ctx.operation == upgrade_operation_export
389 : ? upgrade_ctx.spec.mrenclave_from
390 25 : : upgrade_ctx.spec.mrenclave_to;
391 25 : upgrade_ctx.their_mrenclave =
392 25 : upgrade_ctx.operation == upgrade_operation_export
393 : ? upgrade_ctx.spec.mrenclave_to
394 25 : : upgrade_ctx.spec.mrenclave_from;
395 : LOG("Spec received\n");
396 : LOG_HEX(
397 : "From:", upgrade_ctx.spec.mrenclave_from, UPGRADE_MRENCLAVE_SIZE);
398 : LOG_HEX("To:", upgrade_ctx.spec.mrenclave_to, UPGRADE_MRENCLAVE_SIZE);
399 : LOG("Role: %s\n",
400 : upgrade_ctx.operation == upgrade_operation_export ? "exporter"
401 : : "importer");
402 : // Check this enclave's mrenclave matches the corresponding
403 : // value in the spec according to the specified role
404 25 : explicit_bzero(&format, sizeof(format));
405 25 : format.id = EVIDENCE_FORMAT;
406 25 : upgrade_ctx.evidence_external = false;
407 25 : if (!evidence_generate(&format,
408 : NULL,
409 : 0,
410 : &upgrade_ctx.evidence,
411 : &upgrade_ctx.evidence_size)) {
412 : LOG("Unable to generate enclave evidence for self\n");
413 2 : error = ERR_UPGRADE_INTERNAL;
414 2 : goto upgrade_process_apdu_start_error;
415 : }
416 23 : if (!evidence_verify_and_extract_claims(EVIDENCE_FORMAT,
417 : upgrade_ctx.evidence,
418 : upgrade_ctx.evidence_size,
419 : &claims,
420 : &claims_size)) {
421 : LOG("Error verifying this enclave's evidence\n");
422 2 : error = ERR_UPGRADE_INTERNAL;
423 2 : goto upgrade_process_apdu_start_error;
424 : }
425 21 : if (!(claim = evidence_get_claim(
426 : claims, claims_size, OE_CLAIM_UNIQUE_ID))) {
427 : LOG("Error extracting this enclave's mrenclave\n");
428 2 : error = ERR_UPGRADE_INTERNAL;
429 2 : goto upgrade_process_apdu_start_error;
430 : }
431 : LOG_HEX("This enclave's mrenclave:", claim->value, claim->value_size);
432 19 : if (claim->value_size != UPGRADE_MRENCLAVE_SIZE ||
433 19 : memcmp(claim->value,
434 19 : upgrade_ctx.my_mrenclave,
435 : UPGRADE_MRENCLAVE_SIZE) != 0) {
436 : LOG("This enclave's mrenclave does not match the spec's "
437 : "mrenclave\n");
438 2 : error = ERR_UPGRADE_SPEC;
439 2 : goto upgrade_process_apdu_start_error;
440 : }
441 17 : generate_message_to_verify();
442 : LOG_HEX("Message to verify:",
443 : upgrade_ctx.expected_message_hash,
444 : sizeof(upgrade_ctx.expected_message_hash));
445 17 : upgrade_ctx.state = upgrade_state_await_spec_sigs;
446 17 : if (claims) {
447 17 : if (!evidence_free_claims(claims, claims_size)) {
448 : LOG("Error freeing claims\n");
449 0 : THROW(ERR_INTERNAL);
450 : }
451 17 : claims = NULL;
452 17 : claims_size = 0;
453 17 : claim = NULL;
454 : }
455 17 : free_evidence();
456 17 : return TX_NO_DATA();
457 8 : upgrade_process_apdu_start_error:
458 8 : if (claims) {
459 4 : if (!evidence_free_claims(claims, claims_size)) {
460 : LOG("Error freeing claims\n");
461 0 : THROW(ERR_INTERNAL);
462 : }
463 4 : claims = NULL;
464 4 : claims_size = 0;
465 4 : claim = NULL;
466 : }
467 8 : reset_upgrade();
468 8 : THROW(error);
469 27 : case OP_UPGRADE_SPEC_SIG:
470 27 : check_state(upgrade_state_await_spec_sigs);
471 :
472 27 : if (APDU_DATA_SIZE(rx) < 1) {
473 0 : reset_upgrade();
474 0 : THROW(ERR_UPGRADE_PROTOCOL);
475 : }
476 : // Check to see whether we find a matching authorized signer
477 27 : secp_ctx = assert_secp256k1_context_create_and_randomize();
478 26 : if (!secp256k1_ecdsa_signature_parse_der(
479 26 : secp_ctx, &signature, APDU_DATA_PTR, APDU_DATA_SIZE(rx))) {
480 1 : secp256k1_context_destroy(secp_ctx);
481 1 : reset_upgrade();
482 1 : THROW(ERR_UPGRADE_SIGNATURE);
483 : }
484 39 : for (unsigned int i = 0; i < TOTAL_AUTHORIZERS; i++) {
485 : // Attempt to verify against this public key
486 38 : if (!secp256k1_ec_pubkey_parse(
487 : secp_ctx,
488 : &pubkey,
489 38 : (const unsigned char*)authorizers_pubkeys[i],
490 : sizeof(authorizers_pubkeys[i]))) {
491 0 : secp256k1_context_destroy(secp_ctx);
492 0 : reset_upgrade();
493 0 : THROW(ERR_UPGRADE_SIGNATURE);
494 : }
495 : signature_valid =
496 38 : secp256k1_ecdsa_verify(secp_ctx,
497 : &signature,
498 : upgrade_ctx.expected_message_hash,
499 : &pubkey);
500 :
501 : // Found a valid signature?
502 38 : if (signature_valid) {
503 : LOG("Valid signature received!\n");
504 24 : upgrade_ctx.authorized_signer_verified[i] = true;
505 24 : break;
506 : }
507 : }
508 25 : secp256k1_context_destroy(secp_ctx);
509 :
510 : // Reached the threshold?
511 25 : valid_count = 0;
512 100 : for (unsigned int i = 0; i < TOTAL_AUTHORIZERS; i++)
513 75 : if (upgrade_ctx.authorized_signer_verified[i])
514 36 : valid_count++;
515 :
516 : LOG("Valid signatures so far: %lu\n", valid_count);
517 :
518 25 : if (valid_count >= THRESHOLD_AUTHORIZERS) {
519 11 : SET_APDU_OP(0); // No need for more
520 11 : upgrade_ctx.state = upgrade_state_send_self_id;
521 : LOG("Threshold reached!\n");
522 : } else {
523 14 : SET_APDU_OP(1); // We need more
524 : }
525 25 : return TX_NO_DATA();
526 12 : case OP_UPGRADE_IDENTIFY_SELF:
527 12 : check_state(upgrade_state_send_self_id);
528 :
529 11 : if (!upgrade_ctx.evidence) {
530 11 : secp_ctx = assert_secp256k1_context_create_and_randomize();
531 : do {
532 11 : if (!random_getrandom(upgrade_ctx.my_privkey,
533 : sizeof(upgrade_ctx.my_privkey))) {
534 : LOG("Unable to generate private key\n");
535 0 : THROW(ERR_UPGRADE_INTERNAL);
536 : }
537 11 : } while (!secp256k1_ec_pubkey_create(
538 : secp_ctx, &pubkey, upgrade_ctx.my_privkey));
539 11 : upgrade_ctx.my_pubkey_len = sizeof(upgrade_ctx.my_pubkey);
540 11 : secp256k1_ec_pubkey_serialize(secp_ctx,
541 : upgrade_ctx.my_pubkey,
542 : &upgrade_ctx.my_pubkey_len,
543 : &pubkey,
544 : SECP256K1_EC_COMPRESSED);
545 11 : if (upgrade_ctx.my_pubkey_len != sizeof(upgrade_ctx.my_pubkey)) {
546 : LOG("Unable to serialize pubkey\n");
547 0 : reset_upgrade();
548 0 : secp256k1_context_destroy(secp_ctx);
549 0 : THROW(ERR_UPGRADE_INTERNAL);
550 : }
551 : LOG_HEX("My pubkey:",
552 : upgrade_ctx.my_pubkey,
553 : sizeof(upgrade_ctx.my_pubkey));
554 11 : secp256k1_context_destroy(secp_ctx);
555 11 : explicit_bzero(&format, sizeof(format));
556 11 : format.id = EVIDENCE_FORMAT;
557 11 : if (!evidence_get_format_settings(&format)) {
558 : LOG("Unable to get evidence format\n");
559 0 : reset_upgrade();
560 0 : THROW(ERR_UPGRADE_INTERNAL);
561 : }
562 11 : memcpy(format.settings,
563 11 : upgrade_ctx.their_mrenclave,
564 : UPGRADE_MRENCLAVE_SIZE);
565 11 : upgrade_ctx.evidence_external = false;
566 11 : if (!evidence_generate(&format,
567 : upgrade_ctx.my_pubkey,
568 : sizeof(upgrade_ctx.my_pubkey),
569 : &upgrade_ctx.evidence,
570 : &upgrade_ctx.evidence_size)) {
571 : LOG("Unable to generate enclave evidence for peer\n");
572 0 : reset_upgrade();
573 0 : THROW(ERR_UPGRADE_INTERNAL);
574 : }
575 11 : if (!evidence_free_format_settings(format.settings)) {
576 : LOG("Unable to free format settings\n");
577 0 : THROW(ERR_INTERNAL);
578 : }
579 11 : explicit_bzero(&format, sizeof(format));
580 11 : upgrade_ctx.trx_offset = 0;
581 : }
582 :
583 11 : tx = send_data(upgrade_ctx.evidence,
584 : upgrade_ctx.evidence_size,
585 : &upgrade_ctx.trx_offset,
586 : &baux);
587 11 : SET_APDU_OP(baux ? 1 : 0); // More to send?
588 :
589 11 : if (!baux) {
590 : LOG("Self evidence completely sent\n");
591 11 : free_evidence();
592 11 : upgrade_ctx.state = upgrade_state_await_peer_id;
593 : }
594 :
595 11 : return TX_FOR_DATA_SIZE(tx);
596 13 : case OP_UPGRADE_IDENTIFY_PEER:
597 13 : check_state(upgrade_state_await_peer_id);
598 :
599 13 : upgrade_ctx.evidence_external = true;
600 13 : if (receive_data(rx,
601 : &upgrade_ctx.evidence,
602 : &upgrade_ctx.evidence_size,
603 : &upgrade_ctx.trx_offset)) {
604 2 : SET_APDU_OP(1); // More
605 2 : return TX_NO_DATA();
606 : }
607 : // We received the entire peer evidence. Perform validation
608 8 : if (!evidence_verify_and_extract_claims(EVIDENCE_FORMAT,
609 : upgrade_ctx.evidence,
610 : upgrade_ctx.evidence_size,
611 : &claims,
612 : &claims_size)) {
613 : LOG("Error verifying peer enclave's evidence\n");
614 1 : goto upgrade_process_apdu_identify_peer_error;
615 : }
616 7 : if (!(claim = evidence_get_claim(
617 : claims, claims_size, OE_CLAIM_UNIQUE_ID))) {
618 : LOG("Error extracting peer enclave's mrenclave\n");
619 0 : goto upgrade_process_apdu_identify_peer_error;
620 : }
621 : LOG_HEX("Peer enclave's mrenclave:", claim->value, claim->value_size);
622 7 : if (claim->value_size != UPGRADE_MRENCLAVE_SIZE ||
623 7 : memcmp(claim->value,
624 7 : upgrade_ctx.their_mrenclave,
625 : UPGRADE_MRENCLAVE_SIZE) != 0) {
626 : LOG("Peer enclave's mrenclave does not match the spec's "
627 : "mrenclave\n");
628 2 : goto upgrade_process_apdu_identify_peer_error;
629 : }
630 5 : if (!(claim = evidence_get_custom_claim(claims, claims_size))) {
631 : LOG("Error extracting peer enclave's public key\n");
632 1 : goto upgrade_process_apdu_identify_peer_error;
633 : }
634 4 : secp_ctx = assert_secp256k1_context_create_and_randomize();
635 8 : if (claim->value_size != sizeof(upgrade_ctx.their_pubkey) ||
636 4 : !secp256k1_ec_pubkey_parse(
637 4 : secp_ctx, &pubkey, claim->value, claim->value_size)) {
638 : LOG("Invalid peer public key received");
639 0 : secp256k1_context_destroy(secp_ctx);
640 0 : goto upgrade_process_apdu_identify_peer_error;
641 : }
642 4 : secp256k1_context_destroy(secp_ctx);
643 4 : memcpy(upgrade_ctx.their_pubkey, claim->value, claim->value_size);
644 : LOG_HEX("Peer public key:",
645 : upgrade_ctx.their_pubkey,
646 : sizeof(upgrade_ctx.their_pubkey));
647 4 : upgrade_ctx.state = upgrade_state_ready_for_xchg;
648 4 : SET_APDU_OP(0); // Done
649 4 : if (claims) {
650 4 : if (!evidence_free_claims(claims, claims_size)) {
651 : LOG("Error freeing claims\n");
652 0 : THROW(ERR_INTERNAL);
653 : }
654 4 : claims = NULL;
655 4 : claims_size = 0;
656 4 : claim = NULL;
657 : }
658 4 : free_evidence();
659 4 : return TX_NO_DATA();
660 4 : upgrade_process_apdu_identify_peer_error:
661 4 : if (claims) {
662 3 : if (!evidence_free_claims(claims, claims_size)) {
663 : LOG("Error freeing claims\n");
664 0 : THROW(ERR_INTERNAL);
665 : }
666 3 : claims = NULL;
667 3 : claims_size = 0;
668 3 : claim = NULL;
669 : }
670 4 : reset_upgrade();
671 4 : THROW(ERR_UPGRADE_AUTH);
672 4 : case OP_UPGRADE_PROCESS_DATA:
673 4 : check_state(upgrade_state_ready_for_xchg);
674 :
675 4 : secp_ctx = assert_secp256k1_context_create_and_randomize();
676 4 : if (!secp256k1_ec_pubkey_parse(secp_ctx,
677 : &pubkey,
678 : upgrade_ctx.their_pubkey,
679 4 : sizeof(upgrade_ctx.their_pubkey)) ||
680 4 : !secp256k1_ecdh(secp_ctx,
681 : key,
682 : &pubkey,
683 : upgrade_ctx.my_privkey,
684 : secp256k1_ecdh_hash_function_sha256,
685 : NULL)) {
686 : LOG("Unable to generate data processing key\n");
687 0 : reset_upgrade();
688 0 : secp256k1_context_destroy(secp_ctx);
689 0 : THROW(ERR_UPGRADE_INTERNAL);
690 : }
691 4 : secp256k1_context_destroy(secp_ctx);
692 4 : explicit_bzero(upgrade_ctx.my_privkey, sizeof(upgrade_ctx.my_privkey));
693 4 : explicit_bzero(upgrade_ctx.my_pubkey, sizeof(upgrade_ctx.my_pubkey));
694 4 : explicit_bzero(upgrade_ctx.their_pubkey,
695 : sizeof(upgrade_ctx.their_pubkey));
696 :
697 4 : switch (upgrade_ctx.operation) {
698 2 : case upgrade_operation_export:
699 : LOG("Exporting data...\n");
700 2 : sz = APDU_TOTAL_DATA_SIZE_OUT;
701 2 : if (!migrate_export(key, sizeof(key), APDU_DATA_PTR, &sz) ||
702 1 : sz != (sz & 0xFF)) {
703 1 : reset_upgrade();
704 1 : THROW(ERR_UPGRADE_DATA_PROCESSING);
705 : }
706 : LOG("Data export complete\n");
707 1 : reset_upgrade();
708 1 : return TX_FOR_DATA_SIZE(sz);
709 2 : case upgrade_operation_import:
710 : LOG("Importing data...\n");
711 2 : if (APDU_DATA_SIZE(rx) == 0) {
712 0 : reset_upgrade();
713 0 : THROW(ERR_UPGRADE_PROTOCOL);
714 : }
715 2 : if (!migrate_import(
716 2 : key, sizeof(key), APDU_DATA_PTR, APDU_DATA_SIZE(rx))) {
717 1 : reset_upgrade();
718 1 : THROW(ERR_UPGRADE_DATA_PROCESSING);
719 : }
720 : LOG("Data import complete\n");
721 1 : reset_upgrade();
722 1 : return TX_NO_DATA();
723 0 : default:
724 : // We should never reach this point
725 : LOG("Inconsistent internal state when processing data\n");
726 0 : reset_upgrade();
727 0 : THROW(ERR_UPGRADE_INTERNAL);
728 : }
729 1 : default:
730 1 : reset_upgrade();
731 1 : THROW(ERR_UPGRADE_PROTOCOL);
732 : break;
733 : }
734 : }
|