mixer.c: Fix doxygen \file description.
[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("gcry_mpi_scan: %s\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 }