]> git.tuebingen.mpg.de Git - paraslash.git/blob - openssl.c
apc_priv_decrypt: Let the callee allocate the buffer.
[paraslash.git] / openssl.c
1 /* Copyright (C) 2005 Andre Noll <maan@tuebingen.mpg.de>, see file COPYING. */
2
3 /** \file openssl.c Openssl-based encryption/decryption routines. */
4
5 #include <regex.h>
6 #include <sys/types.h>
7 #include <sys/socket.h>
8 #include <openssl/rand.h>
9 #include <openssl/err.h>
10 #include <openssl/pem.h>
11 #include <openssl/sha.h>
12 #include <openssl/bn.h>
13 #include <openssl/aes.h>
14 #include <openssl/evp.h>
15
16 #include "para.h"
17 #include "error.h"
18 #include "string.h"
19 #include "crypt.h"
20 #include "crypt_backend.h"
21 #include "portable_io.h"
22
23 struct asymmetric_key {
24         RSA *rsa;
25 };
26
27 static int openssl_perror(const char *pfx)
28 {
29         unsigned long err = ERR_get_error();
30         PARA_ERROR_LOG("%s: \"%s\"\n", pfx, ERR_reason_error_string(err));
31         return -E_OPENSSL;
32 }
33
34 void get_random_bytes_or_die(unsigned char *buf, int num)
35 {
36         int ret;
37
38         if (RAND_bytes(buf, num) == 1) /* success */
39                 return;
40         ret = openssl_perror("RAND_bytes");
41         PARA_EMERG_LOG("%s\n", strerror(-ret));
42         exit(EXIT_FAILURE);
43 }
44
45 /*
46  * Read 64 bytes from /dev/urandom and add them to the SSL PRNG. Then seed the
47  * PRNG used by random(3) with a random seed obtained from SSL.
48  */
49 void crypt_init(void)
50 {
51         int seed, ret = RAND_load_file("/dev/urandom", 64);
52
53         if (ret != 64) {
54                 PARA_EMERG_LOG("could not seed PRNG (ret = %d)\n", ret);
55                 exit(EXIT_FAILURE);
56         }
57         get_random_bytes_or_die((unsigned char *)&seed, sizeof(seed));
58         srandom(seed);
59 }
60
61 void crypt_shutdown(void)
62 {
63 #ifdef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA
64         CRYPTO_cleanup_all_ex_data();
65 #endif
66 #ifdef HAVE_OPENSSL_THREAD_STOP /* openssl-1.1 or later */
67         OPENSSL_thread_stop();
68 #else /* openssl-1.0 */
69         ERR_remove_thread_state(NULL);
70 #endif
71         EVP_cleanup();
72 }
73
74 /*
75  * The public key loading functions below were inspired by corresponding code
76  * of openssh-5.2p1, Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo,
77  * Finland. However, not much of the original code remains.
78  */
79
80 static int read_bignum(const unsigned char *buf, size_t len, BIGNUM **result)
81 {
82         const unsigned char *p = buf, *end = buf + len;
83         uint32_t bnsize;
84         BIGNUM *bn;
85
86         if (p + 4 < p)
87                 return -E_BIGNUM;
88         if (p + 4 > end)
89                 return -E_BIGNUM;
90         bnsize = read_u32_be(p);
91         PARA_DEBUG_LOG("bnsize: %u\n", bnsize);
92         p += 4;
93         if (p + bnsize < p)
94                 return -E_BIGNUM;
95         if (p + bnsize > end)
96                 return -E_BIGNUM;
97         if (bnsize > 8192)
98                 return -E_BIGNUM;
99         bn = BN_bin2bn(p, bnsize, NULL);
100         if (!bn)
101                 return -E_BIGNUM;
102         *result = bn;
103         return bnsize + 4;
104 }
105
106 static int read_public_key(const unsigned char *blob, int blen,
107                 struct asymmetric_key *result)
108 {
109         int ret;
110         RSA *rsa;
111         BIGNUM *n, *e;
112         const unsigned char *p = blob, *end = blob + blen;
113
114         assert((rsa = RSA_new()));
115         ret = read_bignum(p, end - p, &e);
116         if (ret < 0)
117                 goto free_rsa;
118         p += ret;
119         ret = read_bignum(p, end - p, &n);
120         if (ret < 0)
121                 goto free_e;
122 #ifdef HAVE_RSA_SET0_KEY
123         RSA_set0_key(rsa, n, e, NULL);
124 #else
125         rsa->n = n;
126         rsa->e = e;
127 #endif
128         result->rsa = rsa;
129         return 1;
130 free_e:
131         BN_free(e);
132 free_rsa:
133         RSA_free(rsa);
134         return ret;
135 }
136
137 static int read_pem_private_key(const char *path, struct asymmetric_key *priv)
138 {
139         EVP_PKEY *pkey;
140         BIO *bio;
141
142         assert((bio = BIO_new(BIO_s_file())));
143         priv->rsa = NULL;
144         if (BIO_read_filename(bio, path) <= 0)
145                 goto bio_free;
146         pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
147         if (!pkey)
148                 goto bio_free;
149         priv->rsa = EVP_PKEY_get1_RSA(pkey);
150         EVP_PKEY_free(pkey);
151 bio_free:
152         BIO_free(bio);
153         return priv->rsa? RSA_size(priv->rsa) : -E_PRIVATE_KEY;
154 }
155
156 static int read_openssh_private_key(const unsigned char *blob,
157                 const unsigned char *end, struct asymmetric_key *priv)
158 {
159         int ret;
160         RSA *rsa;
161         BIGNUM *n, *e, *d, *iqmp, *p, *q; /* stored in the key file */
162         const unsigned char *cp = blob;
163
164         assert((rsa = RSA_new()));
165         ret = read_bignum(cp, end - cp, &n);
166         if (ret < 0)
167                 goto free_rsa;
168         cp += ret;
169         ret = read_bignum(cp, end - cp, &e);
170         if (ret < 0)
171                 goto free_n;
172         cp += ret;
173         ret = read_bignum(cp, end - cp, &d);
174         if (ret < 0)
175                 goto free_e;
176         cp += ret;
177         ret = read_bignum(cp, end - cp, &iqmp);
178         if (ret < 0)
179                 goto free_d;
180         cp += ret;
181         ret = read_bignum(cp, end - cp, &p);
182         if (ret < 0)
183                 goto free_iqmp;
184         cp += ret;
185         ret = read_bignum(cp, end - cp, &q);
186         if (ret < 0)
187                 goto free_p;
188 #ifdef HAVE_RSA_SET0_KEY
189         RSA_set0_key(rsa, n, e, d);
190         RSA_set0_factors(rsa, p, q);
191         RSA_set0_crt_params(rsa, NULL, NULL, iqmp);
192
193 #else
194         rsa->n = n;
195         rsa->e = e;
196         rsa->d = d;
197         rsa->iqmp = iqmp;
198         rsa->p = p;
199         rsa->q = q;
200 #endif
201         priv->rsa = rsa;
202         return 1;
203 free_p:
204         BN_clear_free(p);
205 free_iqmp:
206         BN_clear_free(iqmp);
207 free_d:
208         BN_clear_free(d);
209 free_e:
210         BN_free(e);
211 free_n:
212         BN_free(n);
213 free_rsa:
214         RSA_free(rsa);
215         return ret;
216 }
217
218 static int get_private_key(const char *path, struct asymmetric_key *priv)
219 {
220         int ret;
221         unsigned char *blob, *end;
222         size_t blob_size;
223
224         priv->rsa = NULL;
225         ret = decode_private_key(path, &blob, &blob_size);
226         if (ret < 0)
227                 return ret;
228         end = blob + blob_size;
229         if (ret == PKT_OPENSSH) {
230                 ret = find_openssh_bignum_offset(blob, blob_size);
231                 if (ret < 0)
232                         goto free_blob;
233                 PARA_INFO_LOG("reading RSA params at offset %d\n", ret);
234                 ret = read_openssh_private_key(blob + ret, end, priv);
235         } else
236                 ret = read_pem_private_key(path, priv);
237 free_blob:
238         free(blob);
239         return ret;
240 }
241
242 int apc_get_pubkey(const char *key_file, struct asymmetric_key **result)
243 {
244         unsigned char *blob;
245         size_t decoded_size;
246         int ret;
247         struct asymmetric_key *pub = alloc(sizeof(*pub));
248
249         ret = decode_public_key(key_file, &blob, &decoded_size);
250         if (ret < 0)
251                 goto out;
252         ret = read_public_key(blob + ret, decoded_size - ret, pub);
253         if (ret < 0)
254                 goto free_blob;
255         ret = RSA_size(pub->rsa);
256         assert(ret > 0);
257         *result = pub;
258 free_blob:
259         free(blob);
260 out:
261         if (ret < 0) {
262                 free(pub);
263                 *result = NULL;
264                 PARA_ERROR_LOG("can not load key %s\n", key_file);
265         }
266         return ret;
267 }
268
269 void apc_free_pubkey(struct asymmetric_key *pub)
270 {
271         if (!pub)
272                 return;
273         RSA_free(pub->rsa);
274         free(pub);
275 }
276
277 int apc_priv_decrypt(const char *key_file, unsigned char **outbuf,
278                 unsigned char *inbuf, int inlen)
279 {
280         struct asymmetric_key *priv;
281         int ret;
282
283         *outbuf = NULL;
284         ret = check_private_key_file(key_file);
285         if (ret < 0)
286                 return ret;
287         if (inlen < 0)
288                 return -E_RSA;
289         priv = alloc(sizeof(*priv));
290         ret = get_private_key(key_file, priv);
291         if (ret < 0) {
292                 free(priv);
293                 return ret;
294         }
295         /*
296          * RSA is vulnerable to timing attacks. Generate a random blinding
297          * factor to protect against this kind of attack.
298          */
299         ret = -E_BLINDING;
300         if (RSA_blinding_on(priv->rsa, NULL) == 0)
301                 goto out;
302         *outbuf = alloc(RSA_size(priv->rsa));
303         ret = RSA_private_decrypt(inlen, inbuf, *outbuf, priv->rsa,
304                 RSA_PKCS1_OAEP_PADDING);
305         RSA_blinding_off(priv->rsa);
306         if (ret <= 0) {
307                 free(*outbuf);
308                 *outbuf = NULL;
309                 ret = -E_DECRYPT;
310         }
311 out:
312         RSA_free(priv->rsa);
313         free(priv);
314         return ret;
315 }
316
317 int apc_pub_encrypt(struct asymmetric_key *pub, unsigned char *inbuf,
318                 unsigned len, unsigned char **outbuf)
319 {
320         int ret, flen = len; /* RSA_public_encrypt expects a signed int */
321
322         *outbuf = NULL;
323         if (flen < 0)
324                 return -E_ENCRYPT;
325         *outbuf = alloc(RSA_size(pub->rsa));
326         ret = RSA_public_encrypt(flen, inbuf, *outbuf, pub->rsa,
327                 RSA_PKCS1_OAEP_PADDING);
328         if (ret < 0) {
329                 free(*outbuf);
330                 *outbuf = NULL;
331                 return -E_ENCRYPT;
332         }
333         return ret;
334 }
335
336 struct stream_cipher {
337         EVP_CIPHER_CTX *aes;
338 };
339
340 struct stream_cipher *sc_new(const unsigned char *data, int len)
341 {
342         struct stream_cipher *sc = alloc(sizeof(*sc));
343
344         assert(len >= 2 * AES_CRT128_BLOCK_SIZE);
345         assert((sc->aes = EVP_CIPHER_CTX_new()));
346         EVP_EncryptInit_ex(sc->aes, EVP_aes_128_ctr(), NULL, data,
347                 data + AES_CRT128_BLOCK_SIZE);
348         return sc;
349 }
350
351 void sc_free(struct stream_cipher *sc)
352 {
353         if (!sc)
354                 return;
355         EVP_CIPHER_CTX_free(sc->aes);
356         free(sc);
357 }
358
359 static void aes_ctr128_crypt(EVP_CIPHER_CTX *ctx, struct iovec *src,
360                 struct iovec *dst)
361 {
362         int ret, inlen = src->iov_len, outlen, tmplen;
363
364         *dst = (typeof(*dst)) {
365                 /* Add one for the terminating zero byte. */
366                 .iov_base = alloc(inlen + 1),
367                 .iov_len = inlen
368         };
369         ret = EVP_EncryptUpdate(ctx, dst->iov_base, &outlen, src->iov_base, inlen);
370         assert(ret != 0);
371         ret = EVP_EncryptFinal_ex(ctx, dst->iov_base + outlen, &tmplen);
372         assert(ret != 0);
373         outlen += tmplen;
374         ((char *)dst->iov_base)[outlen] = '\0';
375         dst->iov_len = outlen;
376 }
377
378 void sc_crypt(struct stream_cipher *sc, struct iovec *src, struct iovec *dst)
379 {
380         return aes_ctr128_crypt(sc->aes, src, dst);
381 }
382
383 void hash_function(const char *data, unsigned long len, unsigned char *hash)
384 {
385         int ret;
386         EVP_MD_CTX *c;
387
388         assert((c = EVP_MD_CTX_new()));
389         ret = EVP_DigestInit_ex(c, EVP_sha1(), NULL);
390         assert(ret != 0);
391         ret = EVP_DigestUpdate(c, data, len);
392         assert(ret != 0);
393         ret = EVP_DigestFinal_ex(c, hash, NULL);
394         assert(ret != 0);
395         EVP_MD_CTX_free(c);
396 }
397
398 void hash2_function(const char *data, unsigned long len, unsigned char *hash)
399 {
400         int ret;
401         EVP_MD_CTX *c;
402
403         assert((c = EVP_MD_CTX_new()));
404         ret = EVP_DigestInit_ex(c, EVP_sha256(), NULL);
405         assert(ret != 0);
406         ret = EVP_DigestUpdate(c, data, len);
407         assert(ret != 0);
408         ret = EVP_DigestFinal_ex(c, hash, NULL);
409         assert(ret != 0);
410         EVP_MD_CTX_free(c);
411 }