The big Assuan error code removal.
[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
227   *encval = buf;
228   return 0;
229 }
230
231
232 \f
233 /* do the actual encryption */
234 static int
235 encrypt_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
236 {
237   struct encrypt_cb_parm_s *parm = cb_value;
238   int blklen = parm->dek->ivlen;
239   unsigned char *p;
240   size_t n;
241
242   *nread = 0;
243   if (!buffer)
244     return -1; /* not supported */
245
246   if (parm->ready)
247     return -1;
248
249   if (count < blklen)
250     BUG ();
251      
252   if (!parm->eof_seen)
253     { /* fillup the buffer */
254       p = parm->buffer;
255       for (n=parm->buflen; n < parm->bufsize; n++)
256         {
257           int c = getc (parm->fp);
258           if (c == EOF)
259             {
260               if (ferror (parm->fp))
261                 {
262                   parm->readerror = errno;
263                   return -1;
264                 }
265               parm->eof_seen = 1;
266               break; 
267             }
268           p[n] = c;
269         }
270       parm->buflen = n;
271     }
272   
273   n = parm->buflen < count? parm->buflen : count;
274   n = n/blklen * blklen;
275   if (n)
276     { /* encrypt the stuff */
277       gcry_cipher_encrypt (parm->dek->chd, buffer, n, parm->buffer, n);
278       *nread = n;
279       /* Who cares about cycles, take the easy way and shift the buffer */
280       parm->buflen -= n;
281       memmove (parm->buffer, parm->buffer+n, parm->buflen);
282     }
283   else if (parm->eof_seen)
284     { /* no complete block but eof: add padding */
285       /* fixme: we should try to do this also in the above code path */
286       int i, npad = blklen - (parm->buflen % blklen);
287       p = parm->buffer;
288       for (n=parm->buflen, i=0; n < parm->bufsize && i < npad; n++, i++)
289         p[n] = npad;
290       gcry_cipher_encrypt (parm->dek->chd, buffer, n, parm->buffer, n);
291       *nread = n;
292       parm->ready = 1;
293     }
294
295   return 0;
296 }
297
298
299
300 \f
301 /* Perform an encrypt operation.  
302
303    Encrypt the data received on DATA-FD and write it to OUT_FP.  The
304    recipients are take from the certificate given in recplist; if this
305    is NULL it will be encrypted for a default recipient */
306 int
307 gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
308 {
309   int rc = 0;
310   Base64Context b64writer = NULL;
311   gpg_error_t err;
312   ksba_writer_t writer;
313   ksba_reader_t reader = NULL;
314   ksba_cms_t cms = NULL;
315   ksba_stop_reason_t stopreason;
316   KEYDB_HANDLE kh = NULL;
317   struct encrypt_cb_parm_s encparm;
318   DEK dek = NULL;
319   int recpno;
320   FILE *data_fp = NULL;
321   certlist_t cl;
322
323   memset (&encparm, 0, sizeof encparm);
324
325   /* Check that the certificate list is not empty and that at least
326      one certificate is not flagged as encrypt_to; i.e. is a real
327      recipient. */
328   for (cl = recplist; cl; cl = cl->next)
329     if (!cl->is_encrypt_to)
330       break;
331   if (!cl)
332     {
333       log_error(_("no valid recipients given\n"));
334       gpgsm_status (ctrl, STATUS_NO_RECP, "0");
335       rc = gpg_error (GPG_ERR_NO_PUBKEY);
336       goto leave;
337     }
338
339   kh = keydb_new (0);
340   if (!kh)
341     {
342       log_error (_("failed to allocated keyDB handle\n"));
343       rc = gpg_error (GPG_ERR_GENERAL);
344       goto leave;
345     }
346
347   data_fp = fdopen ( dup (data_fd), "rb");
348   if (!data_fp)
349     {
350       rc = gpg_error (gpg_err_code_from_errno (errno));
351       log_error ("fdopen() failed: %s\n", strerror (errno));
352       goto leave;
353     }
354
355   err = ksba_reader_new (&reader);
356   if (err)
357       rc = err;
358   if (!rc)
359     rc = ksba_reader_set_cb (reader, encrypt_cb, &encparm);
360   if (rc)
361       goto leave;
362
363   encparm.fp = data_fp;
364
365   ctrl->pem_name = "ENCRYPTED MESSAGE";
366   rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
367   if (rc)
368     {
369       log_error ("can't create writer: %s\n", gpg_strerror (rc));
370       goto leave;
371     }
372
373   err = ksba_cms_new (&cms);
374   if (err)
375     {
376       rc = err;
377       goto leave;
378     }
379
380   err = ksba_cms_set_reader_writer (cms, reader, writer);
381   if (err)
382     {
383       log_debug ("ksba_cms_set_reader_writer failed: %s\n",
384                  gpg_strerror (err));
385       rc = err;
386       goto leave;
387     }
388
389   /* We are going to create enveloped data with uninterpreted data as
390      inner content */
391   err = ksba_cms_set_content_type (cms, 0, KSBA_CT_ENVELOPED_DATA);
392   if (!err)
393     err = ksba_cms_set_content_type (cms, 1, KSBA_CT_DATA);
394   if (err)
395     {
396       log_debug ("ksba_cms_set_content_type failed: %s\n",
397                  gpg_strerror (err));
398       rc = err;
399       goto leave;
400     }
401
402   /* Create a session key */
403   dek = xtrycalloc_secure (1, sizeof *dek); 
404   if (!dek)
405     rc = out_of_core ();
406   else
407   {
408     dek->algoid = opt.def_cipher_algoid;
409     rc = init_dek (dek);
410   }
411   if (rc)
412     {
413       log_error ("failed to create the session key: %s\n",
414                  gpg_strerror (rc));
415       goto leave;
416     }
417
418   err = ksba_cms_set_content_enc_algo (cms, dek->algoid, dek->iv, dek->ivlen);
419   if (err)
420     {
421       log_error ("ksba_cms_set_content_enc_algo failed: %s\n",
422                  gpg_strerror (err));
423       rc = err;
424       goto leave;
425     }
426
427   encparm.dek = dek;
428   /* Use a ~8k (AES) or ~4k (3DES) buffer */
429   encparm.bufsize = 500 * dek->ivlen;
430   encparm.buffer = xtrymalloc (encparm.bufsize);
431   if (!encparm.buffer)
432     {
433       rc = out_of_core ();
434       goto leave;
435     }
436
437   /* Gather certificates of recipients, encrypt the session key for
438      each and store them in the CMS object */
439   for (recpno = 0, cl = recplist; cl; recpno++, cl = cl->next)
440     {
441       unsigned char *encval;
442       
443       rc = encrypt_dek (dek, cl->cert, &encval);
444       if (rc)
445         {
446           log_error ("encryption failed for recipient no. %d: %s\n",
447                      recpno, gpg_strerror (rc));
448           goto leave;
449         }
450       
451       err = ksba_cms_add_recipient (cms, cl->cert);
452       if (err)
453         {
454           log_error ("ksba_cms_add_recipient failed: %s\n",
455                      gpg_strerror (err));
456           rc = err;
457           xfree (encval);
458           goto leave;
459         }
460       
461       err = ksba_cms_set_enc_val (cms, recpno, encval);
462       xfree (encval);
463       if (err)
464         {
465           log_error ("ksba_cms_set_enc_val failed: %s\n",
466                      gpg_strerror (err));
467           rc = err;
468           goto leave;
469         }
470   }
471
472   /* Main control loop for encryption. */
473   recpno = 0;
474   do 
475     {
476       err = ksba_cms_build (cms, &stopreason);
477       if (err)
478         {
479           log_debug ("ksba_cms_build failed: %s\n", gpg_strerror (err));
480           rc = err;
481           goto leave;
482         }
483     }
484   while (stopreason != KSBA_SR_READY);   
485
486   if (encparm.readerror)
487     {
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;
491     }
492
493
494   rc = gpgsm_finish_writer (b64writer);
495   if (rc) 
496     {
497       log_error ("write failed: %s\n", gpg_strerror (rc));
498       goto leave;
499     }
500   log_info ("encrypted data created\n");
501
502  leave:
503   ksba_cms_release (cms);
504   gpgsm_destroy_writer (b64writer);
505   ksba_reader_release (reader);
506   keydb_release (kh); 
507   xfree (dek);
508   if (data_fp)
509     fclose (data_fp);
510   xfree (encparm.buffer);
511   return rc;
512 }