gcrypt: Allocate a secmem pool at startup.
[paraslash.git] / gcrypt.c
1 /* Copyright (C) 2011 Andre Noll <maan@tuebingen.mpg.de>, see file COPYING. */
2
3 /** \file gcrypt.c Libgrcypt-based encryption/decryption routines. */
4
5 #include <regex.h>
6 #include <gcrypt.h>
7
8 #include "para.h"
9 #include "error.h"
10 #include "string.h"
11 #include "crypt.h"
12 #include "crypt_backend.h"
13 #include "fd.h"
14 #include "base64.h"
15
16 //#define GCRYPT_DEBUG 1
17
18 #ifdef GCRYPT_DEBUG
19 static void dump_buffer(const char *msg, unsigned char *buf, int len)
20 {
21         int i;
22
23         fprintf(stderr, "%s (%d bytes): ", msg, len);
24         for (i = 0; i < len; i++)
25                 fprintf(stderr, "%02x ", buf[i]);
26         fprintf(stderr, "\n");
27 }
28 #else
29 /** Empty. Define GCRYPT_DEBUG to dump buffers. */
30 #define dump_buffer(a, b, c)
31 #endif
32
33 void hash_function(const char *data, unsigned long len, unsigned char *hash)
34 {
35         gcry_error_t gret;
36         gcry_md_hd_t handle;
37         unsigned char *md;
38
39         gret = gcry_md_open(&handle, GCRY_MD_SHA1, 0);
40         assert(gret == 0);
41         gcry_md_write(handle, data, (size_t)len);
42         gcry_md_final(handle);
43         md = gcry_md_read(handle, GCRY_MD_SHA1);
44         assert(md);
45         memcpy(hash, md, HASH_SIZE);
46         gcry_md_close(handle);
47 }
48
49 void get_random_bytes_or_die(unsigned char *buf, int num)
50 {
51         gcry_randomize(buf, (size_t)num, GCRY_STRONG_RANDOM);
52 }
53
54 /*
55  * This is called at the beginning of every program that uses libgcrypt. The
56  * call to gcry_check_version() initializes the gcrypt library and checks that
57  * we have at least the minimal required version.
58  */
59 void crypt_init(void)
60 {
61         const char *req_ver = "1.5.0";
62         int seed;
63
64         if (!gcry_check_version(req_ver)) {
65                 PARA_EMERG_LOG("fatal: need at least libgcrypt-%s, have: %s\n",
66                         req_ver, gcry_check_version(NULL));
67                 exit(EXIT_FAILURE);
68         }
69
70         /*
71          * Allocate a pool of secure memory. This also drops privileges where
72          * needed.
73          */
74         gcry_control(GCRYCTL_INIT_SECMEM, 65536, 0);
75
76         /* Tell Libgcrypt that initialization has completed. */
77         gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
78
79         get_random_bytes_or_die((unsigned char *)&seed, sizeof(seed));
80         srandom(seed);
81 }
82
83 void crypt_shutdown(void)
84 {
85         /*
86          * WK does not see a way to apply a patch for the sake of Valgrind, so
87          * as of 2018 libgrypt has no deinitialization routine to free the
88          * resources on exit.
89          */
90 }
91
92 /** S-expression for the public part of an RSA key. */
93 #define RSA_PUBKEY_SEXP "(public-key (rsa (n %m) (e %m)))"
94 /** S-expression for a private RSA key. */
95 #define RSA_PRIVKEY_SEXP "(private-key (rsa (n %m) (e %m) (d %m) (p %m) (q %m) (u %m)))"
96 /** S-expression for decryption. */
97 #define RSA_DECRYPT_SEXP "(enc-val(flags oaep)(rsa(a %m)))"
98
99 struct asymmetric_key {
100         gcry_sexp_t sexp;
101         int num_bytes;
102 };
103
104 static const char *gcrypt_strerror(gcry_error_t gret)
105 {
106         return gcry_strerror(gcry_err_code(gret));
107 }
108
109 static int decode_key(const char *key_file, const char *header_str,
110                 const char *footer_str, unsigned char **result)
111 {
112         int ret, ret2, i, j;
113         void *map;
114         size_t map_size, key_size, blob_size;
115         unsigned char *blob = NULL;
116         char *begin, *footer, *key;
117
118         ret = mmap_full_file(key_file, O_RDONLY, &map, &map_size, NULL);
119         if (ret < 0)
120                 goto out;
121         ret = -E_KEY_MARKER;
122         if (strncmp(map, header_str, strlen(header_str)))
123                 goto unmap;
124         footer = strstr(map, footer_str);
125         ret = -E_KEY_MARKER;
126         if (!footer)
127                 goto unmap;
128         begin = map + strlen(header_str);
129         /* skip whitespace at the beginning */
130         for (; begin < footer; begin++) {
131                 if (para_isspace(*begin))
132                         continue;
133                 break;
134         }
135         ret = -E_KEY_MARKER;
136         if (begin >= footer)
137                 goto unmap;
138
139         key_size = footer - begin;
140         key = para_malloc(key_size + 1);
141         for (i = 0, j = 0; begin + i < footer; i++) {
142                 if (para_isspace(begin[i]))
143                         continue;
144                 key[j++] = begin[i];
145         }
146         key[j] = '\0';
147         ret = base64_decode(key, j, (char **)&blob, &blob_size);
148         free(key);
149         if (ret < 0)
150                 goto free_unmap;
151         ret = blob_size;
152         goto unmap;
153 free_unmap:
154         free(blob);
155         blob = NULL;
156 unmap:
157         ret2 = para_munmap(map, map_size);
158         if (ret >= 0 && ret2 < 0)
159                 ret = ret2;
160         if (ret < 0) {
161                 free(blob);
162                 blob = NULL;
163         }
164 out:
165         *result = blob;
166         return ret;
167 }
168
169 /** ASN Types and their code. */
170 enum asn1_types {
171         /** The next object is an integer. */
172         ASN1_TYPE_INTEGER = 0x2,
173         /** Bit string object. */
174         ASN1_TYPE_BIT_STRING = 0x03,
175         /** Keys start with one big type sequence. */
176         ASN1_TYPE_SEQUENCE = 0x30,
177 };
178
179 /* bit 6 has value 0 */
180 static inline bool is_primitive(unsigned char c)
181 {
182         return (c & (1<<6)) == 0;
183 }
184
185 static inline bool is_primitive_integer(unsigned char c)
186 {
187         if (!is_primitive(c))
188                 return false;
189         return (c & 0x1f) == ASN1_TYPE_INTEGER;
190 }
191
192 /* Bit 8 is zero (and bits 7-1 give the length) */
193 static inline bool is_short_form(unsigned char c)
194 {
195         return (c & 0x80) == 0;
196 }
197
198 static inline int get_short_form_length(unsigned char c)
199 {
200         return c & 0x7f;
201 }
202
203 static inline int get_long_form_num_length_bytes(unsigned char c)
204 {
205         return c & 0x7f;
206 }
207
208 /*
209  * Returns: Number of bytes scanned. This may differ from the value returned via
210  * bn_bytes because the latter does not include the ASN.1 prefix and a leading
211  * zero is not considered as an additional byte for bn_bytes.
212  */
213 static int read_bignum(unsigned char *start, unsigned char *end, gcry_mpi_t *bn,
214                 int *bn_bytes)
215 {
216         int i, bn_size;
217         gcry_error_t gret;
218         unsigned char *cp = start;
219
220         if (!is_primitive_integer(*cp))
221                 return -E_BAD_PRIVATE_KEY;
222         cp++;
223         if (is_short_form(*cp)) {
224                 bn_size = get_short_form_length(*cp);
225                 cp++;
226         } else {
227                 int num_bytes = get_long_form_num_length_bytes(*cp);
228                 if (cp + num_bytes > end)
229                         return -E_BAD_PRIVATE_KEY;
230                 if (num_bytes > 4) /* nobody has such a large modulus */
231                         return -E_BAD_PRIVATE_KEY;
232                 cp++;
233                 bn_size = 0;
234                 for (i = 0; i < num_bytes; i++, cp++)
235                         bn_size = (bn_size << 8) + *cp;
236         }
237         PARA_DEBUG_LOG("bn_size %d (0x%x)\n", bn_size, (unsigned)bn_size);
238         gret = gcry_mpi_scan(bn, GCRYMPI_FMT_STD, cp, bn_size, NULL);
239         if (gret) {
240                 PARA_ERROR_LOG("%s while scanning n\n",
241                         gcry_strerror(gcry_err_code(gret)));
242                 return-E_MPI_SCAN;
243         }
244         /*
245          * Don't take the first leading zero into account for the size of the
246          * bignum.
247          */
248         if (*cp == '\0') {
249                 cp++;
250                 bn_size--;
251         }
252         if (bn_bytes)
253                 *bn_bytes = bn_size;
254         cp += bn_size;
255 //      unsigned char *buf;
256 //      gcry_mpi_aprint(GCRYMPI_FMT_HEX, &buf, NULL, *bn);
257 //      PARA_CRIT_LOG("bn: %s\n", buf);
258         return cp - start;
259 }
260
261 static int find_privkey_bignum_offset(const unsigned char *data, int len)
262 {
263         const unsigned char *p = data, *end = data + len;
264
265         /* like the public key, the whole thing is contained in a sequence */
266         if (*p != ASN1_TYPE_SEQUENCE)
267                 return -E_ASN1_PARSE;
268         p++;
269         if (p >= end)
270                 return -E_ASN1_PARSE;
271         if (is_short_form(*p))
272                 p++;
273         else
274                 p += 1 + get_long_form_num_length_bytes(*p);
275         if (p >= end)
276                 return -E_ASN1_PARSE;
277
278         /* skip next integer */
279         if (*p != ASN1_TYPE_INTEGER)
280                 return -E_ASN1_PARSE;
281         p++;
282         if (p >= end)
283                 return -E_ASN1_PARSE;
284         if (is_short_form(*p))
285                 p += 1 + get_short_form_length(*p);
286         else
287                 p += 1 + get_long_form_num_length_bytes(*p);
288         if (p >= end)
289                 return -E_ASN1_PARSE;
290         return p - data;
291 }
292
293 /** Private keys start with this header. */
294 #define PRIVATE_KEY_HEADER "-----BEGIN RSA PRIVATE KEY-----"
295 /** Private keys end with this footer. */
296 #define PRIVATE_KEY_FOOTER "-----END RSA PRIVATE KEY-----"
297
298 static int get_private_key(const char *key_file, struct asymmetric_key **result)
299 {
300         gcry_mpi_t n = NULL, e = NULL, d = NULL, p = NULL, q = NULL,
301                 u = NULL;
302         unsigned char *blob, *cp, *end;
303         int blob_size, ret, n_size;
304         gcry_error_t gret;
305         size_t erroff;
306         gcry_sexp_t sexp;
307         struct asymmetric_key *key;
308
309         *result = NULL;
310         ret = decode_key(key_file, PRIVATE_KEY_HEADER, PRIVATE_KEY_FOOTER,
311                 &blob);
312         if (ret < 0)
313                 return ret;
314         blob_size = ret;
315         end = blob + blob_size;
316         ret = find_privkey_bignum_offset(blob, blob_size);
317         if (ret < 0)
318                 goto free_blob;
319         PARA_INFO_LOG("reading RSA params at offset %d\n", ret);
320         cp = blob + ret;
321
322         ret = read_bignum(cp, end, &n, &n_size);
323         if (ret < 0)
324                 goto free_blob;
325         cp += ret;
326
327         ret = read_bignum(cp, end, &e, NULL);
328         if (ret < 0)
329                 goto release_n;
330         cp += ret;
331
332         ret = read_bignum(cp, end, &d, NULL);
333         if (ret < 0)
334                 goto release_e;
335         cp += ret;
336
337         ret = read_bignum(cp, end, &p, NULL);
338         if (ret < 0)
339                 goto release_d;
340         cp += ret;
341
342         ret = read_bignum(cp, end, &q, NULL);
343         if (ret < 0)
344                 goto release_p;
345         cp += ret;
346         ret = read_bignum(cp, end, &u, NULL);
347         if (ret < 0)
348                 goto release_q;
349         /*
350          * OpenSSL uses slightly different parameters than gcrypt. To use these
351          * parameters we need to swap the values of p and q and recompute u.
352          */
353         if (gcry_mpi_cmp(p, q) > 0) {
354                 gcry_mpi_swap(p, q);
355                 gcry_mpi_invm(u, p, q);
356         }
357         gret = gcry_sexp_build(&sexp, &erroff, RSA_PRIVKEY_SEXP,
358                 n, e, d, p, q, u);
359
360         if (gret) {
361                 PARA_ERROR_LOG("offset %zu: %s\n", erroff,
362                         gcry_strerror(gcry_err_code(gret)));
363                 ret = -E_SEXP_BUILD;
364                 goto release_u;
365         }
366         key = para_malloc(sizeof(*key));
367         key->sexp = sexp;
368         *result = key;
369         ret = n_size * 8;
370         PARA_INFO_LOG("succesfully read %d bit private key\n", ret);
371 release_u:
372         gcry_mpi_release(u);
373 release_q:
374         gcry_mpi_release(q);
375 release_p:
376         gcry_mpi_release(p);
377 release_d:
378         gcry_mpi_release(d);
379 release_e:
380         gcry_mpi_release(e);
381 release_n:
382         gcry_mpi_release(n);
383 free_blob:
384         free(blob);
385         return ret;
386 }
387
388 int apc_get_pubkey(const char *key_file, struct asymmetric_key **result)
389 {
390         unsigned char *blob, *p, *end;
391         int ret;
392         gcry_error_t gret;
393         size_t nr_scanned, erroff, decoded_size;
394         gcry_mpi_t e, n;
395         gcry_sexp_t sexp;
396         struct asymmetric_key *key;
397
398         ret = decode_ssh_key(key_file, &blob, &decoded_size);
399         if (ret < 0)
400                 return ret;
401         p = blob + ret;
402         end = blob + decoded_size;
403         PARA_DEBUG_LOG("scanning modulus and public exponent\n");
404         gret = gcry_mpi_scan(&e, GCRYMPI_FMT_SSH, p, end - p, &nr_scanned);
405         if (gret) {
406                 ret = -E_MPI_SCAN;
407                 PARA_CRIT_LOG("%s\n", gcry_strerror(gcry_err_code(gret)));
408                 goto free_blob;
409         }
410         PARA_DEBUG_LOG("scanned e (%zu bytes)\n", nr_scanned);
411         p += nr_scanned;
412         if (p >= end)
413                 goto release_e;
414         gret = gcry_mpi_scan(&n, GCRYMPI_FMT_SSH, p, end - p, &nr_scanned);
415         if (gret) {
416                 ret = -E_MPI_SCAN;
417                 PARA_ERROR_LOG("%s\n", gcry_strerror(gcry_err_code(gret)));
418                 goto release_e;
419         }
420         PARA_DEBUG_LOG("scanned n (%zu bytes)\n", nr_scanned);
421         gret = gcry_sexp_build(&sexp, &erroff, RSA_PUBKEY_SEXP, n, e);
422         if (gret) {
423                 PARA_ERROR_LOG("offset %zu: %s\n", erroff,
424                         gcry_strerror(gcry_err_code(gret)));
425                 ret = -E_SEXP_BUILD;
426                 goto release_n;
427         }
428         ret = ROUND_DOWN(nr_scanned, 32);
429         PARA_INFO_LOG("successfully read %d bit ssh public key\n", ret * 8);
430         key = para_malloc(sizeof(*key));
431         key->num_bytes = ret;
432         key->sexp = sexp;
433         *result = key;
434 release_n:
435         gcry_mpi_release(n);
436 release_e:
437         gcry_mpi_release(e);
438 free_blob:
439         free(blob);
440         return ret;
441 }
442
443 void apc_free_pubkey(struct asymmetric_key *key)
444 {
445         if (!key)
446                 return;
447         gcry_sexp_release(key->sexp);
448         free(key);
449 }
450
451 static int decode_rsa(gcry_sexp_t sexp, unsigned char *outbuf, size_t *nbytes)
452 {
453         const char *p = gcry_sexp_nth_data(sexp, 1, nbytes);
454
455         if (!p)
456                 return -E_RSA_DECODE;
457         memcpy(outbuf, p, *nbytes);
458         return 1;
459 }
460
461 int apc_priv_decrypt(const char *key_file, unsigned char *outbuf,
462                 unsigned char *inbuf, int inlen)
463 {
464         gcry_error_t gret;
465         int ret;
466         struct asymmetric_key *priv;
467         gcry_mpi_t in_mpi = NULL;
468         gcry_sexp_t in, out, priv_key;
469         size_t nbytes;
470
471         ret = check_private_key_file(key_file);
472         if (ret < 0)
473                 return ret;
474         PARA_INFO_LOG("decrypting %d byte input\n", inlen);
475         /* key_file -> asymmetric key priv */
476         ret = get_private_key(key_file, &priv);
477         if (ret < 0)
478                 return ret;
479
480         /* asymmetric key priv -> sexp priv_key */
481         ret = -E_SEXP_FIND;
482         priv_key = gcry_sexp_find_token(priv->sexp, "private-key", 0);
483         if (!priv_key)
484                 goto free_key;
485
486         /* inbuf -> in_mpi */
487         gret = gcry_mpi_scan(&in_mpi, GCRYMPI_FMT_USG, inbuf,
488                 inlen, NULL);
489         if (gret) {
490                 PARA_ERROR_LOG("%s\n", gcrypt_strerror(gret));
491                 ret = -E_MPI_SCAN;
492                 goto key_release;
493         }
494         /* in_mpi -> in sexp */
495         gret = gcry_sexp_build(&in, NULL, RSA_DECRYPT_SEXP, in_mpi);
496         if (gret) {
497                 PARA_ERROR_LOG("%s\n", gcrypt_strerror(gret));
498                 ret = -E_SEXP_BUILD;
499                 goto in_mpi_release;
500         }
501
502         /* rsa decryption: in sexp -> out sexp */
503         gret = gcry_pk_decrypt(&out, in, priv_key);
504         if (gret) {
505                 PARA_ERROR_LOG("decrypt: %s\n", gcrypt_strerror(gret));
506                 ret = -E_SEXP_DECRYPT;
507                 goto in_release;
508         }
509         ret = decode_rsa(out, outbuf, &nbytes);
510         if (ret < 0)
511                 goto out_release;
512         PARA_INFO_LOG("successfully decrypted %zu byte message\n", nbytes);
513         ret = nbytes;
514 out_release:
515         gcry_sexp_release(out);
516 in_release:
517         gcry_sexp_release(in);
518 in_mpi_release:
519         gcry_mpi_release(in_mpi);
520 key_release:
521         gcry_sexp_release(priv_key);
522 free_key:
523         gcry_sexp_release(priv->sexp);
524         free(priv);
525         return ret;
526 }
527
528 int apc_pub_encrypt(struct asymmetric_key *pub, unsigned char *inbuf,
529                 unsigned len, unsigned char *outbuf)
530 {
531         gcry_error_t gret;
532         gcry_sexp_t pub_key, in, out, out_a;
533         gcry_mpi_t out_mpi = NULL;
534         size_t nbytes;
535         int ret;
536
537         PARA_INFO_LOG("encrypting %u byte input with %d-byte key\n", len, pub->num_bytes);
538
539         /* get pub key */
540         pub_key = gcry_sexp_find_token(pub->sexp, "public-key", 0);
541         if (!pub_key)
542                 return -E_SEXP_FIND;
543         gret = gcry_sexp_build(&in, NULL, "(data(flags oaep)(value %b))", len, inbuf);
544         if (gret) {
545                 PARA_ERROR_LOG("%s\n", gcrypt_strerror(gret));
546                 ret = -E_SEXP_BUILD;
547                 goto key_release;
548         }
549         /* rsa sexp encryption: in -> out */
550         gret = gcry_pk_encrypt(&out, in, pub_key);
551         if (gret) {
552                 PARA_ERROR_LOG("%s\n", gcrypt_strerror(gret));
553                 ret = -E_SEXP_ENCRYPT;
554                 goto in_release;
555         }
556         /* extract a, an MPI with the result of the RSA operation */
557         ret = -E_SEXP_FIND;
558         out_a = gcry_sexp_find_token(out, "a", 0);
559         if (!out_a)
560                 goto out_release;
561         /* convert sexp out_a -> out_mpi */
562         out_mpi = gcry_sexp_nth_mpi(out_a, 1, GCRYMPI_FMT_USG);
563         if (!out_mpi) {
564                 ret = -E_SEXP_FIND;
565                 goto out_a_release;
566         }
567         gret = gcry_mpi_print(GCRYMPI_FMT_USG, outbuf, 512 /* FIXME */, &nbytes, out_mpi);
568         if (gret) {
569                 PARA_ERROR_LOG("%s\n", gcrypt_strerror(gret));
570                 ret = -E_SEXP_ENCRYPT;
571                 goto out_mpi_release;
572         }
573         PARA_INFO_LOG("encrypted buffer is %zu bytes\n", nbytes);
574         dump_buffer("enc buf", outbuf, nbytes);
575         ret = nbytes;
576
577 out_mpi_release:
578         gcry_mpi_release(out_mpi);
579 out_a_release:
580         gcry_sexp_release(out_a);
581 out_release:
582         gcry_sexp_release(out);
583 in_release:
584         gcry_sexp_release(in);
585 key_release:
586         gcry_sexp_release(pub_key);
587         return ret;
588 }
589
590 struct stream_cipher {
591         gcry_cipher_hd_t handle;
592 };
593
594 struct stream_cipher *sc_new(const unsigned char *data, int len)
595 {
596         gcry_error_t gret;
597         struct stream_cipher *sc = para_malloc(sizeof(*sc));
598
599         assert(len >= 2 * AES_CRT128_BLOCK_SIZE);
600         gret = gcry_cipher_open(&sc->handle, GCRY_CIPHER_AES128,
601                 GCRY_CIPHER_MODE_CTR, 0);
602         assert(gret == 0);
603         gret = gcry_cipher_setkey(sc->handle, data,
604                 AES_CRT128_BLOCK_SIZE);
605         assert(gret == 0);
606         gret = gcry_cipher_setctr(sc->handle,
607                 data + AES_CRT128_BLOCK_SIZE, AES_CRT128_BLOCK_SIZE);
608         assert(gret == 0);
609         return sc;
610 }
611
612 void sc_free(struct stream_cipher *sc)
613 {
614         if (!sc)
615                 return;
616         gcry_cipher_close(sc->handle);
617         free(sc);
618 }
619
620 void sc_crypt(struct stream_cipher *sc, struct iovec *src, struct iovec *dst)
621 {
622         gcry_cipher_hd_t handle = sc->handle;
623         gcry_error_t gret;
624
625         /* perform in-place encryption */
626         *dst = *src;
627         gret = gcry_cipher_encrypt(handle, src->iov_base, src->iov_len,
628                 NULL, 0);
629         assert(gret == 0);
630 }