/*
- * Copyright (C) 2005-2009 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2011 Andre Noll <maan@systemlinux.org>
*
* Licensed under the GPL v2. For licencing details see COPYING.
*/
/** \file crypt.c openssl-based RSA encryption/decryption routines */
+#include <regex.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/socket.h>
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;
ret = get_rsa_key(key_file, &rsa, LOAD_PRIVATE_KEY);
if (ret < 0)
return ret;
- ret = RSA_private_decrypt(inlen, inbuf, outbuf, rsa, RSA_PKCS1_PADDING);
+ /*
+ * 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 > 0)? ret : -E_DECRYPT;
-}
-
-/**
- * decrypt the challenge number sent by para_server
- *
- * \param key_file full path of the rsa key
- * \param challenge_nr result is stored here
- * \param inbuf the input buffer
- * \param rsa_inlen the length of \a inbuf
- *
- * \return positive on success, negative on errors
- *
- * \sa para_decrypt_buffer()
- */
-int para_decrypt_challenge(char *key_file, long unsigned *challenge_nr,
- 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);
-
- if (ret >= 0) {
- rsa_out[ret] = '\0';
- ret = sscanf((char *)rsa_out, "%lu", challenge_nr) == 1?
- 1 : -E_CHALLENGE;
- }
- OPENSSL_free(rsa_out);
return ret;
}
if (flen < 0)
return -E_ENCRYPT;
- ret = RSA_public_encrypt(flen, inbuf, outbuf, rsa, RSA_PKCS1_PADDING);
- return ret < 0? -E_ENCRYPT : ret;
-}
-
-/**
- * encrypt the given challenge number
- *
- * \param rsa: public rsa key
- * \param challenge_nr the number to be encrypted
- * \param outbuf the output buffer
- *
- * \a outbuf must be at least 64 bytes long
- *
- * \return The size of the encrypted data on success, negative on errors
- *
- * \sa para_encrypt_buffer()
- *
- */
-int para_encrypt_challenge(RSA* rsa, long unsigned challenge_nr,
- unsigned char *outbuf)
-{
- unsigned char *inbuf = (unsigned char*) make_message("%lu", challenge_nr);
- int ret = para_encrypt_buffer(rsa, inbuf, strlen((char *)inbuf), outbuf);
- free(inbuf);
- return ret;
+ ret = RSA_public_encrypt(flen, inbuf, outbuf, rsa, RSA_PKCS1_OAEP_PADDING);
+ return ret < 0? -E_ENCRYPT : ret;
}
/**
unsigned char *tmp;
assert(len);
- tmp = para_malloc(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);