123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651 |
- /* Copyright 2001,2002 Roger Dingledine, Matej Pfajfar. */
- /* See LICENSE for licensing information */
- /* $Id$ */
- #include <string.h>
- #include <openssl/err.h>
- #include <openssl/rsa.h>
- #include <openssl/pem.h>
- #include <openssl/evp.h>
- #include <openssl/rand.h>
- #include <openssl/opensslv.h>
- #include <stdlib.h>
- #include <assert.h>
- #include "crypto.h"
- #include "config.h"
- #include "log.h"
- #if OPENSSL_VERSION_NUMBER < 0x00905000l
- #error "We require openssl >= 0.9.5"
- #elif OPENSSL_VERSION_NUMBER < 0x00906000l
- #define OPENSSL_095
- #endif
- /*
- * Certain functions that return a success code in OpenSSL 0.9.6 return void
- * (and don't indicate errors) in OpenSSL version 0.9.5.
- *
- * [OpenSSL 0.9.5 matters, because it ships with Redhat 6.2.]
- */
- #ifdef OPENSSL_095
- #define RETURN_SSL_OUTCOME(exp) (exp); return 0
- #else
- #define RETURN_SSL_OUTCOME(exp) return !(exp)
- #endif
- int crypto_global_init()
- {
- ERR_load_crypto_strings();
- return 0;
- }
- int crypto_global_cleanup()
- {
- ERR_free_strings();
- return 0;
- }
- crypto_pk_env_t *crypto_new_pk_env(int type)
- {
- crypto_pk_env_t *env;
-
- env = (crypto_pk_env_t *)malloc(sizeof(crypto_pk_env_t));
- if (!env)
- return 0;
-
- env->type = type;
- env->refs = 1;
- env->key = NULL;
- env->aux = NULL;
-
- switch(type) {
- case CRYPTO_PK_RSA:
- env->key = (unsigned char *)RSA_new();
- if (!env->key) {
- free((void *)env);
- return NULL;
- }
- break;
- default:
- free((void *)env);
- return NULL;
- break;
- }
- return env;
- }
- void crypto_free_pk_env(crypto_pk_env_t *env)
- {
- assert(env);
- if(--env->refs > 0)
- return;
-
- switch(env->type) {
- case CRYPTO_PK_RSA:
- if (env->key)
- RSA_free((RSA *)env->key);
- break;
- default:
- break;
- }
-
- free((void *)env);
- return;
- }
- crypto_cipher_env_t *crypto_new_cipher_env(int type)
- {
- crypto_cipher_env_t *env;
-
- env = (crypto_cipher_env_t *)malloc(sizeof(crypto_cipher_env_t));
- if (!env)
- return NULL;
-
- env->type = type;
- env->key = NULL;
- env->iv = NULL;
- env->aux = NULL;
-
- switch(type) {
- case CRYPTO_CIPHER_IDENTITY:
- env->aux = (unsigned char *)malloc(sizeof(EVP_CIPHER_CTX));
- if (!env->aux) {
- free((void *)env);
- return NULL;
- }
- EVP_CIPHER_CTX_init((EVP_CIPHER_CTX *)env->aux);
- break;
- case CRYPTO_CIPHER_DES:
- env->aux = (unsigned char *)malloc(sizeof(EVP_CIPHER_CTX));
- if (!env->aux) {
- free((void *)env);
- return NULL;
- }
- env->key = (unsigned char *)malloc(8);
- if (!env->key) {
- free((void *)env->aux);
- free((void *)env);
- return NULL;
- }
- env->iv = (unsigned char *)malloc(8);
- if (!env->iv) {
- free((void *)env->key);
- free((void *)env->aux);
- return NULL;
- }
- EVP_CIPHER_CTX_init((EVP_CIPHER_CTX *)env->aux);
- break;
- case CRYPTO_CIPHER_RC4:
- env->aux = (unsigned char *)malloc(sizeof(EVP_CIPHER_CTX));
- if (!env->aux) {
- free((void *)env);
- return NULL;
- }
- env->key = (unsigned char *)malloc(16);
- if (!env->key) {
- free((void *)env->aux);
- free((void *)env);
- return NULL;
- }
- env->iv = (unsigned char *)malloc(16);
- if (!env->iv) {
- free((void *)env->key);
- free((void *)env->aux);
- return NULL;
- }
- break;
- EVP_CIPHER_CTX_init((EVP_CIPHER_CTX *)env->aux);
- default:
- free((void *)env);
- return NULL;
- break;
- }
-
- return env;
- }
- void crypto_free_cipher_env(crypto_cipher_env_t *env)
- {
- assert(env);
-
- switch(env->type) {
- case CRYPTO_CIPHER_IDENTITY:
- if (env->aux) {
- EVP_CIPHER_CTX_cleanup((EVP_CIPHER_CTX *)env->aux);
- free((void *)env->aux);
- }
- break;
- case CRYPTO_CIPHER_DES:
- if (env->aux) {
- EVP_CIPHER_CTX_cleanup((EVP_CIPHER_CTX *)env->aux);
- free((void *)env->aux);
- }
- if (env->key)
- free((void *)env->key);
- if (env->iv)
- free((void *)env->iv);
- break;
- case CRYPTO_CIPHER_RC4:
- if (env->aux) {
- EVP_CIPHER_CTX_cleanup((EVP_CIPHER_CTX *)env->aux);
- free((void *)env->aux);
- }
- if (env->key)
- free((void *)env->key);
- if (env->iv)
- free((void *)env->iv);
- break;
- default:
- break;
- }
-
- free((void *)env);
- return;
- }
- /* public key crypto */
- int crypto_pk_generate_key(crypto_pk_env_t *env)
- {
- assert(env);
-
- switch(env->type) {
- case CRYPTO_PK_RSA:
- if (env->key)
- RSA_free((RSA *)env->key);
- env->key = (unsigned char *)RSA_generate_key(1024,65537, NULL, NULL);
- if (!env->key)
- return -1;
- break;
- default:
- return -1;
- }
-
- return 0;
- }
- int crypto_pk_read_private_key_from_file(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);*/
- env->key = (unsigned char *)PEM_read_RSAPrivateKey(src, (RSA **)&env->key, NULL, NULL);
- if (!env->key)
- return -1;
- break;
- default :
- return -1;
- }
-
- return 0;
- }
- int crypto_pk_read_private_key_from_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_from_file(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_from_file(crypto_pk_env_t *env, FILE *src)
- {
- assert(env && src);
-
- switch(env->type) {
- case CRYPTO_PK_RSA:
- env->key = (unsigned char *)PEM_read_RSAPublicKey(src, (RSA **)&env->key, NULL, NULL);
- if (!env->key)
- return -1;
- break;
- default :
- return -1;
- }
-
- return 0;
- }
- int crypto_pk_write_public_key_to_string(crypto_pk_env_t *env, char **dest, int *len) {
- BUF_MEM *buf;
- BIO *b;
- assert(env && env->key && dest);
- switch(env->type) {
- case CRYPTO_PK_RSA:
- b = BIO_new(BIO_s_mem()); /* Create a memory BIO */
- /* Now you can treat b as if it were a file. Just use the
- * * PEM_*_bio_* functions instead of the non-bio variants.
- * */
- if(!PEM_write_bio_RSAPublicKey(b, (RSA *)env->key))
- return -1;
- BIO_get_mem_ptr(b, &buf);
- BIO_set_close(b, BIO_NOCLOSE); /* so BIO_free doesn't free buf */
- BIO_free(b);
- *dest = malloc(buf->length+1);
- if(!*dest)
- return -1;
- memcpy(*dest, buf->data, buf->length);
- (*dest)[buf->length] = 0; /* null terminate it */
- *len = buf->length;
- BUF_MEM_free(buf);
- break;
- default:
- return -1;
- }
-
- return 0;
- }
- int crypto_pk_read_public_key_from_string(crypto_pk_env_t *env, char *src, int len) {
- BIO *b;
- assert(env && src);
- switch(env->type) {
- case CRYPTO_PK_RSA:
- b = BIO_new(BIO_s_mem()); /* Create a memory BIO */
- BIO_write(b, src, len);
- RSA_free((RSA *)env->key);
- env->key = (unsigned char *)PEM_read_bio_RSAPublicKey(b, NULL, NULL, NULL);
- if(!env->key)
- return -1;
- BIO_free(b);
- break;
- default:
- return -1;
- }
-
- return 0;
- }
- int crypto_pk_write_private_key_to_file(crypto_pk_env_t *env, FILE *dest)
- {
- assert(env && dest);
-
- switch(env->type) {
- case CRYPTO_PK_RSA:
- if (!env->key)
- return -1;
- if (PEM_write_RSAPrivateKey(dest, (RSA *)env->key, NULL, NULL, 0,0, NULL) == 0)
- return -1;
- break;
- default :
- return -1;
- }
-
- return 0;
- }
- int crypto_pk_write_public_key_to_file(crypto_pk_env_t *env, FILE *dest)
- {
- assert(env && dest);
-
- switch(env->type) {
- case CRYPTO_PK_RSA:
- if (!env->key)
- return -1;
- if (PEM_write_RSAPublicKey(dest, (RSA *)env->key) == 0)
- return -1;
- break;
- default :
- return -1;
- }
-
- return 0;
- }
- int crypto_pk_check_key(crypto_pk_env_t *env)
- {
- assert(env);
-
- switch(env->type) {
- case CRYPTO_PK_RSA:
- return RSA_check_key((RSA *)env->key);
- default:
- return -1;
- }
- }
- int crypto_pk_set_key(crypto_pk_env_t *env, unsigned char *key)
- {
- assert(env && key);
-
- switch(env->type) {
- case CRYPTO_PK_RSA:
- if (!env->key)
- return -1;
- memcpy((void *)env->key, (void *)key, sizeof(RSA));
- /* XXX BUG XXX you can't memcpy an RSA, it's got a bunch of subpointers */
- break;
- default :
- return -1;
- }
-
- 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);
- }
- crypto_pk_env_t *crypto_pk_dup_key(crypto_pk_env_t *env) {
- assert(env && env->key);
- switch(env->type) {
- case CRYPTO_PK_RSA:
- env->refs++;
- break;
- default:
- return NULL;
- }
-
- return env;
- }
- int crypto_pk_public_encrypt(crypto_pk_env_t *env, unsigned char *from, int fromlen, unsigned char *to, int padding)
- {
- assert(env && from && to);
-
- switch(env->type) {
- case CRYPTO_PK_RSA:
- return RSA_public_encrypt(fromlen, from, to, (RSA *)env->key, padding);
- default:
- return -1;
- }
- }
- int crypto_pk_private_decrypt(crypto_pk_env_t *env, unsigned char *from, int fromlen, unsigned char *to, int padding)
- {
- assert(env && from && to);
-
- switch(env->type) {
- case CRYPTO_PK_RSA:
- return RSA_private_decrypt(fromlen, from, to, (RSA *)env->key, padding);
- default:
- return -1;
- }
- }
- /* 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);
-
- switch(env->type) {
- 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)
- return -1;
- memcpy((void *)env->iv, (void *)iv, 16);
- break;
- default:
- return -1;
- }
-
- return 0;
- }
- int crypto_cipher_set_key(crypto_cipher_env_t *env, unsigned char *key)
- {
- assert(env && key);
-
- switch(env->type) {
- 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)
- return -1;
- memcpy((void *)env->key, (void *)key, 16);
- break;
- default:
- return -1;
- }
-
- return 0;
- }
- int crypto_cipher_encrypt_init_cipher(crypto_cipher_env_t *env)
- {
- assert(env);
- switch(env->type) {
- case CRYPTO_CIPHER_IDENTITY:
- RETURN_SSL_OUTCOME(EVP_EncryptInit((EVP_CIPHER_CTX *)env->aux, EVP_enc_null(), env->key, env->iv));
- case CRYPTO_CIPHER_DES:
- RETURN_SSL_OUTCOME(EVP_EncryptInit((EVP_CIPHER_CTX *)env->aux, EVP_des_ofb(), env->key, env->iv));
- case CRYPTO_CIPHER_RC4:
- RETURN_SSL_OUTCOME(EVP_EncryptInit((EVP_CIPHER_CTX *)env->aux, EVP_rc4(), env->key, env->iv));
- default:
- return -1;
- }
-
- return 0;
- }
- int crypto_cipher_decrypt_init_cipher(crypto_cipher_env_t *env)
- {
- assert(env);
-
- switch(env->type) {
- case CRYPTO_CIPHER_IDENTITY:
- RETURN_SSL_OUTCOME(EVP_DecryptInit((EVP_CIPHER_CTX *)env->aux, EVP_enc_null(), env->key, env->iv));
- case CRYPTO_CIPHER_DES:
- RETURN_SSL_OUTCOME(EVP_DecryptInit((EVP_CIPHER_CTX *)env->aux, EVP_des_ofb(), env->key, env->iv));
- case CRYPTO_CIPHER_RC4:
- RETURN_SSL_OUTCOME(EVP_DecryptInit((EVP_CIPHER_CTX *)env->aux, EVP_rc4(), env->key, env->iv));
- default:
- return -1;
- }
-
- return 0;
- }
- int crypto_cipher_encrypt(crypto_cipher_env_t *env, unsigned char *from, unsigned int fromlen, unsigned char *to)
- {
- int tolen;
-
- assert(env && from && to);
-
- RETURN_SSL_OUTCOME(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 tolen;
-
- assert(env && from && to);
-
- RETURN_SSL_OUTCOME(EVP_DecryptUpdate((EVP_CIPHER_CTX *)env->aux, to, &tolen, from, fromlen));
- }
- /* SHA-1 */
- int crypto_SHA_digest(unsigned char *m, int len, unsigned char *digest)
- {
- assert(m && digest);
- return (SHA1(m,len,digest) == NULL);
- }
- /* random numbers */
- int crypto_rand(unsigned int n, unsigned char *to)
- {
- assert(to);
- return (RAND_bytes(to, n) != 1);
- }
- int crypto_pseudo_rand(unsigned int n, unsigned char *to)
- {
- assert(to);
- return (RAND_pseudo_bytes(to, n) == -1);
- }
- /* errors */
- char *crypto_perror()
- {
- return (char *)ERR_reason_error_string(ERR_get_error());
- }
|