Fixed a bunch of little bugs as reported by Fabian Keil.
[gnupg.git] / sm / decrypt.c
1 /* decrypt.c - Decrypt a message
2  *      Copyright (C) 2001, 2003 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 3 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, see <http://www.gnu.org/licenses/>.
18  */
19
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>
28
29 #include "gpgsm.h"
30 #include <gcrypt.h>
31 #include <ksba.h>
32
33 #include "keydb.h"
34 #include "i18n.h"
35
36 struct decrypt_filter_parm_s {
37   int algo;
38   int mode;
39   int blklen;
40   gcry_cipher_hd_t hd;
41   char iv[16];
42   size_t ivlen;
43   int any_data;  /* dod we push anything through the filter at all? */
44   unsigned char lastblock[16];  /* to strip the padding we have to
45                                    keep this one */
46   char helpblock[16];  /* needed because there is no block buffering in
47                           libgcrypt (yet) */
48   int  helpblocklen;
49 };
50
51
52
53 /* Decrypt the session key and fill in the parm structure.  The
54    algo and the IV is expected to be already in PARM. */
55 static int 
56 prepare_decryption (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
57                     ksba_const_sexp_t enc_val,
58                     struct decrypt_filter_parm_s *parm)
59 {
60   char *seskey = NULL;
61   size_t n, seskeylen;
62   int rc;
63
64   rc = gpgsm_agent_pkdecrypt (ctrl, hexkeygrip, desc, enc_val,
65                               &seskey, &seskeylen);
66   if (rc)
67     {
68       log_error ("error decrypting session key: %s\n", gpg_strerror (rc));
69       goto leave;
70     }
71
72   if (DBG_CRYPTO)
73     log_printhex ("pkcs1 encoded session key:", seskey, seskeylen);
74
75   n=0;
76   if (seskeylen == 24)
77     {
78       /* Smells like a 3-des key.  This might happen because a SC has
79          already done the unpacking. */
80     }
81   else
82     {
83       if (n + 7 > seskeylen )
84         {
85           rc = gpg_error (GPG_ERR_INV_SESSION_KEY);
86           goto leave; 
87         }
88       
89       /* FIXME: Actually the leading zero is required but due to the way
90          we encode the output in libgcrypt as an MPI we are not able to
91          encode that leading zero.  However, when using a Smartcard we are
92          doing it the right way and therefore we have to skip the zero.  This
93          should be fixed in gpg-agent of course. */
94       if (!seskey[n])
95         n++;
96       
97       if (seskey[n] != 2 )  /* Wrong block type version. */
98         { 
99           rc = gpg_error (GPG_ERR_INV_SESSION_KEY);
100           goto leave; 
101         }
102       
103       for (n++; n < seskeylen && seskey[n]; n++) /* Skip the random bytes. */
104         ;
105       n++; /* and the zero byte */
106       if (n >= seskeylen )
107         { 
108           rc = gpg_error (GPG_ERR_INV_SESSION_KEY);
109           goto leave; 
110         }
111     }
112
113   if (DBG_CRYPTO)
114     log_printhex ("session key:", seskey+n, seskeylen-n);
115
116   rc = gcry_cipher_open (&parm->hd, parm->algo, parm->mode, 0);
117   if (rc)
118     {
119       log_error ("error creating decryptor: %s\n", gpg_strerror (rc));
120       goto leave;
121     }
122                         
123   rc = gcry_cipher_setkey (parm->hd, seskey+n, seskeylen-n);
124   if (gpg_err_code (rc) == GPG_ERR_WEAK_KEY)
125     {
126       log_info (_("WARNING: message was encrypted with "
127                   "a weak key in the symmetric cipher.\n"));
128       rc = 0;
129     }
130   if (rc)
131     {
132       log_error("key setup failed: %s\n", gpg_strerror(rc) );
133       goto leave;
134     }
135
136   gcry_cipher_setiv (parm->hd, parm->iv, parm->ivlen);
137
138  leave:
139   xfree (seskey);
140   return rc;
141 }
142
143
144 /* This function is called by the KSBA writer just before the actual
145    write is done.  The function must take INLEN bytes from INBUF,
146    decrypt it and store it inoutbuf which has a maximum size of
147    maxoutlen.  The valid bytes in outbuf should be return in outlen.
148    Due to different buffer sizes or different length of input and
149    output, it may happen that fewer bytes are processed or fewer bytes
150    are written. */
151 static gpg_error_t
152 decrypt_filter (void *arg,
153                 const void *inbuf, size_t inlen, size_t *inused,
154                 void *outbuf, size_t maxoutlen, size_t *outlen)
155 {
156   struct decrypt_filter_parm_s *parm = arg;
157   int blklen = parm->blklen;
158   size_t orig_inlen = inlen;
159
160   /* fixme: Should we issue an error when we have not seen one full block? */
161   if (!inlen)
162     return gpg_error (GPG_ERR_BUG);
163
164   if (maxoutlen < 2*parm->blklen)
165     return gpg_error (GPG_ERR_BUG);
166   /* Make some space because we will later need an extra block at the end.  */
167   maxoutlen -= blklen;
168
169   if (parm->helpblocklen)
170     {
171       int i, j;
172
173       for (i=parm->helpblocklen,j=0; i < blklen && j < inlen; i++, j++)
174         parm->helpblock[i] = ((const char*)inbuf)[j];
175       inlen -= j;
176       if (blklen > maxoutlen)
177         return gpg_error (GPG_ERR_BUG);
178       if (i < blklen)
179         {
180           parm->helpblocklen = i;
181           *outlen = 0;
182         }
183       else
184         {
185           parm->helpblocklen = 0;
186           if (parm->any_data)
187             {
188               memcpy (outbuf, parm->lastblock, blklen);
189               *outlen =blklen;
190             }
191           else
192             *outlen = 0;
193           gcry_cipher_decrypt (parm->hd, parm->lastblock, blklen,
194                                parm->helpblock, blklen);
195           parm->any_data = 1;
196         }
197       *inused = orig_inlen - inlen;
198       return 0;
199     }
200
201
202   if (inlen > maxoutlen)
203     inlen = maxoutlen;
204   if (inlen % blklen)
205     { /* store the remainder away */
206       parm->helpblocklen = inlen%blklen;
207       inlen = inlen/blklen*blklen;
208       memcpy (parm->helpblock, (const char*)inbuf+inlen, parm->helpblocklen);
209     }
210
211   *inused = inlen + parm->helpblocklen;
212   if (inlen)
213     {
214       assert (inlen >= blklen);
215       if (parm->any_data)
216         {
217           gcry_cipher_decrypt (parm->hd, (char*)outbuf+blklen, inlen,
218                                inbuf, inlen);
219           memcpy (outbuf, parm->lastblock, blklen);
220           memcpy (parm->lastblock,(char*)outbuf+inlen, blklen);
221           *outlen = inlen;
222         }
223       else
224         {
225           gcry_cipher_decrypt (parm->hd, outbuf, inlen, inbuf, inlen);
226           memcpy (parm->lastblock, (char*)outbuf+inlen-blklen, blklen);
227           *outlen = inlen - blklen;
228           parm->any_data = 1;
229         }
230     }
231   else
232     *outlen = 0;
233   return 0;
234 }
235
236
237 \f
238 /* Perform a decrypt operation.  */
239 int
240 gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp)
241 {
242   int rc;
243   Base64Context b64reader = NULL;
244   Base64Context b64writer = NULL;
245   ksba_reader_t reader;
246   ksba_writer_t writer;
247   ksba_cms_t cms = NULL;
248   ksba_stop_reason_t stopreason;
249   KEYDB_HANDLE kh;
250   int recp;
251   FILE *in_fp = NULL;
252   struct decrypt_filter_parm_s dfparm;
253
254   memset (&dfparm, 0, sizeof dfparm);
255
256   kh = keydb_new (0);
257   if (!kh)
258     {
259       log_error (_("failed to allocated keyDB handle\n"));
260       rc = gpg_error (GPG_ERR_GENERAL);
261       goto leave;
262     }
263
264
265   in_fp = fdopen ( dup (in_fd), "rb");
266   if (!in_fp)
267     {
268       rc = gpg_error (gpg_err_code_from_errno (errno));
269       log_error ("fdopen() failed: %s\n", strerror (errno));
270       goto leave;
271     }
272
273   rc = gpgsm_create_reader (&b64reader, ctrl, in_fp, 0, &reader);
274   if (rc)
275     {
276       log_error ("can't create reader: %s\n", gpg_strerror (rc));
277       goto leave;
278     }
279
280   rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, NULL, &writer);
281   if (rc)
282     {
283       log_error ("can't create writer: %s\n", gpg_strerror (rc));
284       goto leave;
285     }
286
287   rc = ksba_cms_new (&cms);
288   if (rc)
289     goto leave;
290
291   rc = ksba_cms_set_reader_writer (cms, reader, writer);
292   if (rc)
293     {
294       log_debug ("ksba_cms_set_reader_writer failed: %s\n",
295                  gpg_strerror (rc));
296       goto leave;
297     }
298
299   /* Parser loop. */
300   do 
301     {
302       rc = ksba_cms_parse (cms, &stopreason);
303       if (rc)
304         {
305           log_debug ("ksba_cms_parse failed: %s\n", gpg_strerror (rc));
306           goto leave;
307         }
308
309       if (stopreason == KSBA_SR_BEGIN_DATA
310           || stopreason == KSBA_SR_DETACHED_DATA)
311         {
312           int algo, mode;
313           const char *algoid;
314           int any_key = 0;
315           
316           algoid = ksba_cms_get_content_oid (cms, 2/* encryption algo*/);
317           algo = gcry_cipher_map_name (algoid);
318           mode = gcry_cipher_mode_from_oid (algoid);
319           if (!algo || !mode)
320             {
321               rc = gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
322               log_error ("unsupported algorithm `%s'\n", algoid? algoid:"?");
323               if (algoid && !strcmp (algoid, "1.2.840.113549.3.2"))
324                 log_info (_("(this is the RC2 algorithm)\n"));
325               else if (!algoid)
326                 log_info (_("(this does not seem to be an encrypted"
327                             " message)\n"));
328               {
329                 char numbuf[50];
330                 sprintf (numbuf, "%d", rc);
331                 gpgsm_status2 (ctrl, STATUS_ERROR, "decrypt.algorithm",
332                                numbuf, algoid?algoid:"?", NULL);
333               }
334
335               /* If it seems that this is not an encrypted message we
336                  return a more sensible error code. */
337               if (!algoid)
338                 rc = gpg_error (GPG_ERR_NO_DATA);
339
340               goto leave;
341             }
342           dfparm.algo = algo;
343           dfparm.mode = mode;
344           dfparm.blklen = gcry_cipher_get_algo_blklen (algo);
345           if (dfparm.blklen > sizeof (dfparm.helpblock))
346             return gpg_error (GPG_ERR_BUG);
347
348           rc = ksba_cms_get_content_enc_iv (cms,
349                                             dfparm.iv,
350                                             sizeof (dfparm.iv),
351                                             &dfparm.ivlen);
352           if (rc)
353             {
354               log_error ("error getting IV: %s\n", gpg_strerror (rc));
355               goto leave;
356             }
357           
358           for (recp=0; !any_key; recp++)
359             {
360               char *issuer;
361               ksba_sexp_t serial;
362               ksba_sexp_t enc_val;
363               char *hexkeygrip = NULL;
364               char *desc = NULL;
365               char kidbuf[16+1];
366
367               *kidbuf = 0;
368
369               rc = ksba_cms_get_issuer_serial (cms, recp, &issuer, &serial);
370               if (rc == -1 && recp)
371                 break; /* no more recipients */
372               if (rc)
373                 log_error ("recp %d - error getting info: %s\n",
374                            recp, gpg_strerror (rc));
375               else
376                 {
377                   ksba_cert_t cert = NULL;
378
379                   log_debug ("recp %d - issuer: `%s'\n",
380                              recp, issuer? issuer:"[NONE]");
381                   log_debug ("recp %d - serial: ", recp);
382                   gpgsm_dump_serial (serial);
383                   log_printf ("\n");
384
385                   keydb_search_reset (kh);
386                   rc = keydb_search_issuer_sn (kh, issuer, serial);
387                   if (rc)
388                     {
389                       log_error ("failed to find the certificate: %s\n",
390                                  gpg_strerror(rc));
391                       goto oops;
392                     }
393
394                   rc = keydb_get_cert (kh, &cert);
395                   if (rc)
396                     {
397                       log_error ("failed to get cert: %s\n", gpg_strerror (rc));
398                       goto oops;     
399                     }
400
401                   /* Print the ENC_TO status line.  Note that we can
402                      do so only if we have the certificate.  This is
403                      in contrast to gpg where the keyID is commonly
404                      included in the encrypted messages. It is too
405                      cumbersome to retrieve the used algorithm, thus
406                      we don't print it for now.  We also record the
407                      keyid for later use.  */
408                   {
409                     unsigned long kid[2];
410                     
411                     kid[0] = gpgsm_get_short_fingerprint (cert, kid+1);
412                     snprintf (kidbuf, sizeof kidbuf, "%08lX%08lX",
413                               kid[1], kid[0]);
414                     gpgsm_status2 (ctrl, STATUS_ENC_TO, 
415                                    kidbuf, "0", "0", NULL);
416                   }
417
418
419                   /* Just in case there is a problem with the own
420                      certificate we print this message - should never
421                      happen of course */
422                   rc = gpgsm_cert_use_decrypt_p (cert);
423                   if (rc)
424                     {
425                       char numbuf[50];
426                       sprintf (numbuf, "%d", rc);
427                       gpgsm_status2 (ctrl, STATUS_ERROR, "decrypt.keyusage",
428                                      numbuf, NULL);
429                       rc = 0;
430                     }
431
432                   hexkeygrip = gpgsm_get_keygrip_hexstring (cert);
433                   desc = gpgsm_format_keydesc (cert);
434
435                 oops:
436                   xfree (issuer);
437                   xfree (serial);
438                   ksba_cert_release (cert);
439                 }
440
441               if (!hexkeygrip)
442                 ;
443               else if (!(enc_val = ksba_cms_get_enc_val (cms, recp)))
444                 log_error ("recp %d - error getting encrypted session key\n",
445                            recp);
446               else
447                 {
448                   rc = prepare_decryption (ctrl,
449                                            hexkeygrip, desc, enc_val, &dfparm);
450                   xfree (enc_val);
451                   if (rc)
452                     {
453                       log_info ("decrypting session key failed: %s\n",
454                                 gpg_strerror (rc));
455                       if (gpg_err_code (rc) == GPG_ERR_NO_SECKEY && *kidbuf)
456                         gpgsm_status2 (ctrl, STATUS_NO_SECKEY, kidbuf, NULL);
457                     }
458                   else
459                     { /* setup the bulk decrypter */
460                       any_key = 1;
461                       ksba_writer_set_filter (writer,
462                                               decrypt_filter,
463                                               &dfparm);
464                     }
465                 }
466               xfree (hexkeygrip);
467               xfree (desc);
468             }
469           if (!any_key)
470             {
471               rc = gpg_error (GPG_ERR_NO_SECKEY);
472               goto leave;
473             }
474         }
475       else if (stopreason == KSBA_SR_END_DATA)
476         {
477           ksba_writer_set_filter (writer, NULL, NULL);
478           if (dfparm.any_data)
479             { /* write the last block with padding removed */
480               int i, npadding = dfparm.lastblock[dfparm.blklen-1];
481               if (!npadding || npadding > dfparm.blklen)
482                 {
483                   log_error ("invalid padding with value %d\n", npadding);
484                   rc = gpg_error (GPG_ERR_INV_DATA);
485                   goto leave;
486                 }
487               rc = ksba_writer_write (writer,
488                                       dfparm.lastblock, 
489                                       dfparm.blklen - npadding);
490               if (rc)
491                   goto leave;
492
493               for (i=dfparm.blklen - npadding; i < dfparm.blklen; i++)
494                 {
495                   if (dfparm.lastblock[i] != npadding)
496                     {
497                       log_error ("inconsistent padding\n");
498                       rc = gpg_error (GPG_ERR_INV_DATA);
499                       goto leave;
500                     }
501                 }
502             }
503         }
504
505     }
506   while (stopreason != KSBA_SR_READY);   
507
508   rc = gpgsm_finish_writer (b64writer);
509   if (rc) 
510     {
511       log_error ("write failed: %s\n", gpg_strerror (rc));
512       goto leave;
513     }
514   gpgsm_status (ctrl, STATUS_DECRYPTION_OKAY, NULL);
515
516
517  leave:
518   if (rc)
519     {
520       gpgsm_status (ctrl, STATUS_DECRYPTION_FAILED, NULL);
521       log_error ("message decryption failed: %s <%s>\n",
522                  gpg_strerror (rc), gpg_strsource (rc));
523     }
524   ksba_cms_release (cms);
525   gpgsm_destroy_reader (b64reader);
526   gpgsm_destroy_writer (b64writer);
527   keydb_release (kh); 
528   if (in_fp)
529     fclose (in_fp);
530   if (dfparm.hd)
531     gcry_cipher_close (dfparm.hd); 
532   return rc;
533 }
534
535