X-Git-Url: http://git.tuebingen.mpg.de/?a=blobdiff_plain;f=crypt.c;h=8116fb6eeacdbeaa0f1f22d14cfcc3726ee3bbbf;hb=refs%2Fheads%2Fmaint;hp=917948c6185710fb828b441025b8d46a0fdc2924;hpb=a365b8263a0d7a1673699bdf454677c95b38eb95;p=paraslash.git diff --git a/crypt.c b/crypt.c deleted file mode 100644 index 917948c6..00000000 --- a/crypt.c +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright (C) 2005-2011 Andre Noll - * - * Licensed under the GPL v2. For licencing details see COPYING. - */ - -/** \file crypt.c openssl-based RSA encryption/decryption routines */ - -#include -#include -#include -#include -#include -#include -#include - -#include "para.h" -#include "error.h" -#include "string.h" -#include "crypt.h" -#include "fd.h" -/** - * 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 int check_key_file(const char *file, int private) -{ - struct stat st; - - if (stat(file, &st) != 0) - return -ERRNO_TO_PARA_ERROR(errno); - if (private != LOAD_PRIVATE_KEY) - return 0; - if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0) - return -E_KEY_PERM; - return 1; -} - -static EVP_PKEY *load_key(const char *file, int private) -{ - BIO *key; - EVP_PKEY *pkey = NULL; - int ret = check_key_file(file, private); - - if (ret < 0) { - PARA_ERROR_LOG("%s\n", para_strerror(-ret)); - return NULL; - } - key = BIO_new(BIO_s_file()); - if (!key) - return NULL; - if (BIO_read_filename(key, file) > 0) { - if (private == LOAD_PRIVATE_KEY) - pkey = PEM_read_bio_PrivateKey(key, NULL, NULL, NULL); - else - pkey = PEM_read_bio_PUBKEY(key, NULL, NULL, NULL); - } - BIO_free(key); - 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; - *rsa = EVP_PKEY_get1_RSA(key); - EVP_PKEY_free(key); - if (!*rsa) - return -E_RSA; - 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 - * - * \param key_file full path of the rsa key - * \param outbuf the output buffer - * \param inbuf the encrypted input buffer - * \param rsa_inlen the length of \a inbuf - * - * The \a outbuf must be large enough to hold at least \a rsa_inlen bytes. - * - * \return The size of the recovered plaintext on success, negative on errors. - * - * \sa RSA_private_decrypt(3) - **/ -int para_decrypt_buffer(char *key_file, unsigned char *outbuf, unsigned char *inbuf, - unsigned rsa_inlen) -{ - RSA *rsa; - 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; - /* - * RSA is vulnerable to timing attacks. Generate a random blinding - * factor to protect against this kind of attack. - */ - ret = -E_BLINDING; - if (RSA_blinding_on(rsa, NULL) == 0) - goto out; - ret = RSA_private_decrypt(inlen, inbuf, outbuf, rsa, RSA_PKCS1_OAEP_PADDING); - RSA_blinding_off(rsa); - if (ret <= 0) - ret = -E_DECRYPT; -out: - rsa_free(rsa); - return ret; -} - -/** - * encrypt a buffer using an RSA key - * - * \param rsa: public rsa key - * \param inbuf the input buffer - * \param len the length of \a inbuf - * \param outbuf the output buffer - * - * \return The size of the encrypted data on success, negative on errors - * - * \sa RSA_public_encrypt(3) - */ -int para_encrypt_buffer(RSA *rsa, unsigned char *inbuf, - unsigned len, unsigned char *outbuf) -{ - 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_OAEP_PADDING); - return ret < 0? -E_ENCRYPT : ret; -} - -/** - * Encrypt and send a buffer. - * - * \param rc4c The rc4 crypt context. - * \param buf The buffer to send. - * \param len The size of \a buf in bytes. - * - * \return The return value of the underyling call to write_all(). - * - * \sa \ref write_all(), RC4(3). - */ -int rc4_send_bin_buffer(struct rc4_context *rc4c, const char *buf, size_t len) -{ - int ret; - unsigned char *tmp; - - assert(len); - tmp = para_malloc(len + 8); - RC4(&rc4c->send_key, len, (const unsigned char *)buf, tmp); - ret = write_all(rc4c->fd, (char *)tmp, &len); - free(tmp); - return ret; -} - -/** - * Encrypt and send a \p NULL-terminated buffer. - * - * \param rc4c The rc4 crypt context. - * \param buf The buffer to send. - * - * \return The return value of the underyling call to rc4_send_bin_buffer(). - */ -int rc4_send_buffer(struct rc4_context *rc4c, const char *buf) -{ - return rc4_send_bin_buffer(rc4c, buf, strlen(buf)); -} - -/** - * Format, encrypt and send a buffer. - * - * \param rc4c The rc4 crypt context. - * \param fmt A format string. - * - * \return The return value of the underyling call to rc4_send_buffer(). - */ -__printf_2_3 int rc4_send_va_buffer(struct rc4_context *rc4c, const char *fmt, ...) -{ - char *msg; - int ret; - - PARA_VSPRINTF(fmt, msg); - ret = rc4_send_buffer(rc4c, msg); - free(msg); - return ret; -} - -/** - * Receive a buffer and decrypt it. - * - * \param rc4c The rc4 crypt context. - * \param buf The buffer to write the decrypted data to. - * \param size The size of \a buf. - * - * \return The number of bytes received on success, negative on errors, zero if - * the peer has performed an orderly shutdown. - * - * \sa recv(2), RC4(3). - */ -int rc4_recv_bin_buffer(struct rc4_context *rc4c, char *buf, size_t size) -{ - unsigned char *tmp = para_malloc(size); - ssize_t ret = recv(rc4c->fd, tmp, size, 0); - - if (ret > 0) - RC4(&rc4c->recv_key, ret, tmp, (unsigned char *)buf); - else if (ret < 0) - ret = -ERRNO_TO_PARA_ERROR(errno); - free(tmp); - return ret; -} - -/** - * Receive a buffer, decrypt it and write terminating NULL byte. - * - * \param rc4c The rc4 crypt context. - * \param buf The buffer to write the decrypted data to. - * \param size The size of \a buf. - * - * Read at most \a size - 1 bytes from file descriptor given by \a rc4c, - * decrypt the received data and write a NULL byte at the end of the decrypted - * data. - * - * \return The return value of the underlying call to \ref - * rc4_recv_bin_buffer(). - */ -int rc4_recv_buffer(struct rc4_context *rc4c, char *buf, size_t size) -{ - int n; - - assert(size); - n = rc4_recv_bin_buffer(rc4c, buf, size - 1); - if (n >= 0) - buf[n] = '\0'; - else - *buf = '\0'; - return n; -}