Merge branch 'maint'
[paraslash.git] / crypt.c
diff --git a/crypt.c b/crypt.c
index 352c5b8d8e97832ed3d782ce3ad1984890ad5cf7..49e9e8ae7863fed3f40881a356957f115bf31769 100644 (file)
--- a/crypt.c
+++ b/crypt.c
@@ -65,11 +65,29 @@ void init_random_seed_or_die(void)
        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;
@@ -146,9 +164,20 @@ int para_decrypt_buffer(char *key_file, unsigned char *outbuf, unsigned char *in
        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 > 0)? ret : -E_DECRYPT;
+       return ret;
 }
 
 /**