2006-12-21 Marcus Brinkmann <marcus@g10code.de>
[gnupg.git] / sm / encrypt.c
1 /* encrypt.c - Encrypt a message
2  *      Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
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 2 of the License, or
9  * (at your option) any later version.
10  *
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.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19  * USA.
20  */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <unistd.h> 
28 #include <time.h>
29 #include <assert.h>
30
31 #include "gpgsm.h"
32 #include <gcrypt.h>
33 #include <ksba.h>
34
35 #include "keydb.h"
36 #include "i18n.h"
37
38
39 struct dek_s {
40   const char *algoid;
41   int algo;
42   gcry_cipher_hd_t chd;
43   char key[32];
44   int keylen;
45   char iv[32];
46   int ivlen;
47 };
48 typedef struct dek_s *DEK;
49
50 struct encrypt_cb_parm_s {
51   FILE *fp;
52   DEK dek;
53   int eof_seen;
54   int ready;
55   int readerror;
56   int bufsize;
57   unsigned char *buffer;
58   int buflen;
59 };
60
61
62
63
64 \f
65 /* Initialize the data encryption key (session key). */
66 static int
67 init_dek (DEK dek)
68 {
69   int rc=0, mode, i;
70
71   dek->algo = gcry_cipher_map_name (dek->algoid);
72   mode = gcry_cipher_mode_from_oid (dek->algoid);
73   if (!dek->algo || !mode)
74     {
75       log_error ("unsupported algorithm `%s'\n", dek->algoid);
76       return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
77     }
78   
79   /* Extra check for algorithms we considere to be to weak for
80      encryption, qlthough we suppor them fro decryption.  Note that
81      there is another check below discriminating on the key length. */
82   switch (dek->algo)
83     {
84     case GCRY_CIPHER_DES:
85     case GCRY_CIPHER_RFC2268_40:
86       log_error ("cipher algorithm `%s' not allowed: too weak\n",
87                  gcry_cipher_algo_name (dek->algo));
88       return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
89     default:
90       break;
91     }
92
93   dek->keylen = gcry_cipher_get_algo_keylen (dek->algo);
94   if (!dek->keylen || dek->keylen > sizeof (dek->key))
95     return gpg_error (GPG_ERR_BUG);
96
97   dek->ivlen = gcry_cipher_get_algo_blklen (dek->algo);
98   if (!dek->ivlen || dek->ivlen > sizeof (dek->iv))
99     return gpg_error (GPG_ERR_BUG);
100
101   /* Make sure we don't use weak keys. */
102   if (dek->keylen < 100/8)
103     { 
104       log_error ("key length of `%s' too small\n", dek->algoid);
105       return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
106     }
107   
108   rc = gcry_cipher_open (&dek->chd, dek->algo, mode, GCRY_CIPHER_SECURE);
109   if (rc)
110     {
111       log_error ("failed to create cipher context: %s\n", gpg_strerror (rc));
112       return rc;
113     }
114   
115   for (i=0; i < 8; i++)
116     {
117       gcry_randomize (dek->key, dek->keylen, GCRY_STRONG_RANDOM );
118       rc = gcry_cipher_setkey (dek->chd, dek->key, dek->keylen);
119       if (gpg_err_code (rc) != GPG_ERR_WEAK_KEY)
120         break;
121       log_info(_("weak key created - retrying\n") );
122     }
123   if (rc)
124     {
125       log_error ("failed to set the key: %s\n", gpg_strerror (rc));
126       gcry_cipher_close (dek->chd);
127       dek->chd = NULL;
128       return rc;
129     }
130
131   gcry_create_nonce (dek->iv, dek->ivlen);
132   rc = gcry_cipher_setiv (dek->chd, dek->iv, dek->ivlen);
133   if (rc)
134     {
135       log_error ("failed to set the IV: %s\n", gpg_strerror (rc));
136       gcry_cipher_close (dek->chd);
137       dek->chd = NULL;
138       return rc;
139     }
140   
141   return 0;
142 }
143
144
145 static int
146 encode_session_key (DEK dek, gcry_sexp_t * r_data)
147 {
148   gcry_sexp_t data;
149   char * p, tmp[3];
150   int i;
151   int rc;
152
153   p = xmalloc (64 + 2 * dek->keylen);
154   strcpy (p, "(data\n (flags pkcs1)\n (value #");
155   for (i=0; i < dek->keylen; i++)
156     {
157       sprintf (tmp, "%02x", (unsigned char) dek->key[i]);
158       strcat (p, tmp);   
159     }
160   strcat (p, "#))\n");
161   rc = gcry_sexp_sscan (&data, NULL, p, strlen (p));
162   xfree (p);
163   *r_data = data;
164   return rc;    
165 }
166
167
168 /* Encrypt the DEK under the key contained in CERT and return it as a
169    canonical S-Exp in encval. */
170 static int
171 encrypt_dek (const DEK dek, ksba_cert_t cert, unsigned char **encval)
172 {
173   gcry_sexp_t s_ciph, s_data, s_pkey;
174   int rc;
175   ksba_sexp_t buf;
176   size_t len;
177
178   *encval = NULL;
179
180   /* get the key from the cert */
181   buf = ksba_cert_get_public_key (cert);
182   if (!buf)
183     {
184       log_error ("no public key for recipient\n");
185       return gpg_error (GPG_ERR_NO_PUBKEY);
186     }
187   len = gcry_sexp_canon_len (buf, 0, NULL, NULL);
188   if (!len)
189     {
190       log_error ("libksba did not return a proper S-Exp\n");
191       return gpg_error (GPG_ERR_BUG);
192     }
193   rc = gcry_sexp_sscan (&s_pkey, NULL, (char*)buf, len);
194   xfree (buf); buf = NULL;
195   if (rc)
196     {
197       log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
198       return rc;
199     }
200
201   /* put the encoded cleartext into a simple list */
202   rc = encode_session_key (dek, &s_data);
203   if (rc)
204   {
205     log_error ("encode_session_key failed: %s\n", gpg_strerror (rc));
206     return rc;
207   }
208
209   /* pass it to libgcrypt */
210   rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey);
211   gcry_sexp_release (s_data);
212   gcry_sexp_release (s_pkey);
213   
214   /* reformat it */
215   len = gcry_sexp_sprint (s_ciph, GCRYSEXP_FMT_CANON, NULL, 0);
216   assert (len); 
217   buf = xtrymalloc (len);
218   if (!buf)
219     {
220       gpg_error_t tmperr = out_of_core ();
221       gcry_sexp_release (s_ciph);
222       return tmperr;
223     }
224   len = gcry_sexp_sprint (s_ciph, GCRYSEXP_FMT_CANON, (char*)buf, len);
225   assert (len);
226   gcry_sexp_release (s_ciph);
227
228   *encval = buf;
229   return 0;
230 }
231
232
233 \f
234 /* do the actual encryption */
235 static int
236 encrypt_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
237 {
238   struct encrypt_cb_parm_s *parm = cb_value;
239   int blklen = parm->dek->ivlen;
240   unsigned char *p;
241   size_t n;
242
243   *nread = 0;
244   if (!buffer)
245     return -1; /* not supported */
246
247   if (parm->ready)
248     return -1;
249
250   if (count < blklen)
251     BUG ();
252      
253   if (!parm->eof_seen)
254     { /* fillup the buffer */
255       p = parm->buffer;
256       for (n=parm->buflen; n < parm->bufsize; n++)
257         {
258           int c = getc (parm->fp);
259           if (c == EOF)
260             {
261               if (ferror (parm->fp))
262                 {
263                   parm->readerror = errno;
264                   return -1;
265                 }
266               parm->eof_seen = 1;
267               break; 
268             }
269           p[n] = c;
270         }
271       parm->buflen = n;
272     }
273   
274   n = parm->buflen < count? parm->buflen : count;
275   n = n/blklen * blklen;
276   if (n)
277     { /* encrypt the stuff */
278       gcry_cipher_encrypt (parm->dek->chd, buffer, n, parm->buffer, n);
279       *nread = n;
280       /* Who cares about cycles, take the easy way and shift the buffer */
281       parm->buflen -= n;
282       memmove (parm->buffer, parm->buffer+n, parm->buflen);
283     }
284   else if (parm->eof_seen)
285     { /* no complete block but eof: add padding */
286       /* fixme: we should try to do this also in the above code path */
287       int i, npad = blklen - (parm->buflen % blklen);
288       p = parm->buffer;
289       for (n=parm->buflen, i=0; n < parm->bufsize && i < npad; n++, i++)
290         p[n] = npad;
291       gcry_cipher_encrypt (parm->dek->chd, buffer, n, parm->buffer, n);
292       *nread = n;
293       parm->ready = 1;
294     }
295
296   return 0;
297 }
298
299
300
301 \f
302 /* Perform an encrypt operation.  
303
304    Encrypt the data received on DATA-FD and write it to OUT_FP.  The
305    recipients are take from the certificate given in recplist; if this
306    is NULL it will be encrypted for a default recipient */
307 int
308 gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
309 {
310   int rc = 0;
311   Base64Context b64writer = NULL;
312   gpg_error_t err;
313   ksba_writer_t writer;
314   ksba_reader_t reader = NULL;
315   ksba_cms_t cms = NULL;
316   ksba_stop_reason_t stopreason;
317   KEYDB_HANDLE kh = NULL;
318   struct encrypt_cb_parm_s encparm;
319   DEK dek = NULL;
320   int recpno;
321   FILE *data_fp = NULL;
322   certlist_t cl;
323
324   memset (&encparm, 0, sizeof encparm);
325
326   /* Check that the certificate list is not empty and that at least
327      one certificate is not flagged as encrypt_to; i.e. is a real
328      recipient. */
329   for (cl = recplist; cl; cl = cl->next)
330     if (!cl->is_encrypt_to)
331       break;
332   if (!cl)
333     {
334       log_error(_("no valid recipients given\n"));
335       gpgsm_status (ctrl, STATUS_NO_RECP, "0");
336       rc = gpg_error (GPG_ERR_NO_PUBKEY);
337       goto leave;
338     }
339
340   kh = keydb_new (0);
341   if (!kh)
342     {
343       log_error (_("failed to allocated keyDB handle\n"));
344       rc = gpg_error (GPG_ERR_GENERAL);
345       goto leave;
346     }
347
348   data_fp = fdopen ( dup (data_fd), "rb");
349   if (!data_fp)
350     {
351       rc = gpg_error (gpg_err_code_from_errno (errno));
352       log_error ("fdopen() failed: %s\n", strerror (errno));
353       goto leave;
354     }
355
356   err = ksba_reader_new (&reader);
357   if (err)
358       rc = err;
359   if (!rc)
360     rc = ksba_reader_set_cb (reader, encrypt_cb, &encparm);
361   if (rc)
362       goto leave;
363
364   encparm.fp = data_fp;
365
366   ctrl->pem_name = "ENCRYPTED MESSAGE";
367   rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
368   if (rc)
369     {
370       log_error ("can't create writer: %s\n", gpg_strerror (rc));
371       goto leave;
372     }
373
374   err = ksba_cms_new (&cms);
375   if (err)
376     {
377       rc = err;
378       goto leave;
379     }
380
381   err = ksba_cms_set_reader_writer (cms, reader, writer);
382   if (err)
383     {
384       log_debug ("ksba_cms_set_reader_writer failed: %s\n",
385                  gpg_strerror (err));
386       rc = err;
387       goto leave;
388     }
389
390   /* We are going to create enveloped data with uninterpreted data as
391      inner content */
392   err = ksba_cms_set_content_type (cms, 0, KSBA_CT_ENVELOPED_DATA);
393   if (!err)
394     err = ksba_cms_set_content_type (cms, 1, KSBA_CT_DATA);
395   if (err)
396     {
397       log_debug ("ksba_cms_set_content_type failed: %s\n",
398                  gpg_strerror (err));
399       rc = err;
400       goto leave;
401     }
402
403   /* Create a session key */
404   dek = xtrycalloc_secure (1, sizeof *dek); 
405   if (!dek)
406     rc = out_of_core ();
407   else
408   {
409     dek->algoid = opt.def_cipher_algoid;
410     rc = init_dek (dek);
411   }
412   if (rc)
413     {
414       log_error ("failed to create the session key: %s\n",
415                  gpg_strerror (rc));
416       goto leave;
417     }
418
419   err = ksba_cms_set_content_enc_algo (cms, dek->algoid, dek->iv, dek->ivlen);
420   if (err)
421     {
422       log_error ("ksba_cms_set_content_enc_algo failed: %s\n",
423                  gpg_strerror (err));
424       rc = err;
425       goto leave;
426     }
427
428   encparm.dek = dek;
429   /* Use a ~8k (AES) or ~4k (3DES) buffer */
430   encparm.bufsize = 500 * dek->ivlen;
431   encparm.buffer = xtrymalloc (encparm.bufsize);
432   if (!encparm.buffer)
433     {
434       rc = out_of_core ();
435       goto leave;
436     }
437
438   /* Gather certificates of recipients, encrypt the session key for
439      each and store them in the CMS object */
440   for (recpno = 0, cl = recplist; cl; recpno++, cl = cl->next)
441     {
442       unsigned char *encval;
443       
444       rc = encrypt_dek (dek, cl->cert, &encval);
445       if (rc)
446         {
447           log_error ("encryption failed for recipient no. %d: %s\n",
448                      recpno, gpg_strerror (rc));
449           goto leave;
450         }
451       
452       err = ksba_cms_add_recipient (cms, cl->cert);
453       if (err)
454         {
455           log_error ("ksba_cms_add_recipient failed: %s\n",
456                      gpg_strerror (err));
457           rc = err;
458           xfree (encval);
459           goto leave;
460         }
461       
462       err = ksba_cms_set_enc_val (cms, recpno, encval);
463       xfree (encval);
464       if (err)
465         {
466           log_error ("ksba_cms_set_enc_val failed: %s\n",
467                      gpg_strerror (err));
468           rc = err;
469           goto leave;
470         }
471   }
472
473   /* Main control loop for encryption. */
474   recpno = 0;
475   do 
476     {
477       err = ksba_cms_build (cms, &stopreason);
478       if (err)
479         {
480           log_debug ("ksba_cms_build failed: %s\n", gpg_strerror (err));
481           rc = err;
482           goto leave;
483         }
484     }
485   while (stopreason != KSBA_SR_READY);   
486
487   if (encparm.readerror)
488     {
489       log_error ("error reading input: %s\n", strerror (encparm.readerror));
490       rc = gpg_error (gpg_err_code_from_errno (encparm.readerror));
491       goto leave;
492     }
493
494
495   rc = gpgsm_finish_writer (b64writer);
496   if (rc) 
497     {
498       log_error ("write failed: %s\n", gpg_strerror (rc));
499       goto leave;
500     }
501   log_info ("encrypted data created\n");
502
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;
513 }