|
@@ -81,11 +81,11 @@ struct NodeCommState {
|
|
|
|
|
|
// The function to call after the last chunk of a message has been
|
|
|
// received. If in_msg_get_buf allocated memory, this function
|
|
|
- // should deallocate it. in_msg_size, in_msg_offset, and in_msg_buf
|
|
|
- // will already have been reset when this function is called. The
|
|
|
- // uint32_t that is passed are the total size of the _decrypted_
|
|
|
- // data and the original total size of the _encrypted_ chunks that
|
|
|
- // was passed to in_msg_get_buf.
|
|
|
+ // should deallocate it. in_msg_size, in_msg_offset,
|
|
|
+ // in_msg_plaintext_processed, and in_msg_buf will already have been
|
|
|
+ // reset when this function is called. The uint32_t that is passed
|
|
|
+ // are the total size of the _decrypted_ data and the original total
|
|
|
+ // size of the _encrypted_ chunks that was passed to in_msg_get_buf.
|
|
|
std::function<void(NodeCommState&,uint8_t*,uint32_t,uint32_t)>
|
|
|
in_msg_received;
|
|
|
|
|
@@ -133,6 +133,13 @@ static uint8_t* default_in_msg_get_buf(NodeCommState &commst,
|
|
|
return new uint8_t[max_plaintext_bytes];
|
|
|
}
|
|
|
|
|
|
+static void handshake_1_msg_received(NodeCommState &nodest,
|
|
|
+ uint8_t *data, uint32_t plaintext_len, uint32_t);
|
|
|
+static void handshake_2_msg_received(NodeCommState &nodest,
|
|
|
+ uint8_t *data, uint32_t plaintext_len, uint32_t);
|
|
|
+static void handshake_3_msg_received(NodeCommState &nodest,
|
|
|
+ uint8_t *data, uint32_t plaintext_len, uint32_t);
|
|
|
+
|
|
|
// Receive (at the server) the first handshake message
|
|
|
static void handshake_1_msg_received(NodeCommState &nodest,
|
|
|
uint8_t *data, uint32_t plaintext_len, uint32_t)
|
|
@@ -151,26 +158,108 @@ static void handshake_1_msg_received(NodeCommState &nodest,
|
|
|
return;
|
|
|
}
|
|
|
sgx_ecc_state_handle_t ecc_handle;
|
|
|
- sgx_ec256_public_t pubkey;
|
|
|
- memmove(&pubkey, data, sizeof(pubkey));
|
|
|
+ sgx_ec256_public_t peer_pubkey;
|
|
|
+ memmove(&peer_pubkey, data, sizeof(peer_pubkey));
|
|
|
+ delete[] data;
|
|
|
sgx_ecc256_open_context(&ecc_handle);
|
|
|
int valid;
|
|
|
- if (sgx_ecc256_check_point(&pubkey, ecc_handle, &valid) || !valid) {
|
|
|
+ if (sgx_ecc256_check_point(&peer_pubkey, ecc_handle, &valid) || !valid) {
|
|
|
printf("Invalid public key received from node %hu\n",
|
|
|
nodest.node_num);
|
|
|
sgx_ecc256_close_context(ecc_handle);
|
|
|
return;
|
|
|
}
|
|
|
- delete[] data;
|
|
|
|
|
|
printf("Valid public key received from node %hu\n", nodest.node_num);
|
|
|
- memmove(&nodest.handshake_peer_pubkey, &pubkey, sizeof(pubkey));
|
|
|
|
|
|
// Create our own DH key pair
|
|
|
- sgx_ecc256_create_key_pair(&nodest.handshake_privkey,
|
|
|
- &nodest.handshake_pubkey, ecc_handle);
|
|
|
+ sgx_ec256_public_t our_pubkey;
|
|
|
+ sgx_ec256_private_t our_privkey;
|
|
|
+ sgx_ecc256_create_key_pair(&our_privkey, &our_pubkey, ecc_handle);
|
|
|
+
|
|
|
+ // Construct the shared secret
|
|
|
+ sgx_ec256_dh_shared_t sharedsecret;
|
|
|
+ sgx_ecc256_compute_shared_dhkey(&our_privkey, &peer_pubkey,
|
|
|
+ &sharedsecret, ecc_handle);
|
|
|
+ memset(&our_privkey, 0, sizeof(our_privkey));
|
|
|
+
|
|
|
+ // Compute H1(sharedsecret) and H2(sharedsecret)
|
|
|
+ sgx_sha_state_handle_t sha_handle;
|
|
|
+ sgx_sha256_hash_t h1, h2;
|
|
|
+
|
|
|
+ sgx_sha256_init(&sha_handle);
|
|
|
+ sgx_sha256_update((const uint8_t*)"\x01", 1, sha_handle);
|
|
|
+ sgx_sha256_update((uint8_t*)&sharedsecret, sizeof(sharedsecret),
|
|
|
+ sha_handle);
|
|
|
+ sgx_sha256_get_hash(sha_handle, &h1);
|
|
|
+ sgx_sha256_close(sha_handle);
|
|
|
+
|
|
|
+ sgx_sha256_init(&sha_handle);
|
|
|
+ sgx_sha256_update((const uint8_t*)"\x02", 1, sha_handle);
|
|
|
+ sgx_sha256_update((uint8_t*)&sharedsecret, sizeof(sharedsecret),
|
|
|
+ sha_handle);
|
|
|
+ sgx_sha256_get_hash(sha_handle, &h2);
|
|
|
+ sgx_sha256_close(sha_handle);
|
|
|
+
|
|
|
+ // Compute the server-to-client MAC
|
|
|
+ sgx_hmac_state_handle_t hmac_handle;
|
|
|
+ uint8_t srv_cli_mac[16];
|
|
|
+ sgx_hmac256_init(h1, 16, &hmac_handle);
|
|
|
+ sgx_hmac256_update((uint8_t*)&our_pubkey, sizeof(our_pubkey),
|
|
|
+ hmac_handle);
|
|
|
+ sgx_hmac256_update((uint8_t*)&peer_pubkey, sizeof(peer_pubkey),
|
|
|
+ hmac_handle);
|
|
|
+ sgx_hmac256_update((uint8_t*)&g_pubkey, sizeof(g_pubkey),
|
|
|
+ hmac_handle);
|
|
|
+ sgx_hmac256_update((uint8_t*)&nodest.pubkey, sizeof(nodest.pubkey),
|
|
|
+ hmac_handle);
|
|
|
+ sgx_hmac256_final(srv_cli_mac, 16, hmac_handle);
|
|
|
+ sgx_hmac256_close(hmac_handle);
|
|
|
+
|
|
|
+ // Compute the client-to-server MAC
|
|
|
+ uint8_t cli_srv_mac[16];
|
|
|
+ sgx_hmac256_init(((uint8_t*)h1)+16, 16, &hmac_handle);
|
|
|
+ sgx_hmac256_update((uint8_t*)&peer_pubkey, sizeof(peer_pubkey),
|
|
|
+ hmac_handle);
|
|
|
+ sgx_hmac256_update((uint8_t*)&our_pubkey, sizeof(our_pubkey),
|
|
|
+ hmac_handle);
|
|
|
+ sgx_hmac256_update((uint8_t*)&nodest.pubkey, sizeof(nodest.pubkey),
|
|
|
+ hmac_handle);
|
|
|
+ sgx_hmac256_update((uint8_t*)&g_pubkey, sizeof(g_pubkey),
|
|
|
+ hmac_handle);
|
|
|
+ sgx_hmac256_final(cli_srv_mac, 16, hmac_handle);
|
|
|
+ sgx_hmac256_close(hmac_handle);
|
|
|
+
|
|
|
+ // Sign the server-to-client MAC
|
|
|
+ sgx_ec256_signature_t srv_cli_sig;
|
|
|
+ sgx_ecdsa_sign(srv_cli_mac, 16, &g_privkey, &srv_cli_sig, ecc_handle);
|
|
|
|
|
|
sgx_ecc256_close_context(ecc_handle);
|
|
|
+
|
|
|
+ // Get us ready to receive handshake message 3
|
|
|
+ nodest.in_msg_get_buf = default_in_msg_get_buf;
|
|
|
+ nodest.in_msg_received = handshake_3_msg_received;
|
|
|
+ nodest.handshake_step = HANDSHAKE_S_SENT_2;
|
|
|
+
|
|
|
+ // Send handshake message 2
|
|
|
+ nodest.message_start(sizeof(our_pubkey) + sizeof(srv_cli_sig));
|
|
|
+ nodest.message_data((uint8_t*)&our_pubkey, sizeof(our_pubkey));
|
|
|
+ nodest.message_data((uint8_t*)&srv_cli_sig, sizeof(srv_cli_sig));
|
|
|
+}
|
|
|
+
|
|
|
+static void handshake_2_msg_received(NodeCommState &nodest,
|
|
|
+ uint8_t *data, uint32_t plaintext_len, uint32_t)
|
|
|
+{
|
|
|
+ printf("Received handshake_2 message of %u bytes:\n", plaintext_len);
|
|
|
+ for (uint32_t i=0;i<plaintext_len;++i) {
|
|
|
+ printf("%02x", data[i]);
|
|
|
+ }
|
|
|
+ printf("\n");
|
|
|
+}
|
|
|
+
|
|
|
+static void handshake_3_msg_received(NodeCommState &nodest,
|
|
|
+ uint8_t *data, uint32_t plaintext_len, uint32_t)
|
|
|
+{
|
|
|
}
|
|
|
|
|
|
// Start a new outgoing message. Pass the number of _plaintext_ bytes
|
|
@@ -469,8 +558,14 @@ bool ecall_chunk(nodenum_t node_num, const uint8_t *chunkdata,
|
|
|
nodest.in_msg_offset += chunklen;
|
|
|
if (nodest.in_msg_offset == nodest.in_msg_size) {
|
|
|
// This was the last chunk; handle the received message
|
|
|
- nodest.in_msg_received(nodest, nodest.in_msg_buf,
|
|
|
- nodest.in_msg_plaintext_processed, nodest.in_msg_size);
|
|
|
+ uint8_t* buf = nodest.in_msg_buf;
|
|
|
+ uint32_t plaintext_processed = nodest.in_msg_plaintext_processed;
|
|
|
+ uint32_t msg_size = nodest.in_msg_size;
|
|
|
+ nodest.in_msg_buf = NULL;
|
|
|
+ nodest.in_msg_size = 0;
|
|
|
+ nodest.in_msg_offset = 0;
|
|
|
+ nodest.in_msg_plaintext_processed = 0;
|
|
|
+ nodest.in_msg_received(nodest, buf, plaintext_processed, msg_size);
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
@@ -488,6 +583,11 @@ void NodeCommState::handshake_start()
|
|
|
|
|
|
sgx_ecc256_close_context(ecc_handle);
|
|
|
|
|
|
+ // Get us ready to receive handshake message 2
|
|
|
+ in_msg_get_buf = default_in_msg_get_buf;
|
|
|
+ in_msg_received = handshake_2_msg_received;
|
|
|
+ handshake_step = HANDSHAKE_C_SENT_1;
|
|
|
+
|
|
|
// Send the public key as the first message
|
|
|
message_start(sizeof(handshake_pubkey));
|
|
|
|