agent/
[gnupg.git] / sm / encrypt.c
bloba526a649e57bde79910e4d01076927a4ff0d6741
1 /* encrypt.c - Encrypt a message
2 * Copyright (C) 2001, 2003, 2004, 2007, 2008 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include <config.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <unistd.h>
26 #include <time.h>
27 #include <assert.h>
29 #include "gpgsm.h"
30 #include <gcrypt.h>
31 #include <ksba.h>
33 #include "keydb.h"
34 #include "i18n.h"
37 struct dek_s {
38 const char *algoid;
39 int algo;
40 gcry_cipher_hd_t chd;
41 char key[32];
42 int keylen;
43 char iv[32];
44 int ivlen;
46 typedef struct dek_s *DEK;
48 struct encrypt_cb_parm_s {
49 FILE *fp;
50 DEK dek;
51 int eof_seen;
52 int ready;
53 int readerror;
54 int bufsize;
55 unsigned char *buffer;
56 int buflen;
63 /* Initialize the data encryption key (session key). */
64 static int
65 init_dek (DEK dek)
67 int rc=0, mode, i;
69 dek->algo = gcry_cipher_map_name (dek->algoid);
70 mode = gcry_cipher_mode_from_oid (dek->algoid);
71 if (!dek->algo || !mode)
73 log_error ("unsupported algorithm `%s'\n", dek->algoid);
74 return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
77 /* Extra check for algorithms we consider to be too weak for
78 encryption, although we support them for decryption. Note that
79 there is another check below discriminating on the key length. */
80 switch (dek->algo)
82 case GCRY_CIPHER_DES:
83 case GCRY_CIPHER_RFC2268_40:
84 log_error ("cipher algorithm `%s' not allowed: too weak\n",
85 gcry_cipher_algo_name (dek->algo));
86 return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
87 default:
88 break;
91 dek->keylen = gcry_cipher_get_algo_keylen (dek->algo);
92 if (!dek->keylen || dek->keylen > sizeof (dek->key))
93 return gpg_error (GPG_ERR_BUG);
95 dek->ivlen = gcry_cipher_get_algo_blklen (dek->algo);
96 if (!dek->ivlen || dek->ivlen > sizeof (dek->iv))
97 return gpg_error (GPG_ERR_BUG);
99 /* Make sure we don't use weak keys. */
100 if (dek->keylen < 100/8)
102 log_error ("key length of `%s' too small\n", dek->algoid);
103 return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
106 rc = gcry_cipher_open (&dek->chd, dek->algo, mode, GCRY_CIPHER_SECURE);
107 if (rc)
109 log_error ("failed to create cipher context: %s\n", gpg_strerror (rc));
110 return rc;
113 for (i=0; i < 8; i++)
115 gcry_randomize (dek->key, dek->keylen, GCRY_STRONG_RANDOM );
116 rc = gcry_cipher_setkey (dek->chd, dek->key, dek->keylen);
117 if (gpg_err_code (rc) != GPG_ERR_WEAK_KEY)
118 break;
119 log_info(_("weak key created - retrying\n") );
121 if (rc)
123 log_error ("failed to set the key: %s\n", gpg_strerror (rc));
124 gcry_cipher_close (dek->chd);
125 dek->chd = NULL;
126 return rc;
129 gcry_create_nonce (dek->iv, dek->ivlen);
130 rc = gcry_cipher_setiv (dek->chd, dek->iv, dek->ivlen);
131 if (rc)
133 log_error ("failed to set the IV: %s\n", gpg_strerror (rc));
134 gcry_cipher_close (dek->chd);
135 dek->chd = NULL;
136 return rc;
139 return 0;
143 static int
144 encode_session_key (DEK dek, gcry_sexp_t * r_data)
146 gcry_sexp_t data;
147 char *p;
148 int rc;
150 p = xtrymalloc (64 + 2 * dek->keylen);
151 if (!p)
152 return gpg_error_from_syserror ();
153 strcpy (p, "(data\n (flags pkcs1)\n (value #");
154 bin2hex (dek->key, dek->keylen, p + strlen (p));
155 strcat (p, "#))\n");
156 rc = gcry_sexp_sscan (&data, NULL, p, strlen (p));
157 xfree (p);
158 *r_data = data;
159 return rc;
163 /* Encrypt the DEK under the key contained in CERT and return it as a
164 canonical S-Exp in encval. */
165 static int
166 encrypt_dek (const DEK dek, ksba_cert_t cert, unsigned char **encval)
168 gcry_sexp_t s_ciph, s_data, s_pkey;
169 int rc;
170 ksba_sexp_t buf;
171 size_t len;
173 *encval = NULL;
175 /* get the key from the cert */
176 buf = ksba_cert_get_public_key (cert);
177 if (!buf)
179 log_error ("no public key for recipient\n");
180 return gpg_error (GPG_ERR_NO_PUBKEY);
182 len = gcry_sexp_canon_len (buf, 0, NULL, NULL);
183 if (!len)
185 log_error ("libksba did not return a proper S-Exp\n");
186 return gpg_error (GPG_ERR_BUG);
188 rc = gcry_sexp_sscan (&s_pkey, NULL, (char*)buf, len);
189 xfree (buf); buf = NULL;
190 if (rc)
192 log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
193 return rc;
196 /* Put the encoded cleartext into a simple list. */
197 s_data = NULL; /* (avoid compiler warning) */
198 rc = encode_session_key (dek, &s_data);
199 if (rc)
201 log_error ("encode_session_key failed: %s\n", gpg_strerror (rc));
202 return rc;
205 /* pass it to libgcrypt */
206 rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey);
207 gcry_sexp_release (s_data);
208 gcry_sexp_release (s_pkey);
210 /* Reformat it. */
211 rc = make_canon_sexp (s_ciph, encval, NULL);
212 gcry_sexp_release (s_ciph);
213 return rc;
218 /* do the actual encryption */
219 static int
220 encrypt_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
222 struct encrypt_cb_parm_s *parm = cb_value;
223 int blklen = parm->dek->ivlen;
224 unsigned char *p;
225 size_t n;
227 *nread = 0;
228 if (!buffer)
229 return -1; /* not supported */
231 if (parm->ready)
232 return -1;
234 if (count < blklen)
235 BUG ();
237 if (!parm->eof_seen)
238 { /* fillup the buffer */
239 p = parm->buffer;
240 for (n=parm->buflen; n < parm->bufsize; n++)
242 int c = getc (parm->fp);
243 if (c == EOF)
245 if (ferror (parm->fp))
247 parm->readerror = errno;
248 return -1;
250 parm->eof_seen = 1;
251 break;
253 p[n] = c;
255 parm->buflen = n;
258 n = parm->buflen < count? parm->buflen : count;
259 n = n/blklen * blklen;
260 if (n)
261 { /* encrypt the stuff */
262 gcry_cipher_encrypt (parm->dek->chd, buffer, n, parm->buffer, n);
263 *nread = n;
264 /* Who cares about cycles, take the easy way and shift the buffer */
265 parm->buflen -= n;
266 memmove (parm->buffer, parm->buffer+n, parm->buflen);
268 else if (parm->eof_seen)
269 { /* no complete block but eof: add padding */
270 /* fixme: we should try to do this also in the above code path */
271 int i, npad = blklen - (parm->buflen % blklen);
272 p = parm->buffer;
273 for (n=parm->buflen, i=0; n < parm->bufsize && i < npad; n++, i++)
274 p[n] = npad;
275 gcry_cipher_encrypt (parm->dek->chd, buffer, n, parm->buffer, n);
276 *nread = n;
277 parm->ready = 1;
280 return 0;
286 /* Perform an encrypt operation.
288 Encrypt the data received on DATA-FD and write it to OUT_FP. The
289 recipients are take from the certificate given in recplist; if this
290 is NULL it will be encrypted for a default recipient */
292 gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
294 int rc = 0;
295 Base64Context b64writer = NULL;
296 gpg_error_t err;
297 ksba_writer_t writer;
298 ksba_reader_t reader = NULL;
299 ksba_cms_t cms = NULL;
300 ksba_stop_reason_t stopreason;
301 KEYDB_HANDLE kh = NULL;
302 struct encrypt_cb_parm_s encparm;
303 DEK dek = NULL;
304 int recpno;
305 FILE *data_fp = NULL;
306 certlist_t cl;
307 int count;
309 memset (&encparm, 0, sizeof encparm);
311 audit_set_type (ctrl->audit, AUDIT_TYPE_ENCRYPT);
313 /* Check that the certificate list is not empty and that at least
314 one certificate is not flagged as encrypt_to; i.e. is a real
315 recipient. */
316 for (cl = recplist; cl; cl = cl->next)
317 if (!cl->is_encrypt_to)
318 break;
319 if (!cl)
321 log_error(_("no valid recipients given\n"));
322 gpgsm_status (ctrl, STATUS_NO_RECP, "0");
323 audit_log_i (ctrl->audit, AUDIT_GOT_RECIPIENTS, 0);
324 rc = gpg_error (GPG_ERR_NO_PUBKEY);
325 goto leave;
328 for (count = 0, cl = recplist; cl; cl = cl->next)
329 count++;
330 audit_log_i (ctrl->audit, AUDIT_GOT_RECIPIENTS, count);
332 kh = keydb_new (0);
333 if (!kh)
335 log_error (_("failed to allocated keyDB handle\n"));
336 rc = gpg_error (GPG_ERR_GENERAL);
337 goto leave;
340 data_fp = fdopen ( dup (data_fd), "rb");
341 if (!data_fp)
343 rc = gpg_error (gpg_err_code_from_errno (errno));
344 log_error ("fdopen() failed: %s\n", strerror (errno));
345 goto leave;
348 err = ksba_reader_new (&reader);
349 if (err)
350 rc = err;
351 if (!rc)
352 rc = ksba_reader_set_cb (reader, encrypt_cb, &encparm);
353 if (rc)
354 goto leave;
356 encparm.fp = data_fp;
358 ctrl->pem_name = "ENCRYPTED MESSAGE";
359 rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, NULL, &writer);
360 if (rc)
362 log_error ("can't create writer: %s\n", gpg_strerror (rc));
363 goto leave;
366 err = ksba_cms_new (&cms);
367 if (err)
369 rc = err;
370 goto leave;
373 err = ksba_cms_set_reader_writer (cms, reader, writer);
374 if (err)
376 log_debug ("ksba_cms_set_reader_writer failed: %s\n",
377 gpg_strerror (err));
378 rc = err;
379 goto leave;
382 audit_log (ctrl->audit, AUDIT_GOT_DATA);
384 /* We are going to create enveloped data with uninterpreted data as
385 inner content */
386 err = ksba_cms_set_content_type (cms, 0, KSBA_CT_ENVELOPED_DATA);
387 if (!err)
388 err = ksba_cms_set_content_type (cms, 1, KSBA_CT_DATA);
389 if (err)
391 log_debug ("ksba_cms_set_content_type failed: %s\n",
392 gpg_strerror (err));
393 rc = err;
394 goto leave;
397 /* Create a session key */
398 dek = xtrycalloc_secure (1, sizeof *dek);
399 if (!dek)
400 rc = out_of_core ();
401 else
403 dek->algoid = opt.def_cipher_algoid;
404 rc = init_dek (dek);
406 if (rc)
408 log_error ("failed to create the session key: %s\n",
409 gpg_strerror (rc));
410 goto leave;
413 err = ksba_cms_set_content_enc_algo (cms, dek->algoid, dek->iv, dek->ivlen);
414 if (err)
416 log_error ("ksba_cms_set_content_enc_algo failed: %s\n",
417 gpg_strerror (err));
418 rc = err;
419 goto leave;
422 encparm.dek = dek;
423 /* Use a ~8k (AES) or ~4k (3DES) buffer */
424 encparm.bufsize = 500 * dek->ivlen;
425 encparm.buffer = xtrymalloc (encparm.bufsize);
426 if (!encparm.buffer)
428 rc = out_of_core ();
429 goto leave;
432 audit_log_s (ctrl->audit, AUDIT_SESSION_KEY, dek->algoid);
434 /* Gather certificates of recipients, encrypt the session key for
435 each and store them in the CMS object */
436 for (recpno = 0, cl = recplist; cl; recpno++, cl = cl->next)
438 unsigned char *encval;
440 rc = encrypt_dek (dek, cl->cert, &encval);
441 if (rc)
443 audit_log_cert (ctrl->audit, AUDIT_ENCRYPTED_TO, cl->cert, rc);
444 log_error ("encryption failed for recipient no. %d: %s\n",
445 recpno, gpg_strerror (rc));
446 goto leave;
449 err = ksba_cms_add_recipient (cms, cl->cert);
450 if (err)
452 audit_log_cert (ctrl->audit, AUDIT_ENCRYPTED_TO, cl->cert, err);
453 log_error ("ksba_cms_add_recipient failed: %s\n",
454 gpg_strerror (err));
455 rc = err;
456 xfree (encval);
457 goto leave;
460 err = ksba_cms_set_enc_val (cms, recpno, encval);
461 xfree (encval);
462 audit_log_cert (ctrl->audit, AUDIT_ENCRYPTED_TO, cl->cert, err);
463 if (err)
465 log_error ("ksba_cms_set_enc_val failed: %s\n",
466 gpg_strerror (err));
467 rc = err;
468 goto leave;
472 /* Main control loop for encryption. */
473 recpno = 0;
476 err = ksba_cms_build (cms, &stopreason);
477 if (err)
479 log_debug ("ksba_cms_build failed: %s\n", gpg_strerror (err));
480 rc = err;
481 goto leave;
484 while (stopreason != KSBA_SR_READY);
486 if (encparm.readerror)
488 log_error ("error reading input: %s\n", strerror (encparm.readerror));
489 rc = gpg_error (gpg_err_code_from_errno (encparm.readerror));
490 goto leave;
494 rc = gpgsm_finish_writer (b64writer);
495 if (rc)
497 log_error ("write failed: %s\n", gpg_strerror (rc));
498 goto leave;
500 audit_log (ctrl->audit, AUDIT_ENCRYPTION_DONE);
501 log_info ("encrypted data created\n");
503 leave:
504 ksba_cms_release (cms);
505 gpgsm_destroy_writer (b64writer);
506 ksba_reader_release (reader);
507 keydb_release (kh);
508 xfree (dek);
509 if (data_fp)
510 fclose (data_fp);
511 xfree (encparm.buffer);
512 return rc;