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 88 : static void free_evidence() {
154 88 : 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 88 : upgrade_ctx.evidence = NULL;
161 88 : upgrade_ctx.evidence_size = 0;
162 88 : }
163 :
164 : /*
165 : * Reset the upgrade context
166 : */
167 56 : static void reset_upgrade() {
168 56 : free_evidence();
169 56 : explicit_bzero(&upgrade_ctx, sizeof(upgrade_ctx));
170 56 : }
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 89 : static void check_state(upgrade_state_t expected) {
181 : // Consistency check
182 89 : 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 89 : } else if (upgrade_ctx.state != upgrade_state_await_spec &&
187 59 : upgrade_ctx.operation == upgrade_operation_none) {
188 0 : reset_upgrade();
189 0 : THROW(ERR_UPGRADE_PROTOCOL);
190 : }
191 : // Expectation check
192 89 : if (upgrade_ctx.state != expected) {
193 2 : reset_upgrade();
194 2 : THROW(ERR_UPGRADE_PROTOCOL);
195 : }
196 87 : }
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 : *dest_offset = 0;
288 : LOG("Expecting %lu bytes of data\n", *dest_size);
289 : }
290 11 : if (APDU_DATA_SIZE(rx) - pl > *dest_size - *dest_offset) {
291 : LOG("Data buffer overflow\n");
292 1 : reset_upgrade();
293 1 : THROW(ERR_UPGRADE_PROTOCOL);
294 : }
295 10 : memcpy(*dest + *dest_offset, APDU_DATA_PTR + pl, APDU_DATA_SIZE(rx) - pl);
296 10 : *dest_offset += APDU_DATA_SIZE(rx) - pl;
297 : LOG("Received %lu bytes of data\n", APDU_DATA_SIZE(rx) - pl);
298 10 : return *dest_offset < *dest_size; // More?
299 : }
300 :
301 : // -----------------------------------------------------------------------
302 : // Protocol implementation
303 : // -----------------------------------------------------------------------
304 :
305 30 : void upgrade_init() {
306 : // Build should fail when more authorizers than supported are provided
307 : COMPILE_TIME_ASSERT(TOTAL_AUTHORIZERS <= MAX_AUTHORIZERS);
308 : // Build should fail if hash size size differs from expected key size
309 : COMPILE_TIME_ASSERT(HASH_LENGTH == AES_GCM_KEY_SIZE);
310 :
311 30 : reset_upgrade();
312 : LOG("Upgrade module initialized\n");
313 30 : }
314 :
315 1 : void upgrade_reset() {
316 1 : reset_upgrade();
317 1 : }
318 :
319 90 : unsigned int upgrade_process_apdu(volatile unsigned int rx) {
320 : uint8_t key[AES_GCM_KEY_SIZE];
321 90 : size_t sz = 0;
322 : unsigned int tx;
323 : bool baux;
324 : int signature_valid;
325 : long unsigned valid_count;
326 : secp256k1_context* secp_ctx;
327 : secp256k1_ecdsa_signature signature;
328 : secp256k1_pubkey pubkey;
329 90 : oe_claim_t* claims = NULL;
330 : size_t claims_size;
331 : oe_claim_t* claim;
332 : evidence_format_t format;
333 : uint16_t error;
334 :
335 90 : switch (APDU_OP()) {
336 31 : case OP_UPGRADE_START:
337 31 : check_state(upgrade_state_await_spec);
338 :
339 : // We expect a from/to upgrade spec plus an operation type byte
340 30 : if (APDU_DATA_SIZE(rx) != UPGRADE_MRENCLAVE_SIZE * 2 + 1) {
341 2 : reset_upgrade();
342 2 : THROW(ERR_UPGRADE_PROTOCOL);
343 : }
344 : // Operation validations
345 28 : switch (APDU_DATA_PTR[0]) {
346 20 : case upgrade_operation_export:
347 20 : REQUIRE_ONBOARDED();
348 19 : REQUIRE_UNLOCKED();
349 18 : break;
350 8 : case upgrade_operation_import:
351 8 : REQUIRE_NOT_ONBOARDED();
352 7 : break;
353 0 : default:
354 0 : reset_upgrade();
355 0 : THROW(ERR_UPGRADE_PROTOCOL);
356 : }
357 25 : upgrade_ctx.operation = APDU_DATA_PTR[0];
358 : // Spec
359 25 : memcpy(upgrade_ctx.spec.mrenclave_from,
360 25 : APDU_DATA_PTR + 1,
361 : UPGRADE_MRENCLAVE_SIZE);
362 25 : memcpy(upgrade_ctx.spec.mrenclave_to,
363 25 : APDU_DATA_PTR + 1 + UPGRADE_MRENCLAVE_SIZE,
364 : UPGRADE_MRENCLAVE_SIZE);
365 25 : upgrade_ctx.my_mrenclave =
366 25 : upgrade_ctx.operation == upgrade_operation_export
367 : ? upgrade_ctx.spec.mrenclave_from
368 25 : : upgrade_ctx.spec.mrenclave_to;
369 25 : upgrade_ctx.their_mrenclave =
370 25 : upgrade_ctx.operation == upgrade_operation_export
371 : ? upgrade_ctx.spec.mrenclave_to
372 25 : : upgrade_ctx.spec.mrenclave_from;
373 : LOG("Spec received\n");
374 : LOG_HEX(
375 : "From:", upgrade_ctx.spec.mrenclave_from, UPGRADE_MRENCLAVE_SIZE);
376 : LOG_HEX("To:", upgrade_ctx.spec.mrenclave_to, UPGRADE_MRENCLAVE_SIZE);
377 : LOG("Role: %s\n",
378 : upgrade_ctx.operation == upgrade_operation_export ? "exporter"
379 : : "importer");
380 : // Check this enclave's mrenclave matches the corresponding
381 : // value in the spec according to the specified role
382 25 : explicit_bzero(&format, sizeof(format));
383 25 : format.id = EVIDENCE_FORMAT;
384 25 : upgrade_ctx.evidence_external = false;
385 25 : if (!evidence_generate(&format,
386 : NULL,
387 : 0,
388 : &upgrade_ctx.evidence,
389 : &upgrade_ctx.evidence_size)) {
390 : LOG("Unable to generate enclave evidence for self\n");
391 2 : error = ERR_UPGRADE_INTERNAL;
392 2 : goto upgrade_process_apdu_start_error;
393 : }
394 23 : if (!evidence_verify_and_extract_claims(EVIDENCE_FORMAT,
395 : upgrade_ctx.evidence,
396 : upgrade_ctx.evidence_size,
397 : &claims,
398 : &claims_size)) {
399 : LOG("Error verifying this enclave's evidence\n");
400 2 : error = ERR_UPGRADE_INTERNAL;
401 2 : goto upgrade_process_apdu_start_error;
402 : }
403 21 : if (!(claim = evidence_get_claim(
404 : claims, claims_size, OE_CLAIM_UNIQUE_ID))) {
405 : LOG("Error extracting this enclave's mrenclave\n");
406 2 : error = ERR_UPGRADE_INTERNAL;
407 2 : goto upgrade_process_apdu_start_error;
408 : }
409 : LOG_HEX("This enclave's mrenclave:", claim->value, claim->value_size);
410 19 : if (claim->value_size != UPGRADE_MRENCLAVE_SIZE ||
411 19 : memcmp(claim->value,
412 19 : upgrade_ctx.my_mrenclave,
413 : UPGRADE_MRENCLAVE_SIZE) != 0) {
414 : LOG("This enclave's mrenclave does not match the spec's "
415 : "mrenclave\n");
416 2 : error = ERR_UPGRADE_SPEC;
417 2 : goto upgrade_process_apdu_start_error;
418 : }
419 17 : generate_message_to_verify();
420 : LOG_HEX("Message to verify:",
421 : upgrade_ctx.expected_message_hash,
422 : sizeof(upgrade_ctx.expected_message_hash));
423 17 : upgrade_ctx.state = upgrade_state_await_spec_sigs;
424 17 : oe_free(claims);
425 17 : free_evidence();
426 17 : return TX_NO_DATA();
427 8 : upgrade_process_apdu_start_error:
428 8 : if (claims)
429 4 : oe_free(claims);
430 8 : reset_upgrade();
431 8 : THROW(error);
432 28 : case OP_UPGRADE_SPEC_SIG:
433 28 : check_state(upgrade_state_await_spec_sigs);
434 :
435 28 : if (APDU_DATA_SIZE(rx) < 1) {
436 0 : reset_upgrade();
437 0 : THROW(ERR_UPGRADE_PROTOCOL);
438 : }
439 : // Check to see whether we find a matching authorized signer
440 28 : secp_ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
441 28 : if (!secp256k1_ecdsa_signature_parse_der(
442 28 : secp_ctx, &signature, APDU_DATA_PTR, APDU_DATA_SIZE(rx))) {
443 1 : secp256k1_context_destroy(secp_ctx);
444 1 : reset_upgrade();
445 1 : THROW(ERR_UPGRADE_SIGNATURE);
446 : }
447 27 : signature_valid = 0;
448 42 : for (unsigned int i = 0; i < TOTAL_AUTHORIZERS; i++) {
449 : // Attempt to verify against this public key
450 41 : if (!secp256k1_ec_pubkey_parse(
451 : secp_ctx,
452 : &pubkey,
453 41 : (const unsigned char*)authorizers_pubkeys[i],
454 : sizeof(authorizers_pubkeys[i]))) {
455 0 : secp256k1_context_destroy(secp_ctx);
456 0 : reset_upgrade();
457 0 : THROW(ERR_UPGRADE_SIGNATURE);
458 : }
459 : signature_valid =
460 41 : secp256k1_ecdsa_verify(secp_ctx,
461 : &signature,
462 : upgrade_ctx.expected_message_hash,
463 : &pubkey);
464 :
465 : // Found a valid signature?
466 41 : if (signature_valid) {
467 : LOG("Valid signature received!\n");
468 26 : upgrade_ctx.authorized_signer_verified[i] = true;
469 26 : break;
470 : }
471 : }
472 27 : secp256k1_context_destroy(secp_ctx);
473 :
474 : // Reached the threshold?
475 27 : valid_count = 0;
476 108 : for (unsigned int i = 0; i < TOTAL_AUTHORIZERS; i++)
477 81 : if (upgrade_ctx.authorized_signer_verified[i])
478 39 : valid_count++;
479 :
480 : LOG("Valid signatures so far: %lu\n", valid_count);
481 :
482 27 : if (valid_count >= THRESHOLD_AUTHORIZERS) {
483 12 : SET_APDU_OP(0); // No need for more
484 12 : upgrade_ctx.state = upgrade_state_send_self_id;
485 : LOG("Threshold reached!\n");
486 : } else {
487 15 : SET_APDU_OP(1); // We need more
488 : }
489 27 : return TX_NO_DATA();
490 13 : case OP_UPGRADE_IDENTIFY_SELF:
491 13 : check_state(upgrade_state_send_self_id);
492 :
493 12 : if (!upgrade_ctx.evidence) {
494 12 : secp_ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
495 : do {
496 12 : if (!random_getrandom(upgrade_ctx.my_privkey,
497 : sizeof(upgrade_ctx.my_privkey))) {
498 : LOG("Unable to generate private key\n");
499 1 : THROW(ERR_UPGRADE_INTERNAL);
500 : }
501 11 : } while (!secp256k1_ec_pubkey_create(
502 : secp_ctx, &pubkey, upgrade_ctx.my_privkey));
503 11 : upgrade_ctx.my_pubkey_len = sizeof(upgrade_ctx.my_pubkey);
504 11 : secp256k1_ec_pubkey_serialize(secp_ctx,
505 : upgrade_ctx.my_pubkey,
506 : &upgrade_ctx.my_pubkey_len,
507 : &pubkey,
508 : SECP256K1_EC_COMPRESSED);
509 11 : if (upgrade_ctx.my_pubkey_len != sizeof(upgrade_ctx.my_pubkey)) {
510 : LOG("Unable to serialize pubkey\n");
511 0 : reset_upgrade();
512 0 : secp256k1_context_destroy(secp_ctx);
513 0 : THROW(ERR_UPGRADE_INTERNAL);
514 : }
515 : LOG_HEX("My pubkey:",
516 : upgrade_ctx.my_pubkey,
517 : sizeof(upgrade_ctx.my_pubkey));
518 11 : secp256k1_context_destroy(secp_ctx);
519 11 : explicit_bzero(&format, sizeof(format));
520 11 : format.id = EVIDENCE_FORMAT;
521 11 : if (!evidence_get_format_settings(&format)) {
522 : LOG("Unable to get evidence format\n");
523 0 : reset_upgrade();
524 0 : THROW(ERR_UPGRADE_INTERNAL);
525 : }
526 11 : memcpy(format.settings,
527 11 : upgrade_ctx.their_mrenclave,
528 : UPGRADE_MRENCLAVE_SIZE);
529 11 : upgrade_ctx.evidence_external = false;
530 11 : if (!evidence_generate(&format,
531 : upgrade_ctx.my_pubkey,
532 : sizeof(upgrade_ctx.my_pubkey),
533 : &upgrade_ctx.evidence,
534 : &upgrade_ctx.evidence_size)) {
535 : LOG("Unable to generate enclave evidence for peer\n");
536 0 : reset_upgrade();
537 0 : THROW(ERR_UPGRADE_INTERNAL);
538 : }
539 11 : oe_free(format.settings);
540 11 : explicit_bzero(&format, sizeof(format));
541 11 : upgrade_ctx.trx_offset = 0;
542 : }
543 :
544 11 : tx = send_data(upgrade_ctx.evidence,
545 : upgrade_ctx.evidence_size,
546 : &upgrade_ctx.trx_offset,
547 : &baux);
548 11 : SET_APDU_OP(baux ? 1 : 0); // More to send?
549 :
550 11 : if (!baux) {
551 : LOG("Self evidence completely sent\n");
552 11 : free_evidence();
553 11 : upgrade_ctx.state = upgrade_state_await_peer_id;
554 : }
555 :
556 11 : return TX_FOR_DATA_SIZE(tx);
557 13 : case OP_UPGRADE_IDENTIFY_PEER:
558 13 : check_state(upgrade_state_await_peer_id);
559 :
560 13 : upgrade_ctx.evidence_external = true;
561 13 : if (receive_data(rx,
562 : &upgrade_ctx.evidence,
563 : &upgrade_ctx.evidence_size,
564 : &upgrade_ctx.trx_offset)) {
565 2 : SET_APDU_OP(1); // More
566 2 : return TX_NO_DATA();
567 : }
568 : // We received the entire peer evidence. Perform validation
569 8 : if (!evidence_verify_and_extract_claims(EVIDENCE_FORMAT,
570 : upgrade_ctx.evidence,
571 : upgrade_ctx.evidence_size,
572 : &claims,
573 : &claims_size)) {
574 : LOG("Error verifying peer enclave's evidence\n");
575 1 : goto upgrade_process_apdu_identify_peer_error;
576 : }
577 7 : if (!(claim = evidence_get_claim(
578 : claims, claims_size, OE_CLAIM_UNIQUE_ID))) {
579 : LOG("Error extracting peer enclave's mrenclave\n");
580 0 : goto upgrade_process_apdu_identify_peer_error;
581 : }
582 : LOG_HEX("Peer enclave's mrenclave:", claim->value, claim->value_size);
583 7 : if (claim->value_size != UPGRADE_MRENCLAVE_SIZE ||
584 7 : memcmp(claim->value,
585 7 : upgrade_ctx.their_mrenclave,
586 : UPGRADE_MRENCLAVE_SIZE) != 0) {
587 : LOG("Peer enclave's mrenclave does not match the spec's "
588 : "mrenclave\n");
589 2 : goto upgrade_process_apdu_identify_peer_error;
590 : }
591 5 : if (!(claim = evidence_get_custom_claim(claims, claims_size))) {
592 : LOG("Error extracting peer enclave's public key\n");
593 1 : goto upgrade_process_apdu_identify_peer_error;
594 : }
595 4 : secp_ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
596 8 : if (claim->value_size != sizeof(upgrade_ctx.their_pubkey) ||
597 4 : !secp256k1_ec_pubkey_parse(
598 4 : secp_ctx, &pubkey, claim->value, claim->value_size)) {
599 : LOG("Invalid peer public key received");
600 0 : secp256k1_context_destroy(secp_ctx);
601 0 : goto upgrade_process_apdu_identify_peer_error;
602 : }
603 4 : secp256k1_context_destroy(secp_ctx);
604 4 : memcpy(upgrade_ctx.their_pubkey, claim->value, claim->value_size);
605 : LOG_HEX("Peer public key:",
606 : upgrade_ctx.their_pubkey,
607 : sizeof(upgrade_ctx.their_pubkey));
608 4 : upgrade_ctx.state = upgrade_state_ready_for_xchg;
609 4 : SET_APDU_OP(0); // Done
610 4 : if (claims)
611 4 : oe_free(claims);
612 4 : free_evidence();
613 4 : return TX_NO_DATA();
614 4 : upgrade_process_apdu_identify_peer_error:
615 4 : if (claims)
616 3 : oe_free(claims);
617 4 : reset_upgrade();
618 4 : THROW(ERR_UPGRADE_AUTH);
619 4 : case OP_UPGRADE_PROCESS_DATA:
620 4 : check_state(upgrade_state_ready_for_xchg);
621 :
622 4 : secp_ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
623 4 : if (!secp256k1_ec_pubkey_parse(secp_ctx,
624 : &pubkey,
625 : upgrade_ctx.their_pubkey,
626 4 : sizeof(upgrade_ctx.their_pubkey)) ||
627 4 : !secp256k1_ecdh(secp_ctx,
628 : key,
629 : &pubkey,
630 : upgrade_ctx.my_privkey,
631 : secp256k1_ecdh_hash_function_sha256,
632 : NULL)) {
633 : LOG("Unable to generate data processing key\n");
634 0 : reset_upgrade();
635 0 : secp256k1_context_destroy(secp_ctx);
636 0 : THROW(ERR_UPGRADE_INTERNAL);
637 : }
638 4 : secp256k1_context_destroy(secp_ctx);
639 4 : explicit_bzero(upgrade_ctx.my_privkey, sizeof(upgrade_ctx.my_privkey));
640 4 : explicit_bzero(upgrade_ctx.my_pubkey, sizeof(upgrade_ctx.my_pubkey));
641 4 : explicit_bzero(upgrade_ctx.their_pubkey,
642 : sizeof(upgrade_ctx.their_pubkey));
643 :
644 4 : switch (upgrade_ctx.operation) {
645 2 : case upgrade_operation_export:
646 : LOG("Exporting data...\n");
647 2 : sz = APDU_TOTAL_DATA_SIZE_OUT;
648 2 : if (!migrate_export(key, sizeof(key), APDU_DATA_PTR, &sz) ||
649 1 : sz != (sz & 0xFF)) {
650 1 : reset_upgrade();
651 1 : THROW(ERR_UPGRADE_DATA_PROCESSING);
652 : }
653 : LOG("Data export complete\n");
654 1 : reset_upgrade();
655 1 : return TX_FOR_DATA_SIZE(sz);
656 2 : case upgrade_operation_import:
657 : LOG("Importing data...\n");
658 2 : if (APDU_DATA_SIZE(rx) == 0) {
659 0 : reset_upgrade();
660 0 : THROW(ERR_UPGRADE_PROTOCOL);
661 : }
662 2 : if (!migrate_import(
663 2 : key, sizeof(key), APDU_DATA_PTR, APDU_DATA_SIZE(rx))) {
664 1 : reset_upgrade();
665 1 : THROW(ERR_UPGRADE_DATA_PROCESSING);
666 : }
667 : LOG("Data import complete\n");
668 1 : reset_upgrade();
669 1 : return TX_NO_DATA();
670 0 : default:
671 : // We should never reach this point
672 : LOG("Inconsistent internal state when processing data\n");
673 0 : reset_upgrade();
674 0 : THROW(ERR_UPGRADE_INTERNAL);
675 : }
676 1 : default:
677 1 : reset_upgrade();
678 1 : THROW(ERR_UPGRADE_PROTOCOL);
679 : break;
680 : }
681 : }
|