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