X-Git-Url: http://git.tuebingen.mpg.de/?a=blobdiff_plain;ds=inline;f=crypt.c;h=580974d7d74a6b97d1f4b2d6a436adc98ba7408b;hb=5d91cb9b0ed833517cc9288e9ca802d8a1b62757;hp=cf1cabecbad80cdca6d69cf2bbc2165427a84ed8;hpb=1fe76952bf4244b93808da5e8fc45e92d8b37c58;p=paraslash.git diff --git a/crypt.c b/crypt.c index cf1cabec..580974d7 100644 --- a/crypt.c +++ b/crypt.c @@ -1,19 +1,7 @@ /* - * Copyright (C) 2005-2006 Andre Noll + * Copyright (C) 2005-2009 Andre Noll * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + * Licensed under the GPL v2. For licencing details see COPYING. */ /** \file crypt.c openssl-based RSA encryption/decryption routines */ @@ -22,6 +10,54 @@ #include "error.h" #include "string.h" #include "crypt.h" +#include +#include + +/** + * Fill a buffer with random content. + * + * \param buf The buffer to fill. + * \param num The size of \a buf in bytes. + * + * This function puts \a num cryptographically strong pseudo-random bytes into + * buf. If libssl can not guarantee an unpredictable byte sequence (for example + * because the PRNG has not been seeded with enough randomness) the function + * logs an error message and calls exit(). + */ +void get_random_bytes_or_die(unsigned char *buf, int num) +{ + unsigned long err; + + /* RAND_bytes() returns 1 on success, 0 otherwise. */ + if (RAND_bytes(buf, num) == 1) + return; + err = ERR_get_error(); + PARA_EMERG_LOG("%s\n", ERR_reason_error_string(err)); + exit(EXIT_FAILURE); +} + +/** + * Seed pseudo random number generators. + * + * This function reads 64 bytes from /dev/urandom and adds them to the SSL + * PRNG. It also seeds the PRNG used by random() with a random seed obtained + * from SSL. If /dev/random could not be read, an error message is logged and + * the function calls exit(). + * + * \sa RAND_load_file(3), \ref get_random_bytes_or_die(), srandom(3), + * random(3), \ref para_random(). + */ +void init_random_seed_or_die(void) +{ + int seed, ret = RAND_load_file("/dev/urandom", 64); + + if (ret != 64) { + PARA_EMERG_LOG("could not seed PRNG (ret = %d)\n", ret); + exit(EXIT_FAILURE); + } + get_random_bytes_or_die((unsigned char *)&seed, sizeof(seed)); + srandom(seed); +} static EVP_PKEY *load_key(const char *file, int private) { @@ -41,13 +77,24 @@ static EVP_PKEY *load_key(const char *file, int private) return pkey; } - +/** + * read an RSA key from a file + * + * \param key_file the file containing the key + * \param rsa RSA structure is returned here + * \param private if non-zero, read the private key, otherwise the public key + * + * \return The size of the RSA key on success, negative on errors. + * + * \sa openssl(1), rsa(1). + */ int get_rsa_key(char *key_file, RSA **rsa, int private) { EVP_PKEY *key = load_key(key_file, private); if (!key) - return (private == LOAD_PRIVATE_KEY)? -E_PRIVATE_KEY : -E_PUBLIC_KEY; + return (private == LOAD_PRIVATE_KEY)? -E_PRIVATE_KEY + : -E_PUBLIC_KEY; *rsa = EVP_PKEY_get1_RSA(key); EVP_PKEY_free(key); if (!*rsa) @@ -55,6 +102,19 @@ int get_rsa_key(char *key_file, RSA **rsa, int private) return RSA_size(*rsa); } +/** + * free an RSA structure + * + * \param rsa pointer to the RSA struct to free + * + * This must be called for any key obtained by get_rsa_key(). + */ +void rsa_free(RSA *rsa) +{ + if (rsa) + RSA_free(rsa); +} + /** * decrypt a buffer using an RSA key * @@ -70,14 +130,18 @@ int get_rsa_key(char *key_file, RSA **rsa, int private) * \sa RSA_private_decrypt(3) **/ int para_decrypt_buffer(char *key_file, unsigned char *outbuf, unsigned char *inbuf, - int rsa_inlen) + unsigned rsa_inlen) { RSA *rsa; - int ret = get_rsa_key(key_file, &rsa, LOAD_PRIVATE_KEY); + int ret, inlen = rsa_inlen; + if (inlen < 0) + return -E_RSA; + ret = get_rsa_key(key_file, &rsa, LOAD_PRIVATE_KEY); if (ret < 0) return ret; - ret = RSA_private_decrypt(rsa_inlen, inbuf, outbuf, rsa, RSA_PKCS1_PADDING); + ret = RSA_private_decrypt(inlen, inbuf, outbuf, rsa, RSA_PKCS1_PADDING); + rsa_free(rsa); return (ret > 0)? ret : -E_DECRYPT; } @@ -94,7 +158,7 @@ int para_decrypt_buffer(char *key_file, unsigned char *outbuf, unsigned char *in * \sa para_decrypt_buffer() */ int para_decrypt_challenge(char *key_file, long unsigned *challenge_nr, - unsigned char *inbuf, int rsa_inlen) + unsigned char *inbuf, unsigned rsa_inlen) { unsigned char *rsa_out = OPENSSL_malloc(rsa_inlen + 1); int ret = para_decrypt_buffer(key_file, rsa_out, inbuf, rsa_inlen); @@ -121,10 +185,13 @@ int para_decrypt_challenge(char *key_file, long unsigned *challenge_nr, * \sa RSA_public_encrypt(3) */ int para_encrypt_buffer(RSA *rsa, unsigned char *inbuf, - const unsigned len, unsigned char *outbuf) + unsigned len, unsigned char *outbuf) { - int ret = RSA_public_encrypt(len, inbuf, outbuf, rsa, - RSA_PKCS1_PADDING); + int ret, flen = len; /* RSA_public_encrypt expects a signed int */ + + if (flen < 0) + return -E_ENCRYPT; + ret = RSA_public_encrypt(flen, inbuf, outbuf, rsa, RSA_PKCS1_PADDING); return ret < 0? -E_ENCRYPT : ret; }