-/*
- * Copyright (C) 2005 Andre Noll <maan@tuebingen.mpg.de>
- *
- * Licensed under the GPL v2. For licencing details see COPYING.
- */
+/* Copyright (C) 2005 Andre Noll <maan@tuebingen.mpg.de>, see file COPYING. */
/** \file crypt.c Openssl-based encryption/decryption routines. */
#include <sys/socket.h>
#include <openssl/rand.h>
#include <openssl/err.h>
-#include <openssl/rc4.h>
#include <openssl/pem.h>
#include <openssl/sha.h>
#include <openssl/bn.h>
#include "fd.h"
#include "crypt_backend.h"
#include "base64.h"
+#include "portable_io.h"
struct asymmetric_key {
RSA *rsa;
}
/*
- * Read 64 bytes from /dev/urandom and adds them to the SSL PRNG. Seed the PRNG
- * used by random() with a random seed obtained from SSL. If /dev/random is not
- * readable the function calls exit().
+ * Read 64 bytes from /dev/urandom and add them to the SSL PRNG. Seed the PRNG
+ * used by random(3) with a random seed obtained from SSL. If /dev/urandom is
+ * not readable, the function calls exit().
*
* \sa RAND_load_file(3), \ref get_random_bytes_or_die(), srandom(3),
* random(3), \ref para_random().
srandom(seed);
}
-static EVP_PKEY *load_key(const char *file)
-{
- BIO *key;
- EVP_PKEY *pkey = NULL;
-
- key = BIO_new(BIO_s_file());
- if (!key)
- return NULL;
- if (BIO_read_filename(key, file) > 0)
- pkey = PEM_read_bio_PrivateKey(key, NULL, NULL, NULL);
- BIO_free(key);
- return pkey;
-}
-
-static int get_private_key(const char *key_file, RSA **rsa)
+static int get_private_key(const char *path, RSA **rsa)
{
- EVP_PKEY *key = load_key(key_file);
+ EVP_PKEY *pkey;
+ BIO *bio = BIO_new(BIO_s_file());
- if (!key)
+ *rsa = NULL;
+ if (!bio)
return -E_PRIVATE_KEY;
- *rsa = EVP_PKEY_get1_RSA(key);
- EVP_PKEY_free(key);
- if (!*rsa)
- return -E_RSA;
- return RSA_size(*rsa);
+ if (BIO_read_filename(bio, path) <= 0)
+ goto bio_free;
+ pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
+ if (!pkey)
+ goto bio_free;
+ *rsa = EVP_PKEY_get1_RSA(pkey);
+ EVP_PKEY_free(pkey);
+bio_free:
+ BIO_free(bio);
+ return *rsa? RSA_size(*rsa) : -E_PRIVATE_KEY;
}
/*
return -E_BIGNUM;
if (p + 4 > end)
return -E_BIGNUM;
- bnsize = read_ssh_u32(p);
+ bnsize = read_u32_be(p);
PARA_DEBUG_LOG("bnsize: %u\n", bnsize);
p += 4;
if (p + bnsize < p)
goto out;
ret = is_ssh_rsa_key(map, map_size);
if (!ret) {
- para_munmap(map, map_size);
- return -E_SSH_PARSE;
+ ret = -E_SSH_PARSE;
+ goto out_unmap;
}
cp = map + ret;
encoded_size = map_size - ret;
}
struct stream_cipher {
- bool use_aes;
- union {
- RC4_KEY rc4_key;
- EVP_CIPHER_CTX *aes;
- } context;
+ EVP_CIPHER_CTX *aes;
};
-struct stream_cipher *sc_new(const unsigned char *data, int len,
- bool use_aes)
+struct stream_cipher *sc_new(const unsigned char *data, int len)
{
struct stream_cipher *sc = para_malloc(sizeof(*sc));
- sc->use_aes = use_aes;
- if (!use_aes) {
- RC4_set_key(&sc->context.rc4_key, len, data);
- return sc;
- }
assert(len >= 2 * AES_CRT128_BLOCK_SIZE);
- sc->context.aes = EVP_CIPHER_CTX_new();
- EVP_EncryptInit_ex(sc->context.aes, EVP_aes_128_ctr(), NULL, data,
+ sc->aes = EVP_CIPHER_CTX_new();
+ EVP_EncryptInit_ex(sc->aes, EVP_aes_128_ctr(), NULL, data,
data + AES_CRT128_BLOCK_SIZE);
return sc;
}
{
if (!sc)
return;
- EVP_CIPHER_CTX_free(sc->context.aes);
+ EVP_CIPHER_CTX_free(sc->aes);
free(sc);
}
-/**
- * The RC4() implementation of openssl apparently reads and writes data in
- * blocks of 8 bytes. So we have to make sure our buffer sizes are a multiple
- * of this.
- */
-#define RC4_ALIGN 8
-
-static void rc4_crypt(RC4_KEY *key, struct iovec *src, struct iovec *dst)
-{
- size_t len = src->iov_len, l1, l2;
-
- assert(len > 0);
- assert(len < ((typeof(src->iov_len))-1) / 2);
- l1 = ROUND_DOWN(len, RC4_ALIGN);
- l2 = ROUND_UP(len, RC4_ALIGN);
-
- *dst = (typeof(*dst)) {
- /* Add one for the terminating zero byte. */
- .iov_base = para_malloc(l2 + 1),
- .iov_len = len
- };
- RC4(key, l1, src->iov_base, dst->iov_base);
- if (len > l1) {
- unsigned char remainder[RC4_ALIGN] = "";
- memcpy(remainder, src->iov_base + l1, len - l1);
- RC4(key, len - l1, remainder, dst->iov_base + l1);
- }
- ((char *)dst->iov_base)[len] = '\0';
-}
-
static void aes_ctr128_crypt(EVP_CIPHER_CTX *ctx, struct iovec *src,
struct iovec *dst)
{
void sc_crypt(struct stream_cipher *sc, struct iovec *src, struct iovec *dst)
{
- if (sc->use_aes)
- return aes_ctr128_crypt(sc->context.aes, src, dst);
- return rc4_crypt(&sc->context.rc4_key, src, dst);
+ return aes_ctr128_crypt(sc->aes, src, dst);
}
void hash_function(const char *data, unsigned long len, unsigned char *hash)