intermediate commit for handshake
Working on negotiations between GO and C version of IPFS
This commit is contained in:
parent
be9f278ebf
commit
773c980f1f
5 changed files with 193 additions and 71 deletions
|
@ -187,6 +187,9 @@ exit:
|
||||||
*/
|
*/
|
||||||
int libp2p_crypto_public_key_to_peer_id(struct PublicKey* public_key, char** peer_id) {
|
int libp2p_crypto_public_key_to_peer_id(struct PublicKey* public_key, char** peer_id) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converting to a peer id involves protobufing the struct PublicKey, SHA256 it, turn it into a MultiHash and base58 it
|
||||||
|
*/
|
||||||
size_t protobuf_len = libp2p_crypto_public_key_protobuf_encode_size(public_key);
|
size_t protobuf_len = libp2p_crypto_public_key_protobuf_encode_size(public_key);
|
||||||
unsigned char protobuf[protobuf_len];
|
unsigned char protobuf[protobuf_len];
|
||||||
|
|
||||||
|
@ -198,6 +201,7 @@ int libp2p_crypto_public_key_to_peer_id(struct PublicKey* public_key, char** pee
|
||||||
size_t final_id_size = 100;
|
size_t final_id_size = 100;
|
||||||
unsigned char final_id[final_id_size];
|
unsigned char final_id[final_id_size];
|
||||||
memset(final_id, 0, final_id_size);
|
memset(final_id, 0, final_id_size);
|
||||||
|
// turn it into a multihash and base58 it
|
||||||
if (!PrettyID(final_id, &final_id_size, hashed, 32))
|
if (!PrettyID(final_id, &final_id_size, hashed, 32))
|
||||||
return 0;
|
return 0;
|
||||||
*peer_id = (char*)malloc(final_id_size + 1);
|
*peer_id = (char*)malloc(final_id_size + 1);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
struct Propose {
|
struct Propose {
|
||||||
unsigned char* rand;
|
unsigned char* rand;
|
||||||
size_t rand_size;
|
size_t rand_size;
|
||||||
|
// a protobuf'd struct PublicKey (defined in crypto/key.h)
|
||||||
unsigned char* public_key;
|
unsigned char* public_key;
|
||||||
size_t public_key_size;
|
size_t public_key_size;
|
||||||
char* exchanges;
|
char* exchanges;
|
||||||
|
|
|
@ -33,49 +33,46 @@ int libp2p_net_multistream_send(int socket_fd, const unsigned char* data, size_t
|
||||||
return num_bytes;
|
return num_bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
|
||||||
* Parse the incoming data, removing the size indicator at the front of the array
|
|
||||||
* @param incoming the incoming data
|
|
||||||
* @param incoming_size the size of the incoming data
|
|
||||||
* @param outgoing the buffer to hold the outgoing data, allocated within this function
|
|
||||||
* @param outgoing_size the outgoing size
|
|
||||||
* @returns true(1) on success, otherwise false(0)
|
|
||||||
*/
|
|
||||||
int libp2p_net_multistream_parse_results(char* incoming, size_t incoming_size, char** outgoing, size_t* outgoing_size) {
|
|
||||||
int retVal = 0;
|
|
||||||
if (incoming_size > 0) {
|
|
||||||
// TODO: handle this differently
|
|
||||||
// read the varint
|
|
||||||
// allocate memory
|
|
||||||
*outgoing = (char*)malloc(incoming_size - 1);
|
|
||||||
if (*outgoing == NULL)
|
|
||||||
return 0;
|
|
||||||
// copy in the data
|
|
||||||
memcpy(*outgoing, &incoming[1], incoming_size - 1);
|
|
||||||
*outgoing_size = incoming_size - 1;
|
|
||||||
retVal = 1;
|
|
||||||
}
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read from a multistream socket
|
* Read from a multistream socket
|
||||||
* @param socket_fd the socket file descriptor
|
* @param socket_fd the socket file descriptor
|
||||||
* @param results where to put the results. NOTE: this memory is allocated
|
* @param results where to put the results. NOTE: this memory is allocated
|
||||||
* @param results_size the size of the results in bytes
|
* @param results_size the size of the results in bytes
|
||||||
* @returns true(1) on success, otherwise false(0)
|
* @returns number of bytes received
|
||||||
*/
|
*/
|
||||||
int libp2p_net_multistream_receive(int socket_fd, char** results, size_t* results_size) {
|
int libp2p_net_multistream_receive(int socket_fd, char** results, size_t* results_size) {
|
||||||
int bytes = 0;
|
int bytes = 0;
|
||||||
size_t buffer_size = 65535;
|
size_t buffer_size = 65535;
|
||||||
char buffer[buffer_size];
|
char buffer[buffer_size];
|
||||||
|
char* pos = buffer;
|
||||||
|
int num_bytes = 0;
|
||||||
|
|
||||||
|
// first read the varint
|
||||||
|
while(1) {
|
||||||
|
unsigned char c;
|
||||||
|
bytes = socket_read(socket_fd, (char*)&c, 1, 0);
|
||||||
|
pos[0] = c;
|
||||||
|
if (c >> 7 == 0) {
|
||||||
|
pos[1] = 0;
|
||||||
|
num_bytes = varint_decode((unsigned char*)buffer, strlen(buffer), NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
if (num_bytes <= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// now read the number of bytes we've found
|
||||||
|
bytes = socket_read(socket_fd, buffer, num_bytes, 0);
|
||||||
|
|
||||||
bytes = socket_read(socket_fd, buffer, buffer_size, 0);
|
|
||||||
if (bytes == 0)
|
if (bytes == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// parse the results, removing the leading size indicator
|
// parse the results, removing the leading size indicator
|
||||||
return libp2p_net_multistream_parse_results(buffer, bytes, results, results_size);
|
*results = malloc(bytes);
|
||||||
|
memcpy(*results, buffer, bytes);
|
||||||
|
*results_size = bytes;
|
||||||
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,7 @@ int libp2p_secio_propose_protobuf_encode(struct Propose* in, unsigned char* buff
|
||||||
*/
|
*/
|
||||||
int libp2p_secio_propose_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct Propose** out) {
|
int libp2p_secio_propose_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct Propose** out) {
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
int retVal = 0;
|
int retVal = 0, got_something = 0;;
|
||||||
|
|
||||||
if ( (*out = libp2p_secio_propose_new()) == NULL)
|
if ( (*out = libp2p_secio_propose_new()) == NULL)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
@ -113,37 +113,45 @@ int libp2p_secio_propose_protobuf_decode(unsigned char* buffer, size_t buffer_le
|
||||||
if (protobuf_decode_field_and_type(&buffer[pos], buffer_length, &field_no, &field_type, &bytes_read) == 0) {
|
if (protobuf_decode_field_and_type(&buffer[pos], buffer_length, &field_no, &field_type, &bytes_read) == 0) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
if (field_no < 1 || field_no > 5) {
|
||||||
|
fprintf(stderr, "Invalid character in Propose protobuf at position %lu. Value: %02x\n", pos, buffer[pos]);
|
||||||
|
}
|
||||||
pos += bytes_read;
|
pos += bytes_read;
|
||||||
switch(field_no) {
|
switch(field_no) {
|
||||||
case (1): // rand
|
case (1): // rand
|
||||||
if (protobuf_decode_length_delimited(&buffer[pos], buffer_length - pos, (char**)&((*out)->rand), &((*out)->rand_size), &bytes_read) == 0)
|
if (protobuf_decode_length_delimited(&buffer[pos], buffer_length - pos, (char**)&((*out)->rand), &((*out)->rand_size), &bytes_read) == 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
pos += bytes_read;
|
pos += bytes_read;
|
||||||
|
got_something = 1;
|
||||||
break;
|
break;
|
||||||
case (2): // public key
|
case (2): // public key
|
||||||
if (protobuf_decode_length_delimited(&buffer[pos], buffer_length - pos, (char**)&((*out)->public_key), &((*out)->public_key_size), &bytes_read) == 0)
|
if (protobuf_decode_length_delimited(&buffer[pos], buffer_length - pos, (char**)&((*out)->public_key), &((*out)->public_key_size), &bytes_read) == 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
pos += bytes_read;
|
pos += bytes_read;
|
||||||
|
got_something = 1;
|
||||||
break;
|
break;
|
||||||
case (3): // ciphers
|
case (3): // ciphers
|
||||||
if (protobuf_decode_length_delimited(&buffer[pos], buffer_length - pos, (char**)&((*out)->ciphers), &((*out)->ciphers_size), &bytes_read) == 0)
|
if (protobuf_decode_length_delimited(&buffer[pos], buffer_length - pos, (char**)&((*out)->ciphers), &((*out)->ciphers_size), &bytes_read) == 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
pos += bytes_read;
|
pos += bytes_read;
|
||||||
|
got_something = 1;
|
||||||
break;
|
break;
|
||||||
case (4): // exchanges
|
case (4): // exchanges
|
||||||
if (protobuf_decode_length_delimited(&buffer[pos], buffer_length - pos, (char**)&((*out)->exchanges), &((*out)->exchanges_size), &bytes_read) == 0)
|
if (protobuf_decode_length_delimited(&buffer[pos], buffer_length - pos, (char**)&((*out)->exchanges), &((*out)->exchanges_size), &bytes_read) == 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
pos += bytes_read;
|
pos += bytes_read;
|
||||||
|
got_something = 1;
|
||||||
break;
|
break;
|
||||||
case (5): // hashes
|
case (5): // hashes
|
||||||
if (protobuf_decode_length_delimited(&buffer[pos], buffer_length - pos, (char**)&((*out)->hashes), &((*out)->hashes_size), &bytes_read) == 0)
|
if (protobuf_decode_length_delimited(&buffer[pos], buffer_length - pos, (char**)&((*out)->hashes), &((*out)->hashes_size), &bytes_read) == 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
pos += bytes_read;
|
pos += bytes_read;
|
||||||
|
got_something = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
retVal = 1;
|
retVal = got_something;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if (retVal == 0) {
|
if (retVal == 0) {
|
||||||
|
|
190
secio/secio.c
190
secio/secio.c
|
@ -2,11 +2,14 @@
|
||||||
#include <stdio.h> // for debugging, can remove
|
#include <stdio.h> // for debugging, can remove
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
#include "libp2p/secio/secio.h"
|
#include "libp2p/secio/secio.h"
|
||||||
#include "libp2p/secio/propose.h"
|
#include "libp2p/secio/propose.h"
|
||||||
#include "libp2p/secio/exchange.h"
|
#include "libp2p/secio/exchange.h"
|
||||||
#include "libp2p/net/multistream.h"
|
#include "libp2p/net/multistream.h"
|
||||||
|
#include "libp2p/net/p2pnet.h"
|
||||||
#include "libp2p/crypto/ephemeral.h"
|
#include "libp2p/crypto/ephemeral.h"
|
||||||
#include "libp2p/crypto/sha1.h"
|
#include "libp2p/crypto/sha1.h"
|
||||||
#include "libp2p/crypto/sha256.h"
|
#include "libp2p/crypto/sha256.h"
|
||||||
|
@ -196,7 +199,8 @@ int libp2p_secio_sign(struct PrivateKey* private_key, const char* in, size_t in_
|
||||||
rsa_key.der = (char*)private_key->data;
|
rsa_key.der = (char*)private_key->data;
|
||||||
rsa_key.der_length = private_key->data_size;
|
rsa_key.der_length = private_key->data_size;
|
||||||
// SHA2-256 signatures are 32 bytes
|
// SHA2-256 signatures are 32 bytes
|
||||||
*signature = (unsigned char*)malloc(32);
|
*signature_size = 32;
|
||||||
|
*signature = (unsigned char*)malloc(*signature_size);
|
||||||
return libp2p_crypto_rsa_sign(&rsa_key, in, in_length, *signature);
|
return libp2p_crypto_rsa_sign(&rsa_key, in, in_length, *signature);
|
||||||
}
|
}
|
||||||
// TODO: Implement this method for non-RSA
|
// TODO: Implement this method for non-RSA
|
||||||
|
@ -361,14 +365,103 @@ int libp2p_secio_make_mac_and_cipher(struct SecureSession* session) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int libp2p_secio_write(struct SecureSession* session, unsigned char* bytes, size_t length) {
|
int libp2p_secio_write(struct SecureSession* session, unsigned char* bytes, size_t data_length) {
|
||||||
// TODO: Implement this method
|
int num_bytes = 0;
|
||||||
|
|
||||||
|
if (data_length > 0) { // only do this is if there is something to send
|
||||||
|
// first send the size
|
||||||
|
uint32_t size = htonl(data_length);
|
||||||
|
char* size_as_char = (char*)&size;
|
||||||
|
int left = 4;
|
||||||
|
int written = 0;
|
||||||
|
int written_this_time = 0;
|
||||||
|
do {
|
||||||
|
written_this_time = socket_write(session->socket_descriptor, &size_as_char[written], left, 0);
|
||||||
|
if (written_this_time < 0) {
|
||||||
|
written_this_time = 0;
|
||||||
|
if ( (errno == EAGAIN) || (errno == EWOULDBLOCK)) {
|
||||||
|
// TODO: use epoll or select to wait for socket to be writable
|
||||||
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
left = left - written_this_time;
|
||||||
|
} while (left > 0);
|
||||||
|
// then send the actual data
|
||||||
|
left = data_length;
|
||||||
|
written = 0;
|
||||||
|
do {
|
||||||
|
written_this_time = socket_write(session->socket_descriptor, (char*)&bytes[written], left, 0);
|
||||||
|
if (written_this_time < 0) {
|
||||||
|
written_this_time = 0;
|
||||||
|
if ( (errno == EAGAIN) || (errno == EWOULDBLOCK)) {
|
||||||
|
// TODO: use epoll or select to wait for socket to be writable
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
left = left - written_this_time;
|
||||||
|
written += written_this_time;
|
||||||
|
} while (left > 0);
|
||||||
|
num_bytes = written;
|
||||||
|
} // there was something to send
|
||||||
|
|
||||||
|
return num_bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
int libp2p_secio_read(struct SecureSession* session, unsigned char** bytes, size_t* bytes_read) {
|
int libp2p_secio_read(struct SecureSession* session, unsigned char** results, size_t* results_size) {
|
||||||
// TODO: Implement this method
|
uint32_t buffer_size;
|
||||||
|
|
||||||
|
// first read the 4 byte integer
|
||||||
|
char* size = (char*)&buffer_size;
|
||||||
|
int left = 4;
|
||||||
|
int read = 0;
|
||||||
|
int read_this_time = 0;
|
||||||
|
do {
|
||||||
|
read_this_time = socket_read(session->socket_descriptor, &size[read], 1, 0);
|
||||||
|
if (read_this_time < 0) {
|
||||||
|
read_this_time = 0;
|
||||||
|
if ( (errno == EAGAIN) || (errno == EWOULDBLOCK)) {
|
||||||
|
// TODO: use epoll or select to wait for socket to be writable
|
||||||
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (read == 0 && size[0] == 10) {
|
||||||
|
// a spurious \n
|
||||||
|
// write over this value by not adding it
|
||||||
|
} else {
|
||||||
|
left = left - read_this_time;
|
||||||
|
read += read_this_time;
|
||||||
|
}
|
||||||
|
} while (left > 0);
|
||||||
|
// now read the number of bytes we've found, minus the 4 that we just read
|
||||||
|
buffer_size = ntohl(buffer_size);
|
||||||
|
// JMJ
|
||||||
|
fprintf(stderr, "which switching bits results in %u.\n", buffer_size);
|
||||||
|
if (buffer_size == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
left = buffer_size;
|
||||||
|
read = 0;
|
||||||
|
read_this_time = 0;
|
||||||
|
*results = malloc(left);
|
||||||
|
unsigned char* ptr = *results;
|
||||||
|
do {
|
||||||
|
read_this_time = socket_read(session->socket_descriptor, (char*)&ptr[read], left, 0);
|
||||||
|
if (read_this_time < 0) {
|
||||||
|
read_this_time = 0;
|
||||||
|
if ( (errno == EAGAIN) || (errno == EWOULDBLOCK)) {
|
||||||
|
// TODO: use epoll or select to wait for socket to be writable
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
left = left - read_this_time;
|
||||||
|
} while (left > 0);
|
||||||
|
|
||||||
|
*results_size = buffer_size;
|
||||||
|
return buffer_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
|
@ -406,41 +499,15 @@ int libp2p_secio_handshake(struct SecureSession* local_session, struct RsaPrivat
|
||||||
if (bytes_written <= 0)
|
if (bytes_written <= 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
// we should get back the protocol to signify it was accepted, as well as the protobuf of the Propose struct
|
// we should get back the secio confirmation
|
||||||
bytes_written = libp2p_net_multistream_receive(local_session->socket_descriptor, (char**)&results, &results_size);
|
bytes_written = libp2p_net_multistream_receive(local_session->socket_descriptor, (char**)&results, &results_size);
|
||||||
if (bytes_written < 1 || strstr((char*)results, "secio") == NULL)
|
if (bytes_written < 1 || strstr((char*)results, "secio") == NULL)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
// skip to the protobuf section
|
|
||||||
propose_in_bytes = (unsigned char*)strchr((char*)results, '\n');
|
|
||||||
if (propose_in_bytes == NULL)
|
|
||||||
goto exit;
|
|
||||||
// are we at the end of the buffer?
|
|
||||||
if (propose_in_bytes - results + 1 >= results_size) {
|
|
||||||
free(results);
|
|
||||||
// read some more
|
|
||||||
bytes_written = libp2p_net_multistream_receive(local_session->socket_descriptor, (char**)&results, &results_size);
|
|
||||||
propose_in_bytes = results;
|
|
||||||
} else {
|
|
||||||
propose_in_bytes++;
|
|
||||||
}
|
|
||||||
propose_in_size = results_size - (propose_in_bytes - results);
|
|
||||||
|
|
||||||
if (!libp2p_secio_propose_protobuf_decode(propose_in_bytes, propose_in_size, &propose_in))
|
|
||||||
goto exit;
|
|
||||||
|
|
||||||
// clear results
|
|
||||||
free(results);
|
free(results);
|
||||||
results = NULL;
|
results = NULL;
|
||||||
results_size = 0;
|
results_size = 0;
|
||||||
|
|
||||||
// get public key and put it in a struct PublicKey
|
|
||||||
if (!libp2p_crypto_public_key_protobuf_decode(propose_in->public_key, propose_in->public_key_size, &public_key))
|
|
||||||
goto exit;
|
|
||||||
// generate their peer id
|
|
||||||
char* remote_peer_id;
|
|
||||||
libp2p_crypto_public_key_to_peer_id(public_key, &remote_peer_id);
|
|
||||||
|
|
||||||
//TODO: make sure we're not talking to ourself
|
//TODO: make sure we're not talking to ourself
|
||||||
|
|
||||||
// generate 16 byte nonce
|
// generate 16 byte nonce
|
||||||
|
@ -451,17 +518,54 @@ int libp2p_secio_handshake(struct SecureSession* local_session, struct RsaPrivat
|
||||||
propose_out = libp2p_secio_propose_new();
|
propose_out = libp2p_secio_propose_new();
|
||||||
libp2p_secio_propose_set_property((void**)&propose_out->rand, &propose_out->rand_size, local_session->nonce, 16);
|
libp2p_secio_propose_set_property((void**)&propose_out->rand, &propose_out->rand_size, local_session->nonce, 16);
|
||||||
|
|
||||||
// we have their information, now we need to gather ours.
|
// public key - protobuf it and stick it in propose_out
|
||||||
// public key
|
struct PublicKey pub_key;
|
||||||
propose_out->public_key_size = public_key->data_size;
|
pub_key.type = KEYTYPE_RSA;
|
||||||
propose_out->public_key = (unsigned char*)malloc(public_key->data_size);
|
pub_key.data_size = private_key->public_key_length;
|
||||||
memcpy(propose_out->public_key, public_key->data, public_key->data_size);
|
pub_key.data = malloc(pub_key.data_size);
|
||||||
|
results_size = libp2p_crypto_public_key_protobuf_encode_size(&pub_key);
|
||||||
|
results = malloc(results_size);
|
||||||
|
if (libp2p_crypto_public_key_protobuf_encode(&pub_key, results, result_size, &results_size) == 0)
|
||||||
|
goto exit;
|
||||||
|
propose_out->public_key_size = results_size;
|
||||||
|
propose_out->public_key = malloc(results_size);
|
||||||
|
memcpy(propose_out->public_key, results, results_size);
|
||||||
|
free(results);
|
||||||
|
results = NULL;
|
||||||
|
results_size = 0;
|
||||||
// supported exchanges
|
// supported exchanges
|
||||||
libp2p_secio_propose_set_property((void**)&propose_out->exchanges, &propose_out->exchanges_size, SupportedExchanges, strlen(SupportedExchanges));
|
libp2p_secio_propose_set_property((void**)&propose_out->exchanges, &propose_out->exchanges_size, SupportedExchanges, strlen(SupportedExchanges));
|
||||||
// supported ciphers
|
// supported ciphers
|
||||||
libp2p_secio_propose_set_property((void**)&propose_out->ciphers, &propose_out->ciphers_size, SupportedCiphers, strlen(SupportedCiphers));
|
libp2p_secio_propose_set_property((void**)&propose_out->ciphers, &propose_out->ciphers_size, SupportedCiphers, strlen(SupportedCiphers));
|
||||||
// supported hashes
|
// supported hashes
|
||||||
libp2p_secio_propose_set_property((void**)&propose_out->hashes, &propose_out->hashes_size, SupportedHashes, strlen(SupportedHashes));
|
libp2p_secio_propose_set_property((void**)&propose_out->hashes, &propose_out->hashes_size, SupportedHashes, strlen(SupportedHashes));
|
||||||
|
|
||||||
|
// send 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;
|
||||||
|
|
||||||
|
bytes_written = libp2p_secio_write(local_session, propose_out_bytes, propose_out_size);
|
||||||
|
if (bytes_written < propose_out_size)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
// try to get the propose object from the server
|
||||||
|
bytes_written = libp2p_secio_read(local_session, &propose_in_bytes, &propose_in_size);
|
||||||
|
if (bytes_written <= 0)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
if (!libp2p_secio_propose_protobuf_decode(propose_in_bytes, propose_in_size, &propose_in))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
// get public key and put it in a struct PublicKey
|
||||||
|
if (!libp2p_crypto_public_key_protobuf_decode(propose_in->public_key, propose_in->public_key_size, &public_key))
|
||||||
|
goto exit;
|
||||||
|
// generate their peer id
|
||||||
|
char* remote_peer_id;
|
||||||
|
libp2p_crypto_public_key_to_peer_id(public_key, &remote_peer_id);
|
||||||
|
|
||||||
|
|
||||||
// negotiate encryption parameters NOTE: SelectBest must match, otherwise this won't work
|
// negotiate encryption parameters NOTE: SelectBest must match, otherwise this won't work
|
||||||
// first determine order
|
// first determine order
|
||||||
libp2p_secio_hash(propose_in, order_hash_in);
|
libp2p_secio_hash(propose_in, order_hash_in);
|
||||||
|
@ -474,6 +578,7 @@ int libp2p_secio_handshake(struct SecureSession* local_session, struct RsaPrivat
|
||||||
// hash
|
// hash
|
||||||
libp2p_secio_select_best(order, propose_out->hashes, propose_out->hashes_size, propose_in->hashes, propose_in->hashes_size, &local_session->chosen_hash);
|
libp2p_secio_select_best(order, propose_out->hashes, propose_out->hashes_size, propose_in->hashes, propose_in->hashes_size, &local_session->chosen_hash);
|
||||||
|
|
||||||
|
|
||||||
// prepare exchange of encryption parameters
|
// prepare exchange of encryption parameters
|
||||||
struct SecureSession remote_session;
|
struct SecureSession remote_session;
|
||||||
remote_session.chosen_cipher = local_session->chosen_cipher;
|
remote_session.chosen_cipher = local_session->chosen_cipher;
|
||||||
|
@ -515,11 +620,11 @@ int libp2p_secio_handshake(struct SecureSession* local_session, struct RsaPrivat
|
||||||
if (exchange_out_protobuf == NULL)
|
if (exchange_out_protobuf == NULL)
|
||||||
goto exit;
|
goto exit;
|
||||||
libp2p_secio_exchange_protobuf_encode(exchange_out, exchange_out_protobuf, exchange_out_protobuf_size, &bytes_written);
|
libp2p_secio_exchange_protobuf_encode(exchange_out, exchange_out_protobuf, exchange_out_protobuf_size, &bytes_written);
|
||||||
bytes_written = libp2p_net_multistream_send(local_session->socket_descriptor, exchange_out_protobuf, exchange_out_protobuf_size);
|
bytes_written = libp2p_secio_write(local_session, exchange_out_protobuf, exchange_out_protobuf_size);
|
||||||
free(exchange_out_protobuf);
|
free(exchange_out_protobuf);
|
||||||
|
|
||||||
// receive Exchange packet
|
// receive Exchange packet
|
||||||
bytes_written = libp2p_net_multistream_receive(local_session->socket_descriptor, (char**)&results, &results_size);
|
bytes_written = libp2p_secio_read(local_session, &results, &results_size);
|
||||||
if (bytes_written == 0)
|
if (bytes_written == 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
libp2p_secio_exchange_protobuf_decode(results, results_size, &exchange_in);
|
libp2p_secio_exchange_protobuf_decode(results, results_size, &exchange_in);
|
||||||
|
@ -568,6 +673,13 @@ int libp2p_secio_handshake(struct SecureSession* local_session, struct RsaPrivat
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
|
|
||||||
|
if (propose_in_bytes != NULL)
|
||||||
|
free(propose_in_bytes);
|
||||||
|
if (propose_out_bytes != NULL)
|
||||||
|
free(propose_out_bytes);
|
||||||
|
if (results != NULL)
|
||||||
|
free(results);
|
||||||
|
|
||||||
libp2p_secio_propose_free(propose_out);
|
libp2p_secio_propose_free(propose_out);
|
||||||
libp2p_secio_propose_free(propose_in);
|
libp2p_secio_propose_free(propose_in);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue