mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
Decryption does now work
This commit is contained in:
parent
e4a72423ff
commit
ce32f6b6c8
@ -553,8 +553,3 @@ gpgsm_destroy_writer (Base64Context ctx)
|
|||||||
{
|
{
|
||||||
xfree (ctx);
|
xfree (ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -190,10 +190,12 @@ start_agent (void)
|
|||||||
|
|
||||||
log_debug ("connection to agent established\n");
|
log_debug ("connection to agent established\n");
|
||||||
|
|
||||||
log_debug ("waiting for debugger .....\n");
|
if (DBG_AGENT)
|
||||||
getchar ();
|
{
|
||||||
log_debug ("okay\n");
|
log_debug ("waiting for debugger [hit RETURN when ready] .....\n");
|
||||||
|
getchar ();
|
||||||
|
log_debug ("... okay\n");
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -288,7 +290,8 @@ gpgsm_agent_pkdecrypt (const char *keygrip,
|
|||||||
char line[LINELENGTH];
|
char line[LINELENGTH];
|
||||||
struct membuf data;
|
struct membuf data;
|
||||||
struct cipher_parm_s cipher_parm;
|
struct cipher_parm_s cipher_parm;
|
||||||
size_t len;
|
size_t n, len;
|
||||||
|
char *buf, *endp;
|
||||||
|
|
||||||
if (!keygrip || strlen(keygrip) != 40 || !ciphertext || !r_buf || !r_buflen)
|
if (!keygrip || strlen(keygrip) != 40 || !ciphertext || !r_buf || !r_buflen)
|
||||||
return GNUPG_Invalid_Value;
|
return GNUPG_Invalid_Value;
|
||||||
@ -321,7 +324,28 @@ gpgsm_agent_pkdecrypt (const char *keygrip,
|
|||||||
xfree (get_membuf (&data, &len));
|
xfree (get_membuf (&data, &len));
|
||||||
return map_assuan_err (rc);
|
return map_assuan_err (rc);
|
||||||
}
|
}
|
||||||
*r_buf = get_membuf (&data, r_buflen);
|
|
||||||
return *r_buf? 0 : GNUPG_Out_Of_Core;
|
put_membuf (&data, "", 1); /* make sure it is 0 terminated */
|
||||||
|
buf = get_membuf (&data, &len);
|
||||||
|
if (!buf)
|
||||||
|
return seterr (Out_Of_Core);
|
||||||
|
assert (len);
|
||||||
|
len--; /* remove the terminating 0 */
|
||||||
|
n = strtoul (buf, &endp, 10);
|
||||||
|
if (!n || *endp != ':')
|
||||||
|
return seterr (Invalid_Sexp);
|
||||||
|
endp++;
|
||||||
|
if (endp-buf+n > len)
|
||||||
|
return seterr (Invalid_Sexp); /* oops len does not match internal len*/
|
||||||
|
memmove (buf, endp, n);
|
||||||
|
*r_buflen = n;
|
||||||
|
*r_buf = buf;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
279
sm/decrypt.c
279
sm/decrypt.c
@ -34,6 +34,21 @@
|
|||||||
#include "keydb.h"
|
#include "keydb.h"
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
|
struct decrypt_filter_parm_s {
|
||||||
|
int algo;
|
||||||
|
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 bufferin in
|
||||||
|
libgcrypt (yet) */
|
||||||
|
int helpblocklen;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_integer (unsigned char *p)
|
print_integer (unsigned char *p)
|
||||||
{
|
{
|
||||||
@ -49,6 +64,174 @@ print_integer (unsigned char *p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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, const char *enc_val,
|
||||||
|
struct decrypt_filter_parm_s *parm)
|
||||||
|
{
|
||||||
|
char *seskey = NULL;
|
||||||
|
size_t n, seskeylen;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = gpgsm_agent_pkdecrypt (hexkeygrip, enc_val, strlen (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 (n + 7 > seskeylen )
|
||||||
|
{
|
||||||
|
rc = seterr (Invalid_Session_Key);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
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, GCRY_CIPHER_MODE_CBC, 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 KSab 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -67,6 +250,9 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp)
|
|||||||
KEYDB_HANDLE kh;
|
KEYDB_HANDLE kh;
|
||||||
int recp;
|
int recp;
|
||||||
FILE *in_fp = NULL;
|
FILE *in_fp = NULL;
|
||||||
|
struct decrypt_filter_parm_s dfparm;
|
||||||
|
|
||||||
|
memset (&dfparm, 0, sizeof dfparm);
|
||||||
|
|
||||||
kh = keydb_new (0);
|
kh = keydb_new (0);
|
||||||
if (!kh)
|
if (!kh)
|
||||||
@ -130,6 +316,33 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp)
|
|||||||
if (stopreason == KSBA_SR_BEGIN_DATA
|
if (stopreason == KSBA_SR_BEGIN_DATA
|
||||||
|| stopreason == KSBA_SR_DETACHED_DATA)
|
|| stopreason == KSBA_SR_DETACHED_DATA)
|
||||||
{
|
{
|
||||||
|
int algo;
|
||||||
|
const char *algoid;
|
||||||
|
|
||||||
|
algoid = ksba_cms_get_content_oid (cms, 2/* encryption algo*/);
|
||||||
|
algo = gcry_cipher_map_name (algoid);
|
||||||
|
if (!algo)
|
||||||
|
{
|
||||||
|
log_error ("unsupported algorithm `%s'\n", algoid? algoid:"?");
|
||||||
|
rc = GNUPG_Unsupported_Algorithm;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
dfparm.algo = algo;
|
||||||
|
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; recp < 1; recp++)
|
for (recp=0; recp < 1; recp++)
|
||||||
{
|
{
|
||||||
char *issuer;
|
char *issuer;
|
||||||
@ -164,8 +377,7 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp)
|
|||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
log_debug ("failed to get cert: %s\n", gnupg_strerror (rc));
|
log_debug ("failed to get cert: %s\n", gnupg_strerror (rc));
|
||||||
goto oops;
|
goto oops; }
|
||||||
}
|
|
||||||
|
|
||||||
hexkeygrip = gpgsm_get_keygrip_hexstring (cert);
|
hexkeygrip = gpgsm_get_keygrip_hexstring (cert);
|
||||||
|
|
||||||
@ -181,31 +393,54 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp)
|
|||||||
recp);
|
recp);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char *seskey;
|
|
||||||
size_t seskeylen;
|
|
||||||
|
|
||||||
log_debug ("recp %d - enc-val: `%s'\n",
|
log_debug ("recp %d - enc-val: `%s'\n",
|
||||||
recp, enc_val);
|
recp, enc_val);
|
||||||
|
rc = prepare_decryption (hexkeygrip, enc_val,
|
||||||
rc = gpgsm_agent_pkdecrypt (hexkeygrip,
|
&dfparm);
|
||||||
enc_val, strlen (enc_val),
|
|
||||||
&seskey, &seskeylen);
|
|
||||||
if (rc)
|
|
||||||
log_debug ("problem: %s\n", gnupg_strerror (rc));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
unsigned char *p;
|
|
||||||
log_debug ("plaintext=");
|
|
||||||
for (p=seskey; seskeylen; seskeylen--, p++)
|
|
||||||
log_printf (" %02X", *p);
|
|
||||||
log_printf ("\n");
|
|
||||||
}
|
|
||||||
xfree (enc_val);
|
xfree (enc_val);
|
||||||
|
if (rc)
|
||||||
|
log_error ("decrypting session key failed: %s\n",
|
||||||
|
gnupg_strerror (rc));
|
||||||
|
else
|
||||||
|
{ /* setup the bulk decrypter */
|
||||||
|
ksba_writer_set_filter (writer,
|
||||||
|
decrypt_filter,
|
||||||
|
&dfparm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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);
|
while (stopreason != KSBA_SR_READY);
|
||||||
@ -217,6 +452,8 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp)
|
|||||||
keydb_release (kh);
|
keydb_release (kh);
|
||||||
if (in_fp)
|
if (in_fp)
|
||||||
fclose (in_fp);
|
fclose (in_fp);
|
||||||
|
if (dfparm.hd)
|
||||||
|
gcry_cipher_close (dfparm.hd);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,5 +167,10 @@ int gpgsm_agent_pksign (const char *keygrip,
|
|||||||
size_t digestlen,
|
size_t digestlen,
|
||||||
int digestalgo,
|
int digestalgo,
|
||||||
char **r_buf, size_t *r_buflen);
|
char **r_buf, size_t *r_buflen);
|
||||||
|
int gpgsm_agent_pkdecrypt (const char *keygrip,
|
||||||
|
const char *ciphertext, size_t ciphertextlen,
|
||||||
|
char **r_buf, size_t *r_buflen);
|
||||||
|
|
||||||
|
|
||||||
#endif /*GPGSM_H*/
|
#endif /*GPGSM_H*/
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user