Merge branch 'refs/heads/t/wma'
[paraslash.git] / crypt.c
1 /*
2  * Copyright (C) 2005 Andre Noll <maan@tuebingen.mpg.de>
3  *
4  * Licensed under the GPL v2. For licencing details see COPYING.
5  */
6
7 /** \file crypt.c Openssl-based encryption/decryption routines. */
8
9 #include <regex.h>
10 #include <sys/types.h>
11 #include <sys/socket.h>
12 #include <openssl/rand.h>
13 #include <openssl/err.h>
14 #include <openssl/pem.h>
15 #include <openssl/sha.h>
16 #include <openssl/bn.h>
17 #include <openssl/aes.h>
18
19 #include "para.h"
20 #include "error.h"
21 #include "string.h"
22 #include "crypt.h"
23 #include "fd.h"
24 #include "crypt_backend.h"
25 #include "base64.h"
26
27 struct asymmetric_key {
28         RSA *rsa;
29 };
30
31 void get_random_bytes_or_die(unsigned char *buf, int num)
32 {
33         unsigned long err;
34
35         /* RAND_bytes() returns 1 on success, 0 otherwise. */
36         if (RAND_bytes(buf, num) == 1)
37                 return;
38         err = ERR_get_error();
39         PARA_EMERG_LOG("%s\n", ERR_reason_error_string(err));
40         exit(EXIT_FAILURE);
41 }
42
43 /*
44  * Read 64 bytes from /dev/urandom and adds them to the SSL PRNG. Seed the PRNG
45  * used by random() with a random seed obtained from SSL. If /dev/random is not
46  * readable the function calls exit().
47  *
48  * \sa RAND_load_file(3), \ref get_random_bytes_or_die(), srandom(3),
49  * random(3), \ref para_random().
50  */
51 void init_random_seed_or_die(void)
52 {
53         int seed, ret = RAND_load_file("/dev/urandom", 64);
54
55         if (ret != 64) {
56                 PARA_EMERG_LOG("could not seed PRNG (ret = %d)\n", ret);
57                 exit(EXIT_FAILURE);
58         }
59         get_random_bytes_or_die((unsigned char *)&seed, sizeof(seed));
60         srandom(seed);
61 }
62
63 static int get_private_key(const char *path, RSA **rsa)
64 {
65         EVP_PKEY *pkey;
66         BIO *bio = BIO_new(BIO_s_file());
67
68         *rsa = NULL;
69         if (!bio)
70                 return -E_PRIVATE_KEY;
71         if (BIO_read_filename(bio, path) <= 0)
72                 goto bio_free;
73         pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
74         if (!pkey)
75                 goto bio_free;
76         *rsa = EVP_PKEY_get1_RSA(pkey);
77         EVP_PKEY_free(pkey);
78 bio_free:
79         BIO_free(bio);
80         return *rsa? RSA_size(*rsa) : -E_PRIVATE_KEY;
81 }
82
83 /*
84  * The public key loading functions below were inspired by corresponding code
85  * of openssh-5.2p1, Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo,
86  * Finland. However, not much of the original code remains.
87  */
88
89 static int read_bignum(const unsigned char *buf, size_t len, BIGNUM **result)
90 {
91         const unsigned char *p = buf, *end = buf + len;
92         uint32_t bnsize;
93         BIGNUM *bn;
94
95         if (p + 4 < p)
96                 return -E_BIGNUM;
97         if (p + 4 > end)
98                 return -E_BIGNUM;
99         bnsize = read_ssh_u32(p);
100         PARA_DEBUG_LOG("bnsize: %u\n", bnsize);
101         p += 4;
102         if (p + bnsize < p)
103                 return -E_BIGNUM;
104         if (p + bnsize > end)
105                 return -E_BIGNUM;
106         if (bnsize > 8192)
107                 return -E_BIGNUM;
108         bn = BN_bin2bn(p, bnsize, NULL);
109         if (!bn)
110                 return -E_BIGNUM;
111         *result = bn;
112         return bnsize + 4;
113 }
114
115 static int read_rsa_bignums(const unsigned char *blob, int blen, RSA **result)
116 {
117         int ret;
118         RSA *rsa;
119         BIGNUM *n, *e;
120         const unsigned char *p = blob, *end = blob + blen;
121
122         rsa = RSA_new();
123         if (!rsa)
124                 return -E_BIGNUM;
125         ret = read_bignum(p, end - p, &e);
126         if (ret < 0)
127                 goto fail;
128         p += ret;
129         ret = read_bignum(p, end - p, &n);
130         if (ret < 0)
131                 goto fail;
132 #ifdef HAVE_RSA_SET0_KEY
133         RSA_set0_key(rsa, n, e, NULL);
134 #else
135         rsa->n = n;
136         rsa->e = e;
137 #endif
138         *result = rsa;
139         return 1;
140 fail:
141         RSA_free(rsa);
142         return ret;
143 }
144
145 int get_public_key(const char *key_file, struct asymmetric_key **result)
146 {
147         struct asymmetric_key *key = NULL;
148         void *map = NULL;
149         unsigned char *blob = NULL;
150         size_t map_size, encoded_size, decoded_size;
151         int ret, ret2;
152         char *cp;
153
154         key = para_malloc(sizeof(*key));
155         ret = mmap_full_file(key_file, O_RDONLY, &map, &map_size, NULL);
156         if (ret < 0)
157                 goto out;
158         ret = is_ssh_rsa_key(map, map_size);
159         if (!ret) {
160                 para_munmap(map, map_size);
161                 return -E_SSH_PARSE;
162         }
163         cp = map + ret;
164         encoded_size = map_size - ret;
165         PARA_INFO_LOG("decoding public rsa-ssh key %s\n", key_file);
166         ret = uudecode(cp, encoded_size, (char **)&blob, &decoded_size);
167         if (ret < 0)
168                 goto out_unmap;
169         ret = check_ssh_key_header(blob, decoded_size);
170         if (ret < 0)
171                 goto out_unmap;
172         ret = read_rsa_bignums(blob + ret, decoded_size - ret, &key->rsa);
173         if (ret < 0)
174                 goto out_unmap;
175         ret = RSA_size(key->rsa);
176 out_unmap:
177         ret2 = para_munmap(map, map_size);
178         if (ret >= 0 && ret2 < 0)
179                 ret = ret2;
180 out:
181         if (ret < 0) {
182                 free(key);
183                 *result = NULL;
184                 PARA_ERROR_LOG("key %s: %s\n", key_file, para_strerror(-ret));
185         } else
186                 *result = key;
187         free(blob);
188         return ret;
189 }
190
191 void free_public_key(struct asymmetric_key *key)
192 {
193         if (!key)
194                 return;
195         RSA_free(key->rsa);
196         free(key);
197 }
198
199 int priv_decrypt(const char *key_file, unsigned char *outbuf,
200                 unsigned char *inbuf, int inlen)
201 {
202         struct asymmetric_key *priv;
203         int ret;
204
205         ret = check_private_key_file(key_file);
206         if (ret < 0)
207                 return ret;
208         if (inlen < 0)
209                 return -E_RSA;
210         priv = para_malloc(sizeof(*priv));
211         ret = get_private_key(key_file, &priv->rsa);
212         if (ret < 0) {
213                 free(priv);
214                 return ret;
215         }
216         /*
217          * RSA is vulnerable to timing attacks. Generate a random blinding
218          * factor to protect against this kind of attack.
219          */
220         ret = -E_BLINDING;
221         if (RSA_blinding_on(priv->rsa, NULL) == 0)
222                 goto out;
223         ret = RSA_private_decrypt(inlen, inbuf, outbuf, priv->rsa,
224                 RSA_PKCS1_OAEP_PADDING);
225         RSA_blinding_off(priv->rsa);
226         if (ret <= 0)
227                 ret = -E_DECRYPT;
228 out:
229         RSA_free(priv->rsa);
230         free(priv);
231         return ret;
232 }
233
234 int pub_encrypt(struct asymmetric_key *pub, unsigned char *inbuf,
235                 unsigned len, unsigned char *outbuf)
236 {
237         int ret, flen = len; /* RSA_public_encrypt expects a signed int */
238
239         if (flen < 0)
240                 return -E_ENCRYPT;
241         ret = RSA_public_encrypt(flen, inbuf, outbuf, pub->rsa,
242                 RSA_PKCS1_OAEP_PADDING);
243         return ret < 0? -E_ENCRYPT : ret;
244 }
245
246 struct stream_cipher {
247         EVP_CIPHER_CTX *aes;
248 };
249
250 struct stream_cipher *sc_new(const unsigned char *data, int len)
251 {
252         struct stream_cipher *sc = para_malloc(sizeof(*sc));
253
254         assert(len >= 2 * AES_CRT128_BLOCK_SIZE);
255         sc->aes = EVP_CIPHER_CTX_new();
256         EVP_EncryptInit_ex(sc->aes, EVP_aes_128_ctr(), NULL, data,
257                 data + AES_CRT128_BLOCK_SIZE);
258         return sc;
259 }
260
261 void sc_free(struct stream_cipher *sc)
262 {
263         if (!sc)
264                 return;
265         EVP_CIPHER_CTX_free(sc->aes);
266         free(sc);
267 }
268
269 static void aes_ctr128_crypt(EVP_CIPHER_CTX *ctx, struct iovec *src,
270                 struct iovec *dst)
271 {
272         int ret, inlen = src->iov_len, outlen, tmplen;
273
274         *dst = (typeof(*dst)) {
275                 /* Add one for the terminating zero byte. */
276                 .iov_base = para_malloc(inlen + 1),
277                 .iov_len = inlen
278         };
279         ret = EVP_EncryptUpdate(ctx, dst->iov_base, &outlen, src->iov_base, inlen);
280         assert(ret != 0);
281         ret = EVP_EncryptFinal_ex(ctx, dst->iov_base + outlen, &tmplen);
282         assert(ret != 0);
283         outlen += tmplen;
284         ((char *)dst->iov_base)[outlen] = '\0';
285         dst->iov_len = outlen;
286 }
287
288 void sc_crypt(struct stream_cipher *sc, struct iovec *src, struct iovec *dst)
289 {
290         return aes_ctr128_crypt(sc->aes, src, dst);
291 }
292
293 void hash_function(const char *data, unsigned long len, unsigned char *hash)
294 {
295         SHA_CTX c;
296         SHA1_Init(&c);
297         SHA1_Update(&c, data, len);
298         SHA1_Final(hash, &c);
299 }