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
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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
+129 −17
Original line number Diff line number Diff line
@@ -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,10 +433,14 @@ 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;
    if (!env->iv)
      return -1;
    memcpy((void *)env->iv, (void *)iv, 16);
    break;
    default:
    return -1;
@@ -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 −4
Original line number Diff line number Diff line
@@ -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);
+2 −2
Original line number Diff line number Diff line
@@ -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;
+62 −41
Original line number Diff line number Diff line
@@ -67,8 +67,10 @@ 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;
      }
Loading