|
|
|
@ -50,7 +50,7 @@ int libp2p_secio_can_handle(const uint8_t* incoming, size_t incoming_size) {
|
|
|
|
|
|
|
|
|
|
int libp2p_secio_handle_message(const uint8_t* incoming, size_t incoming_size, struct SessionContext* session_context, void* protocol_context) {
|
|
|
|
|
struct SecioContext* ctx = (struct SecioContext*)protocol_context;
|
|
|
|
|
return libp2p_secio_handshake(session_context, ctx->private_key, ctx->peer_store, 1);
|
|
|
|
|
return libp2p_secio_handshake(session_context, ctx->private_key, ctx->peer_store, incoming, incoming_size);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int libp2p_secio_shutdown(void* context) {
|
|
|
|
@ -770,6 +770,29 @@ int libp2p_secio_encrypted_read(void* stream_context, unsigned char** bytes, siz
|
|
|
|
|
return retVal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Pull the Propose struct out of what the remote node sent us
|
|
|
|
|
* @param buffer incoming bytes
|
|
|
|
|
* @param buffer_size the size of the incoming buffer
|
|
|
|
|
* @returns a Propose struct or NULL on error
|
|
|
|
|
*/
|
|
|
|
|
struct Propose* libp2p_secio_get_propose_in(const uint8_t* buffer, size_t buffer_size) {
|
|
|
|
|
struct Propose* retVal = NULL;
|
|
|
|
|
const uint8_t* buffer_ptr = buffer;
|
|
|
|
|
// strip off the protocol id
|
|
|
|
|
for(int i = 0; i < buffer_size; i++) {
|
|
|
|
|
if (buffer[i] == '\n') {
|
|
|
|
|
buffer_ptr = &buffer[i+1];
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// get the Propose struct
|
|
|
|
|
if (!libp2p_secio_propose_protobuf_decode(buffer_ptr, buffer_size - (buffer_ptr - buffer), &retVal)) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
return retVal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/***
|
|
|
|
|
* performs initial communication over an insecure channel to share
|
|
|
|
|
* keys, IDs, and initiate connection. This is a framed messaging system
|
|
|
|
@ -779,7 +802,7 @@ int libp2p_secio_encrypted_read(void* stream_context, unsigned char** bytes, siz
|
|
|
|
|
* @param remote_requested it is the other side that requested the upgrade to secio
|
|
|
|
|
* @returns true(1) on success, false(0) otherwise
|
|
|
|
|
*/
|
|
|
|
|
int libp2p_secio_handshake(struct SessionContext* local_session, struct RsaPrivateKey* private_key, struct Peerstore* peerstore, int remote_requested) {
|
|
|
|
|
int libp2p_secio_handshake(struct SessionContext* local_session, struct RsaPrivateKey* private_key, struct Peerstore* peerstore, const uint8_t* incoming, size_t incoming_size) {
|
|
|
|
|
int retVal = 0;
|
|
|
|
|
size_t results_size = 0, bytes_written = 0;
|
|
|
|
|
unsigned char* propose_in_bytes = NULL; // the remote protobuf
|
|
|
|
@ -804,30 +827,7 @@ int libp2p_secio_handshake(struct SessionContext* local_session, struct RsaPriva
|
|
|
|
|
|
|
|
|
|
//TODO: make sure we're not talking to ourself
|
|
|
|
|
|
|
|
|
|
// prepare the multistream send of the protocol ID
|
|
|
|
|
const unsigned char* protocol = (unsigned char*)"/secio/1.0.0\n";
|
|
|
|
|
int protocol_len = strlen((char*)protocol);
|
|
|
|
|
unsigned char* total = malloc(protocol_len + propose_out_size);
|
|
|
|
|
memcpy(total, protocol, protocol_len);
|
|
|
|
|
memcpy(&total[protocol_len], propose_out_bytes, propose_out_size);
|
|
|
|
|
|
|
|
|
|
libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Writing protocol\n");
|
|
|
|
|
bytes_written = libp2p_net_multistream_write(local_session, total, protocol_len + propose_out_size);
|
|
|
|
|
free(total);
|
|
|
|
|
if (bytes_written <= 0)
|
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
|
|
if (!remote_requested) {
|
|
|
|
|
// we should get back the secio confirmation
|
|
|
|
|
libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Reading protocol response\n");
|
|
|
|
|
bytes_written = libp2p_net_multistream_read(local_session, &results, &results_size, 20);
|
|
|
|
|
if (bytes_written < 5 || strstr((char*)results, "secio") == NULL)
|
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
|
|
free(results);
|
|
|
|
|
results = NULL;
|
|
|
|
|
results_size = 0;
|
|
|
|
|
}
|
|
|
|
|
// send the protocol id and the outgoing Propose struct
|
|
|
|
|
|
|
|
|
|
// generate 16 byte nonce
|
|
|
|
|
if (!libp2p_secio_generate_nonce(&local_session->local_nonce[0], 16)) {
|
|
|
|
@ -868,26 +868,40 @@ int libp2p_secio_handshake(struct SessionContext* local_session, struct RsaPriva
|
|
|
|
|
// supported hashes
|
|
|
|
|
libp2p_secio_propose_set_property((void**)&propose_out->hashes, &propose_out->hashes_size, SupportedHashes, strlen(SupportedHashes));
|
|
|
|
|
|
|
|
|
|
// send proposal
|
|
|
|
|
// protobuf the proposal
|
|
|
|
|
propose_out_size = libp2p_secio_propose_protobuf_encode_size(propose_out);
|
|
|
|
|
propose_out_bytes = (unsigned char*)malloc(propose_out_size);
|
|
|
|
|
if (libp2p_secio_propose_protobuf_encode(propose_out, propose_out_bytes, propose_out_size, &propose_out_size) == 0)
|
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
|
|
// tack on the protocol id in front
|
|
|
|
|
const unsigned char* protocol = (unsigned char*)"/secio/1.0.0\n";
|
|
|
|
|
int protocol_len = strlen((char*)protocol);
|
|
|
|
|
unsigned char* total = malloc(protocol_len + propose_out_size);
|
|
|
|
|
memcpy(total, protocol, protocol_len);
|
|
|
|
|
memcpy(&total[protocol_len], propose_out_bytes, propose_out_size);
|
|
|
|
|
|
|
|
|
|
libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Writing propose_out\n");
|
|
|
|
|
bytes_written = libp2p_secio_unencrypted_write(local_session, propose_out_bytes, propose_out_size);
|
|
|
|
|
if (bytes_written < propose_out_size)
|
|
|
|
|
// write the Proposal to the stream
|
|
|
|
|
bytes_written = libp2p_secio_unencrypted_write(local_session, total, protocol_len + propose_out_size);
|
|
|
|
|
if (bytes_written < propose_out_size + protocol_len)
|
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
|
|
// now receive the proposal from the new connection
|
|
|
|
|
libp2p_logger_log("secio", LOGLEVEL_DEBUG, "receiving propose_in\n");
|
|
|
|
|
bytes_written = libp2p_secio_unencrypted_read(local_session, &propose_in_bytes, &propose_in_size, 10);
|
|
|
|
|
if (bytes_written <= 0)
|
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
|
|
if (!libp2p_secio_propose_protobuf_decode(propose_in_bytes, propose_in_size, &propose_in))
|
|
|
|
|
if (incoming_size > 0) {
|
|
|
|
|
propose_in_bytes = (uint8_t*)incoming;
|
|
|
|
|
propose_in_size = incoming_size;
|
|
|
|
|
} else {
|
|
|
|
|
bytes_written = libp2p_secio_unencrypted_read(local_session, &propose_in_bytes, &propose_in_size, 10);
|
|
|
|
|
if (bytes_written <= 0)
|
|
|
|
|
goto exit;
|
|
|
|
|
}
|
|
|
|
|
propose_in = libp2p_secio_get_propose_in(propose_in_bytes, propose_in_size);
|
|
|
|
|
if (propose_in == NULL) {
|
|
|
|
|
libp2p_logger_error("secio", "Unable to get the remote's Propose struct\n");
|
|
|
|
|
if (incoming_size == 0) {
|
|
|
|
|
free(propose_in_bytes);
|
|
|
|
|
}
|
|
|
|
|
goto exit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// get their nonce
|
|
|
|
|
if (propose_in->rand_size != 16)
|
|
|
|
@ -1102,8 +1116,6 @@ int libp2p_secio_handshake(struct SessionContext* local_session, struct RsaPriva
|
|
|
|
|
libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Handshake complete\n");
|
|
|
|
|
exit:
|
|
|
|
|
|
|
|
|
|
if (propose_in_bytes != NULL)
|
|
|
|
|
free(propose_in_bytes);
|
|
|
|
|
if (propose_out_bytes != NULL)
|
|
|
|
|
free(propose_out_bytes);
|
|
|
|
|
if (results != NULL)
|
|
|
|
|