1 /* Copyright (C) 2011 Andre Noll <maan@tuebingen.mpg.de>, see file COPYING. */
3 /** \file gcrypt.c Libgrcypt-based encryption/decryption routines. */
12 #include "crypt_backend.h"
16 //#define GCRYPT_DEBUG 1
19 static void dump_buffer(const char *msg
, unsigned char *buf
, int len
)
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");
29 /** Empty. Define GCRYPT_DEBUG to dump buffers. */
30 #define dump_buffer(a, b, c)
33 void hash_function(const char *data
, unsigned long len
, unsigned char *hash
)
39 gret
= gcry_md_open(&handle
, GCRY_MD_SHA1
, 0);
41 gcry_md_write(handle
, data
, (size_t)len
);
42 gcry_md_final(handle
);
43 md
= gcry_md_read(handle
, GCRY_MD_SHA1
);
45 memcpy(hash
, md
, HASH_SIZE
);
46 gcry_md_close(handle
);
49 void get_random_bytes_or_die(unsigned char *buf
, int num
)
51 gcry_randomize(buf
, (size_t)num
, GCRY_STRONG_RANDOM
);
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.
61 const char *req_ver
= "1.5.0";
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
));
71 * Allocate a pool of secure memory. This also drops privileges where
74 gcry_control(GCRYCTL_INIT_SECMEM
, 65536, 0);
76 /* Tell Libgcrypt that initialization has completed. */
77 gcry_control(GCRYCTL_INITIALIZATION_FINISHED
, 0);
79 get_random_bytes_or_die((unsigned char *)&seed
, sizeof(seed
));
83 void crypt_shutdown(void)
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
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)))"
99 struct asymmetric_key
{
104 static const char *gcrypt_strerror(gcry_error_t gret
)
106 return gcry_strerror(gcry_err_code(gret
));
109 /** ASN Types and their code. */
111 /** The next object is an integer. */
112 ASN1_TYPE_INTEGER
= 0x2,
113 /** Bit string object. */
114 ASN1_TYPE_BIT_STRING
= 0x03,
115 /** Keys start with one big type sequence. */
116 ASN1_TYPE_SEQUENCE
= 0x30,
119 /* bit 6 has value 0 */
120 static inline bool is_primitive(unsigned char c
)
122 return (c
& (1<<6)) == 0;
125 static inline bool is_primitive_integer(unsigned char c
)
127 if (!is_primitive(c
))
129 return (c
& 0x1f) == ASN1_TYPE_INTEGER
;
132 /* Bit 8 is zero (and bits 7-1 give the length) */
133 static inline bool is_short_form(unsigned char c
)
135 return (c
& 0x80) == 0;
138 static inline int get_short_form_length(unsigned char c
)
143 static inline int get_long_form_num_length_bytes(unsigned char c
)
149 * Returns: Number of bytes scanned. This may differ from the value returned via
150 * bitsp because the latter does not include the ASN.1 prefix and a leading
151 * zero is not considered as an additional byte for the number of bits.
153 static int read_pem_bignum(unsigned char *start
, unsigned char *end
, gcry_mpi_t
*bn
,
158 unsigned char *cp
= start
;
160 if (!is_primitive_integer(*cp
))
161 return -E_BAD_PRIVATE_KEY
;
163 if (is_short_form(*cp
)) {
164 bn_size
= get_short_form_length(*cp
);
167 int num_bytes
= get_long_form_num_length_bytes(*cp
);
168 if (cp
+ num_bytes
> end
)
169 return -E_BAD_PRIVATE_KEY
;
170 if (num_bytes
> 4) /* nobody has such a large modulus */
171 return -E_BAD_PRIVATE_KEY
;
174 for (i
= 0; i
< num_bytes
; i
++, cp
++)
175 bn_size
= (bn_size
<< 8) + *cp
;
177 PARA_DEBUG_LOG("bn_size %d (0x%x)\n", bn_size
, (unsigned)bn_size
);
178 gret
= gcry_mpi_scan(bn
, GCRYMPI_FMT_STD
, cp
, bn_size
, NULL
);
180 PARA_ERROR_LOG("gcry_mpi_scan: %s\n",
181 gcry_strerror(gcry_err_code(gret
)));
185 * Don't take the first leading zero into account for the size of the
193 *bitsp
= bn_size
* 8;
195 // unsigned char *buf;
196 // gcry_mpi_aprint(GCRYMPI_FMT_HEX, &buf, NULL, *bn);
197 // PARA_CRIT_LOG("bn: %s\n", buf);
202 gcry_mpi_t n
, e
, d
, p
, q
, u
;
205 static int read_pem_rsa_params(unsigned char *start
, unsigned char *end
,
206 struct rsa_params
*p
)
208 unsigned char *cp
= start
;
212 ret
= read_pem_bignum(cp
, end
, &p
->n
, &bits
);
216 ret
= read_pem_bignum(cp
, end
, &p
->e
, NULL
);
220 ret
= read_pem_bignum(cp
, end
, &p
->d
, NULL
);
224 ret
= read_pem_bignum(cp
, end
, &p
->p
, NULL
);
228 ret
= read_pem_bignum(cp
, end
, &p
->q
, NULL
);
232 ret
= read_pem_bignum(cp
, end
, &p
->u
, NULL
);
237 gcry_mpi_release(p
->q
);
239 gcry_mpi_release(p
->p
);
241 gcry_mpi_release(p
->d
);
243 gcry_mpi_release(p
->e
);
245 gcry_mpi_release(p
->n
);
249 static int find_pem_bignum_offset(const unsigned char *data
, int len
)
251 const unsigned char *p
= data
, *end
= data
+ len
;
253 /* like the public key, the whole thing is contained in a sequence */
254 if (*p
!= ASN1_TYPE_SEQUENCE
)
255 return -E_ASN1_PARSE
;
258 return -E_ASN1_PARSE
;
259 if (is_short_form(*p
))
262 p
+= 1 + get_long_form_num_length_bytes(*p
);
264 return -E_ASN1_PARSE
;
266 /* skip next integer */
267 if (*p
!= ASN1_TYPE_INTEGER
)
268 return -E_ASN1_PARSE
;
271 return -E_ASN1_PARSE
;
272 if (is_short_form(*p
))
273 p
+= 1 + get_short_form_length(*p
);
275 p
+= 1 + get_long_form_num_length_bytes(*p
);
277 return -E_ASN1_PARSE
;
281 static int read_openssh_bignum(unsigned char *start
, unsigned char *end
,
282 gcry_mpi_t
*bn
, unsigned *bitsp
)
288 gret
= gcry_mpi_scan(bn
, GCRYMPI_FMT_SSH
, start
, end
- start
, &nscanned
);
290 PARA_ERROR_LOG("gcry_mpi_scan: %s\n",
291 gcry_strerror(gcry_err_code(gret
)));
294 bits
= (nscanned
- 4 - (start
[4] == '\0')) * 8;
297 PARA_DEBUG_LOG("scanned %u-bit bignum\n", bits
);
301 static int read_openssh_rsa_params(unsigned char *start
, unsigned char *end
,
302 struct rsa_params
*p
)
304 unsigned char *cp
= start
;
308 ret
= read_openssh_bignum(cp
, end
, &p
->n
, &bits
);
312 ret
= read_openssh_bignum(cp
, end
, &p
->e
, NULL
);
316 ret
= read_openssh_bignum(cp
, end
, &p
->d
, NULL
);
320 ret
= read_openssh_bignum(cp
, end
, &p
->u
, NULL
);
324 ret
= read_openssh_bignum(cp
, end
, &p
->p
, NULL
);
328 ret
= read_openssh_bignum(cp
, end
, &p
->q
, NULL
);
333 gcry_mpi_release(p
->p
);
335 gcry_mpi_release(p
->u
);
337 gcry_mpi_release(p
->d
);
339 gcry_mpi_release(p
->e
);
341 gcry_mpi_release(p
->n
);
345 static int get_private_key(const char *key_file
, struct asymmetric_key
**result
)
347 struct rsa_params params
;
348 unsigned char *blob
, *end
;
352 size_t erroff
, blob_size
;
354 struct asymmetric_key
*key
;
357 ret
= decode_private_key(key_file
, &blob
, &blob_size
);
361 end
= blob
+ blob_size
;
362 if (key_type
== PKT_PEM
)
363 ret
= find_pem_bignum_offset(blob
, blob_size
);
365 ret
= find_openssh_bignum_offset(blob
, blob_size
);
368 PARA_INFO_LOG("reading RSA params at offset %d\n", ret
);
369 if (key_type
== PKT_PEM
)
370 ret
= read_pem_rsa_params(blob
+ ret
, end
, ¶ms
);
372 ret
= read_openssh_rsa_params(blob
+ ret
, end
, ¶ms
);
377 * OpenSSL uses slightly different parameters than gcrypt. To use these
378 * parameters we need to swap the values of p and q and recompute u.
380 if (gcry_mpi_cmp(params
.p
, params
.q
) > 0) {
381 gcry_mpi_swap(params
.p
, params
.q
);
382 gcry_mpi_invm(params
.u
, params
.p
, params
.q
);
384 gret
= gcry_sexp_build(&sexp
, &erroff
, RSA_PRIVKEY_SEXP
, params
.n
,
385 params
.e
, params
.d
, params
.p
, params
.q
, params
.u
);
388 PARA_ERROR_LOG("offset %zu: %s\n", erroff
,
389 gcry_strerror(gcry_err_code(gret
)));
393 key
= para_malloc(sizeof(*key
));
397 PARA_INFO_LOG("succesfully read %d bit private key\n", ret
);
399 gcry_mpi_release(params
.n
);
400 gcry_mpi_release(params
.e
);
401 gcry_mpi_release(params
.d
);
402 gcry_mpi_release(params
.u
);
403 gcry_mpi_release(params
.p
);
404 gcry_mpi_release(params
.q
);
411 int apc_get_pubkey(const char *key_file
, struct asymmetric_key
**result
)
413 unsigned char *blob
, *p
, *end
;
416 size_t erroff
, decoded_size
;
419 struct asymmetric_key
*key
;
422 ret
= decode_public_key(key_file
, &blob
, &decoded_size
);
426 end
= blob
+ decoded_size
;
427 PARA_DEBUG_LOG("scanning modulus and public exponent\n");
428 ret
= read_openssh_bignum(p
, end
, &e
, NULL
);
432 ret
= read_openssh_bignum(p
, end
, &n
, &bits
);
435 gret
= gcry_sexp_build(&sexp
, &erroff
, RSA_PUBKEY_SEXP
, n
, e
);
437 PARA_ERROR_LOG("offset %zu: %s\n", erroff
,
438 gcry_strerror(gcry_err_code(gret
)));
442 PARA_INFO_LOG("successfully read %u bit ssh public key\n", bits
);
443 key
= para_malloc(sizeof(*key
));
444 key
->num_bytes
= ret
;
457 void apc_free_pubkey(struct asymmetric_key
*key
)
461 gcry_sexp_release(key
->sexp
);
465 static int decode_rsa(gcry_sexp_t sexp
, unsigned char *outbuf
, size_t *nbytes
)
467 const char *p
= gcry_sexp_nth_data(sexp
, 1, nbytes
);
470 return -E_RSA_DECODE
;
471 memcpy(outbuf
, p
, *nbytes
);
475 int apc_priv_decrypt(const char *key_file
, unsigned char *outbuf
,
476 unsigned char *inbuf
, int inlen
)
480 struct asymmetric_key
*priv
;
481 gcry_mpi_t in_mpi
= NULL
;
482 gcry_sexp_t in
, out
, priv_key
;
485 ret
= check_private_key_file(key_file
);
488 PARA_INFO_LOG("decrypting %d byte input\n", inlen
);
489 /* key_file -> asymmetric key priv */
490 ret
= get_private_key(key_file
, &priv
);
494 /* asymmetric key priv -> sexp priv_key */
496 priv_key
= gcry_sexp_find_token(priv
->sexp
, "private-key", 0);
500 /* inbuf -> in_mpi */
501 gret
= gcry_mpi_scan(&in_mpi
, GCRYMPI_FMT_USG
, inbuf
,
504 PARA_ERROR_LOG("%s\n", gcrypt_strerror(gret
));
508 /* in_mpi -> in sexp */
509 gret
= gcry_sexp_build(&in
, NULL
, RSA_DECRYPT_SEXP
, in_mpi
);
511 PARA_ERROR_LOG("%s\n", gcrypt_strerror(gret
));
516 /* rsa decryption: in sexp -> out sexp */
517 gret
= gcry_pk_decrypt(&out
, in
, priv_key
);
519 PARA_ERROR_LOG("decrypt: %s\n", gcrypt_strerror(gret
));
520 ret
= -E_SEXP_DECRYPT
;
523 ret
= decode_rsa(out
, outbuf
, &nbytes
);
526 PARA_INFO_LOG("successfully decrypted %zu byte message\n", nbytes
);
529 gcry_sexp_release(out
);
531 gcry_sexp_release(in
);
533 gcry_mpi_release(in_mpi
);
535 gcry_sexp_release(priv_key
);
537 gcry_sexp_release(priv
->sexp
);
542 int apc_pub_encrypt(struct asymmetric_key
*pub
, unsigned char *inbuf
,
543 unsigned len
, unsigned char *outbuf
)
546 gcry_sexp_t pub_key
, in
, out
, out_a
;
547 gcry_mpi_t out_mpi
= NULL
;
551 PARA_INFO_LOG("encrypting %u byte input with %d-byte key\n", len
, pub
->num_bytes
);
554 pub_key
= gcry_sexp_find_token(pub
->sexp
, "public-key", 0);
557 gret
= gcry_sexp_build(&in
, NULL
, "(data(flags oaep)(value %b))", len
, inbuf
);
559 PARA_ERROR_LOG("%s\n", gcrypt_strerror(gret
));
563 /* rsa sexp encryption: in -> out */
564 gret
= gcry_pk_encrypt(&out
, in
, pub_key
);
566 PARA_ERROR_LOG("%s\n", gcrypt_strerror(gret
));
567 ret
= -E_SEXP_ENCRYPT
;
570 /* extract a, an MPI with the result of the RSA operation */
572 out_a
= gcry_sexp_find_token(out
, "a", 0);
575 /* convert sexp out_a -> out_mpi */
576 out_mpi
= gcry_sexp_nth_mpi(out_a
, 1, GCRYMPI_FMT_USG
);
581 gret
= gcry_mpi_print(GCRYMPI_FMT_USG
, outbuf
, 512 /* FIXME */, &nbytes
, out_mpi
);
583 PARA_ERROR_LOG("%s\n", gcrypt_strerror(gret
));
584 ret
= -E_SEXP_ENCRYPT
;
585 goto out_mpi_release
;
587 PARA_INFO_LOG("encrypted buffer is %zu bytes\n", nbytes
);
588 dump_buffer("enc buf", outbuf
, nbytes
);
592 gcry_mpi_release(out_mpi
);
594 gcry_sexp_release(out_a
);
596 gcry_sexp_release(out
);
598 gcry_sexp_release(in
);
600 gcry_sexp_release(pub_key
);
604 struct stream_cipher
{
605 gcry_cipher_hd_t handle
;
608 struct stream_cipher
*sc_new(const unsigned char *data
, int len
)
611 struct stream_cipher
*sc
= para_malloc(sizeof(*sc
));
613 assert(len
>= 2 * AES_CRT128_BLOCK_SIZE
);
614 gret
= gcry_cipher_open(&sc
->handle
, GCRY_CIPHER_AES128
,
615 GCRY_CIPHER_MODE_CTR
, 0);
617 gret
= gcry_cipher_setkey(sc
->handle
, data
,
618 AES_CRT128_BLOCK_SIZE
);
620 gret
= gcry_cipher_setctr(sc
->handle
,
621 data
+ AES_CRT128_BLOCK_SIZE
, AES_CRT128_BLOCK_SIZE
);
626 void sc_free(struct stream_cipher
*sc
)
630 gcry_cipher_close(sc
->handle
);
634 void sc_crypt(struct stream_cipher
*sc
, struct iovec
*src
, struct iovec
*dst
)
636 gcry_cipher_hd_t handle
= sc
->handle
;
639 /* perform in-place encryption */
641 gret
= gcry_cipher_encrypt(handle
, src
->iov_base
, src
->iov_len
,