/*
- * Copyright (C) 2005-2011 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2012 Andre Noll <maan@systemlinux.org>
*
* Licensed under the GPL v2. For licencing details see COPYING.
*/
/** \file crypt.c Openssl-based encryption/decryption routines. */
#include <regex.h>
-#include <stdbool.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <openssl/rand.h>
RSA *rsa;
};
-/**
- * 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;
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().
+/*
+ * 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().
*
* \sa RAND_load_file(3), \ref get_random_bytes_or_die(), srandom(3),
* random(3), \ref para_random().
return ret;
}
-/**
- * Read an asymmetric key from a file.
- *
- * \param key_file The file containing the key.
- * \param private if non-zero, read the private key, otherwise the public key.
- * \param result The key structure is returned here.
- *
- * \return The size of the key on success, negative on errors.
- *
- * \sa openssl(1), rsa(1).
- */
int get_asymmetric_key(const char *key_file, int private,
struct asymmetric_key **result)
{
PARA_INFO_LOG("decoding public rsa-ssh key %s\n", key_file);
ret = -ERRNO_TO_PARA_ERROR(EOVERFLOW);
if (map_size > INT_MAX / 4)
- goto out;
+ goto out_unmap;
blob_size = 2 * map_size;
blob = para_malloc(blob_size);
ret = uudecode(cp, blob, blob_size);
if (ret < 0)
- goto out;
+ goto out_unmap;
decoded_size = ret;
ret = check_ssh_key_header(blob, decoded_size);
if (ret < 0)
- goto out;
+ goto out_unmap;
ret = read_rsa_bignums(blob + ret, decoded_size - ret, &key->rsa);
if (ret < 0)
- goto out;
+ goto out_unmap;
ret = RSA_size(key->rsa);
-out:
+out_unmap:
ret2 = para_munmap(map, map_size);
if (ret >= 0 && ret2 < 0)
ret = ret2;
+out:
if (ret < 0) {
free(key);
- result = NULL;
+ *result = NULL;
PARA_ERROR_LOG("key %s: %s\n", key_file, para_strerror(-ret));
} else
*result = key;
return ret;
}
-/**
- * Deallocate an asymmetric key structure.
- *
- * \param key Pointer to the key structure to free.
- *
- * This must be called for any key obtained by get_asymmetric_key().
- */
void free_asymmetric_key(struct asymmetric_key *key)
{
if (!key)
free(key);
}
-/**
- * Decrypt a buffer using a private key.
- *
- * \param key_file Full path of the key.
- * \param outbuf The output buffer.
- * \param inbuf The encrypted input buffer.
- * \param inlen The length of \a inbuf in bytes.
- *
- * 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 priv_decrypt(const char *key_file, unsigned char *outbuf,
unsigned char *inbuf, int inlen)
{
return ret;
}
-/**
- * Encrypt a buffer using an RSA key
- *
- * \param pub: The public 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 pub_encrypt(struct asymmetric_key *pub, unsigned char *inbuf,
unsigned len, unsigned char *outbuf)
{
RC4_KEY key;
};
-/**
- * Allocate and initialize a stream cipher structure.
- *
- * \param data The key.
- * \param len The size of the key.
- *
- * \return A new stream cipher structure.
- */
struct stream_cipher *sc_new(const unsigned char *data, int len)
{
struct stream_cipher *sc = para_malloc(sizeof(*sc));
return sc;
}
-/**
- * Deallocate a stream cipher structure.
- *
- * \param sc A stream cipher previously obtained by sc_new().
- */
void sc_free(struct stream_cipher *sc)
{
free(sc);
*/
#define RC4_ALIGN 8
-/**
- * Encrypt and send a buffer.
- *
- * \param scc The 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 sc_send_bin_buffer(struct stream_cipher_context *scc, const char *buf,
+int sc_send_bin_buffer(struct stream_cipher_context *scc, char *buf,
size_t len)
{
int ret;
memcpy(remainder, buf + l1, len - l1);
RC4(&scc->send->key, len - l1, remainder, tmp + l1);
}
- ret = write_all(scc->fd, (char *)tmp, &len);
+ ret = xwrite(scc->fd, (char *)tmp, len);
free(tmp);
return ret;
}
-/**
- * Receive a buffer and decrypt it.
- *
- * \param scc The 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 sc_recv_bin_buffer(struct stream_cipher_context *scc, char *buf,
size_t size)
{
- unsigned char *tmp = para_malloc(size);
+ unsigned char *tmp = para_malloc(ROUND_UP(size, RC4_ALIGN));
ssize_t ret = recv(scc->fd, tmp, size, 0);
if (ret > 0)
return ret;
}
-/**
- * Compute the hash of the given input data.
- *
- * \param data Pointer to the data to compute the hash value from.
- * \param len The length of \a data in bytes.
- * \param hash Result pointer.
- *
- * \a hash must point to an area at least \p HASH_SIZE bytes large.
- *
- * \sa sha(3), openssl(1).
- * */
+void sc_crypt(struct stream_cipher *sc, struct iovec *src, struct iovec *dst)
+{
+ RC4_KEY *key = &sc->key;
+
+ *dst = (typeof(*dst)) {
+ /*
+ * Add one for the terminating zero byte. Integer overflow is
+ * no problem here as para_malloc() aborts when given a zero
+ * size argument.
+ */
+ .iov_base = para_malloc(src->iov_len + 1),
+ .iov_len = src->iov_len
+ };
+ RC4(key, src->iov_len, src->iov_base, dst->iov_base);
+ ((char *)dst->iov_base)[dst->iov_len] = '\0';
+}
+
void hash_function(const char *data, unsigned long len, unsigned char *hash)
{
SHA_CTX c;