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