]> git.tuebingen.mpg.de Git - paraslash.git/blob - openssl.c
openssl: Use the EVP library for RSA private decryption.
[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         EVP_PKEY *pkey;
26         EVP_PKEY_CTX *ctx;
27 };
28
29 static int openssl_perror(const char *pfx)
30 {
31         unsigned long err = ERR_get_error();
32         PARA_ERROR_LOG("%s: \"%s\"\n", pfx, ERR_reason_error_string(err));
33         return -E_OPENSSL;
34 }
35
36 void get_random_bytes_or_die(unsigned char *buf, int num)
37 {
38         int ret;
39
40         if (RAND_bytes(buf, num) == 1) /* success */
41                 return;
42         ret = openssl_perror("RAND_bytes");
43         PARA_EMERG_LOG("%s\n", strerror(-ret));
44         exit(EXIT_FAILURE);
45 }
46
47 /*
48  * Read 64 bytes from /dev/urandom and add them to the SSL PRNG. Then seed the
49  * PRNG used by random(3) with a random seed obtained from SSL.
50  */
51 void crypt_init(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 void crypt_shutdown(void)
64 {
65 #ifdef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA
66         CRYPTO_cleanup_all_ex_data();
67 #endif
68 #ifdef HAVE_OPENSSL_THREAD_STOP /* openssl-1.1 or later */
69         OPENSSL_thread_stop();
70 #else /* openssl-1.0 */
71         ERR_remove_thread_state(NULL);
72 #endif
73         EVP_cleanup();
74 }
75
76 /*
77  * The public key loading functions below were inspired by corresponding code
78  * of openssh-5.2p1, Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo,
79  * Finland. However, not much of the original code remains.
80  */
81
82 static int read_bignum(const unsigned char *buf, size_t len, BIGNUM **result)
83 {
84         const unsigned char *p = buf, *end = buf + len;
85         uint32_t bnsize;
86         BIGNUM *bn;
87
88         if (p + 4 < p)
89                 return -E_BIGNUM;
90         if (p + 4 > end)
91                 return -E_BIGNUM;
92         bnsize = read_u32_be(p);
93         PARA_DEBUG_LOG("bnsize: %u\n", bnsize);
94         p += 4;
95         if (p + bnsize < p)
96                 return -E_BIGNUM;
97         if (p + bnsize > end)
98                 return -E_BIGNUM;
99         if (bnsize > 8192)
100                 return -E_BIGNUM;
101         bn = BN_bin2bn(p, bnsize, NULL);
102         if (!bn)
103                 return -E_BIGNUM;
104         *result = bn;
105         return bnsize + 4;
106 }
107
108 #ifdef HAVE_OSSL_PARAM /* openssl-3 */
109
110 static int generate_private_pkey(struct asymmetric_key *priv,
111                 const BIGNUM *n, const BIGNUM *e, const BIGNUM *d,
112                 const BIGNUM *p, const BIGNUM *q)
113 {
114         const BIGNUM *bignums[] = {n, e, d, p, q};
115         const char *strings[] = {"n", "e", "d", "p", "q"};
116         int ret, bytes[ARRAY_SIZE(bignums)];
117         unsigned char *bufs[ARRAY_SIZE(bignums)];
118         OSSL_PARAM params[ARRAY_SIZE(bignums) + 1];
119         /*
120          * Convert bignums to buffers for OSSL_PARAM_construct_BN() and init
121          * params[].
122          */
123         for (int i = 0; i < ARRAY_SIZE(bignums); i++) {
124                 bytes[i] = BN_num_bytes(bignums[i]);
125                 PARA_DEBUG_LOG("%s: %d bits\n", strings[i], bytes[i] * 8);
126                 bufs[i] = alloc(bytes[i]);
127                 assert(BN_bn2nativepad(bignums[i], bufs[i], bytes[i]) > 0);
128                 params[i] = OSSL_PARAM_construct_BN(strings[i], bufs[i],
129                         bytes[i]);
130         }
131         params[ARRAY_SIZE(bignums)] = OSSL_PARAM_construct_end();
132         /* Transfer buffers to openssl to create the pkey from it */
133         priv->ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
134         assert(priv->ctx);
135         assert(EVP_PKEY_fromdata_init(priv->ctx) > 0);
136         ret = EVP_PKEY_fromdata(priv->ctx, &priv->pkey,
137                 EVP_PKEY_KEYPAIR, params);
138         for (int i = 0; i < ARRAY_SIZE(bignums); i++)
139                 free(bufs[i]);
140         if (ret <= 0) {
141                 EVP_PKEY_CTX_free(priv->ctx);
142                 return openssl_perror("EVP_PKEY_fromdata()");
143         }
144         assert(priv->pkey);
145         return BN_num_bytes(n) * 8;
146 }
147
148 /*
149  * Convert bignumns e and n to a pkey and context.
150  */
151 static int generate_public_pkey(struct asymmetric_key *pub,
152                 const BIGNUM *e, const BIGNUM *n)
153 {
154         unsigned char *ebuf, *nbuf;
155         int ret, ebytes = BN_num_bytes(e), nbytes = BN_num_bytes(n);
156         OSSL_PARAM params[3];
157
158         /* Convert e and n to a buffer for OSSL_PARAM_construct_BN() */
159         ebuf = alloc(ebytes);
160         assert(BN_bn2nativepad(e, ebuf, ebytes) > 0);
161         nbuf = alloc(nbytes);
162         assert(BN_bn2nativepad(n, nbuf, nbytes) > 0);
163         /* Init params[] with {e,n}buf and create the pkey from it */
164         params[0] = OSSL_PARAM_construct_BN("e", ebuf, ebytes);
165         params[1] = OSSL_PARAM_construct_BN("n", nbuf, nbytes);
166         params[2] = OSSL_PARAM_construct_end();
167         pub->ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
168         assert(pub->ctx);
169         assert(EVP_PKEY_fromdata_init(pub->ctx) > 0);
170         ret = EVP_PKEY_fromdata(pub->ctx, &pub->pkey, EVP_PKEY_PUBLIC_KEY,
171                 params);
172         free(nbuf);
173         free(ebuf);
174         if (ret <= 0) {
175                 EVP_PKEY_CTX_free(pub->ctx);
176                 return openssl_perror("EVP_PKEY_fromdata()");
177         }
178         assert(pub->pkey);
179         return nbytes * 8;
180 }
181
182 #endif /* HAVE_OSSL_PARAM */
183
184 static int read_public_key(const unsigned char *blob, size_t blen,
185                 struct asymmetric_key *pub)
186 {
187         int ret, bits;
188         const unsigned char *p = blob, *end = blob + blen;
189         BIGNUM *e, *n;
190
191         ret = read_bignum(p, end - p, &e);
192         if (ret < 0)
193                 return ret;
194         p += ret;
195         ret = read_bignum(p, end - p, &n);
196         if (ret < 0) {
197                 BN_free(e);
198                 return ret;
199         }
200         bits = BN_num_bytes(n) * 8;
201         PARA_DEBUG_LOG("modulus: %d bits\n", bits);
202 #ifdef HAVE_OSSL_PARAM /* openssl-3 */
203         ret = generate_public_pkey(pub, e, n);
204         BN_free(e);
205         BN_free(n);
206         if (ret < 0)
207                 return ret;
208 #else /* openssl < 3.0 */
209         pub->rsa = RSA_new();
210         assert(pub->rsa);
211         #if HAVE_RSA_SET0_KEY /* openssl-1.1 */
212                 RSA_set0_key(pub->rsa, n, e, NULL);
213         #else /* openssl-1.0 */
214                 pub->rsa->n = n;
215                 pub->rsa->e = e;
216         #endif
217         /* e and n are now owned by openssl */
218 #endif /* HAVE_OSSL_PARAM */
219         return bits;
220 }
221
222 static int read_pem_private_key(const char *path, struct asymmetric_key *priv)
223 {
224         BIO *bio;
225         int ret;
226
227         assert((bio = BIO_new(BIO_s_file())));
228         ret = BIO_read_filename(bio, path);
229         if (ret <= 0) {
230                 priv->pkey = NULL;
231                 ret = openssl_perror("BIO_read_filename");
232                 goto free_bio;
233         }
234         priv->pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
235         if (!priv->pkey) {
236                 ret = openssl_perror("PEM_read_bio_PrivateKey");
237                 goto free_bio;
238         }
239 #ifndef HAVE_OSSL_PARAM /* openssl-1 */
240         priv->rsa = EVP_PKEY_get1_RSA(priv->pkey);
241 #endif
242 free_bio:
243         BIO_free(bio);
244         return ret;
245 }
246
247 static int read_openssh_private_key(const unsigned char *blob,
248                 const unsigned char *end, struct asymmetric_key *priv)
249 {
250         int ret;
251         BIGNUM *n, *e, *d, *iqmp, *p, *q; /* stored in the key file */
252         const unsigned char *cp = blob;
253
254         ret = read_bignum(cp, end - cp, &n);
255         if (ret < 0)
256                 return ret;
257         cp += ret;
258         ret = read_bignum(cp, end - cp, &e);
259         if (ret < 0)
260                 goto free_n;
261         cp += ret;
262         ret = read_bignum(cp, end - cp, &d);
263         if (ret < 0)
264                 goto free_e;
265         cp += ret;
266         ret = read_bignum(cp, end - cp, &iqmp);
267         if (ret < 0)
268                 goto free_d;
269         cp += ret;
270         ret = read_bignum(cp, end - cp, &p);
271         if (ret < 0)
272                 goto free_iqmp;
273         cp += ret;
274         ret = read_bignum(cp, end - cp, &q);
275         if (ret < 0)
276                 goto free_p;
277 #ifdef HAVE_OSSL_PARAM /* openssl-3 */
278         /*
279          * Ignore iqmp, the coefficient for Chinese remainder theorem. It is
280          * dispensable because it can be derived from the other values. Passing
281          * it to the EVP API results in a memory leak.
282          */
283         ret = generate_private_pkey(priv, n, e, d, p, q);
284 #else
285         assert((priv->rsa = RSA_new()));
286         #ifdef HAVE_RSA_SET0_KEY
287                 RSA_set0_key(priv->rsa, n, e, d);
288                 RSA_set0_factors(priv->rsa, p, q);
289                 RSA_set0_crt_params(priv->rsa, NULL, NULL, iqmp);
290         #else
291                 priv->rsa->n = n;
292                 priv->rsa->e = e;
293                 priv->rsa->d = d;
294                 priv->rsa->iqmp = iqmp;
295                 priv->rsa->p = p;
296                 priv->rsa->q = q;
297         #endif
298         return 1;
299 #endif /* HAVE_OSSL_PARAM */
300         BN_clear_free(q);
301 free_p:
302         BN_clear_free(p);
303 free_iqmp:
304         BN_clear_free(iqmp);
305 free_d:
306         BN_clear_free(d);
307 free_e:
308         BN_free(e);
309 free_n:
310         BN_free(n);
311         return ret;
312 }
313
314 static int get_private_key(const char *path, struct asymmetric_key *priv)
315 {
316         int ret;
317         unsigned char *blob, *end;
318         size_t blob_size;
319
320         ret = decode_private_key(path, &blob, &blob_size);
321         if (ret < 0)
322                 return ret;
323         end = blob + blob_size;
324         if (ret == PKT_OPENSSH) {
325                 ret = find_openssh_bignum_offset(blob, blob_size);
326                 if (ret < 0)
327                         goto free_blob;
328                 PARA_INFO_LOG("reading RSA params at offset %d\n", ret);
329                 ret = read_openssh_private_key(blob + ret, end, priv);
330         } else
331                 ret = read_pem_private_key(path, priv);
332 free_blob:
333         free(blob);
334         return ret;
335 }
336
337 int apc_get_pubkey(const char *key_file, struct asymmetric_key **result)
338 {
339         unsigned char *blob;
340         size_t decoded_size;
341         int ret;
342         struct asymmetric_key *pub;
343
344         ret = decode_public_key(key_file, &blob, &decoded_size);
345         if (ret < 0)
346                 return ret;
347         pub = zalloc(sizeof(*pub)); /* ->pkey needs to start out zeroed */
348         ret = read_public_key(blob + ret, decoded_size - ret, pub);
349         free(blob);
350         if (ret < 0) {
351                 free(pub);
352                 *result = NULL;
353                 PARA_ERROR_LOG("can not load key %s\n", key_file);
354                 return ret;
355         }
356         PARA_NOTICE_LOG("loaded %d bit key from %s\n", ret, key_file);
357         *result = pub;
358         return ret / 8;
359 }
360
361 void apc_free_pubkey(struct asymmetric_key *pub)
362 {
363         if (!pub)
364                 return;
365 #ifdef HAVE_OSSL_PARAM /* openssl-3 */
366         EVP_PKEY_CTX_free(pub->ctx);
367         EVP_PKEY_free(pub->pkey);
368 #else
369         RSA_free(pub->rsa);
370 #endif
371         free(pub);
372 }
373
374 #ifdef HAVE_OSSL_PARAM /* openssl-3 */
375 static int pkey_priv_decrypt(const struct asymmetric_key *priv,
376                 unsigned char **outbuf, unsigned char *inbuf, int inlen)
377 {
378         EVP_PKEY_CTX *ctx;
379         size_t outlen;
380
381         assert((ctx = EVP_PKEY_CTX_new(priv->pkey, NULL)));
382         assert((EVP_PKEY_decrypt_init(ctx) > 0));
383         assert(EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) > 0);
384         if (EVP_PKEY_decrypt(ctx, NULL, &outlen, inbuf, inlen) <= 0) {
385                 *outbuf = NULL;
386                 EVP_PKEY_CTX_free(ctx);
387                 return openssl_perror("EVP_PKEY_encrypt()");
388         }
389         *outbuf = alloc(outlen);
390         assert((EVP_PKEY_decrypt(ctx, *outbuf, &outlen, inbuf, inlen) > 0));
391         EVP_PKEY_CTX_free(ctx);
392         PARA_INFO_LOG("wrote %zu decrypted data bytes\n", outlen);
393         return outlen;
394 }
395 #endif /* HAVE_OSSL_PARAM */
396
397 int apc_priv_decrypt(const char *key_file, unsigned char **outbuf,
398                 unsigned char *inbuf, int inlen)
399 {
400         struct asymmetric_key *priv;
401         int ret;
402
403         *outbuf = NULL;
404         ret = check_private_key_file(key_file);
405         if (ret < 0)
406                 return ret;
407         if (inlen < 0)
408                 return -E_RSA;
409         priv = zalloc(sizeof(*priv)); /* ->pkey needs to start out zeroed */
410         ret = get_private_key(key_file, priv);
411         if (ret < 0) {
412                 free(priv);
413                 return ret;
414         }
415 #ifdef HAVE_OSSL_PARAM /* openssl-3 */
416         ret = pkey_priv_decrypt(priv, outbuf, inbuf, inlen);
417         EVP_PKEY_CTX_free(priv->ctx);
418         EVP_PKEY_free(priv->pkey);
419 #else
420         /*
421          * RSA is vulnerable to timing attacks. Generate a random blinding
422          * factor to protect against this kind of attack.
423          */
424         ret = -E_BLINDING;
425         if (RSA_blinding_on(priv->rsa, NULL) == 0)
426                 goto out;
427         *outbuf = alloc(RSA_size(priv->rsa));
428         ret = RSA_private_decrypt(inlen, inbuf, *outbuf, priv->rsa,
429                 RSA_PKCS1_OAEP_PADDING);
430         RSA_blinding_off(priv->rsa);
431         if (ret <= 0) {
432                 free(*outbuf);
433                 *outbuf = NULL;
434                 ret = -E_DECRYPT;
435         }
436 out:
437         RSA_free(priv->rsa);
438 #endif
439         free(priv);
440         return ret;
441 }
442
443 int apc_pub_encrypt(struct asymmetric_key *pub, unsigned char *inbuf,
444                 unsigned len, unsigned char **outbuf)
445 {
446         int ret;
447 #ifdef HAVE_OSSL_PARAM /* openssl-3 */
448         EVP_PKEY_CTX *ctx;
449         size_t outlen;
450
451         *outbuf = NULL;
452         assert((ctx = EVP_PKEY_CTX_new(pub->pkey, NULL)));
453         assert((EVP_PKEY_encrypt_init(ctx) > 0));
454         assert((EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) > 0));
455         if (EVP_PKEY_encrypt(ctx, NULL, &outlen, inbuf, len) <= 0) {
456                 ret = openssl_perror("EVP_PKEY_encrypt()");
457                 goto free_ctx;
458         }
459         *outbuf = alloc(outlen);
460         assert((EVP_PKEY_encrypt(ctx, *outbuf, &outlen, inbuf, len) > 0));
461         PARA_INFO_LOG("wrote %zu encrypted data bytes\n", outlen);
462         ret = outlen;
463 free_ctx:
464         EVP_PKEY_CTX_free(ctx);
465         return ret;
466 #else /* openssl < 3.0 */
467         *outbuf = alloc(RSA_size(pub->rsa));
468         ret = RSA_public_encrypt((int)len, inbuf, *outbuf, pub->rsa,
469                 RSA_PKCS1_OAEP_PADDING);
470         if (ret < 0) {
471                 free(*outbuf);
472                 *outbuf = NULL;
473                 return -E_ENCRYPT;
474         }
475         return ret;
476 #endif /* HAVE_OSSL_PARAM */
477 }
478
479 struct stream_cipher {
480         EVP_CIPHER_CTX *aes;
481 };
482
483 struct stream_cipher *sc_new(const unsigned char *data, int len)
484 {
485         struct stream_cipher *sc = alloc(sizeof(*sc));
486
487         assert(len >= 2 * AES_CRT128_BLOCK_SIZE);
488         assert((sc->aes = EVP_CIPHER_CTX_new()));
489         EVP_EncryptInit_ex(sc->aes, EVP_aes_128_ctr(), NULL, data,
490                 data + AES_CRT128_BLOCK_SIZE);
491         return sc;
492 }
493
494 void sc_free(struct stream_cipher *sc)
495 {
496         if (!sc)
497                 return;
498         EVP_CIPHER_CTX_free(sc->aes);
499         free(sc);
500 }
501
502 static void aes_ctr128_crypt(EVP_CIPHER_CTX *ctx, struct iovec *src,
503                 struct iovec *dst)
504 {
505         int ret, inlen = src->iov_len, outlen, tmplen;
506
507         *dst = (typeof(*dst)) {
508                 /* Add one for the terminating zero byte. */
509                 .iov_base = alloc(inlen + 1),
510                 .iov_len = inlen
511         };
512         ret = EVP_EncryptUpdate(ctx, dst->iov_base, &outlen, src->iov_base, inlen);
513         assert(ret != 0);
514         ret = EVP_EncryptFinal_ex(ctx, dst->iov_base + outlen, &tmplen);
515         assert(ret != 0);
516         outlen += tmplen;
517         ((char *)dst->iov_base)[outlen] = '\0';
518         dst->iov_len = outlen;
519 }
520
521 void sc_crypt(struct stream_cipher *sc, struct iovec *src, struct iovec *dst)
522 {
523         return aes_ctr128_crypt(sc->aes, src, dst);
524 }
525
526 void hash_function(const char *data, unsigned long len, unsigned char *hash)
527 {
528         int ret;
529         EVP_MD_CTX *c;
530
531         assert((c = EVP_MD_CTX_new()));
532         ret = EVP_DigestInit_ex(c, EVP_sha1(), NULL);
533         assert(ret != 0);
534         ret = EVP_DigestUpdate(c, data, len);
535         assert(ret != 0);
536         ret = EVP_DigestFinal_ex(c, hash, NULL);
537         assert(ret != 0);
538         EVP_MD_CTX_free(c);
539 }
540
541 void hash2_function(const char *data, unsigned long len, unsigned char *hash)
542 {
543         int ret;
544         EVP_MD_CTX *c;
545
546         assert((c = EVP_MD_CTX_new()));
547         ret = EVP_DigestInit_ex(c, EVP_sha256(), NULL);
548         assert(ret != 0);
549         ret = EVP_DigestUpdate(c, data, len);
550         assert(ret != 0);
551         ret = EVP_DigestFinal_ex(c, hash, NULL);
552         assert(ret != 0);
553         EVP_MD_CTX_free(c);
554 }