#include "system.h"
#include "splay_tree.h"
+#include "cipher.h"
#include "conf.h"
#include "list.h"
#include "logger.h"
if(c->hostname)
free(c->hostname);
- if(c->inkey)
- free(c->inkey);
-
- if(c->outkey)
- free(c->outkey);
-
- if(c->mychallenge)
- free(c->mychallenge);
+ cipher_close(&c->incipher);
+ cipher_close(&c->outcipher);
if(c->hischallenge)
free(c->hischallenge);
#ifndef __TINC_CONNECTION_H__
#define __TINC_CONNECTION_H__
-#include <openssl/rsa.h>
-#include <openssl/evp.h>
-
#include <event.h>
+#include "cipher.h"
+#include "digest.h"
+#include "rsa.h"
#include "splay_tree.h"
#define OPTION_INDIRECT 0x0001
struct node_t *node; /* node associated with the other end */
struct edge_t *edge; /* edge associated with this connection */
- RSA *rsa_key; /* his public/private key */
- const EVP_CIPHER *incipher; /* Cipher he will use to send data to us */
- const EVP_CIPHER *outcipher; /* Cipher we will use to send data to him */
- EVP_CIPHER_CTX *inctx; /* Context of encrypted meta data that will come from him to us */
- EVP_CIPHER_CTX *outctx; /* Context of encrypted meta data that will be sent from us to him */
- char *inkey; /* His symmetric meta key + iv */
- char *outkey; /* Our symmetric meta key + iv */
- int inkeylength; /* Length of his key + iv */
- int outkeylength; /* Length of our key + iv */
- const EVP_MD *indigest;
- const EVP_MD *outdigest;
+ rsa_t rsa; /* his public/private key */
+ cipher_t incipher; /* Cipher he will use to send data to us */
+ cipher_t outcipher; /* Cipher we will use to send data to him */
+ digest_t indigest;
+ digest_t outdigest;
+
int inmaclength;
int outmaclength;
int incompression;
int outcompression;
- char *mychallenge; /* challenge we received from him */
- char *hischallenge; /* challenge we sent to him */
+
+ char *hischallenge; /* The challenge we sent to him */
struct bufferevent *buffer; /* buffer events on this metadata connection */
struct event inevent; /* input event on this metadata connection */
#include "system.h"
-#include <openssl/err.h>
-#include <openssl/evp.h>
-
#include "splay_tree.h"
+#include "cipher.h"
#include "connection.h"
#include "logger.h"
#include "meta.h"
#include "xalloc.h"
bool send_meta(connection_t *c, const char *buffer, int length) {
- int outlen;
- int result;
cp();
ifdebug(META) logger(LOG_DEBUG, _("Sending %d bytes of metadata to %s (%s)"), length,
/* Add our data to buffer */
if(c->status.encryptout) {
char outbuf[length];
+ size_t outlen = length;
- result = EVP_EncryptUpdate(c->outctx, (unsigned char *)outbuf, &outlen, (unsigned char *)buffer, length);
- if(!result || outlen != length) {
- logger(LOG_ERR, _("Error while encrypting metadata to %s (%s): %s"),
- c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL));
+ if(!cipher_encrypt(&c->outcipher, buffer, length, outbuf, &outlen, false) || outlen != length) {
+ logger(LOG_ERR, _("Error while encrypting metadata to %s (%s)"),
+ c->name, c->hostname);
return false;
}
}
bool receive_meta(connection_t *c) {
- int result, inlen, outlen;
+ size_t inlen;
char inbuf[MAXBUFSIZE];
char *bufp = inbuf, *endp;
inlen -= endp - bufp;
bufp = endp;
} else {
+ size_t outlen = inlen;
ifdebug(META) logger(LOG_DEBUG, _("Received encrypted %d bytes"), inlen);
evbuffer_expand(c->buffer->input, c->buffer->input->off + inlen);
- result = EVP_DecryptUpdate(c->inctx, (unsigned char *)c->buffer->input->buffer + c->buffer->input->off, &outlen, (unsigned char *)bufp, inlen);
- if(!result || outlen != inlen) {
- logger(LOG_ERR, _("Error while decrypting metadata from %s (%s): %s"),
- c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL));
+
+ if(!cipher_decrypt(&c->incipher, bufp, inlen, c->buffer->input->buffer + c->buffer->input->off, &outlen, false) || inlen != outlen) {
+ logger(LOG_ERR, _("Error while decrypting metadata from %s (%s)"),
+ c->name, c->hostname);
return false;
}
c->buffer->input->off += inlen;
char *request = evbuffer_readline(c->buffer->input);
if(request) {
- receive_request(c, request);
+ bool result = receive_request(c, request);
free(request);
+ if(!result)
+ return false;
continue;
} else {
break;
#include "system.h"
-#include <openssl/rand.h>
-#include <openssl/err.h>
-#include <openssl/evp.h>
-#include <openssl/pem.h>
-#include <openssl/hmac.h>
-
#include <zlib.h>
#include LZO1X_H
#include "splay_tree.h"
+#include "cipher.h"
#include "conf.h"
#include "connection.h"
+#include "crypto.h"
+#include "digest.h"
#include "device.h"
#include "ethernet.h"
#include "graph.h"
#endif
int keylifetime = 0;
-EVP_CIPHER_CTX packet_ctx;
static char lzo_wrkmem[LZO1X_999_MEM_COMPRESS > LZO1X_1_MEM_COMPRESS ? LZO1X_999_MEM_COMPRESS : LZO1X_1_MEM_COMPRESS];
static void send_udppacket(node_t *, vpn_packet_t *);
len = 64;
memset(packet.data, 0, 14);
- RAND_pseudo_bytes(packet.data + 14, len - 14);
+ randomize(packet.data + 14, len - 14);
packet.len = len;
ifdebug(TRAFFIC) logger(LOG_INFO, _("Sending MTU probe length %d to %s (%s)"), len, n->name, n->hostname);
vpn_packet_t *pkt[] = { &pkt1, &pkt2, &pkt1, &pkt2 };
int nextpkt = 0;
vpn_packet_t *outpkt = pkt[0];
- int outlen, outpad;
- unsigned char hmac[EVP_MAX_MD_SIZE];
+ size_t outlen;
int i;
cp();
/* Check packet length */
- if(inpkt->len < sizeof(inpkt->seqno) + myself->maclength) {
+ if(inpkt->len < sizeof(inpkt->seqno) + digest_length(&myself->digest)) {
ifdebug(TRAFFIC) logger(LOG_DEBUG, _("Got too short packet from %s (%s)"),
n->name, n->hostname);
return;
/* Check the message authentication code */
- if(myself->digest && myself->maclength) {
- inpkt->len -= myself->maclength;
- HMAC(myself->digest, myself->key, myself->keylength,
- (unsigned char *) &inpkt->seqno, inpkt->len, (unsigned char *)hmac, NULL);
-
- if(memcmp(hmac, (char *) &inpkt->seqno + inpkt->len, myself->maclength)) {
- ifdebug(TRAFFIC) logger(LOG_DEBUG, _("Got unauthenticated packet from %s (%s)"),
- n->name, n->hostname);
- return;
- }
+ if(digest_active(&myself->digest) && !digest_verify(&myself->digest, &inpkt->seqno, inpkt->len, &inpkt->seqno + inpkt->len)) {
+ ifdebug(TRAFFIC) logger(LOG_DEBUG, _("Got unauthenticated packet from %s (%s)"), n->name, n->hostname);
+ return;
}
/* Decrypt the packet */
- if(myself->cipher) {
+ if(cipher_active(&myself->cipher)) {
outpkt = pkt[nextpkt++];
+ outlen = MAXSIZE;
- if(!EVP_DecryptInit_ex(&packet_ctx, NULL, NULL, NULL, NULL)
- || !EVP_DecryptUpdate(&packet_ctx, (unsigned char *) &outpkt->seqno, &outlen,
- (unsigned char *) &inpkt->seqno, inpkt->len)
- || !EVP_DecryptFinal_ex(&packet_ctx, (unsigned char *) &outpkt->seqno + outlen, &outpad)) {
- ifdebug(TRAFFIC) logger(LOG_DEBUG, _("Error decrypting packet from %s (%s): %s"),
- n->name, n->hostname, ERR_error_string(ERR_get_error(), NULL));
+ if(!cipher_decrypt(&myself->cipher, &inpkt->seqno, inpkt->len, &outpkt->seqno, &outlen, true)) {
+ ifdebug(TRAFFIC) logger(LOG_DEBUG, _("Error decrypting packet from %s (%s)"), n->name, n->hostname);
return;
}
- outpkt->len = outlen + outpad;
+ outpkt->len = outlen;
inpkt = outpkt;
}
int nextpkt = 0;
vpn_packet_t *outpkt;
int origlen;
- int outlen, outpad;
+ size_t outlen;
vpn_packet_t *copy;
static int priority = 0;
int origpriority;
/* Encrypt the packet */
- if(n->cipher) {
+ if(cipher_active(&n->cipher)) {
outpkt = pkt[nextpkt++];
+ outlen = MAXSIZE;
- if(!EVP_EncryptInit_ex(&n->packet_ctx, NULL, NULL, NULL, NULL)
- || !EVP_EncryptUpdate(&n->packet_ctx, (unsigned char *) &outpkt->seqno, &outlen,
- (unsigned char *) &inpkt->seqno, inpkt->len)
- || !EVP_EncryptFinal_ex(&n->packet_ctx, (unsigned char *) &outpkt->seqno + outlen, &outpad)) {
- ifdebug(TRAFFIC) logger(LOG_ERR, _("Error while encrypting packet to %s (%s): %s"),
- n->name, n->hostname, ERR_error_string(ERR_get_error(), NULL));
+ if(!cipher_encrypt(&n->cipher, &inpkt->seqno, inpkt->len, &outpkt->seqno, &outlen, true)) {
+ ifdebug(TRAFFIC) logger(LOG_ERR, _("Error while encrypting packet to %s (%s)"), n->name, n->hostname);
goto end;
}
- outpkt->len = outlen + outpad;
+ outpkt->len = outlen;
inpkt = outpkt;
}
/* Add the message authentication code */
- if(n->digest && n->maclength) {
- HMAC(n->digest, n->key, n->keylength, (unsigned char *) &inpkt->seqno,
- inpkt->len, (unsigned char *) &inpkt->seqno + inpkt->len, NULL);
- inpkt->len += n->maclength;
+ if(digest_active(&n->digest)) {
+ digest_create(&n->digest, &inpkt->seqno, inpkt->len, &inpkt->seqno + inpkt->len);
+ inpkt->len += digest_length(&n->digest);
}
/* Determine which socket we have to use */
#include "system.h"
-#include <openssl/pem.h>
-#include <openssl/rsa.h>
-#include <openssl/rand.h>
-#include <openssl/err.h>
-#include <openssl/evp.h>
-
#include "splay_tree.h"
+#include "cipher.h"
#include "conf.h"
#include "connection.h"
#include "control.h"
#include "device.h"
+#include "digest.h"
#include "graph.h"
#include "logger.h"
#include "net.h"
#include "process.h"
#include "protocol.h"
#include "route.h"
+#include "rsa.h"
#include "subnet.h"
#include "utils.h"
#include "xalloc.h"
bool read_rsa_public_key(connection_t *c) {
FILE *fp;
char *fname;
- char *key;
+ char *n;
+ bool result;
cp();
- if(!c->rsa_key) {
- c->rsa_key = RSA_new();
-// RSA_blinding_on(c->rsa_key, NULL);
- }
-
/* First, check for simple PublicKey statement */
- if(get_config_string(lookup_config(c->config_tree, "PublicKey"), &key)) {
- BN_hex2bn(&c->rsa_key->n, key);
- BN_hex2bn(&c->rsa_key->e, "FFFF");
- free(key);
- return true;
+ if(get_config_string(lookup_config(c->config_tree, "PublicKey"), &n)) {
+ result = rsa_set_hex_public_key(&c->rsa, n, "FFFF");
+ free(n);
+ return result;
}
/* Else, check for PublicKeyFile statement and read it */
- if(get_config_string(lookup_config(c->config_tree, "PublicKeyFile"), &fname)) {
- fp = fopen(fname, "r");
-
- if(!fp) {
- logger(LOG_ERR, _("Error reading RSA public key file `%s': %s"),
- fname, strerror(errno));
- free(fname);
- return false;
- }
-
- free(fname);
- c->rsa_key = PEM_read_RSAPublicKey(fp, &c->rsa_key, NULL, NULL);
- fclose(fp);
-
- if(c->rsa_key)
- return true; /* Woohoo. */
+ if(!get_config_string(lookup_config(c->config_tree, "PublicKeyFile"), &fname))
+ asprintf(&fname, "%s/hosts/%s", confbase, c->name);
- /* If it fails, try PEM_read_RSA_PUBKEY. */
- fp = fopen(fname, "r");
-
- if(!fp) {
- logger(LOG_ERR, _("Error reading RSA public key file `%s': %s"),
- fname, strerror(errno));
- free(fname);
- return false;
- }
-
- free(fname);
- c->rsa_key = PEM_read_RSA_PUBKEY(fp, &c->rsa_key, NULL, NULL);
- fclose(fp);
-
- if(c->rsa_key) {
-// RSA_blinding_on(c->rsa_key, NULL);
- return true;
- }
+ fp = fopen(fname, "r");
- logger(LOG_ERR, _("Reading RSA public key file `%s' failed: %s"),
+ if(!fp) {
+ logger(LOG_ERR, _("Error reading RSA public key file `%s': %s"),
fname, strerror(errno));
+ free(fname);
return false;
}
- /* Else, check if a harnessed public key is in the config file */
-
- asprintf(&fname, "%s/hosts/%s", confbase, c->name);
- fp = fopen(fname, "r");
-
- if(fp) {
- c->rsa_key = PEM_read_RSAPublicKey(fp, &c->rsa_key, NULL, NULL);
- fclose(fp);
- }
-
- free(fname);
-
- if(c->rsa_key)
- return true;
-
- /* Try again with PEM_read_RSA_PUBKEY. */
-
- asprintf(&fname, "%s/hosts/%s", confbase, c->name);
- fp = fopen(fname, "r");
-
- if(fp) {
- c->rsa_key = PEM_read_RSA_PUBKEY(fp, &c->rsa_key, NULL, NULL);
-// RSA_blinding_on(c->rsa_key, NULL);
- fclose(fp);
- }
+ result = rsa_read_pem_public_key(&c->rsa, fp);
+ fclose(fp);
+ if(!result)
+ logger(LOG_ERR, _("Reading RSA public key file `%s' failed: %s"), fname, strerror(errno));
free(fname);
-
- if(c->rsa_key)
- return true;
-
- logger(LOG_ERR, _("No public key for %s specified!"), c->name);
-
- return false;
+ return result;
}
-bool read_rsa_private_key(void) {
+bool read_rsa_private_key() {
FILE *fp;
- char *fname, *key, *pubkey;
- struct stat s;
+ char *fname;
+ char *n, *d;
+ bool result;
cp();
- if(get_config_string(lookup_config(config_tree, "PrivateKey"), &key)) {
- if(!get_config_string(lookup_config(myself->connection->config_tree, "PublicKey"), &pubkey)) {
+ /* First, check for simple PrivateKey statement */
+
+ if(get_config_string(lookup_config(config_tree, "PrivateKey"), &d)) {
+ if(!get_config_string(lookup_config(myself->connection->config_tree, "PublicKey"), &n)) {
logger(LOG_ERR, _("PrivateKey used but no PublicKey found!"));
+ free(d);
return false;
}
- myself->connection->rsa_key = RSA_new();
-// RSA_blinding_on(myself->connection->rsa_key, NULL);
- BN_hex2bn(&myself->connection->rsa_key->d, key);
- BN_hex2bn(&myself->connection->rsa_key->n, pubkey);
- BN_hex2bn(&myself->connection->rsa_key->e, "FFFF");
- free(key);
- free(pubkey);
+ result = rsa_set_hex_private_key(&myself->connection->rsa, n, "FFFF", d);
+ free(n);
+ free(d);
return true;
}
+ /* Else, check for PrivateKeyFile statement and read it */
+
if(!get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &fname))
asprintf(&fname, "%s/rsa_key.priv", confbase);
}
#if !defined(HAVE_MINGW) && !defined(HAVE_CYGWIN)
+ struct stat s;
+
if(fstat(fileno(fp), &s)) {
- logger(LOG_ERR, _("Could not stat RSA private key file `%s': %s'"),
- fname, strerror(errno));
+ logger(LOG_ERR, _("Could not stat RSA private key file `%s': %s'"), fname, strerror(errno));
free(fname);
return false;
}
logger(LOG_WARNING, _("Warning: insecure file permissions for RSA private key file `%s'!"), fname);
#endif
- myself->connection->rsa_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
+ result = rsa_read_pem_private_key(&myself->connection->rsa, fp);
fclose(fp);
- if(!myself->connection->rsa_key) {
- logger(LOG_ERR, _("Reading RSA private key file `%s' failed: %s"),
- fname, strerror(errno));
- free(fname);
- return false;
- }
-
+ if(!result)
+ logger(LOG_ERR, _("Reading RSA private key file `%s' failed: %s"), fname, strerror(errno));
free(fname);
- return true;
+ return result;
}
static struct event keyexpire_event;
}
void regenerate_key() {
- RAND_pseudo_bytes((unsigned char *)myself->key, myself->keylength);
+ ifdebug(STATUS) logger(LOG_INFO, _("Regenerating symmetric key"));
+
+ if(!cipher_regenerate_key(&myself->cipher, true)) {
+ logger(LOG_ERR, _("Error regenerating key!"));
+ abort();
+ }
if(timeout_initialized(&keyexpire_event)) {
- ifdebug(STATUS) logger(LOG_INFO, _("Regenerating symmetric key"));
event_del(&keyexpire_event);
send_key_changed(broadcast, myself);
} else {
}
event_add(&keyexpire_event, &(struct timeval){keylifetime, 0});
-
- if(myself->cipher) {
- EVP_CIPHER_CTX_init(&packet_ctx);
- if(!EVP_DecryptInit_ex(&packet_ctx, myself->cipher, NULL, (unsigned char *)myself->key, (unsigned char *)myself->key + myself->cipher->key_len)) {
- logger(LOG_ERR, _("Error during initialisation of cipher for %s (%s): %s"),
- myself->name, myself->hostname, ERR_error_string(ERR_get_error(), NULL));
- abort();
- }
-
- }
}
/*
/* Generate packet encryption key */
- if(get_config_string
- (lookup_config(myself->connection->config_tree, "Cipher"), &cipher)) {
- if(!strcasecmp(cipher, "none")) {
- myself->cipher = NULL;
- } else {
- myself->cipher = EVP_get_cipherbyname(cipher);
-
- if(!myself->cipher) {
- logger(LOG_ERR, _("Unrecognized cipher type!"));
- return false;
- }
- }
- } else
- myself->cipher = EVP_bf_cbc();
-
- if(myself->cipher)
- myself->keylength = myself->cipher->key_len + myself->cipher->iv_len;
- else
- myself->keylength = 1;
-
- myself->connection->outcipher = EVP_bf_ofb();
+ if(!get_config_string(lookup_config(myself->connection->config_tree, "Cipher"), &cipher))
+ cipher = xstrdup("blowfish");
- myself->key = xmalloc(myself->keylength);
+ if(!cipher_open_by_name(&myself->cipher, cipher)) {
+ logger(LOG_ERR, _("Unrecognized cipher type!"));
+ return false;
+ }
if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime))
keylifetime = 3600;
regenerate_key();
+
/* Check if we want to use message authentication codes... */
- if(get_config_string
- (lookup_config(myself->connection->config_tree, "Digest"), &digest)) {
- if(!strcasecmp(digest, "none")) {
- myself->digest = NULL;
- } else {
- myself->digest = EVP_get_digestbyname(digest);
-
- if(!myself->digest) {
- logger(LOG_ERR, _("Unrecognized digest type!"));
- return false;
- }
- }
- } else
- myself->digest = EVP_sha1();
-
- myself->connection->outdigest = EVP_sha1();
-
- if(get_config_int(lookup_config(myself->connection->config_tree, "MACLength"),
- &myself->maclength)) {
- if(myself->digest) {
- if(myself->maclength > myself->digest->md_size) {
- logger(LOG_ERR, _("MAC length exceeds size of digest!"));
- return false;
- } else if(myself->maclength < 0) {
- logger(LOG_ERR, _("Bogus MAC length!"));
- return false;
- }
- }
- } else
- myself->maclength = 4;
+ if(!get_config_string(lookup_config(myself->connection->config_tree, "Digest"), &digest))
+ digest = xstrdup("sha1");
- myself->connection->outmaclength = 0;
+ if(!digest_open_by_name(&myself->digest, digest)) {
+ logger(LOG_ERR, _("Unrecognized digest type!"));
+ return false;
+ }
+
+ if(!get_config_int(lookup_config(myself->connection->config_tree, "MACLength"), &myself->maclength))
+
+ if(digest_active(&myself->digest)) {
+ if(myself->maclength > digest_length(&myself->digest)) {
+ logger(LOG_ERR, _("MAC length exceeds size of digest!"));
+ return false;
+ } else if(myself->maclength < 0) {
+ logger(LOG_ERR, _("Bogus MAC length!"));
+ return false;
+ }
+ }
/* Compression */
- if(get_config_int(lookup_config(myself->connection->config_tree, "Compression"),
- &myself->compression)) {
+ if(get_config_int(lookup_config(myself->connection->config_tree, "Compression"), &myself->compression)) {
if(myself->compression < 0 || myself->compression > 11) {
logger(LOG_ERR, _("Bogus compression level!"));
return false;
if(!setup_device())
return false;
- event_set(&device_ev, device_fd, EV_READ|EV_PERSIST,
- handle_device_data, NULL);
+ event_set(&device_ev, device_fd, EV_READ|EV_PERSIST, handle_device_data, NULL);
+
if (event_add(&device_ev, NULL) < 0) {
logger(LOG_ERR, _("event_add failed: %s"), strerror(errno));
close_device();
n->subnet_tree = new_subnet_tree();
n->edge_tree = new_edge_tree();
n->queue = list_alloc((list_action_t) free);
- EVP_CIPHER_CTX_init(&n->packet_ctx);
n->mtu = MTU;
n->maxmtu = MTU;
if(n->queue)
list_delete_list(n->queue);
- if(n->key)
- free(n->key);
-
if(n->subnet_tree)
free_subnet_tree(n->subnet_tree);
sockaddrfree(&n->address);
- EVP_CIPHER_CTX_cleanup(&n->packet_ctx);
+ cipher_close(&n->cipher);
+ digest_close(&n->digest);
event_del(&n->mtuevent);
for(node = node_tree->head; node; node = node->next) {
n = node->data;
if(evbuffer_add_printf(out, _(" %s at %s cipher %d digest %d maclength %d compression %d options %lx status %04x nexthop %s via %s pmtu %d (min %d max %d)\n"),
- n->name, n->hostname, n->cipher ? n->cipher->nid : 0,
- n->digest ? n->digest->type : 0, n->maclength, n->compression,
+ n->name, n->hostname, cipher_get_nid(&n->cipher),
+ digest_get_nid(&n->digest), n->maclength, n->compression,
n->options, *(uint32_t *)&n->status, n->nexthop ? n->nexthop->name : "-",
n->via ? n->via->name : "-", n->mtu, n->minmtu, n->maxmtu) == -1)
return errno;
#define __TINC_NODE_H__
#include "splay_tree.h"
+#include "cipher.h"
#include "connection.h"
+#include "digest.h"
#include "list.h"
#include "subnet.h"
node_status_t status;
- const EVP_CIPHER *cipher; /* Cipher type for UDP packets */
- char *key; /* Cipher key and iv */
- int keylength; /* Cipher key and iv length */
- EVP_CIPHER_CTX packet_ctx; /* Cipher context */
-
- const EVP_MD *digest; /* Digest type for MAC */
- int maclength; /* Length of MAC */
+ cipher_t cipher; /* Cipher for UDP packets */
+ digest_t digest; /* Digest for UDP packets */
+ int maclength; /* Portion of digest to use */
int compression; /* Compressionlevel, 0 = no compression */
#include "system.h"
-#include <openssl/sha.h>
-#include <openssl/rand.h>
-#include <openssl/err.h>
-#include <openssl/evp.h>
-
#include "splay_tree.h"
#include "conf.h"
#include "connection.h"
+#include "crypto.h"
#include "edge.h"
#include "graph.h"
#include "logger.h"
#include "netutl.h"
#include "node.h"
#include "protocol.h"
+#include "rsa.h"
#include "utils.h"
#include "xalloc.h"
}
bool send_metakey(connection_t *c) {
- char *buffer;
- int len;
- bool x;
+ size_t len = rsa_size(&c->rsa);
+ char key[len];
+ char enckey[len];
+ char hexkey[2 * len + 1];
cp();
- len = RSA_size(c->rsa_key);
-
- /* Allocate buffers for the meta key */
-
- buffer = alloca(2 * len + 1);
+ if(!cipher_open_blowfish_ofb(&c->outcipher))
+ return false;
- if(!c->outkey)
- c->outkey = xmalloc(len);
+ if(!digest_open_sha1(&c->outdigest))
+ return false;
- if(!c->outctx)
- c->outctx = xmalloc_and_zero(sizeof(*c->outctx));
- cp();
- /* Copy random data to the buffer */
+ /* Create a random key */
- RAND_pseudo_bytes((unsigned char *)c->outkey, len);
+ randomize(key, len);
/* The message we send must be smaller than the modulus of the RSA key.
By definition, for a key of k bits, the following formula holds:
This can be done by setting the most significant bit to zero.
*/
- c->outkey[0] &= 0x7F;
+ key[0] &= 0x7F;
+
+ cipher_set_key_from_rsa(&c->outcipher, key, len, true);
ifdebug(SCARY_THINGS) {
- bin2hex(c->outkey, buffer, len);
- buffer[len * 2] = '\0';
- logger(LOG_DEBUG, _("Generated random meta key (unencrypted): %s"),
- buffer);
+ bin2hex(key, hexkey, len);
+ hexkey[len * 2] = '\0';
+ logger(LOG_DEBUG, _("Generated random meta key (unencrypted): %s"), hexkey);
}
/* Encrypt the random data
with a length equal to that of the modulus of the RSA key.
*/
- if(RSA_public_encrypt(len, (unsigned char *)c->outkey, (unsigned char *)buffer, c->rsa_key, RSA_NO_PADDING) != len) {
- logger(LOG_ERR, _("Error during encryption of meta key for %s (%s)"),
- c->name, c->hostname);
+ if(!rsa_public_encrypt(&c->rsa, key, len, enckey)) {
+ logger(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), c->name, c->hostname);
return false;
}
/* Convert the encrypted random data to a hexadecimal formatted string */
- bin2hex(buffer, buffer, len);
- buffer[len * 2] = '\0';
+ bin2hex(enckey, hexkey, len);
+ hexkey[len * 2] = '\0';
/* Send the meta key */
- x = send_request(c, "%d %d %d %d %d %s", METAKEY,
- c->outcipher ? c->outcipher->nid : 0,
- c->outdigest ? c->outdigest->type : 0, c->outmaclength,
- c->outcompression, buffer);
-
- /* Further outgoing requests are encrypted with the key we just generated */
-
- if(c->outcipher) {
- if(!EVP_EncryptInit(c->outctx, c->outcipher,
- (unsigned char *)c->outkey + len - c->outcipher->key_len,
- (unsigned char *)c->outkey + len - c->outcipher->key_len -
- c->outcipher->iv_len)) {
- logger(LOG_ERR, _("Error during initialisation of cipher for %s (%s): %s"),
- c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL));
- return false;
- }
-
- c->status.encryptout = true;
- }
-
- return x;
+ bool result = send_request(c, "%d %d %d %d %d %s", METAKEY,
+ cipher_get_nid(&c->outcipher),
+ digest_get_nid(&c->outdigest), c->outmaclength,
+ c->outcompression, hexkey);
+
+ c->status.encryptout = true;
+ return result;
}
bool metakey_h(connection_t *c, char *request) {
- char buffer[MAX_STRING_SIZE];
+ char hexkey[MAX_STRING_SIZE];
int cipher, digest, maclength, compression;
- int len;
+ size_t len = rsa_size(&myself->connection->rsa);
+ char enckey[len];
+ char key[len];
cp();
- if(sscanf(request, "%*d %d %d %d %d " MAX_STRING, &cipher, &digest, &maclength, &compression, buffer) != 5) {
- logger(LOG_ERR, _("Got bad %s from %s (%s)"), "METAKEY", c->name,
- c->hostname);
+ if(sscanf(request, "%*d %d %d %d %d " MAX_STRING, &cipher, &digest, &maclength, &compression, hexkey) != 5) {
+ logger(LOG_ERR, _("Got bad %s from %s (%s)"), "METAKEY", c->name, c->hostname);
return false;
}
- len = RSA_size(myself->connection->rsa_key);
-
/* Check if the length of the meta key is all right */
- if(strlen(buffer) != len * 2) {
+ if(strlen(hexkey) != len * 2) {
logger(LOG_ERR, _("Possible intruder %s (%s): %s"), c->name, c->hostname, "wrong keylength");
return false;
}
- /* Allocate buffers for the meta key */
-
- if(!c->inkey)
- c->inkey = xmalloc(len);
-
- if(!c->inctx)
- c->inctx = xmalloc_and_zero(sizeof(*c->inctx));
-
/* Convert the challenge from hexadecimal back to binary */
- hex2bin(buffer, buffer, len);
+ hex2bin(hexkey, enckey, len);
/* Decrypt the meta key */
- if(RSA_private_decrypt(len, (unsigned char *)buffer, (unsigned char *)c->inkey, myself->connection->rsa_key, RSA_NO_PADDING) != len) { /* See challenge() */
- logger(LOG_ERR, _("Error during encryption of meta key for %s (%s)"),
- c->name, c->hostname);
+ if(!rsa_private_decrypt(&myself->connection->rsa, enckey, len, key)) {
+ logger(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), c->name, c->hostname);
return false;
}
ifdebug(SCARY_THINGS) {
- bin2hex(c->inkey, buffer, len);
- buffer[len * 2] = '\0';
- logger(LOG_DEBUG, _("Received random meta key (unencrypted): %s"), buffer);
+ bin2hex(key, hexkey, len);
+ hexkey[len * 2] = '\0';
+ logger(LOG_DEBUG, _("Received random meta key (unencrypted): %s"), hexkey);
}
- /* All incoming requests will now be encrypted. */
-
/* Check and lookup cipher and digest algorithms */
- if(cipher) {
- c->incipher = EVP_get_cipherbynid(cipher);
-
- if(!c->incipher) {
- logger(LOG_ERR, _("%s (%s) uses unknown cipher!"), c->name, c->hostname);
- return false;
- }
-
- if(!EVP_DecryptInit(c->inctx, c->incipher,
- (unsigned char *)c->inkey + len - c->incipher->key_len,
- (unsigned char *)c->inkey + len - c->incipher->key_len -
- c->incipher->iv_len)) {
- logger(LOG_ERR, _("Error during initialisation of cipher from %s (%s): %s"),
- c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL));
- return false;
- }
-
- c->status.decryptin = true;
- } else {
- c->incipher = NULL;
+ if(!cipher_open_by_nid(&c->incipher, cipher) || !cipher_set_key_from_rsa(&c->incipher, key, len, false)) {
+ logger(LOG_ERR, _("Error during initialisation of cipher from %s (%s)"), c->name, c->hostname);
+ return false;
}
- c->inmaclength = maclength;
-
- if(digest) {
- c->indigest = EVP_get_digestbynid(digest);
-
- if(!c->indigest) {
- logger(LOG_ERR, _("Node %s (%s) uses unknown digest!"), c->name, c->hostname);
- return false;
- }
-
- if(c->inmaclength > c->indigest->md_size || c->inmaclength < 0) {
- logger(LOG_ERR, _("%s (%s) uses bogus MAC length!"), c->name, c->hostname);
- return false;
- }
- } else {
- c->indigest = NULL;
+ if(!digest_open_by_nid(&c->indigest, digest)) {
+ logger(LOG_ERR, _("Error during initialisation of digest from %s (%s)"), c->name, c->hostname);
+ return false;
}
- c->incompression = compression;
+ c->status.decryptin = true;
c->allow_request = CHALLENGE;
}
bool send_challenge(connection_t *c) {
- char *buffer;
- int len;
+ size_t len = rsa_size(&c->rsa);
+ char buffer[len * 2 + 1];
cp();
- /* CHECKME: what is most reasonable value for len? */
-
- len = RSA_size(c->rsa_key);
-
- /* Allocate buffers for the challenge */
-
- buffer = alloca(2 * len + 1);
-
if(!c->hischallenge)
c->hischallenge = xmalloc(len);
/* Copy random data to the buffer */
- RAND_pseudo_bytes((unsigned char *)c->hischallenge, len);
+ randomize(c->hischallenge, len);
/* Convert to hex */
bool challenge_h(connection_t *c, char *request) {
char buffer[MAX_STRING_SIZE];
- int len;
+ size_t len = rsa_size(&myself->connection->rsa);
+ size_t digestlen = digest_length(&c->outdigest);
+ char digest[digestlen];
cp();
if(sscanf(request, "%*d " MAX_STRING, buffer) != 1) {
- logger(LOG_ERR, _("Got bad %s from %s (%s)"), "CHALLENGE", c->name,
- c->hostname);
+ logger(LOG_ERR, _("Got bad %s from %s (%s)"), "CHALLENGE", c->name, c->hostname);
return false;
}
- len = RSA_size(myself->connection->rsa_key);
-
/* Check if the length of the challenge is all right */
if(strlen(buffer) != len * 2) {
- logger(LOG_ERR, _("Possible intruder %s (%s): %s"), c->name,
- c->hostname, "wrong challenge length");
+ logger(LOG_ERR, _("Possible intruder %s (%s): %s"), c->name, c->hostname, "wrong challenge length");
return false;
}
- /* Allocate buffers for the challenge */
-
- if(!c->mychallenge)
- c->mychallenge = xmalloc(len);
-
/* Convert the challenge from hexadecimal back to binary */
- hex2bin(buffer, c->mychallenge, len);
+ hex2bin(buffer, buffer, len);
c->allow_request = CHAL_REPLY;
- /* Rest is done by send_chal_reply() */
-
- return send_chal_reply(c);
-}
-
-bool send_chal_reply(connection_t *c) {
- char hash[EVP_MAX_MD_SIZE * 2 + 1];
- EVP_MD_CTX ctx;
-
cp();
/* Calculate the hash from the challenge we received */
- if(!EVP_DigestInit(&ctx, c->indigest)
- || !EVP_DigestUpdate(&ctx, c->mychallenge, RSA_size(myself->connection->rsa_key))
- || !EVP_DigestFinal(&ctx, (unsigned char *)hash, NULL)) {
- logger(LOG_ERR, _("Error during calculation of response for %s (%s): %s"),
- c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL));
- return false;
- }
+ digest_create(&c->indigest, buffer, len, digest);
/* Convert the hash to a hexadecimal formatted string */
- bin2hex(hash, hash, c->indigest->md_size);
- hash[c->indigest->md_size * 2] = '\0';
+ bin2hex(digest, buffer, digestlen);
+ buffer[digestlen * 2] = '\0';
/* Send the reply */
- return send_request(c, "%d %s", CHAL_REPLY, hash);
+ return send_request(c, "%d %s", CHAL_REPLY, buffer);
}
bool chal_reply_h(connection_t *c, char *request) {
char hishash[MAX_STRING_SIZE];
- char myhash[EVP_MAX_MD_SIZE];
- EVP_MD_CTX ctx;
cp();
/* Check if the length of the hash is all right */
- if(strlen(hishash) != c->outdigest->md_size * 2) {
- logger(LOG_ERR, _("Possible intruder %s (%s): %s"), c->name,
- c->hostname, _("wrong challenge reply length"));
+ if(strlen(hishash) != digest_length(&c->outdigest) * 2) {
+ logger(LOG_ERR, _("Possible intruder %s (%s): %s"), c->name, c->hostname, _("wrong challenge reply length"));
return false;
}
/* Convert the hash to binary format */
- hex2bin(hishash, hishash, c->outdigest->md_size);
-
- /* Calculate the hash from the challenge we sent */
-
- if(!EVP_DigestInit(&ctx, c->outdigest)
- || !EVP_DigestUpdate(&ctx, c->hischallenge, RSA_size(c->rsa_key))
- || !EVP_DigestFinal(&ctx, (unsigned char *)myhash, NULL)) {
- logger(LOG_ERR, _("Error during calculation of response from %s (%s): %s"),
- c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL));
- return false;
- }
-
- /* Verify the incoming hash with the calculated hash */
+ hex2bin(hishash, hishash, digest_length(&c->outdigest));
- if(memcmp(hishash, myhash, c->outdigest->md_size)) {
- logger(LOG_ERR, _("Possible intruder %s (%s): %s"), c->name,
- c->hostname, _("wrong challenge reply"));
-
- ifdebug(SCARY_THINGS) {
- bin2hex(myhash, hishash, SHA_DIGEST_LENGTH);
- hishash[SHA_DIGEST_LENGTH * 2] = '\0';
- logger(LOG_DEBUG, _("Expected challenge reply: %s"), hishash);
- }
+ /* Verify the hash */
+ if(!digest_verify(&c->outdigest, c->hischallenge, rsa_size(&c->rsa), hishash)) {
+ logger(LOG_ERR, _("Possible intruder %s (%s): %s"), c->name, c->hostname, _("wrong challenge reply"));
return false;
}
Send an acknowledgement with the rest of the information needed.
*/
+ free(c->hischallenge);
+ c->hischallenge = NULL;
c->allow_request = ACK;
return send_ack(c);
#include "system.h"
-#include <openssl/evp.h>
-#include <openssl/err.h>
-
#include "splay_tree.h"
+#include "cipher.h"
#include "connection.h"
#include "logger.h"
#include "net.h"
#include "utils.h"
#include "xalloc.h"
-bool mykeyused = false;
+static bool mykeyused = false;
bool send_key_changed(connection_t *c, const node_t *n) {
cp();
}
bool send_ans_key(connection_t *c, const node_t *from, const node_t *to) {
- char *key;
+ size_t keylen = cipher_keylength(&from->cipher);
+ char key[keylen * 2 + 1];
cp();
- key = alloca(2 * from->keylength + 1);
- bin2hex(from->key, key, from->keylength);
- key[from->keylength * 2] = '\0';
+ cipher_get_key(&from->cipher, key);
+ bin2hex(key, key, keylen);
+ key[keylen * 2] = '\0';
return send_request(c, "%d %s %s %s %d %d %d %d", ANS_KEY,
from->name, to->name, key,
- from->cipher ? from->cipher->nid : 0,
- from->digest ? from->digest->type : 0, from->maclength,
+ cipher_get_nid(&from->cipher),
+ digest_get_nid(&from->digest), from->maclength,
from->compression);
}
return send_request(to->nexthop->connection, "%s", request);
}
- /* Update our copy of the origin's packet key */
-
- if(from->key)
- free(from->key);
-
- from->key = xstrdup(key);
- from->keylength = strlen(key) / 2;
- hex2bin(from->key, from->key, from->keylength);
- from->key[from->keylength] = '\0';
-
- from->status.validkey = true;
- from->status.waitingforkey = false;
- from->sent_seqno = 0;
-
/* Check and lookup cipher and digest algorithms */
- if(cipher) {
- from->cipher = EVP_get_cipherbynid(cipher);
-
- if(!from->cipher) {
- logger(LOG_ERR, _("Node %s (%s) uses unknown cipher!"), from->name,
- from->hostname);
- return false;
- }
+ if(!cipher_open_by_nid(&from->cipher, cipher)) {
+ logger(LOG_ERR, _("Node %s (%s) uses unknown cipher!"), from->name, from->hostname);
+ return false;
+ }
- if(from->keylength != from->cipher->key_len + from->cipher->iv_len) {
- logger(LOG_ERR, _("Node %s (%s) uses wrong keylength!"), from->name,
- from->hostname);
- return false;
- }
- } else {
- from->cipher = NULL;
+ if(strlen(key) / 2 != cipher_keylength(&from->cipher)) {
+ logger(LOG_ERR, _("Node %s (%s) uses wrong keylength!"), from->name, from->hostname);
+ return false;
}
from->maclength = maclength;
- if(digest) {
- from->digest = EVP_get_digestbynid(digest);
-
- if(!from->digest) {
- logger(LOG_ERR, _("Node %s (%s) uses unknown digest!"), from->name,
- from->hostname);
- return false;
- }
+ if(!digest_open_by_nid(&from->digest, digest)) {
+ logger(LOG_ERR, _("Node %s (%s) uses unknown digest!"), from->name, from->hostname);
+ return false;
+ }
- if(from->maclength > from->digest->md_size || from->maclength < 0) {
- logger(LOG_ERR, _("Node %s (%s) uses bogus MAC length!"),
- from->name, from->hostname);
- return false;
- }
- } else {
- from->digest = NULL;
+ if(from->maclength > digest_length(&from->digest) || from->maclength < 0) {
+ logger(LOG_ERR, _("Node %s (%s) uses bogus MAC length!"), from->name, from->hostname);
+ return false;
}
if(compression < 0 || compression > 11) {
from->compression = compression;
- if(from->cipher)
- if(!EVP_EncryptInit_ex(&from->packet_ctx, from->cipher, NULL, (unsigned char *)from->key, (unsigned char *)from->key + from->cipher->key_len)) {
- logger(LOG_ERR, _("Error during initialisation of key from %s (%s): %s"),
- from->name, from->hostname, ERR_error_string(ERR_get_error(), NULL));
- return false;
- }
+ /* Update our copy of the origin's packet key */
+
+ hex2bin(key, key, cipher_keylength(&from->cipher));
+ cipher_set_key(&from->cipher, key, false);
+
+ from->status.validkey = true;
+ from->status.waitingforkey = false;
+ from->sent_seqno = 0;
if(from->options & OPTION_PMTU_DISCOVERY && !from->mtuprobes)
send_mtu_probe(from);
#include <sys/mman.h>
#endif
-#include <openssl/rand.h>
-#include <openssl/rsa.h>
-#include <openssl/pem.h>
-#include <openssl/evp.h>
-#include <openssl/engine.h>
-
#include LZO1X_H
#include <getopt.h>
#include "conf.h"
#include "control.h"
+#include "crypto.h"
#include "device.h"
#include "logger.h"
#include "net.h"
/* Slllluuuuuuurrrrp! */
srand(time(NULL));
- RAND_load_file("/dev/urandom", 1024);
-
- ENGINE_load_builtin_engines();
- ENGINE_register_all_complete();
-
- OpenSSL_add_all_algorithms();
+ crypto_init();
if(!read_server_config())
return 1;
exit_control();
#endif
- EVP_cleanup();
-
+ crypto_exit();
+
return status;
}