Another night's work - move to ECDH + AES256 from RSA pubkey
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
#!/usr/bin/make -f
|
||||
CFLAGS := $(CFLAGS) -Wall -Werror --std=c99
|
||||
|
||||
LDFLAGS := $(LDFLAGS) -ljson-c -lssl -lcrypto
|
||||
CFLAGS := $(CFLAGS) -Wall -Werror --std=c99
|
||||
LDFLAGS := $(LDFLAGS) -ljson-c -lssl -lcrypto
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
|
@@ -108,7 +108,11 @@ int wrap_ipv4_packet(struct rlocs* reg, struct recv_pkt* pkt, struct rsp_data* o
|
||||
unsigned short *pkt_enc_size = (unsigned short *) scratch;
|
||||
scratch += 2;
|
||||
|
||||
enc_size = rloc_encrypt( d_rloc, (unsigned char *)&pkt->hdr, bytes_to_encrypt, scratch, enc_max_len - 2 );
|
||||
enc_size = rlocs_encrypt(
|
||||
reg, s_rloc, d_rloc,
|
||||
(unsigned char *)&pkt->hdr, bytes_to_encrypt, scratch, enc_max_len - 2
|
||||
);
|
||||
|
||||
if ( enc_size < 0 ) {
|
||||
warn( "failed to encrypt, dropping packet" );
|
||||
return 0;
|
||||
@@ -118,8 +122,6 @@ int wrap_ipv4_packet(struct rlocs* reg, struct recv_pkt* pkt, struct rsp_data* o
|
||||
enc_size += 2;
|
||||
scratch = (unsigned char*) pkt_enc_size;
|
||||
|
||||
|
||||
|
||||
warn( "Encrypted size: 2 + %zu", enc_size - 2);
|
||||
|
||||
out->iovs[1].iov_base = scratch;
|
||||
@@ -163,12 +165,19 @@ int unwrap_ipv4_packet(struct rlocs* reg, struct recv_pkt* pkt, struct rsp_data*
|
||||
return 0;
|
||||
}
|
||||
|
||||
// We need to know destination rloc to decrypt the packet
|
||||
struct rloc* rloc;
|
||||
// We need to know source and destination rloc to decrypt the packet
|
||||
struct rloc *s_rloc, *d_rloc;
|
||||
struct in_addr tmp;
|
||||
|
||||
tmp.s_addr = pkt->hdr.ip.saddr;
|
||||
if ( ( s_rloc = rloc_find_by_address( reg, &tmp, NULL ) ) == NULL ) {
|
||||
warn( "Couldn't find rloc from source IP, dropping packet" );
|
||||
// TODO: we should be able to specify we need it to have a private key
|
||||
return 0;
|
||||
}
|
||||
|
||||
tmp.s_addr = pkt->hdr.ip.daddr;
|
||||
if ( ( rloc = rloc_find_by_address( reg, &tmp, NULL ) ) == NULL ) {
|
||||
if ( ( d_rloc = rloc_find_by_address( reg, &tmp, NULL ) ) == NULL ) {
|
||||
warn( "Couldn't find rloc from destination IP, dropping packet" );
|
||||
// TODO: we should be able to specify we need it to have a private key
|
||||
return 0;
|
||||
@@ -182,7 +191,10 @@ int unwrap_ipv4_packet(struct rlocs* reg, struct recv_pkt* pkt, struct rsp_data*
|
||||
unsigned char *encrypted_data = ((unsigned char *)pkt) + hdr_size + 2;
|
||||
unsigned char *scratch = &out->scratch[0];
|
||||
|
||||
int decrypted_size = rloc_decrypt( rloc, encrypted_data, encrypted_size, scratch, IP_MAXPACKET );
|
||||
int decrypted_size = rlocs_decrypt(
|
||||
reg, d_rloc, s_rloc,
|
||||
encrypted_data, encrypted_size, scratch, IP_MAXPACKET
|
||||
);
|
||||
|
||||
if ( decrypted_size < 0 ) {
|
||||
warn( "Failed to decrypt packet!" );
|
||||
|
@@ -2,77 +2,25 @@
|
||||
"type": "rloc-registry",
|
||||
|
||||
"eid_rloc_map": [
|
||||
{ "family":"ipv4", "network":"172.16.10.0", "netmask":24, "rloc":"172.16.10.2"},
|
||||
{ "family":"ipv4", "network":"172.16.11.0", "netmask":24, "rloc":"172.16.10.2"},
|
||||
{ "family":"ipv4", "network":"172.16.12.0", "netmask":24, "rloc":"172.16.12.2"},
|
||||
{ "family":"ipv6", "network":"fc00:1::", "netmask":64, "rloc":"fc00::2" },
|
||||
{ "family":"ipv6", "network":"fc00:2::", "netmask":64, "rloc":"fc00:2::2" }
|
||||
{ "family":"ipv4", "network":"172.16.10.0", "netmask":24, "rloc":"81.187.47.40"},
|
||||
{ "family":"ipv4", "network":"172.16.11.0", "netmask":24, "rloc":"213.138.102.147"}
|
||||
|
||||
],
|
||||
|
||||
"keys": {
|
||||
"172.16.10.2":
|
||||
"-----BEGIN PUBLIC KEY-----
|
||||
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0FxctMUibDqkVhChIvJg
|
||||
6GhzKzaMEKza+9MhO1H0VEnvgMsvZ6S15iSxHVxiO5KpjwYAakW4ELLK7We+exsH
|
||||
zOSAioh1Po3uxTLga7PrEvLkv7hI/2vxWPYk2j2j++WHKXjyNoAKpdC5nrauRPT2
|
||||
DAlbRcRu9gnhLIIDu/HCLLxT1qQgWOaVZBJVxxcPYwrBPSjDAvKn5GKbN8wh4k1h
|
||||
WIkedhHIjzM7mYQfXTaJttP2+9Gco5sOntKVldy2nGWWtaPDtlMmmCdclgrBpxT9
|
||||
EPEZ+H9ApPWHAMEgVvLn9nKPNJ/06jPFEcA5ZEtu6N+lPjkjRU9JfuMPt/jz3otY
|
||||
1iA/Utx1tQQqEzote5V5zxHnBcYtqtftf7PKANVfPnLQxQ9msKmrcBb0bNwn3KdX
|
||||
pavbsPp5W4WGFalt499u3CGmd6AQ9/tZfafTEsAPCpNQrfZ4v0AVIiT6ZuQQ1Vip
|
||||
q14pHlpN3xepxwHZtCJTyU7kHaWKvImFZRY6dg0dRkvWl2bO6xJsYYXTaYHre+Sx
|
||||
ivtEZcM7VPEZlQyBlwTYYHmnllBlnXMJpx20p26Sy4iPX6hzn9sT3UQHE6NAlfON
|
||||
He5Cw+4ma5DA2jQvvIBfYA1ipVfGKD8LyrPrxuD9qErYpPBP23EdJwT0ZL+jKjyT
|
||||
t39smrDydkWUQWYPiiUKKM0CAwEAAQ==
|
||||
-----END PUBLIC KEY-----",
|
||||
|
||||
"172.16.12.2":
|
||||
"81.187.47.40":
|
||||
"-----BEGIN PUBLIC KEY-----
|
||||
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvYljSQd/jHZtSTc6Z2E1
|
||||
6D37s/MDGmWux/0ulRLsnGRnIj/cd8b3wV2AKbucjEOZ70MH5mU3szz/eZwD5z3A
|
||||
hU+2ok9GV3vL1COg692RRV9ydizxc/8PduYyojeBiOgwBQvCS0PM6IcEDbNvgtfY
|
||||
yzcnMf56Iadqukp5ovCZU/xl4zPMNwtVonMoeOgpdPBd9POBAhXI5zvZDEIF+PM3
|
||||
Lfuy+ybn5alJKDQwWE2tjWnNWx3e34JKTulN7xC9Cw4xw+zmoG5GYua5RtM7AYsJ
|
||||
cCBmF4V3XhpPnxgGhO5S3tKWyke317FjNBqbG1Gj30ADYliHZI1KEQbaXCHxB8lQ
|
||||
bII6OEz9liz4QNSDd2iTInA7yv2djOIdEoPCgtY7oXQZi5Ch8q2M9sAVGAyyF2sR
|
||||
2SlUiP0fuH2S5CviI/5KKTHMA8HNg2rH6gPeTDiLDluw+oL3tIy3XEmhUJS3ZSzG
|
||||
PhN1So0n3XwsnAUWvm33ujTtvAGTuUwBKsG8nIb3iwr7Vh8O617yuOl7ab68Dxym
|
||||
fJZZE5wzjzYbNxup8E9VSfHKSCUHptg9cB/1kF5HoshZCZwA62eAtQgaamr64NrT
|
||||
Uuyz1Ng3KTiD1cObXeirB88yyYd1W21deRfGaGZlWpJTAMjy/bXjR6ZAA+xTXllO
|
||||
QFqgpMLJRNxWj7UUOWm3xjECAwEAAQ==
|
||||
-----END PUBLIC KEY-----",
|
||||
MD4wEAYHKoZIzj0CAQYFK4EEAB4DKgAEdlvMHCK1rsACyk53Oo5PEfmj/ZON3oKt
|
||||
wXgyHsydIb6JMt2tD3bFZA==
|
||||
-----END PUBLIC KEY-----",
|
||||
|
||||
"fc00::2":
|
||||
"213.138.102.147":
|
||||
"-----BEGIN PUBLIC KEY-----
|
||||
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnQhQ9S190q/+t0/QqplD
|
||||
+aRHLrVm8oWFHKqfaE11zZ+7adse4NFgzEWMRN2bUIl47W/VuTHn3NtsF3myYjtX
|
||||
n9bXW/fibVj1xFXk5qpsHvC1xgdUTP3msqiEXigHIgJKgaTCDOaYykfBaFKNP334
|
||||
Dz0mZ4xTmMwmp/9MEiaj8ieFWBTJ5+QFJZCwYUCNGI3hWaXrmlNoKBIj4vfpnFv1
|
||||
MUSCcvc3yl4+KBnIqq0rNfQqlvwNl1NfI2P80eGKW6urQSIjxqb966pOilVePoj8
|
||||
iY8LUtT4WknCacM1oi9rVE0sjtZxeLUs5EuToFn6O2L576SJvNg9GvGA4YmqPTkS
|
||||
fkxunarY+I7frdZyTWg/Bgr5rWXP7QJ5VY11VbsTo7vGblWQ6MqYH00owGuKXFqg
|
||||
7Fl+dr+Ko3uLLnWXF92f4xvP5//0YmRADDGNu1Elgr7NxEoIe7iWFuaga2tV3BPf
|
||||
//3nneHhPv3d4OYnImMQLih+OF25hfYFI8V1ef5dpKXuSNQ01nxIexRHTd0sQnTS
|
||||
Agq3TFQzB5U54k554plWUjPvHFvUDmCyAdTAEn2/0xJQZ3X1RqFZfzjW+rcARjnt
|
||||
lxtMZOyE1S1kAg0HS0uEGLYrIp0K+moEKhm3Upvv3ad3FP1695tJUBec0KH8/PbX
|
||||
XlTdlmviw5Fo15QnPOLcsW8CAwEAAQ==
|
||||
-----END PUBLIC KEY-----",
|
||||
MD4wEAYHKoZIzj0CAQYFK4EEAB4DKgAEaDuTFicM87FKVqEHUMGW4BaFz9GAwjAC
|
||||
+pnmMUh00yFgDEyi6ozUrw==
|
||||
-----END PUBLIC KEY-----"
|
||||
|
||||
"fc00:2::2":
|
||||
"-----BEGIN PUBLIC KEY-----
|
||||
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAt/rGbJ46DIciiRHaknkV
|
||||
pQ0ulKtZl5UApOaKTP8SxuEoDDrUZ7w3FnItPYkDh41RisVf7hBAKe+BwCRxodo0
|
||||
++MeMcbrWG16rT/2AVi7V5te936L3O/WiF/BFgWXgJ1+bgXlZlIsJWLqMT5ozcaM
|
||||
XRIosgoYMkvvS4tBYLwQIx3ov+PVfZELOmqtoesv5e70Xg0iXNVb57wTnsnBPHo0
|
||||
u4Pw1oSsqDNM4oblDwXtfJEUMcBA+q12L5lqBEnXGlFQgeViCFnpaR03oc0btn0S
|
||||
PZtAgZ88WPdnf+jAeSeEnVvTmhQtNxmnZXtEy/T0emD+163/lpcr7vIK/iFXvZsx
|
||||
Bf2xdRs7EU/6M+YaE8rhI/uTNgMpR2RGAIyQn8aGCydGf/FCxXMBg99mk5R0h2cD
|
||||
BkGyVbmFzXrsoitw5Foz/JC5svvoR/z16w/+lIbRRx2OMSaMtoRqYO6At2GC30TZ
|
||||
DSDQ5nNOo4hmySZnrEWq+t4BJjJ1wu7eAJpsCVXkyRZUtNt6c98VaAuJQv7FHW/O
|
||||
75XaEHewVAAGTmQEjI/cTY72bHkbtE3vpi0aK8Wc7K4g7slUld0HUsh8xszIhdxu
|
||||
8Y+yuP72oOpicPK8LCDyI28V0HCz44bo1TDrDUC0YZ1fDr8Pk2A+jrlt4/yMcgkn
|
||||
PBcctUqN/b2cIfCA8UDAMZ0CAwEAAQ==
|
||||
-----END PUBLIC KEY-----"
|
||||
|
||||
}
|
||||
|
||||
|
246
pass-1/rlocs.c
246
pass-1/rlocs.c
@@ -17,30 +17,41 @@
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/obj_mac.h>
|
||||
|
||||
#include <json/json_tokener.h>
|
||||
#include <json/linkhash.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "util.h"
|
||||
//#include "util.h"
|
||||
#include "rlocs.h"
|
||||
|
||||
#define JSON_TYPE "rloc-registry"
|
||||
|
||||
void show_ssl_errors(void)
|
||||
{
|
||||
ERR_print_errors_fp(stderr);
|
||||
return;
|
||||
}
|
||||
|
||||
void rlocs_init(void)
|
||||
{
|
||||
uint32_t seed;
|
||||
SSL_load_error_strings(); /* readable error messages */
|
||||
SSL_library_init(); /* initialize library */
|
||||
OpenSSL_add_all_algorithms();
|
||||
|
||||
// set the random seed to something good
|
||||
if ( RAND_bytes( (unsigned char*)&seed, sizeof( uint32_t ) ) != 1 ) {
|
||||
warn( "Failed to initialize random seed" );
|
||||
show_ssl_errors();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
srand( seed );
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -50,7 +61,8 @@ int rlocs_rloc_from_json(struct rlocs* reg, const char* key, json_object* val )
|
||||
ssize_t pem_data_size;
|
||||
const char* pem_data;
|
||||
struct rloc *rloc;
|
||||
RSA *rsa_key, *result;
|
||||
EVP_PKEY *evp_key = NULL;
|
||||
EC_KEY *ec_key = NULL;
|
||||
BIO *bp;
|
||||
|
||||
if ( !json_object_is_type( val, json_type_string ) ) {
|
||||
@@ -80,20 +92,47 @@ int rlocs_rloc_from_json(struct rlocs* reg, const char* key, json_object* val )
|
||||
pem_data = json_object_get_string( val );
|
||||
pem_data_size = json_object_get_string_len( val );
|
||||
|
||||
rsa_key = RSA_new();
|
||||
bp = BIO_new_mem_buf( (void*)pem_data, pem_data_size );
|
||||
result = PEM_read_bio_RSA_PUBKEY( bp, &rsa_key, NULL, NULL );
|
||||
BIO_vfree( bp );
|
||||
|
||||
if ( result == NULL ) {
|
||||
RSA_free( rsa_key );
|
||||
warn( "Couldn't parse key for %s as an RSA public key", key );
|
||||
return 0;
|
||||
if ( ( evp_key = EVP_PKEY_new() ) == NULL ) {
|
||||
warn( "couldn't allocate new EVP_pkey for rloc %s", key );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rloc->key = rsa_key;
|
||||
if ( !( bp = BIO_new_mem_buf( (void*)pem_data, pem_data_size ) ) ) {
|
||||
warn( "couldn't allocate new BIO to interpret key for rloc %s", key );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ec_key = PEM_read_bio_EC_PUBKEY( bp, &ec_key, NULL, NULL );
|
||||
BIO_vfree( bp );
|
||||
|
||||
if ( ec_key == NULL ) {
|
||||
warn( "Couldn't parse key for rloc %s as an EC secp160r2 public key", key );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// assign so we don't have to free the EC_KEY object any more
|
||||
if ( !EVP_PKEY_assign_EC_KEY( evp_key, ec_key ) ) {
|
||||
warn( "couldn't assign key for rloc %s to container", key );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rloc->key = evp_key;
|
||||
rloc->context_id = reg->num_entries;
|
||||
reg->num_entries++;
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
show_ssl_errors();
|
||||
|
||||
if ( evp_key != NULL ) {
|
||||
EVP_PKEY_free( evp_key );
|
||||
}
|
||||
|
||||
if ( ec_key != NULL ) {
|
||||
EC_KEY_free( ec_key );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rlocs_eid_from_json( struct rlocs *reg, json_object *map)
|
||||
@@ -410,53 +449,182 @@ struct rloc *rloc_find_by_address( struct rlocs *reg, struct in_addr *ipv4, stru
|
||||
*/
|
||||
int rloc_add_private_key( struct rloc *rloc, char *filename )
|
||||
{
|
||||
BIO *key_data = BIO_new_file( filename, "r" );
|
||||
|
||||
RSA* key = PEM_read_bio_RSAPrivateKey( key_data, NULL, NULL, NULL );
|
||||
BIO *key_data = BIO_new_file( filename, "r" );
|
||||
EC_KEY* key = PEM_read_bio_ECPrivateKey( key_data, NULL, NULL, NULL );
|
||||
|
||||
if ( key == NULL ) {
|
||||
warn( "Failed to add private key %s", filename );
|
||||
return 0;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
RSA_free( rloc->key );
|
||||
rloc->key = key;
|
||||
if ( !EVP_PKEY_assign_EC_KEY( rloc->key, key ) ) {
|
||||
warn( "Failed to assign private key in %s to rloc", filename );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
show_ssl_errors();
|
||||
|
||||
if ( key != NULL ) {
|
||||
EC_KEY_free( key );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void show_ssl_errors(void)
|
||||
int rlocs_update_key_context(struct rlocs *reg, struct rloc *x, struct rloc *y)
|
||||
{
|
||||
long err;
|
||||
char msg[256];
|
||||
struct key_context *entry = ®->key_contexts[x->context_id][y->context_id];
|
||||
|
||||
unsigned char secret[1024]; // Should be enough buffer space
|
||||
size_t secret_len = 1024;
|
||||
|
||||
while ( ( err = ERR_get_error() ) ) {
|
||||
ERR_error_string( err, &msg[0] );
|
||||
warn( "Error %lu in crypto: %s", err, &msg[0] );
|
||||
unsigned char secret_hash[SHA256_DIGEST_LENGTH];
|
||||
|
||||
EVP_PKEY_CTX *ctx = NULL;
|
||||
int result;
|
||||
|
||||
/* Create the context for the shared secret derivation */
|
||||
if( ( ctx = EVP_PKEY_CTX_new( x->key, NULL ) ) == NULL) {
|
||||
warn( "EVP_PKEY_CTX_new failed" );
|
||||
goto fail;
|
||||
|
||||
}
|
||||
|
||||
/* Initialise */
|
||||
if( ( result = EVP_PKEY_derive_init( ctx ) ) != 1 ) {
|
||||
warn( "EVP_PKEY_derive_init failed: %i", result );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Provide the peer public key */
|
||||
if( ( result = EVP_PKEY_derive_set_peer( ctx, y->key ) ) != 1 ) {
|
||||
warn( "EV_PKEY_derive_set_peer failed: %i", result );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Derive the shared secret */
|
||||
if( ( result = EVP_PKEY_derive( ctx, &secret[0], &secret_len ) ) != 1 ) {
|
||||
warn( "EVP_PKEY_derive failed: %i", result );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* SHA256 hash of the shared secret. TODO: Add a salt if we want one... */
|
||||
if ( !sha256sum( &secret[0], secret_len, secret_hash ) ) {
|
||||
warn( "SHA256( secret ) failed!" );
|
||||
goto fail;
|
||||
}
|
||||
memcpy( &entry->secret[0], &secret_hash[0], SHA256_DIGEST_LENGTH );
|
||||
|
||||
EVP_PKEY_CTX_free( ctx );
|
||||
|
||||
/* Now we finally have our secret key, we can set up an AES256
|
||||
* symmetric key cipher with it, which is what will be used to encrypt /
|
||||
* decrypt packet data. */
|
||||
|
||||
EVP_CIPHER_CTX_init( &entry->ctx );
|
||||
entry->in_use = 1;
|
||||
|
||||
return 1;
|
||||
|
||||
|
||||
fail:
|
||||
show_ssl_errors();
|
||||
if ( ctx != NULL) {
|
||||
EVP_PKEY_CTX_free( ctx );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t rloc_encrypt( struct rloc *rloc, unsigned char *data, size_t data_len, unsigned char *dest, size_t dest_len )
|
||||
{
|
||||
ssize_t result = RSA_public_encrypt( data_len, data, dest, rloc->key, RSA_PKCS1_OAEP_PADDING );
|
||||
|
||||
if ( result < 0 ) {
|
||||
show_ssl_errors();
|
||||
ssize_t rlocs_encrypt( struct rlocs *reg, struct rloc *x, struct rloc *y, unsigned char *data, size_t data_len, unsigned char *dest, size_t dest_len )
|
||||
{
|
||||
struct key_context *entry = ®->key_contexts[x->context_id][y->context_id];
|
||||
|
||||
if ( !entry->in_use && !rlocs_update_key_context( reg, x, y ) ) {
|
||||
warn( "Couldn't build an encryption context for these rlocs" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
return result;
|
||||
// FIXME: I don't know that this is good. It could be terrible.
|
||||
// We use a PRNG to generate an IV per message, and put it at the start of
|
||||
// the encrypted blob. Since we're using aes256 (hardcoded), IV is 128 bits
|
||||
if ( dest_len < 48 ) {
|
||||
warn( "dest_len must be at least 48 bytes, maybe more");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
unsigned char *iv = dest;
|
||||
unsigned char *secret = (unsigned char *)&entry->secret[0];
|
||||
size_t written = 16;
|
||||
int outl = dest_len - written;
|
||||
|
||||
RAND_pseudo_bytes( iv, 16 );
|
||||
|
||||
if ( !EVP_EncryptInit_ex( &entry->ctx, EVP_aes_256_cbc(), NULL, secret, iv ) ) {
|
||||
warn( "EVP_EncryptInit_ex() failed" );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ( !EVP_EncryptUpdate( &entry->ctx, dest + written, &outl, data, data_len ) ) {
|
||||
warn( "EVP_EncryptUpdate() failed" );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
written += outl;
|
||||
outl = dest_len - written;
|
||||
|
||||
if ( !EVP_EncryptFinal_ex( &entry->ctx, dest + written, &outl ) ) {
|
||||
warn( "EVP_EncryptFinal_ex() failed" );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return written + outl;
|
||||
|
||||
fail:
|
||||
show_ssl_errors();
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t rloc_decrypt( struct rloc *rloc, unsigned char *data, size_t data_len, unsigned char *dest, size_t dest_len )
|
||||
ssize_t rlocs_decrypt( struct rlocs *reg, struct rloc *x, struct rloc *y, unsigned char *data, size_t data_len, unsigned char *dest, size_t dest_len )
|
||||
{
|
||||
ssize_t result = RSA_private_decrypt( data_len, data, dest, rloc->key, RSA_PKCS1_OAEP_PADDING );
|
||||
|
||||
if ( result < 0 ) {
|
||||
show_ssl_errors();
|
||||
struct key_context *entry = ®->key_contexts[x->context_id][y->context_id];
|
||||
|
||||
if ( !entry->in_use && !rlocs_update_key_context( reg, x, y ) ) {
|
||||
warn( "Couldn't build a decryption context for these rlocs" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
return result;
|
||||
unsigned char *iv = data;
|
||||
unsigned char *secret = (unsigned char *)&entry->secret[0];
|
||||
size_t written = 0;
|
||||
int outl = dest_len;
|
||||
|
||||
if ( !EVP_DecryptInit_ex( &entry->ctx, EVP_aes_256_cbc(), NULL, secret, iv ) ) {
|
||||
warn( "EVP_DecrypttInit_ex() failed" );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ( !EVP_DecryptUpdate( &entry->ctx, dest, &outl, data, data_len ) ) {
|
||||
warn( "EVP_DecryptUpdate() failed" );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
written += outl;
|
||||
outl = dest_len - written;
|
||||
|
||||
if ( !EVP_DecryptFinal_ex( &entry->ctx, dest + written, &outl ) ) {
|
||||
warn( "EVP_DecryptFinal_ex() failed" );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return written + outl;
|
||||
|
||||
fail:
|
||||
show_ssl_errors();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -497,7 +665,7 @@ void rlocs_free( struct rlocs* registry )
|
||||
|
||||
for( i = 0; i < registry->num_entries; i++ ) {
|
||||
if ( registry->entries[i].key != NULL ) {
|
||||
RSA_free( registry->entries[i].key );
|
||||
EVP_PKEY_free( registry->entries[i].key );
|
||||
}
|
||||
}
|
||||
// No need to do json_object_put() here.
|
||||
|
@@ -1,15 +1,30 @@
|
||||
#ifndef _RLOCS_H_
|
||||
#define _RLOCS_H_
|
||||
|
||||
#include "util.h"
|
||||
|
||||
#include <json/json_object.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
// For now. We can dynamically allocate later.
|
||||
#define MAX_RLOCS 64
|
||||
#define MAX_EID_MAPPINGS 256
|
||||
|
||||
|
||||
struct key_context {
|
||||
int in_use;
|
||||
char secret[SHA256_DIGEST_LENGTH];
|
||||
EVP_CIPHER_CTX ctx;
|
||||
|
||||
/* Probably don't need these
|
||||
struct rloc *rloc_x;
|
||||
struct rloc *rloc_y;
|
||||
*/
|
||||
};
|
||||
|
||||
struct rloc {
|
||||
short family;
|
||||
union {
|
||||
@@ -17,7 +32,9 @@ struct rloc {
|
||||
struct in6_addr ip6;
|
||||
} addr;
|
||||
|
||||
RSA* key;
|
||||
EVP_PKEY *key;
|
||||
// We use this to index our rloc for shared keys
|
||||
int context_id;
|
||||
};
|
||||
|
||||
|
||||
@@ -36,7 +53,7 @@ struct ip6_eid_map_entry {
|
||||
};
|
||||
|
||||
struct rlocs {
|
||||
json_object* config;
|
||||
json_object *config;
|
||||
|
||||
size_t num_entries;
|
||||
struct rloc entries[MAX_RLOCS];
|
||||
@@ -46,6 +63,16 @@ struct rlocs {
|
||||
|
||||
size_t num_ip6_map_entries;
|
||||
struct ip6_eid_map_entry ip6_mappings[MAX_EID_MAPPINGS];
|
||||
|
||||
/* Don't do this, kids.
|
||||
* 2D array - [wrapping_rloc->id][unwrapping_rloc->id]
|
||||
* Obviously, half of the contexts would be identical. So some rules:
|
||||
* - if you're wrapping a packet, you are x. they are y
|
||||
* - if you're unwrapping a packet, you are y. they are x.
|
||||
* Half of the allocated memory goes unused, but we can worry about dynamic
|
||||
* allocation at the same time as MAX_RLOCS and MAX_EID_MAPPINGS
|
||||
*/
|
||||
struct key_context key_contexts[MAX_RLOCS][MAX_RLOCS];
|
||||
};
|
||||
|
||||
|
||||
@@ -62,8 +89,8 @@ int rloc_add_private_key( struct rloc *rloc, char *filename );
|
||||
void rlocs_debug_output( struct rlocs *reg );
|
||||
|
||||
/* Returns -1 on error, or number of bytes written */
|
||||
ssize_t rloc_encrypt( struct rloc *rloc, unsigned char *data, size_t data_len, unsigned char *dest, size_t dest_len );
|
||||
ssize_t rloc_decrypt( struct rloc *rloc, unsigned char *data, size_t data_len, unsigned char *dest, size_t dest_len );
|
||||
ssize_t rlocs_encrypt( struct rlocs *reg, struct rloc *x, struct rloc *y, unsigned char *data, size_t data_len, unsigned char *dest, size_t dest_len );
|
||||
ssize_t rlocs_decrypt( struct rlocs *reg, struct rloc *x, struct rloc *y, unsigned char *data, size_t data_len, unsigned char *dest, size_t dest_len );
|
||||
|
||||
void rlocs_free( struct rlocs *registry );
|
||||
|
||||
|
@@ -1,5 +1,4 @@
|
||||
#include "util.h"
|
||||
#include "rlocs.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
@@ -187,4 +186,22 @@ void session_teardown( struct session *session )
|
||||
if ( session->output_if >= 0 && !session->same_if ) {
|
||||
close( session->output_if );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO: we can speed this one up, if necessary, by re-using the context.
|
||||
// TODO: some error-checking
|
||||
int sha256sum( unsigned char *src, size_t src_len, unsigned char dst[SHA256_DIGEST_LENGTH] )
|
||||
{
|
||||
unsigned int size = SHA256_DIGEST_LENGTH;
|
||||
EVP_MD_CTX *ctx = EVP_MD_CTX_create();
|
||||
EVP_DigestInit_ex( ctx, EVP_sha256(), NULL );
|
||||
|
||||
|
||||
EVP_DigestUpdate( ctx, src, src_len );
|
||||
EVP_DigestFinal_ex( ctx, &dst[0], &size );
|
||||
EVP_MD_CTX_destroy( ctx );
|
||||
|
||||
|
||||
return size == SHA256_DIGEST_LENGTH;
|
||||
}
|
@@ -1,10 +1,14 @@
|
||||
#ifndef _UTIL_H_
|
||||
#define _UTIL_H
|
||||
#define _UTIL_H_
|
||||
|
||||
#include "rlocs.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#define info(msg, ...) { fprintf( stdout, msg, ##__VA_ARGS__ ) ; fprintf( stdout, "\n" ); }
|
||||
#define warn(msg, ...) { fprintf( stderr, msg, ##__VA_ARGS__ ) ; fprintf( stderr, "\n" ); }
|
||||
|
||||
@@ -31,6 +35,8 @@ int session_setup( struct session *session, char *config_file, char *listen_if,
|
||||
int session_upgrade_rlocs( struct session *session, int argc, char** args );
|
||||
void session_teardown( struct session *session );
|
||||
|
||||
int sha256sum( unsigned char *src, size_t src_len, unsigned char dst[SHA256_DIGEST_LENGTH] );
|
||||
|
||||
|
||||
|
||||
#endif
|
@@ -23,8 +23,8 @@ int main(int argc, char** argv)
|
||||
ssize_t count;
|
||||
int result;
|
||||
|
||||
if ( argc < 4 ) {
|
||||
warn( "Usage: %s <rloc database> <listen_ifname> <output_ifname>", argv[0] );
|
||||
if ( argc < 6 ) {
|
||||
warn( "Usage: %s <rloc database> <listen_ifname> <output_ifname> <rloc> <keyfile> [<rloc> <keyfile>]n", argv[0] );
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user