summaryrefslogtreecommitdiffstats
path: root/sm/decrypt.c
diff options
context:
space:
mode:
authorRepo Admin <nobody@gnupg.org>2002-10-19 09:55:27 +0200
committerRepo Admin <nobody@gnupg.org>2002-10-19 09:55:27 +0200
commit82a17c9fb3d64ccdd474c3bedf564368f77e84a4 (patch)
tree0c01ee8cea5f6f77e830955c6b97024752740a2b /sm/decrypt.c
parentBumped version number for cvs version (diff)
downloadgnupg2-82a17c9fb3d64ccdd474c3bedf564368f77e84a4.tar.xz
gnupg2-82a17c9fb3d64ccdd474c3bedf564368f77e84a4.zip
This commit was manufactured by cvs2svn to create branch
'GNUPG-1-9-BRANCH'.
Diffstat (limited to 'sm/decrypt.c')
-rw-r--r--sm/decrypt.c502
1 files changed, 0 insertions, 502 deletions
diff --git a/sm/decrypt.c b/sm/decrypt.c
deleted file mode 100644
index 012254e22..000000000
--- a/sm/decrypt.c
+++ /dev/null
@@ -1,502 +0,0 @@
-/* decrypt.c - Decrypt a message
- * Copyright (C) 2001 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-
-#include <gcrypt.h>
-#include <ksba.h>
-
-#include "gpgsm.h"
-#include "keydb.h"
-#include "i18n.h"
-
-struct decrypt_filter_parm_s {
- int algo;
- int mode;
- int blklen;
- GCRY_CIPHER_HD hd;
- char iv[16];
- size_t ivlen;
- int any_data; /* dod we push anything through the filter at all? */
- unsigned char lastblock[16]; /* to strip the padding we have to
- keep this one */
- char helpblock[16]; /* needed because there is no block buffering in
- libgcrypt (yet) */
- int helpblocklen;
-};
-
-
-
-/* decrypt the session key and fill in the parm structure. The
- algo and the IV is expected to be already in PARM. */
-static int
-prepare_decryption (const char *hexkeygrip, KsbaConstSexp enc_val,
- struct decrypt_filter_parm_s *parm)
-{
- char *seskey = NULL;
- size_t n, seskeylen;
- int rc;
-
- rc = gpgsm_agent_pkdecrypt (hexkeygrip, enc_val,
- &seskey, &seskeylen);
- if (rc)
- {
- log_error ("error decrypting session key: %s\n", gnupg_strerror (rc));
- goto leave;
- }
-
- if (DBG_CRYPTO)
- log_printhex ("pkcs1 encoded session key:", seskey, seskeylen);
-
- n=0;
- if (seskeylen == 24)
- {
- /* Smells like a 3-des key. This might happen because a SC has
- already done the unpacking. fixme! */
- }
- else
- {
- if (n + 7 > seskeylen )
- {
- rc = seterr (Invalid_Session_Key);
- goto leave;
- }
-
- /* FIXME: Actually the leading zero is required but due to the way
- we encode the output in libgcrypt as an MPI we are not able to
- encode that leading zero. However, when using a Smartcard we are
- doing it the rightway and therefore we have to skip the zero. This
- should be fixed in gpg-agent of course. */
- if (!seskey[n])
- n++;
-
- if (seskey[n] != 2 ) /* wrong block type version */
- {
- rc = seterr (Invalid_Session_Key);
- goto leave;
- }
-
- for (n++; n < seskeylen && seskey[n]; n++) /* skip the random bytes */
- ;
- n++; /* and the zero byte */
- if (n >= seskeylen )
- {
- rc = seterr (Invalid_Session_Key);
- goto leave;
- }
- }
-
- if (DBG_CRYPTO)
- log_printhex ("session key:", seskey+n, seskeylen-n);
-
- parm->hd = gcry_cipher_open (parm->algo, parm->mode, 0);
- if (!parm->hd)
- {
- rc = gcry_errno ();
- log_error ("error creating decryptor: %s\n", gcry_strerror (rc));
- rc = map_gcry_err (rc);
- goto leave;
- }
-
- rc = gcry_cipher_setkey (parm->hd, seskey+n, seskeylen-n);
- if (rc == GCRYERR_WEAK_KEY)
- {
- log_info (_("WARNING: message was encrypted with "
- "a weak key in the symmetric cipher.\n"));
- rc = 0;
- }
- if (rc)
- {
- log_error("key setup failed: %s\n", gcry_strerror(rc) );
- rc = map_gcry_err (rc);
- goto leave;
- }
-
- gcry_cipher_setiv (parm->hd, parm->iv, parm->ivlen);
-
- leave:
- xfree (seskey);
- return rc;
-}
-
-
-/* This function is called by the KSBA writer just before the actual
- write is done. The function must take INLEN bytes from INBUF,
- decrypt it and store it inoutbuf which has a maximum size of
- maxoutlen. The valid bytes in outbuf should be return in outlen.
- Due to different buffer sizes or different length of input and
- output, it may happen that fewer bytes are process or fewer bytes
- are written. */
-static KsbaError
-decrypt_filter (void *arg,
- const void *inbuf, size_t inlen, size_t *inused,
- void *outbuf, size_t maxoutlen, size_t *outlen)
-{
- struct decrypt_filter_parm_s *parm = arg;
- int blklen = parm->blklen;
- size_t orig_inlen = inlen;
-
- /* fixme: Should we issue an error when we have not seen one full block? */
- if (!inlen)
- return KSBA_Bug;
-
- if (maxoutlen < 2*parm->blklen)
- return KSBA_Bug;
- /* make some space becuase we will later need an extra block at the end */
- maxoutlen -= blklen;
-
- if (parm->helpblocklen)
- {
- int i, j;
-
- for (i=parm->helpblocklen,j=0; i < blklen && j < inlen; i++, j++)
- parm->helpblock[i] = ((const char*)inbuf)[j];
- inlen -= j;
- if (blklen > maxoutlen)
- return KSBA_Bug;
- if (i < blklen)
- {
- parm->helpblocklen = i;
- *outlen = 0;
- }
- else
- {
- parm->helpblocklen = 0;
- if (parm->any_data)
- {
- memcpy (outbuf, parm->lastblock, blklen);
- *outlen =blklen;
- }
- else
- *outlen = 0;
- gcry_cipher_decrypt (parm->hd, parm->lastblock, blklen,
- parm->helpblock, blklen);
- parm->any_data = 1;
- }
- *inused = orig_inlen - inlen;
- return 0;
- }
-
-
- if (inlen > maxoutlen)
- inlen = maxoutlen;
- if (inlen % blklen)
- { /* store the remainder away */
- parm->helpblocklen = inlen%blklen;
- inlen = inlen/blklen*blklen;
- memcpy (parm->helpblock, (const char*)inbuf+inlen, parm->helpblocklen);
- }
-
- *inused = inlen + parm->helpblocklen;
- if (inlen)
- {
- assert (inlen >= blklen);
- if (parm->any_data)
- {
- gcry_cipher_decrypt (parm->hd, (char*)outbuf+blklen, inlen,
- inbuf, inlen);
- memcpy (outbuf, parm->lastblock, blklen);
- memcpy (parm->lastblock,(char*)outbuf+inlen, blklen);
- *outlen = inlen;
- }
- else
- {
- gcry_cipher_decrypt (parm->hd, outbuf, inlen, inbuf, inlen);
- memcpy (parm->lastblock, (char*)outbuf+inlen-blklen, blklen);
- *outlen = inlen - blklen;
- parm->any_data = 1;
- }
- }
- else
- *outlen = 0;
- return 0;
-}
-
-
-
-/* Perform a decrypt operation. */
-int
-gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp)
-{
- int rc;
- KsbaError err;
- Base64Context b64reader = NULL;
- Base64Context b64writer = NULL;
- KsbaReader reader;
- KsbaWriter writer;
- KsbaCMS cms = NULL;
- KsbaStopReason stopreason;
- KEYDB_HANDLE kh;
- int recp;
- FILE *in_fp = NULL;
- struct decrypt_filter_parm_s dfparm;
-
- memset (&dfparm, 0, sizeof dfparm);
-
- kh = keydb_new (0);
- if (!kh)
- {
- log_error (_("failed to allocated keyDB handle\n"));
- rc = GNUPG_General_Error;
- goto leave;
- }
-
-
- in_fp = fdopen ( dup (in_fd), "rb");
- if (!in_fp)
- {
- log_error ("fdopen() failed: %s\n", strerror (errno));
- rc = seterr (IO_Error);
- goto leave;
- }
-
- rc = gpgsm_create_reader (&b64reader, ctrl, in_fp, &reader);
- if (rc)
- {
- log_error ("can't create reader: %s\n", gnupg_strerror (rc));
- goto leave;
- }
-
- rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
- if (rc)
- {
- log_error ("can't create writer: %s\n", gnupg_strerror (rc));
- goto leave;
- }
-
- cms = ksba_cms_new ();
- if (!cms)
- {
- rc = seterr (Out_Of_Core);
- goto leave;
- }
-
- err = ksba_cms_set_reader_writer (cms, reader, writer);
- if (err)
- {
- log_debug ("ksba_cms_set_reader_writer failed: %s\n",
- ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
- }
-
- /* parser loop */
- do
- {
- err = ksba_cms_parse (cms, &stopreason);
- if (err)
- {
- log_debug ("ksba_cms_parse failed: %s\n", ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
- }
-
- if (stopreason == KSBA_SR_BEGIN_DATA
- || stopreason == KSBA_SR_DETACHED_DATA)
- {
- int algo, mode;
- const char *algoid;
- int any_key = 0;
-
- algoid = ksba_cms_get_content_oid (cms, 2/* encryption algo*/);
- algo = gcry_cipher_map_name (algoid);
- mode = gcry_cipher_mode_from_oid (algoid);
- if (!algo || !mode)
- {
- rc = GNUPG_Unsupported_Algorithm;
- log_error ("unsupported algorithm `%s'\n", algoid? algoid:"?");
- if (algoid && !strcmp (algoid, "1.2.840.113549.3.2"))
- log_info (_("(this is the RC2 algorithm)\n"));
- else if (!algoid)
- log_info (_("(this does not seem to be an encrypted"
- " message)\n"));
- gpgsm_status2 (ctrl, STATUS_ERROR, "decrypt.algorithm",
- gnupg_error_token (rc), algoid?algoid:"?", NULL);
- goto leave;
- }
- dfparm.algo = algo;
- dfparm.mode = mode;
- dfparm.blklen = gcry_cipher_get_algo_blklen (algo);
- if (dfparm.blklen > sizeof (dfparm.helpblock))
- return GNUPG_Bug;
-
- rc = ksba_cms_get_content_enc_iv (cms,
- dfparm.iv,
- sizeof (dfparm.iv),
- &dfparm.ivlen);
- if (rc)
- {
- log_error ("error getting IV: %s\n", ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
- }
-
- for (recp=0; !any_key; recp++)
- {
- char *issuer;
- KsbaSexp serial;
- KsbaSexp enc_val;
- char *hexkeygrip = NULL;
-
- err = ksba_cms_get_issuer_serial (cms, recp, &issuer, &serial);
- if (err == -1 && recp)
- break; /* no more recipients */
- if (err)
- log_error ("recp %d - error getting info: %s\n",
- recp, ksba_strerror (err));
- else
- {
- KsbaCert cert = NULL;
-
- log_debug ("recp %d - issuer: `%s'\n",
- recp, issuer? issuer:"[NONE]");
- log_debug ("recp %d - serial: ", recp);
- gpgsm_dump_serial (serial);
- log_printf ("\n");
-
- keydb_search_reset (kh);
- rc = keydb_search_issuer_sn (kh, issuer, serial);
- if (rc)
- {
- log_error ("failed to find the certificate: %s\n",
- gnupg_strerror(rc));
- goto oops;
- }
-
- rc = keydb_get_cert (kh, &cert);
- if (rc)
- {
- log_error ("failed to get cert: %s\n", gnupg_strerror (rc));
- goto oops;
- }
- /* Just in case there is a problem with the own
- certificate we print this message - should never
- happen of course */
- rc = gpgsm_cert_use_decrypt_p (cert);
- if (rc)
- {
- gpgsm_status2 (ctrl, STATUS_ERROR, "decrypt.keyusage",
- gnupg_error_token (rc), NULL);
- rc = 0;
- }
-
- hexkeygrip = gpgsm_get_keygrip_hexstring (cert);
-
- oops:
- xfree (issuer);
- xfree (serial);
- ksba_cert_release (cert);
- }
-
- if (!hexkeygrip)
- ;
- else if (!(enc_val = ksba_cms_get_enc_val (cms, recp)))
- log_error ("recp %d - error getting encrypted session key\n",
- recp);
- else
- {
- rc = prepare_decryption (hexkeygrip, enc_val, &dfparm);
- xfree (enc_val);
- if (rc)
- {
- log_debug ("decrypting session key failed: %s\n",
- gnupg_strerror (rc));
- }
- else
- { /* setup the bulk decrypter */
- any_key = 1;
- ksba_writer_set_filter (writer,
- decrypt_filter,
- &dfparm);
- }
- }
- }
- if (!any_key)
- {
- rc = GNUPG_No_Secret_Key;
- goto leave;
- }
- }
- else if (stopreason == KSBA_SR_END_DATA)
- {
- ksba_writer_set_filter (writer, NULL, NULL);
- if (dfparm.any_data)
- { /* write the last block with padding removed */
- int i, npadding = dfparm.lastblock[dfparm.blklen-1];
- if (!npadding || npadding > dfparm.blklen)
- {
- log_error ("invalid padding with value %d\n", npadding);
- rc = seterr (Invalid_Data);
- goto leave;
- }
- rc = ksba_writer_write (writer,
- dfparm.lastblock,
- dfparm.blklen - npadding);
- if (rc)
- {
- rc = map_ksba_err (rc);
- goto leave;
- }
- for (i=dfparm.blklen - npadding; i < dfparm.blklen; i++)
- {
- if (dfparm.lastblock[i] != npadding)
- {
- log_error ("inconsistent padding\n");
- rc = seterr (Invalid_Data);
- goto leave;
- }
- }
- }
- }
-
- }
- while (stopreason != KSBA_SR_READY);
-
- rc = gpgsm_finish_writer (b64writer);
- if (rc)
- {
- log_error ("write failed: %s\n", gnupg_strerror (rc));
- goto leave;
- }
- gpgsm_status (ctrl, STATUS_DECRYPTION_OKAY, NULL);
-
-
- leave:
- if (rc)
- gpgsm_status (ctrl, STATUS_DECRYPTION_FAILED, NULL);
- ksba_cms_release (cms);
- gpgsm_destroy_reader (b64reader);
- gpgsm_destroy_writer (b64writer);
- keydb_release (kh);
- if (in_fp)
- fclose (in_fp);
- if (dfparm.hd)
- gcry_cipher_close (dfparm.hd);
- return rc;
-}
-
-