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