1 /* decrypt.c - Decrypt a message
2 * Copyright (C) 2001 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
37 struct decrypt_filter_parm_s {
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
47 char helpblock[16]; /* needed because there is no block buffering in
54 /* decrypt the session key and fill in the parm structure. The
55 algo and the IV is expected to be already in PARM. */
57 prepare_decryption (const char *hexkeygrip, KsbaConstSexp enc_val,
58 struct decrypt_filter_parm_s *parm)
64 rc = gpgsm_agent_pkdecrypt (hexkeygrip, enc_val,
68 log_error ("error decrypting session key: %s\n", gnupg_strerror (rc));
73 log_printhex ("pkcs1 encoded session key:", seskey, seskeylen);
78 /* Smells like a 3-des key. This might happen because a SC has
79 already done the unpacking. fixme! */
83 if (n + 7 > seskeylen )
85 rc = seterr (Invalid_Session_Key);
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 rightway and therefore we have to skip the zero. This
93 should be fixed in gpg-agent of course. */
97 if (seskey[n] != 2 ) /* wrong block type version */
99 rc = seterr (Invalid_Session_Key);
103 for (n++; n < seskeylen && seskey[n]; n++) /* skip the random bytes */
105 n++; /* and the zero byte */
108 rc = seterr (Invalid_Session_Key);
114 log_printhex ("session key:", seskey+n, seskeylen-n);
116 parm->hd = gcry_cipher_open (parm->algo, parm->mode, 0);
120 log_error ("error creating decryptor: %s\n", gcry_strerror (rc));
121 rc = map_gcry_err (rc);
125 rc = gcry_cipher_setkey (parm->hd, seskey+n, seskeylen-n);
126 if (rc == GCRYERR_WEAK_KEY)
128 log_info (_("WARNING: message was encrypted with "
129 "a weak key in the symmetric cipher.\n"));
134 log_error("key setup failed: %s\n", gcry_strerror(rc) );
135 rc = map_gcry_err (rc);
139 gcry_cipher_setiv (parm->hd, parm->iv, parm->ivlen);
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 process or fewer bytes
155 decrypt_filter (void *arg,
156 const void *inbuf, size_t inlen, size_t *inused,
157 void *outbuf, size_t maxoutlen, size_t *outlen)
159 struct decrypt_filter_parm_s *parm = arg;
160 int blklen = parm->blklen;
161 size_t orig_inlen = inlen;
163 /* fixme: Should we issue an error when we have not seen one full block? */
167 if (maxoutlen < 2*parm->blklen)
169 /* make some space becuase we will later need an extra block at the end */
172 if (parm->helpblocklen)
176 for (i=parm->helpblocklen,j=0; i < blklen && j < inlen; i++, j++)
177 parm->helpblock[i] = ((const char*)inbuf)[j];
179 if (blklen > maxoutlen)
183 parm->helpblocklen = i;
188 parm->helpblocklen = 0;
191 memcpy (outbuf, parm->lastblock, blklen);
196 gcry_cipher_decrypt (parm->hd, parm->lastblock, blklen,
197 parm->helpblock, blklen);
200 *inused = orig_inlen - inlen;
205 if (inlen > maxoutlen)
208 { /* store the remainder away */
209 parm->helpblocklen = inlen%blklen;
210 inlen = inlen/blklen*blklen;
211 memcpy (parm->helpblock, (const char*)inbuf+inlen, parm->helpblocklen);
214 *inused = inlen + parm->helpblocklen;
217 assert (inlen >= blklen);
220 gcry_cipher_decrypt (parm->hd, (char*)outbuf+blklen, inlen,
222 memcpy (outbuf, parm->lastblock, blklen);
223 memcpy (parm->lastblock,(char*)outbuf+inlen, blklen);
228 gcry_cipher_decrypt (parm->hd, outbuf, inlen, inbuf, inlen);
229 memcpy (parm->lastblock, (char*)outbuf+inlen-blklen, blklen);
230 *outlen = inlen - blklen;
241 /* Perform a decrypt operation. */
243 gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp)
247 Base64Context b64reader = NULL;
248 Base64Context b64writer = NULL;
252 KsbaStopReason stopreason;
256 struct decrypt_filter_parm_s dfparm;
258 memset (&dfparm, 0, sizeof dfparm);
263 log_error (_("failed to allocated keyDB handle\n"));
264 rc = GNUPG_General_Error;
269 in_fp = fdopen ( dup (in_fd), "rb");
272 log_error ("fdopen() failed: %s\n", strerror (errno));
273 rc = seterr (IO_Error);
277 rc = gpgsm_create_reader (&b64reader, ctrl, in_fp, &reader);
280 log_error ("can't create reader: %s\n", gnupg_strerror (rc));
284 rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
287 log_error ("can't create writer: %s\n", gnupg_strerror (rc));
291 cms = ksba_cms_new ();
294 rc = seterr (Out_Of_Core);
298 err = ksba_cms_set_reader_writer (cms, reader, writer);
301 log_debug ("ksba_cms_set_reader_writer failed: %s\n",
302 ksba_strerror (err));
303 rc = map_ksba_err (err);
310 err = ksba_cms_parse (cms, &stopreason);
313 log_debug ("ksba_cms_parse failed: %s\n", ksba_strerror (err));
314 rc = map_ksba_err (err);
318 if (stopreason == KSBA_SR_BEGIN_DATA
319 || stopreason == KSBA_SR_DETACHED_DATA)
325 algoid = ksba_cms_get_content_oid (cms, 2/* encryption algo*/);
326 algo = gcry_cipher_map_name (algoid);
327 mode = gcry_cipher_mode_from_oid (algoid);
330 rc = GNUPG_Unsupported_Algorithm;
331 log_error ("unsupported algorithm `%s'\n", algoid? algoid:"?");
332 if (algoid && !strcmp (algoid, "1.2.840.113549.3.2"))
333 log_info (_("(this is the RC2 algorithm)\n"));
335 log_info (_("(this does not seem to be an encrypted"
337 gpgsm_status2 (ctrl, STATUS_ERROR, "decrypt.algorithm",
338 gnupg_error_token (rc), algoid?algoid:"?", NULL);
343 dfparm.blklen = gcry_cipher_get_algo_blklen (algo);
344 if (dfparm.blklen > sizeof (dfparm.helpblock))
347 rc = ksba_cms_get_content_enc_iv (cms,
353 log_error ("error getting IV: %s\n", ksba_strerror (err));
354 rc = map_ksba_err (err);
358 for (recp=0; !any_key; recp++)
363 char *hexkeygrip = NULL;
365 err = ksba_cms_get_issuer_serial (cms, recp, &issuer, &serial);
366 if (err == -1 && recp)
367 break; /* no more recipients */
369 log_error ("recp %d - error getting info: %s\n",
370 recp, ksba_strerror (err));
373 KsbaCert cert = NULL;
375 log_debug ("recp %d - issuer: `%s'\n",
376 recp, issuer? issuer:"[NONE]");
377 log_debug ("recp %d - serial: ", recp);
378 gpgsm_dump_serial (serial);
381 keydb_search_reset (kh);
382 rc = keydb_search_issuer_sn (kh, issuer, serial);
385 log_error ("failed to find the certificate: %s\n",
390 rc = keydb_get_cert (kh, &cert);
393 log_error ("failed to get cert: %s\n", gnupg_strerror (rc));
396 /* Just in case there is a problem with the own
397 certificate we print this message - should never
399 rc = gpgsm_cert_use_decrypt_p (cert);
402 gpgsm_status2 (ctrl, STATUS_ERROR, "decrypt.keyusage",
403 gnupg_error_token (rc), NULL);
407 hexkeygrip = gpgsm_get_keygrip_hexstring (cert);
412 ksba_cert_release (cert);
417 else if (!(enc_val = ksba_cms_get_enc_val (cms, recp)))
418 log_error ("recp %d - error getting encrypted session key\n",
422 rc = prepare_decryption (hexkeygrip, enc_val, &dfparm);
426 log_debug ("decrypting session key failed: %s\n",
427 gnupg_strerror (rc));
430 { /* setup the bulk decrypter */
432 ksba_writer_set_filter (writer,
440 rc = GNUPG_No_Secret_Key;
444 else if (stopreason == KSBA_SR_END_DATA)
446 ksba_writer_set_filter (writer, NULL, NULL);
448 { /* write the last block with padding removed */
449 int i, npadding = dfparm.lastblock[dfparm.blklen-1];
450 if (!npadding || npadding > dfparm.blklen)
452 log_error ("invalid padding with value %d\n", npadding);
453 rc = seterr (Invalid_Data);
456 rc = ksba_writer_write (writer,
458 dfparm.blklen - npadding);
461 rc = map_ksba_err (rc);
464 for (i=dfparm.blklen - npadding; i < dfparm.blklen; i++)
466 if (dfparm.lastblock[i] != npadding)
468 log_error ("inconsistent padding\n");
469 rc = seterr (Invalid_Data);
477 while (stopreason != KSBA_SR_READY);
479 rc = gpgsm_finish_writer (b64writer);
482 log_error ("write failed: %s\n", gnupg_strerror (rc));
485 gpgsm_status (ctrl, STATUS_DECRYPTION_OKAY, NULL);
490 gpgsm_status (ctrl, STATUS_DECRYPTION_FAILED, NULL);
491 ksba_cms_release (cms);
492 gpgsm_destroy_reader (b64reader);
493 gpgsm_destroy_writer (b64writer);
498 gcry_cipher_close (dfparm.hd);