Commit 01aadefb authored by Matej Pjafjar's avatar Matej Pjafjar
Browse files

Changed crypto calls to go through common/crypto.[hc] instead of calling OpenSSL directly.


svn:r76
parent ac942bb3
......@@ -3,9 +3,9 @@ noinst_LIBRARIES = libor.a
#CFLAGS = -Wall -Wpointer-arith -O2
libor_a_SOURCES = config.c key.c log.c utils.c crypto.c
libor_a_SOURCES = config.c log.c utils.c crypto.c
noinst_HEADERS = config.h key.h log.h \
noinst_HEADERS = config.h log.h \
policies.h utils.h \
ss.h version.h crypto.h
......@@ -2,11 +2,21 @@
/* See LICENSE for licensing information */
/* $Id$ */
#include "crypto.h"
#include <string.h>
#include <openssl/err.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <stdlib.h>
#include <assert.h>
#include "crypto.h"
#include "config.h"
#include "log.h"
int crypto_global_init()
{
ERR_load_crypto_strings();
......@@ -201,8 +211,9 @@ int crypto_pk_read_private_key(crypto_pk_env_t *env, FILE *src)
switch(env->type) {
case CRYPTO_PK_RSA:
/*
if (env->key)
RSA_free((RSA *)env->key);
RSA_free((RSA *)env->key);*/
env->key = (unsigned char *)PEM_read_RSAPrivateKey(src, (RSA **)&env->key, NULL, NULL);
if (!env->key)
return -1;
......@@ -213,14 +224,60 @@ int crypto_pk_read_private_key(crypto_pk_env_t *env, FILE *src)
return 0;
}
int crypto_pk_read_private_key_filename(crypto_pk_env_t *env, unsigned char *keyfile)
{
FILE *f_pr;
int retval = 0;
assert(env && keyfile);
if (strspn(keyfile,CONFIG_LEGAL_FILENAME_CHARACTERS) == strlen(keyfile)) /* filename contains legal characters only */
{
/* open the keyfile */
f_pr=fopen(keyfile,"r");
if (!f_pr)
return -1;
/* read the private key */
retval = crypto_pk_read_private_key(env, f_pr);
fclose(f_pr);
if (retval == -1)
{
log(LOG_ERR,"Error reading private key : %s",crypto_perror());
return -1;
}
/* check the private key */
retval = crypto_pk_check_key(env);
if (retval == 0)
{
log(LOG_ERR,"Private key read but is invalid : %s.", crypto_perror());
return -1;
}
else if (retval == -1)
{
log(LOG_ERR,"Private key read but validity checking failed : %s",crypto_perror());
return -1;
}
else if (retval == 1)
{
return 0;
}
} /* filename contains legal characters only */
return -1; /* report error */
}
int crypto_pk_read_public_key(crypto_pk_env_t *env, FILE *src)
{
assert(env && src);
switch(env->type) {
case CRYPTO_PK_RSA:
/*
if (env->key)
RSA_free((RSA *)env->key);
RSA_free((RSA *)env->key);*/
env->key = (unsigned char *)PEM_read_RSAPublicKey(src, (RSA **)&env->key, NULL, NULL);
if (!env->key)
return -1;
......@@ -285,9 +342,9 @@ int crypto_pk_set_key(crypto_pk_env_t *env, unsigned char *key)
switch(env->type) {
case CRYPTO_PK_RSA:
if (env->key)
RSA_free((RSA *)env->key);
env->key = key;
if (!env->key)
return -1;
memcpy((void *)env->key, (void *)key, sizeof(RSA));
break;
default :
return -1;
......@@ -296,6 +353,36 @@ int crypto_pk_set_key(crypto_pk_env_t *env, unsigned char *key)
return 0;
}
int crypto_pk_cmp_keys(crypto_pk_env_t *a, crypto_pk_env_t *b) {
int result;
if (!a || !b)
return -1;
if (!a->key || !b->key)
return -1;
if (a->type != b->type)
return -1;
switch(a->type) {
case CRYPTO_PK_RSA:
assert(((RSA *)a->key)->n && ((RSA *)a->key)->e && ((RSA *)b->key)->n && ((RSA *)b->key)->e);
result = BN_cmp(((RSA *)a->key)->n, ((RSA *)b->key)->n);
if (result)
return result;
return BN_cmp(((RSA *)a->key)->e, ((RSA *)b->key)->e);
default:
return -1;
}
}
int crypto_pk_keysize(crypto_pk_env_t *env)
{
assert(env && env->key);
return RSA_size((RSA *)env->key);
}
int crypto_pk_public_encrypt(crypto_pk_env_t *env, unsigned char *from, int fromlen, unsigned char *to, int padding)
{
assert(env && from && to);
......@@ -321,6 +408,23 @@ int crypto_pk_private_decrypt(crypto_pk_env_t *env, unsigned char *from, int fro
}
/* symmetric crypto */
int crypto_cipher_generate_key(crypto_cipher_env_t *env)
{
assert(env);
switch(env->type) {
case CRYPTO_CIPHER_IDENTITY:
return 0;
case CRYPTO_CIPHER_DES:
return crypto_rand(8, env->key);
case CRYPTO_CIPHER_RC4:
return crypto_rand(16, env->key);
default:
return -1;
}
}
int crypto_cipher_set_iv(crypto_cipher_env_t *env, unsigned char *iv)
{
assert(env && iv);
......@@ -329,13 +433,17 @@ int crypto_cipher_set_iv(crypto_cipher_env_t *env, unsigned char *iv)
case CRYPTO_CIPHER_IDENTITY:
break;
case CRYPTO_CIPHER_DES:
if (!env->iv)
return -1;
memcpy((void *)env->iv, (void *)iv, 8);
break;
case CRYPTO_CIPHER_RC4:
if (env->iv)
free((void *)env->iv);
env->iv = iv;
break;
if (!env->iv)
return -1;
memcpy((void *)env->iv, (void *)iv, 16);
break;
default:
return -1;
return -1;
}
return 0;
......@@ -348,10 +456,14 @@ int crypto_cipher_set_key(crypto_cipher_env_t *env, unsigned char *key)
case CRYPTO_CIPHER_IDENTITY:
break;
case CRYPTO_CIPHER_DES:
if (!env->key)
return -1;
memcpy((void *)env->key, (void *)key, 8);
break;
case CRYPTO_CIPHER_RC4:
if (env->key)
free((void *)env->key);
env->key = key;
if (!env->key)
return -1;
memcpy((void *)env->key, (void *)key, 16);
break;
default:
return -1;
......@@ -396,7 +508,7 @@ int crypto_cipher_decrypt_init_cipher(crypto_cipher_env_t *env)
return 0;
}
int crypto_cipher_encrypt(crypto_cipher_env_t *env, unsigned char *from, unsigned int fromlen, unsigned char *to)
int crypto_cipher_encrypt(crypto_cipher_env_t *env, unsigned char *from, size_t fromlen, unsigned char *to)
{
int tolen;
......@@ -405,7 +517,7 @@ int crypto_cipher_encrypt(crypto_cipher_env_t *env, unsigned char *from, unsigne
return !(EVP_EncryptUpdate((EVP_CIPHER_CTX *)env->aux, to, &tolen, from, fromlen));
}
int crypto_cipher_decrypt(crypto_cipher_env_t *env, unsigned char *from, unsigned int fromlen, unsigned char *to)
int crypto_cipher_decrypt(crypto_cipher_env_t *env, unsigned char *from, size_t fromlen, unsigned char *to)
{
int tolen;
......@@ -425,7 +537,7 @@ int crypto_SHA_digest(unsigned char *m, int len, unsigned char *digest)
int crypto_rand(unsigned int n, unsigned char *to)
{
assert(to);
return (RAND_bytes(to, n) == -1);
return (RAND_bytes(to, n) != 1);
}
int crypto_pseudo_rand(unsigned int n, unsigned char *to)
......
......@@ -5,11 +5,8 @@
#ifndef __CRYPTO_H
#define __CRYPTO_H
#include <openssl/err.h>
#include <stdio.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
/* available encryption primitives */
#define CRYPTO_CIPHER_IDENTITY 0
......@@ -54,13 +51,17 @@ int crypto_pk_read_public_key(crypto_pk_env_t *env, FILE *src);
int crypto_pk_write_private_key(crypto_pk_env_t *env, FILE *dest);
int crypto_pk_write_public_key(crypto_pk_env_t *env, FILE *dest);
int crypto_pk_check_key(crypto_pk_env_t *env);
int crypto_pk_read_private_key_filename(crypto_pk_env_t *env, unsigned char *keyfile);
int crypto_pk_set_key(crypto_pk_env_t *env, unsigned char *key);
int crypto_pk_cmp_keys(crypto_pk_env_t *a, crypto_pk_env_t *b);
int crypto_pk_keysize(crypto_pk_env_t *env);
int crypto_pk_public_encrypt(crypto_pk_env_t *env, unsigned char *from, int fromlen, unsigned char *to, int padding);
int crypto_pk_private_decrypt(crypto_pk_env_t *env, unsigned char *from, int fromlen, unsigned char *to, int padding);
/* symmetric crypto */
int crypto_cipher_generate_key(crypto_cipher_env_t *env);
int crypto_cipher_set_iv(crypto_cipher_env_t *env, unsigned char *iv);
int crypto_cipher_set_key(crypto_cipher_env_t *env, unsigned char *key);
int crypto_cipher_encrypt_init_cipher(crypto_cipher_env_t *env);
......
......@@ -21,8 +21,8 @@ static cell_t *new_create_cell(uint16_t aci, unsigned char length, unsigned char
c->seq = 0;
memcpy((void *)c->payload, (void *)buf, length);
retval = RAND_pseudo_bytes((unsigned char *)(c->payload+length),CELL_PAYLOAD_SIZE-length);
if (retval == -1) /* RAND_pseudo_bytes() error */
retval = crypto_pseudo_rand(CELL_PAYLOAD_SIZE-length, (unsigned char *)(c->payload+length));
if (retval) /* RAND_pseudo_bytes() error */
{
free((void *)c);
return NULL;
......
......@@ -66,9 +66,11 @@ circuit_t *circuit_new(aci_t p_aci, connection_t *p_conn) {
}
void circuit_free(circuit_t *circ) {
EVP_CIPHER_CTX_cleanup(&circ->n_ctx);
EVP_CIPHER_CTX_cleanup(&circ->p_ctx);
if (circ->n_crypto)
crypto_free_cipher_env(circ->n_crypto);
if (circ->p_crypto)
crypto_free_cipher_env(circ->p_crypto);
if(circ->onion)
free(circ->onion);
......@@ -93,7 +95,7 @@ aci_t get_unique_aci_by_addr_port(uint32_t addr, uint16_t port, int aci_type) {
log(LOG_DEBUG,"get_unique_aci_by_addr_port() trying to get a unique aci");
RAND_pseudo_bytes((unsigned char *)&test_aci, 2);
crypto_pseudo_rand(2, (unsigned char *)&test_aci);
if(aci_type == ACI_TYPE_LOWER)
test_aci &= htons(0x00FF);
......@@ -117,7 +119,7 @@ aci_t get_unique_aci_by_addr_port(uint32_t addr, uint16_t port, int aci_type) {
int circuit_init(circuit_t *circ, int aci_type) {
onion_layer_t *ol;
int retval = 0;
unsigned char iv[16];
unsigned char digest1[20];
unsigned char digest2[20];
......@@ -143,32 +145,23 @@ int circuit_init(circuit_t *circ, int aci_type) {
log(LOG_DEBUG,"circuit_init(): Chosen ACI %u.",circ->n_aci);
/* keys */
SHA1(ol->keyseed,16,digest1);
SHA1(digest1,20,digest2);
SHA1(digest2,20,digest1);
memcpy(circ->p_key,digest2,16);
memcpy(circ->n_key,digest1,16);
memset((void *)iv, 0, 16);
crypto_SHA_digest(ol->keyseed,16,digest1);
crypto_SHA_digest(digest1,20,digest2);
crypto_SHA_digest(digest2,20,digest1);
log(LOG_DEBUG,"circuit_init(): Computed keys.");
/* set IVs to zero */
memset(circ->n_iv,0,16);
memset(circ->p_iv,0,16);
/* initialize cipher context */
EVP_CIPHER_CTX_init(&circ->n_ctx);
EVP_CIPHER_CTX_init(&circ->p_ctx);
/* initialize crypto engines */
switch(circ->p_f)
{
case ONION_CIPHER_DES :
retval = EVP_EncryptInit(&circ->p_ctx, EVP_des_ofb(), circ->p_key, circ->p_iv);
circ->p_crypto = crypto_new_cipher_env(CRYPTO_CIPHER_DES);
break;
case ONION_CIPHER_RC4 :
retval = EVP_EncryptInit(&circ->p_ctx, EVP_rc4(), circ->p_key,circ->p_iv);
circ->p_crypto = crypto_new_cipher_env(CRYPTO_CIPHER_RC4);
break;
case ONION_CIPHER_IDENTITY :
retval = EVP_EncryptInit(&circ->p_ctx, EVP_enc_null(), circ->p_key, circ->p_iv);
circ->p_crypto = crypto_new_cipher_env(CRYPTO_CIPHER_IDENTITY);
break;
default :
log(LOG_ERR,"Onion contains unrecognized cipher(%u) for ACI : %u.",circ->p_f,circ->n_aci);
......@@ -176,36 +169,65 @@ int circuit_init(circuit_t *circ, int aci_type) {
break;
}
if (!retval) /* EVP_EncryptInit() error */
if (!circ->p_crypto) {
log(LOG_ERR,"Could not create a cryptographic environment.");
return -1;
}
if (crypto_cipher_set_iv(circ->p_crypto, iv) == -1) {
log(LOG_ERR,"Could not set the IV.");
crypto_free_cipher_env(circ->p_crypto);
return -1;
}
if (crypto_cipher_set_key(circ->p_crypto, digest2) == -1) {
log(LOG_ERR,"Could not set encryption key.");
crypto_free_cipher_env(circ->p_crypto);
return -1;
}
if (crypto_cipher_encrypt_init_cipher(circ->p_crypto)) /* crypto_cipher_init_cipher error */
{
log(LOG_ERR,"Cipher initialization failed (ACI %u).",circ->n_aci);
EVP_CIPHER_CTX_cleanup(&circ->n_ctx);
EVP_CIPHER_CTX_cleanup(&circ->p_ctx);
crypto_free_cipher_env(circ->p_crypto);
return -1;
}
switch(circ->n_f)
{
case ONION_CIPHER_DES :
retval = EVP_DecryptInit(&circ->n_ctx, EVP_des_ofb(), circ->n_key, circ->n_iv);
circ->n_crypto = crypto_new_cipher_env(CRYPTO_CIPHER_DES);
break;
case ONION_CIPHER_RC4 :
retval = EVP_DecryptInit(&circ->n_ctx, EVP_rc4(), circ->n_key,circ->n_iv);
circ->n_crypto = crypto_new_cipher_env(CRYPTO_CIPHER_RC4);
break;
case ONION_CIPHER_IDENTITY :
retval = EVP_DecryptInit(&circ->n_ctx, EVP_enc_null(), circ->n_key, circ->n_iv);
circ->n_crypto = crypto_new_cipher_env(CRYPTO_CIPHER_IDENTITY);
break;
default :
log(LOG_ERR,"Onion contains unrecognized cipher for ACI : %u.",circ->n_aci);
log(LOG_ERR,"Onion contains unrecognized cipher(%u) for ACI : %u.",circ->n_f,circ->n_aci);
return -1;
break;
}
if (!retval) /* EVP_EncryptInit() error */
if (!circ->n_crypto) {
log(LOG_ERR,"Could not create a cryptographic environment.");
return -1;
}
if (crypto_cipher_set_iv(circ->n_crypto, iv) == -1) {
log(LOG_ERR,"Could not set the IV.");
crypto_free_cipher_env(circ->n_crypto);
return -1;
}
if (crypto_cipher_set_key(circ->n_crypto, digest1) == -1) {
log(LOG_ERR,"Could not set encryption key.");
crypto_free_cipher_env(circ->n_crypto);
return -1;
}
if (crypto_cipher_decrypt_init_cipher(circ->n_crypto)) /* crypto_cipher_init_cipher error */
{
log(LOG_ERR,"Cipher initialization failed (ACI %u).",circ->n_aci);
EVP_CIPHER_CTX_cleanup(&circ->n_ctx);
EVP_CIPHER_CTX_cleanup(&circ->p_ctx);
crypto_free_cipher_env(circ->n_crypto);
return -1;
}
log(LOG_DEBUG,"circuit_init(): Cipher initialization complete.");
circ->expire = ol->expire;
......@@ -276,13 +298,12 @@ int circuit_deliver_data_cell(cell_t *cell, circuit_t *circ, connection_t *conn,
int circuit_crypt(circuit_t *circ, char *in, size_t inlen, char crypt_type) {
char *out;
int outlen;
int i;
crypt_path_t *thishop;
assert(circ && in);
out = malloc(inlen);
out = (char *)malloc(inlen);
if(!out)
return -1;
......@@ -298,8 +319,8 @@ int circuit_crypt(circuit_t *circ, char *in, size_t inlen, char crypt_type) {
thishop = circ->cpath[i];
/* encrypt */
if(!EVP_EncryptUpdate(&thishop->f_ctx,out,&outlen,in,inlen)) {
log(LOG_ERR,"Error performing encryption:%s",ERR_reason_error_string(ERR_get_error()));
if(crypto_cipher_encrypt(thishop->f_crypto, in, inlen, (unsigned char *)out)) {
log(LOG_ERR,"Error performing encryption:%s",crypto_perror());
free(out);
return -1;
}
......@@ -308,9 +329,9 @@ int circuit_crypt(circuit_t *circ, char *in, size_t inlen, char crypt_type) {
memcpy(in,out,inlen);
}
} else { /* we're in the middle. Just one crypt. */
if(!EVP_EncryptUpdate(&circ->p_ctx,out,&outlen,in,inlen)) {
if(crypto_cipher_encrypt(circ->p_crypto,in, inlen, out)) {
log(LOG_ERR,"circuit_encrypt(): Encryption failed for ACI : %u (%s).",
circ->p_aci, ERR_reason_error_string(ERR_get_error()));
circ->p_aci, crypto_perror());
free(out);
return -1;
}
......@@ -327,8 +348,8 @@ int circuit_crypt(circuit_t *circ, char *in, size_t inlen, char crypt_type) {
thishop = circ->cpath[i];
/* encrypt */
if(!EVP_DecryptUpdate(&thishop->b_ctx,out,&outlen,in,inlen)) {
log(LOG_ERR,"Error performing decryption:%s",ERR_reason_error_string(ERR_get_error()));
if(crypto_cipher_decrypt(thishop->b_crypto, in, inlen, out)) {
log(LOG_ERR,"Error performing decryption:%s",crypto_perror());
free(out);
return -1;
}
......@@ -337,9 +358,9 @@ int circuit_crypt(circuit_t *circ, char *in, size_t inlen, char crypt_type) {
memcpy(in,out,inlen);
}
} else { /* we're in the middle. Just one crypt. */
if(!EVP_DecryptUpdate(&circ->n_ctx,out,&outlen,in,inlen)) {
if(crypto_cipher_decrypt(circ->n_crypto,in, inlen, out)) {
log(LOG_ERR,"circuit_crypt(): Decryption failed for ACI : %u (%s).",
circ->n_aci, ERR_reason_error_string(ERR_get_error()));
circ->n_aci, crypto_perror());
free(out);
return -1;
}
......
......@@ -86,6 +86,20 @@ connection_t *connection_new(int type) {
conn->receiver_bucket = 10240; /* should be enough to do the handshake */
conn->bandwidth = conn->receiver_bucket / 10; /* give it a default */
if (connection_speaks_cells(conn)) {
conn->f_crypto = crypto_new_cipher_env(CRYPTO_CIPHER_DES);
if (!conn->f_crypto) {
free((void *)conn);
return NULL;
}
conn->b_crypto = crypto_new_cipher_env(CRYPTO_CIPHER_DES);
if (!conn->b_crypto) {
crypto_free_cipher_env(conn->f_crypto);
free((void *)conn);
return NULL;
}
}
return conn;
}
......@@ -102,8 +116,10 @@ void connection_free(connection_t *conn) {
free(conn->dest_port);
if(connection_speaks_cells(conn)) {
EVP_CIPHER_CTX_cleanup(&conn->f_ctx);
EVP_CIPHER_CTX_cleanup(&conn->b_ctx);
if (conn->f_crypto)
crypto_free_cipher_env(conn->f_crypto);
if (conn->b_crypto)
crypto_free_cipher_env(conn->b_crypto);
}
if(conn->s > 0)
......@@ -111,7 +127,7 @@ void connection_free(connection_t *conn) {
free(conn);
}
int connection_create_listener(RSA *prkey, struct sockaddr_in *local, int type) {
int connection_create_listener(crypto_pk_env_t *prkey, struct sockaddr_in *local, int type) {
connection_t *conn;
int s;
int one=1;
......@@ -230,7 +246,7 @@ static int learn_local(struct sockaddr_in *local) {
}
int retry_all_connections(int role, routerinfo_t **router_array, int rarray_len,
RSA *prkey, uint16_t or_listenport, uint16_t op_listenport, uint16_t ap_listenport) {
crypto_pk_env_t *prkey, uint16_t or_listenport, uint16_t op_listenport, uint16_t ap_listenport) {
/* start all connections that should be up but aren't */
......@@ -275,7 +291,7 @@ int retry_all_connections(int role, routerinfo_t **router_array, int rarray_len,
return 0;
}
connection_t *connection_connect_to_router_as_op(routerinfo_t *router, RSA *prkey, uint16_t local_or_port) {
connection_t *connection_connect_to_router_as_op(routerinfo_t *router, crypto_pk_env_t *prkey, uint16_t local_or_port) {
struct sockaddr_in local; /* local address */
if(learn_local(&local) < 0)
......@@ -488,7 +504,6 @@ int connection_write_cell_to_buf(cell_t *cellp, connection_t *conn) {
int connection_encrypt_cell_header(cell_t *cellp, connection_t *conn) {
char newheader[8];
int newsize;
#if 0
int x;
char *px;
......@@ -501,7 +516,7 @@ int connection_encrypt_cell_header(cell_t *cellp, connection_t *conn) {
printf("\n");
#endif
if(!EVP_EncryptUpdate(&conn->f_ctx, newheader, &newsize, (char *)cellp, 8)) {
if(crypto_cipher_encrypt(conn->f_crypto, (char *)cellp, 8, newheader)) {
log(LOG_ERR,"Could not encrypt data for connection %s:%u.",conn->address,ntohs(conn->port));
return -1;
}
......@@ -664,7 +679,6 @@ int connection_process_cell_from_inbuf(connection_t *conn) {
*/
char crypted[128];
char outbuf[1024];
int outlen;
// int x;
cell_t *cellp;
......@@ -683,7 +697,7 @@ int connection_process_cell_from_inbuf(connection_t *conn) {
printf("\n");
#endif
/* decrypt */
if(!EVP_DecryptUpdate(&conn->b_ctx,(unsigned char *)outbuf,&outlen,crypted,8)) {
if(crypto_cipher_decrypt(conn->b_crypto,crypted,8,(unsigned char *)outbuf)) {
log(LOG_ERR,"connection_process_cell_from_inbuf(): Decryption failed, dropping.");
return connection_process_inbuf(conn); /* process the remainder of the buffer */
}
......
......@@ -378,7 +378,7 @@ int connection_ap_finished_flushing(connection_t *conn) {
}
int connection_ap_create_listener(RSA *prkey, struct sockaddr_in *local) {
int connection_ap_create_listener(crypto_pk_env_t *prkey, struct sockaddr_in *local) {
log(LOG_DEBUG,"connection_create_ap_listener starting");
return connection_create_listener(prkey, local, CONN_TYPE_AP_LISTENER);
}
......
......@@ -33,6 +33,7 @@ int connection_op_process_inbuf(connection_t *conn) {
int op_handshake_process_keys(connection_t *conn) {
int retval;
int x;
unsigned char iv[16];
/* key exchange message */
unsigned char auth_cipher[128];
......@@ -51,12 +52,12 @@ int op_handshake_process_keys(connection_t *conn) {
log(LOG_DEBUG,"op_handshake_process_keys() : Received auth.");
/* decrypt response */
retval = RSA_private_decrypt(128,auth_cipher,auth_plain,conn->prkey,RSA_PKCS1_PADDING);
retval = crypto_pk_private_decrypt(conn->prkey, auth_cipher, 128, auth_plain,RSA_PKCS1_PADDING);
if (retval == -1)