2 * Copyright (C) 2011-2012 Andre Noll <maan@systemlinux.org>
4 * Licensed under the GPL v2. For licencing details see COPYING.
7 /** \file gcrypt.c Libgrcypt-based encryption/decryption routines. */
16 #include "crypt_backend.h"
19 //#define GCRYPT_DEBUG 1
21 static bool libgcrypt_has_oaep
;
22 static const char *rsa_decrypt_sexp
;
25 static void dump_buffer(const char *msg
, unsigned char *buf
, int len
)
29 fprintf(stderr
, "%s (%u bytes): ", msg
, len
);
30 for (i
= 0; i
< len
; i
++)
31 fprintf(stderr
, "%02x ", buf
[i
]);
32 fprintf(stderr
, "\n");
35 /** Empty. Define GCRYPT_DEBUG to dump buffers. */
36 #define dump_buffer(a, b, c)
39 void hash_function(const char *data
, unsigned long len
, unsigned char *hash
)
45 gret
= gcry_md_open(&handle
, GCRY_MD_SHA1
, 0);
47 gcry_md_write(handle
, data
, (size_t)len
);
48 gcry_md_final(handle
);
49 md
= gcry_md_read(handle
, GCRY_MD_SHA1
);
51 memcpy(hash
, md
, HASH_SIZE
);
52 gcry_md_close(handle
);
55 void get_random_bytes_or_die(unsigned char *buf
, int num
)
57 gcry_randomize(buf
, (size_t)num
, GCRY_STRONG_RANDOM
);
61 * This is called at the beginning of every program that uses libgcrypt. We
62 * don't have to initialize any random seed here, but we must initialize the
63 * gcrypt library. This task is performed by gcry_check_version() which can
64 * also check that the gcrypt library version is at least the minimal required
65 * version. This function also tells us whether we have to use our own OAEP
68 void init_random_seed_or_die(void)
70 const char *ver
, *req_ver
;
72 ver
= gcry_check_version(NULL
);
74 if (!gcry_check_version(req_ver
)) {
75 PARA_EMERG_LOG("fatal: need at least libgcrypt-%s, have: %s\n",
80 if (gcry_check_version(req_ver
)) {
81 libgcrypt_has_oaep
= true;
82 rsa_decrypt_sexp
= "(enc-val(flags oaep)(rsa(a %m)))";
84 libgcrypt_has_oaep
= false;
85 rsa_decrypt_sexp
= "(enc-val(rsa(a %m)))";
89 /** S-expression for the public part of an RSA key. */
90 #define RSA_PUBKEY_SEXP "(public-key (rsa (n %m) (e %m)))"
91 /** S-expression for a private RSA key. */
92 #define RSA_PRIVKEY_SEXP "(private-key (rsa (n %m) (e %m) (d %m) (p %m) (q %m) (u %m)))"
94 /* rfc 3447, appendix B.2 */
95 static void mgf1(unsigned char *seed
, size_t seed_len
, unsigned result_len
,
96 unsigned char *result
)
102 unsigned char octet_string
[4], *rp
= result
, *end
= rp
+ result_len
;
104 assert(result_len
/ HASH_SIZE
< 1ULL << 31);
105 gret
= gcry_md_open(&handle
, GCRY_MD_SHA1
, 0);
107 for (n
= 0; rp
< end
; n
++) {
108 gcry_md_write(handle
, seed
, seed_len
);
109 octet_string
[0] = (unsigned char)((n
>> 24) & 255);
110 octet_string
[1] = (unsigned char)((n
>> 16) & 255);
111 octet_string
[2] = (unsigned char)((n
>> 8)) & 255;
112 octet_string
[3] = (unsigned char)(n
& 255);
113 gcry_md_write(handle
, octet_string
, 4);
114 gcry_md_final(handle
);
115 md
= gcry_md_read(handle
, GCRY_MD_SHA1
);
116 memcpy(rp
, md
, PARA_MIN(HASH_SIZE
, (int)(end
- rp
)));
118 gcry_md_reset(handle
);
120 gcry_md_close(handle
);
123 /** The sha1 hash of an empty file. */
124 static const unsigned char empty_hash
[HASH_SIZE
] =
125 "\xda" "\x39" "\xa3" "\xee" "\x5e"
126 "\x6b" "\x4b" "\x0d" "\x32" "\x55"
127 "\xbf" "\xef" "\x95" "\x60" "\x18"
128 "\x90" "\xaf" "\xd8" "\x07" "\x09";
130 /* rfc3447, section 7.1.1 */
131 static void pad_oaep(unsigned char *in
, size_t in_len
, unsigned char *out
,
134 size_t ps_len
= out_len
- in_len
- 2 * HASH_SIZE
- 2;
135 size_t n
, mask_len
= out_len
- HASH_SIZE
- 1;
136 unsigned char *seed
= out
+ 1, *db
= seed
+ HASH_SIZE
,
137 *ps
= db
+ HASH_SIZE
, *one
= ps
+ ps_len
;
138 unsigned char *db_mask
, seed_mask
[HASH_SIZE
];
140 assert(in_len
<= out_len
- 2 - 2 * HASH_SIZE
);
141 assert(out_len
> 2 * HASH_SIZE
+ 2);
142 PARA_DEBUG_LOG("padding %zu byte input -> %zu byte output\n",
144 dump_buffer("unpadded buffer", in
, in_len
);
147 get_random_bytes_or_die(seed
, HASH_SIZE
);
148 memcpy(db
, empty_hash
, HASH_SIZE
);
149 memset(ps
, 0, ps_len
);
151 memcpy(one
+ 1, in
, in_len
);
152 db_mask
= para_malloc(mask_len
);
153 mgf1(seed
, HASH_SIZE
, mask_len
, db_mask
);
154 for (n
= 0; n
< mask_len
; n
++)
156 mgf1(db
, mask_len
, HASH_SIZE
, seed_mask
);
157 for (n
= 0; n
< HASH_SIZE
; n
++)
158 seed
[n
] ^= seed_mask
[n
];
160 dump_buffer("padded buffer", out
, out_len
);
163 /* rfc 3447, section 7.1.2 */
164 static int unpad_oaep(unsigned char *in
, size_t in_len
, unsigned char *out
,
167 unsigned char *masked_seed
= in
+ 1;
168 unsigned char *db
= in
+ 1 + HASH_SIZE
;
169 unsigned char seed
[HASH_SIZE
], seed_mask
[HASH_SIZE
];
170 unsigned char *db_mask
, *p
;
171 size_t n
, mask_len
= in_len
- HASH_SIZE
- 1;
173 mgf1(db
, mask_len
, HASH_SIZE
, seed_mask
);
174 for (n
= 0; n
< HASH_SIZE
; n
++)
175 seed
[n
] = masked_seed
[n
] ^ seed_mask
[n
];
176 db_mask
= para_malloc(mask_len
);
177 mgf1(seed
, HASH_SIZE
, mask_len
, db_mask
);
178 for (n
= 0; n
< mask_len
; n
++)
181 if (memcmp(db
, empty_hash
, HASH_SIZE
))
183 for (p
= db
+ HASH_SIZE
; p
< in
+ in_len
- 1; p
++)
186 if (p
>= in
+ in_len
- 1)
189 *out_len
= in
+ in_len
- p
;
190 memcpy(out
, p
, *out_len
);
194 struct asymmetric_key
{
199 static const char *gcrypt_strerror(gcry_error_t gret
)
201 return gcry_strerror(gcry_err_code(gret
));
204 static int decode_key(const char *key_file
, const char *header_str
,
205 const char *footer_str
, unsigned char **result
)
209 size_t map_size
, key_size
, blob_size
;
210 unsigned char *blob
= NULL
;
211 char *begin
, *footer
, *key
;
213 ret
= mmap_full_file(key_file
, O_RDONLY
, &map
, &map_size
, NULL
);
217 if (strncmp(map
, header_str
, strlen(header_str
)))
219 footer
= strstr(map
, footer_str
);
223 begin
= map
+ strlen(header_str
);
224 /* skip whitespace at the beginning */
225 for (; begin
< footer
; begin
++) {
226 if (para_isspace(*begin
))
234 key_size
= footer
- begin
;
235 key
= para_malloc(key_size
+ 1);
236 for (i
= 0, j
= 0; begin
+ i
< footer
; i
++) {
237 if (para_isspace(begin
[i
]))
242 //PARA_CRIT_LOG("key: %s\n", key);
243 blob_size
= key_size
* 2;
244 blob
= para_malloc(blob_size
);
245 ret
= base64_decode(key
, blob
, blob_size
);
254 ret2
= para_munmap(map
, map_size
);
255 if (ret
>= 0 && ret2
< 0)
265 /** ASN Types and their code. */
267 /** The next object is an integer. */
268 ASN1_TYPE_INTEGER
= 0x2,
269 /** Bit string object. */
270 ASN1_TYPE_BIT_STRING
= 0x03,
271 /** Keys start with one big type sequence. */
272 ASN1_TYPE_SEQUENCE
= 0x30,
275 /* bit 6 has value 0 */
276 static inline bool is_primitive(unsigned char c
)
278 return ((c
& (1<<6)) == 0);
281 static inline bool is_primitive_integer(unsigned char c
)
283 if (!is_primitive(c
))
285 return ((c
& 0x1f) == ASN1_TYPE_INTEGER
);
288 /* Bit 8 is zero (and bits 7-1 give the length) */
289 static inline bool is_short_form(unsigned char c
)
291 return (c
& 0x80) == 0;
294 static inline int get_short_form_length(unsigned char c
)
299 static inline int get_long_form_num_length_bytes(unsigned char c
)
304 static int find_pubkey_bignum_offset(const unsigned char *data
, int len
)
306 const unsigned char *p
= data
, *end
= data
+ len
;
308 /* the whole thing istarts with one sequence */
309 if (*p
!= ASN1_TYPE_SEQUENCE
)
310 return -E_ASN1_PARSE
;
313 return -E_ASN1_PARSE
;
314 if (is_short_form(*p
))
317 p
+= 1 + get_long_form_num_length_bytes(*p
);
319 return -E_ASN1_PARSE
;
320 /* another sequence containing the object id, skip it */
321 if (*p
!= ASN1_TYPE_SEQUENCE
)
322 return -E_ASN1_PARSE
;
325 return -E_ASN1_PARSE
;
326 if (!is_short_form(*p
))
327 return -E_ASN1_PARSE
;
328 p
+= 1 + get_short_form_length(*p
);
330 return -E_ASN1_PARSE
;
331 /* all numbers are wrapped in a bit string object that follows */
332 if (*p
!= ASN1_TYPE_BIT_STRING
)
333 return -E_ASN1_PARSE
;
336 return -E_ASN1_PARSE
;
337 if (is_short_form(*p
))
340 p
+= 1 + get_long_form_num_length_bytes(*p
);
341 p
++; /* skip number of unused bits in the bit string */
343 return -E_ASN1_PARSE
;
345 /* next, we have a sequence of two integers (n and e) */
346 if (*p
!= ASN1_TYPE_SEQUENCE
)
347 return -E_ASN1_PARSE
;
350 return -E_ASN1_PARSE
;
351 if (is_short_form(*p
))
354 p
+= 1 + get_long_form_num_length_bytes(*p
);
356 return -E_ASN1_PARSE
;
357 if (*p
!= ASN1_TYPE_INTEGER
)
358 return -E_ASN1_PARSE
;
363 * Returns: Number of bytes scanned. This may differ from the value returned via
364 * bn_bytes because the latter does not include the ASN.1 prefix and a leading
365 * zero is not considered as an additional byte for bn_bytes.
367 static int read_bignum(unsigned char *start
, unsigned char *end
, gcry_mpi_t
*bn
,
372 unsigned char *cp
= start
;
374 if (!is_primitive_integer(*cp
))
375 return -E_BAD_PRIVATE_KEY
;
377 if (is_short_form(*cp
)) {
378 bn_size
= get_short_form_length(*cp
);
381 int num_bytes
= get_long_form_num_length_bytes(*cp
);
382 if (cp
+ num_bytes
> end
)
383 return -E_BAD_PRIVATE_KEY
;
384 if (num_bytes
> 4) /* nobody has such a large modulus */
385 return -E_BAD_PRIVATE_KEY
;
388 for (i
= 0; i
< num_bytes
; i
++, cp
++)
389 bn_size
= (bn_size
<< 8) + *cp
;
391 PARA_DEBUG_LOG("bn_size %d (0x%x)\n", bn_size
, bn_size
);
392 gret
= gcry_mpi_scan(bn
, GCRYMPI_FMT_STD
, cp
, bn_size
, NULL
);
394 PARA_ERROR_LOG("%s while scanning n\n",
395 gcry_strerror(gcry_err_code(gret
)));
399 * Don't take the first leading zero into account for the size of the
409 // unsigned char *buf;
410 // gcry_mpi_aprint(GCRYMPI_FMT_HEX, &buf, NULL, *bn);
411 // PARA_CRIT_LOG("bn: %s\n", buf);
415 static int find_privkey_bignum_offset(const unsigned char *data
, int len
)
417 const unsigned char *p
= data
, *end
= data
+ len
;
419 /* like the public key, the whole thing is contained in a sequence */
420 if (*p
!= ASN1_TYPE_SEQUENCE
)
421 return -E_ASN1_PARSE
;
424 return -E_ASN1_PARSE
;
425 if (is_short_form(*p
))
428 p
+= 1 + get_long_form_num_length_bytes(*p
);
430 return -E_ASN1_PARSE
;
432 /* Skip next integer */
433 if (*p
!= ASN1_TYPE_INTEGER
)
434 return -E_ASN1_PARSE
;
437 return -E_ASN1_PARSE
;
438 if (is_short_form(*p
))
439 p
+= 1 + get_short_form_length(*p
);
441 p
+= 1 + get_long_form_num_length_bytes(*p
);
443 return -E_ASN1_PARSE
;
447 /** Private keys start with this header. */
448 #define PRIVATE_KEY_HEADER "-----BEGIN RSA PRIVATE KEY-----"
449 /** Private keys end with this footer. */
450 #define PRIVATE_KEY_FOOTER "-----END RSA PRIVATE KEY-----"
452 static int get_private_key(const char *key_file
, struct asymmetric_key
**result
)
454 gcry_mpi_t n
= NULL
, e
= NULL
, d
= NULL
, p
= NULL
, q
= NULL
,
456 unsigned char *blob
, *cp
, *end
;
457 int blob_size
, ret
, n_size
;
461 struct asymmetric_key
*key
;
463 ret
= decode_key(key_file
, PRIVATE_KEY_HEADER
, PRIVATE_KEY_FOOTER
,
468 end
= blob
+ blob_size
;
469 ret
= find_privkey_bignum_offset(blob
, blob_size
);
472 PARA_INFO_LOG("reading RSA params at offset %d\n", ret
);
475 ret
= read_bignum(cp
, end
, &n
, &n_size
);
480 ret
= read_bignum(cp
, end
, &e
, NULL
);
485 ret
= read_bignum(cp
, end
, &d
, NULL
);
490 ret
= read_bignum(cp
, end
, &p
, NULL
);
495 ret
= read_bignum(cp
, end
, &q
, NULL
);
499 ret
= read_bignum(cp
, end
, &u
, NULL
);
504 * OpenSSL uses slightly different parameters than gcrypt. To use these
505 * parameters we need to swap the values of p and q and recompute u.
507 if (gcry_mpi_cmp(p
, q
) > 0) {
509 gcry_mpi_invm(u
, p
, q
);
511 gret
= gcry_sexp_build(&sexp
, &erroff
, RSA_PRIVKEY_SEXP
,
515 PARA_ERROR_LOG("offset %zu: %s\n", erroff
,
516 gcry_strerror(gcry_err_code(gret
)));
520 key
= para_malloc(sizeof(*key
));
524 PARA_INFO_LOG("succesfully read %d bit private key\n", ret
);
542 /** Public keys start with this header. */
543 #define PUBLIC_KEY_HEADER "-----BEGIN PUBLIC KEY-----"
544 /** Public keys end with this footer. */
545 #define PUBLIC_KEY_FOOTER "-----END PUBLIC KEY-----"
547 static int get_asn_public_key(const char *key_file
, struct asymmetric_key
**result
)
549 gcry_mpi_t n
= NULL
, e
= NULL
;
550 unsigned char *blob
, *cp
, *end
;
551 int blob_size
, ret
, n_size
;
555 struct asymmetric_key
*key
;
557 ret
= decode_key(key_file
, PUBLIC_KEY_HEADER
, PUBLIC_KEY_FOOTER
,
562 end
= blob
+ blob_size
;
563 ret
= find_pubkey_bignum_offset(blob
, blob_size
);
566 PARA_DEBUG_LOG("decoding public RSA params at offset %d\n", ret
);
569 ret
= read_bignum(cp
, end
, &n
, &n_size
);
574 ret
= read_bignum(cp
, end
, &e
, NULL
);
579 gret
= gcry_sexp_build(&sexp
, &erroff
, RSA_PUBKEY_SEXP
, n
, e
);
581 PARA_ERROR_LOG("offset %zu: %s\n", erroff
,
582 gcry_strerror(gcry_err_code(gret
)));
586 key
= para_malloc(sizeof(*key
));
590 PARA_INFO_LOG("successfully read %u bit asn public key\n", n_size
* 8);
601 static int get_ssh_public_key(unsigned char *data
, int size
, gcry_sexp_t
*result
)
605 unsigned char *blob
= NULL
, *p
, *end
;
606 size_t nr_scanned
, erroff
, decoded_size
;
607 gcry_mpi_t e
= NULL
, n
= NULL
;
609 PARA_DEBUG_LOG("decoding %d byte public rsa-ssh key\n", size
);
610 if (size
> INT_MAX
/ 4)
611 return -ERRNO_TO_PARA_ERROR(EOVERFLOW
);
612 blob
= para_malloc(2 * size
);
613 ret
= uudecode((char *)data
, blob
, 2 * size
);
617 end
= blob
+ decoded_size
;
618 dump_buffer("decoded key", blob
, decoded_size
);
619 ret
= check_ssh_key_header(blob
, decoded_size
);
626 PARA_DEBUG_LOG("scanning modulus and public exponent\n");
627 gret
= gcry_mpi_scan(&e
, GCRYMPI_FMT_SSH
, p
, end
- p
, &nr_scanned
);
630 PARA_CRIT_LOG("%s\n", gcry_strerror(gcry_err_code(gret
)));
633 PARA_DEBUG_LOG("scanned e (%zu bytes)\n", nr_scanned
);
634 // gcry_mpi_aprint(GCRYMPI_FMT_HEX, &buf, NULL, rsa_e);
635 // PARA_CRIT_LOG("e: %s\n", buf);
639 gret
= gcry_mpi_scan(&n
, GCRYMPI_FMT_SSH
, p
, end
- p
, &nr_scanned
);
642 PARA_ERROR_LOG("%s\n", gcry_strerror(gcry_err_code(gret
)));
645 PARA_DEBUG_LOG("scanned n (%zu bytes)\n", nr_scanned
);
646 // gcry_mpi_aprint(GCRYMPI_FMT_HEX, &buf, NULL, rsa_n);
647 // PARA_CRIT_LOG("n: %s\n", buf);
648 gret
= gcry_sexp_build(result
, &erroff
, RSA_PUBKEY_SEXP
, n
, e
);
650 PARA_ERROR_LOG("offset %zu: %s\n", erroff
,
651 gcry_strerror(gcry_err_code(gret
)));
655 ret
= nr_scanned
/ 32 * 32;
656 PARA_INFO_LOG("successfully read %u bit ssh public key\n", ret
* 8);
666 int get_asymmetric_key(const char *key_file
, int private,
667 struct asymmetric_key
**result
)
672 unsigned char *start
, *end
;
674 struct asymmetric_key
*key
;
677 return get_private_key(key_file
, result
);
678 ret
= mmap_full_file(key_file
, O_RDONLY
, &map
, &map_size
, NULL
);
681 ret
= is_ssh_rsa_key(map
, map_size
);
683 ret
= para_munmap(map
, map_size
);
686 return get_asn_public_key(key_file
, result
);
689 end
= map
+ map_size
;
693 ret
= get_ssh_public_key(start
, end
- start
, &sexp
);
696 key
= para_malloc(sizeof(*key
));
697 key
->num_bytes
= ret
;
700 ret
= key
->num_bytes
;
702 ret2
= para_munmap(map
, map_size
);
703 if (ret
>= 0 && ret2
< 0)
708 void free_asymmetric_key(struct asymmetric_key
*key
)
712 gcry_sexp_release(key
->sexp
);
716 static int decode_rsa(gcry_sexp_t sexp
, int key_size
, unsigned char *outbuf
,
721 unsigned char oaep_buf
[512];
724 if (libgcrypt_has_oaep
) {
725 const char *p
= gcry_sexp_nth_data(sexp
, 1, nbytes
);
728 PARA_ERROR_LOG("could not get data from list\n");
731 memcpy(outbuf
, p
, *nbytes
);
734 out_mpi
= gcry_sexp_nth_mpi(sexp
, 0, GCRYMPI_FMT_USG
);
737 gret
= gcry_mpi_print(GCRYMPI_FMT_USG
, oaep_buf
, sizeof(oaep_buf
),
740 PARA_ERROR_LOG("mpi_print: %s\n", gcrypt_strerror(gret
));
742 goto out_mpi_release
;
745 * An oaep-encoded buffer always starts with at least one zero byte.
746 * However, leading zeroes in an mpi are omitted in the output of
747 * gcry_mpi_print() when using the GCRYMPI_FMT_USG format. The
748 * alternative, GCRYMPI_FMT_STD, does not work either because here the
749 * leading zero(es) might also be omitted, depending on the value of
752 * To circumvent this, we shift the oaep buffer to the right. But first
753 * we check that the buffer actually started with a zero byte, i.e. that
754 * nbytes < key_size. Otherwise a decoding error occurred.
756 ret
= -E_SEXP_DECRYPT
;
757 if (*nbytes
>= key_size
)
758 goto out_mpi_release
;
759 memmove(oaep_buf
+ key_size
- *nbytes
, oaep_buf
, *nbytes
);
760 memset(oaep_buf
, 0, key_size
- *nbytes
);
762 PARA_DEBUG_LOG("decrypted buffer before unpad (%d bytes):\n",
764 dump_buffer("non-unpadded decrypted buffer", oaep_buf
, key_size
);;
765 ret
= unpad_oaep(oaep_buf
, key_size
, outbuf
, nbytes
);
767 goto out_mpi_release
;
768 PARA_DEBUG_LOG("decrypted buffer after unpad (%zu bytes):\n",
770 dump_buffer("unpadded decrypted buffer", outbuf
, *nbytes
);;
773 gcry_mpi_release(out_mpi
);
777 int priv_decrypt(const char *key_file
, unsigned char *outbuf
,
778 unsigned char *inbuf
, int inlen
)
782 struct asymmetric_key
*priv
;
783 gcry_mpi_t in_mpi
= NULL
;
784 gcry_sexp_t in
, out
, priv_key
;
787 PARA_INFO_LOG("decrypting %d byte input\n", inlen
);
788 /* key_file -> asymmetric key priv */
789 ret
= get_private_key(key_file
, &priv
);
794 /* asymmetric key priv -> sexp priv_key */
796 priv_key
= gcry_sexp_find_token(priv
->sexp
, "private-key", 0);
800 /* inbuf -> in_mpi */
801 gret
= gcry_mpi_scan(&in_mpi
, GCRYMPI_FMT_USG
, inbuf
,
804 PARA_ERROR_LOG("%s\n", gcrypt_strerror(gret
));
808 /* in_mpi -> in sexp */
809 gret
= gcry_sexp_build(&in
, NULL
, rsa_decrypt_sexp
, in_mpi
);
811 PARA_ERROR_LOG("%s\n", gcrypt_strerror(gret
));
816 /* rsa decryption: in sexp -> out sexp */
817 gret
= gcry_pk_decrypt(&out
, in
, priv_key
);
819 PARA_ERROR_LOG("decrypt: %s\n", gcrypt_strerror(gret
));
820 ret
= -E_SEXP_DECRYPT
;
823 ret
= decode_rsa(out
, key_size
, outbuf
, &nbytes
);
826 PARA_INFO_LOG("successfully decrypted %zu byte message\n", nbytes
);
829 gcry_sexp_release(out
);
831 gcry_sexp_release(in
);
833 gcry_mpi_release(in_mpi
);
835 gcry_sexp_release(priv_key
);
837 free_asymmetric_key(priv
);
841 int pub_encrypt(struct asymmetric_key
*pub
, unsigned char *inbuf
,
842 unsigned len
, unsigned char *outbuf
)
845 gcry_sexp_t pub_key
, in
, out
, out_a
;
846 gcry_mpi_t out_mpi
= NULL
;
850 PARA_INFO_LOG("encrypting %u byte input with %d-byte key\n", len
, pub
->num_bytes
);
853 pub_key
= gcry_sexp_find_token(pub
->sexp
, "public-key", 0);
856 if (libgcrypt_has_oaep
) {
857 gret
= gcry_sexp_build(&in
, NULL
,
858 "(data(flags oaep)(value %b))", len
, inbuf
);
860 unsigned char padded_input
[256];
861 const size_t pad_size
= 256;
862 /* inbuf -> padded inbuf */
863 pad_oaep(inbuf
, len
, padded_input
, pad_size
);
864 /* padded inbuf -> in sexp */
865 gret
= gcry_sexp_build(&in
, NULL
,
866 "(data(flags raw)(value %b))", pad_size
, padded_input
);
869 PARA_ERROR_LOG("%s\n", gcrypt_strerror(gret
));
873 /* rsa sexp encryption: in -> out */
874 gret
= gcry_pk_encrypt(&out
, in
, pub_key
);
876 PARA_ERROR_LOG("%s\n", gcrypt_strerror(gret
));
877 ret
= -E_SEXP_ENCRYPT
;
880 /* extract a, an MPI with the result of the RSA operation */
882 out_a
= gcry_sexp_find_token(out
, "a", 0);
885 /* convert sexp out_a -> out_mpi */
886 out_mpi
= gcry_sexp_nth_mpi(out_a
, 1, GCRYMPI_FMT_USG
);
891 gret
= gcry_mpi_print(GCRYMPI_FMT_USG
, outbuf
, 512 /* FIXME */, &nbytes
, out_mpi
);
893 PARA_ERROR_LOG("%s\n", gcrypt_strerror(gret
));
894 ret
= -E_SEXP_ENCRYPT
;
895 goto out_mpi_release
;
897 PARA_INFO_LOG("encrypted buffer is %zu bytes\n", nbytes
);
898 dump_buffer("enc buf", outbuf
, nbytes
);
902 gcry_mpi_release(out_mpi
);
904 gcry_sexp_release(out_a
);
906 gcry_sexp_release(out
);
908 gcry_sexp_release(in
);
910 gcry_sexp_release(pub_key
);
914 struct stream_cipher
{
915 gcry_cipher_hd_t handle
;
918 struct stream_cipher
*sc_new(const unsigned char *data
, int len
)
922 struct stream_cipher
*sc
= para_malloc(sizeof(*sc
));
923 gret
= gcry_cipher_open(&sc
->handle
, GCRY_CIPHER_ARCFOUR
,
924 GCRY_CIPHER_MODE_STREAM
, 0);
926 PARA_ERROR_LOG("%s\n", gcrypt_strerror(gret
));
930 gret
= gcry_cipher_setkey(sc
->handle
, data
, (size_t)len
);
935 void sc_free(struct stream_cipher
*sc
)
939 gcry_cipher_close(sc
->handle
);
943 int sc_send_bin_buffer(struct stream_cipher_context
*scc
, char *buf
,
948 unsigned char *tmp
= para_malloc(size
);
951 gret
= gcry_cipher_encrypt(scc
->send
->handle
, tmp
, size
,
952 (unsigned char *)buf
, size
);
954 ret
= write_all(scc
->fd
, (char *)tmp
, &size
);
959 int sc_recv_bin_buffer(struct stream_cipher_context
*scc
, char *buf
,
963 ssize_t ret
= recv(scc
->fd
, buf
, size
, 0);
966 ret
= -ERRNO_TO_PARA_ERROR(errno
);
969 /* perform in-place encryption */
970 gret
= gcry_cipher_encrypt(scc
->recv
->handle
, (unsigned char *)buf
, ret
,