mirror of git://git.gnupg.org/gnupg.git
sm: Support AES-GCM decryption.
* sm/gpgsm.c (main): Use gpgrt_fcancel on decryption error if gpgrt
supports this.
* sm/decrypt.c (decrypt_gcm_filter): New.
(gpgsm_decrypt): Use this filter if requested. Check authtag.
* common/compliance.c (gnupg_cipher_is_allowed): Allow GCM for gpgsm
in consumer (decrypt) de-vs mode.
--
Backported-from-master: 4980fb3c6d
We allow GCM in de-vs mode for decryption although this has not been
evaluation. It is decryption and thus no serious harm may happen.
Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
c8f0b02936
commit
b722fd755c
|
@ -418,7 +418,8 @@ gnupg_cipher_is_allowed (enum gnupg_compliance_mode compliance, int producer,
|
||||||
|| mode == GCRY_CIPHER_MODE_CFB);
|
|| mode == GCRY_CIPHER_MODE_CFB);
|
||||||
case GNUPG_MODULE_NAME_GPGSM:
|
case GNUPG_MODULE_NAME_GPGSM:
|
||||||
return (mode == GCRY_CIPHER_MODE_NONE
|
return (mode == GCRY_CIPHER_MODE_NONE
|
||||||
|| mode == GCRY_CIPHER_MODE_CBC);
|
|| mode == GCRY_CIPHER_MODE_CBC
|
||||||
|
|| (mode == GCRY_CIPHER_MODE_GCM && !producer));
|
||||||
}
|
}
|
||||||
log_assert (!"reached");
|
log_assert (!"reached");
|
||||||
|
|
||||||
|
|
82
sm/decrypt.c
82
sm/decrypt.c
|
@ -38,6 +38,15 @@
|
||||||
#include "../common/compliance.h"
|
#include "../common/compliance.h"
|
||||||
#include "../common/tlv.h"
|
#include "../common/tlv.h"
|
||||||
|
|
||||||
|
/* We can provide an enum value which is only availabale with KSBA
|
||||||
|
* 1.6.0 so that we can compile even against older versions. Some
|
||||||
|
* calls will of course return an error in this case. This value is
|
||||||
|
* currently not used because the cipher mode is sufficient here. */
|
||||||
|
/* #if KSBA_VERSION_NUMBER < 0x010600 /\* 1.6.0 *\/ */
|
||||||
|
/* # define KSBA_CT_AUTHENVELOPED_DATA 10 */
|
||||||
|
/* #endif */
|
||||||
|
|
||||||
|
|
||||||
struct decrypt_filter_parm_s
|
struct decrypt_filter_parm_s
|
||||||
{
|
{
|
||||||
int algo;
|
int algo;
|
||||||
|
@ -555,6 +564,14 @@ prepare_decryption (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parm->mode == GCRY_CIPHER_MODE_GCM)
|
||||||
|
{
|
||||||
|
/* GCM mode really sucks in CMS. We need to know the AAD before
|
||||||
|
* we start decrypting but CMS puts the AAD after the content.
|
||||||
|
* Thus temporary files are required. Let's hope that no real
|
||||||
|
* messages with actual AAD are ever used. OCB Rules! */
|
||||||
|
}
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
xfree (seskey);
|
xfree (seskey);
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -654,6 +671,36 @@ decrypt_filter (void *arg,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* This is the GCM version of decrypt_filter. */
|
||||||
|
static gpg_error_t
|
||||||
|
decrypt_gcm_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;
|
||||||
|
|
||||||
|
if (!inlen)
|
||||||
|
return gpg_error (GPG_ERR_BUG);
|
||||||
|
|
||||||
|
if (maxoutlen < parm->blklen)
|
||||||
|
return gpg_error (GPG_ERR_BUG);
|
||||||
|
|
||||||
|
if (inlen > maxoutlen)
|
||||||
|
inlen = maxoutlen;
|
||||||
|
|
||||||
|
*inused = inlen;
|
||||||
|
if (inlen)
|
||||||
|
{
|
||||||
|
gcry_cipher_decrypt (parm->hd, outbuf, inlen, inbuf, inlen);
|
||||||
|
*outlen = inlen;
|
||||||
|
parm->any_data = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*outlen = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Perform a decrypt operation. */
|
/* Perform a decrypt operation. */
|
||||||
int
|
int
|
||||||
|
@ -972,9 +1019,11 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, estream_t out_fp)
|
||||||
else
|
else
|
||||||
{ /* setup the bulk decrypter */
|
{ /* setup the bulk decrypter */
|
||||||
any_key = 1;
|
any_key = 1;
|
||||||
ksba_writer_set_filter (writer,
|
ksba_writer_set_filter
|
||||||
decrypt_filter,
|
(writer,
|
||||||
&dfparm);
|
dfparm.mode == GCRY_CIPHER_MODE_GCM?
|
||||||
|
decrypt_gcm_filter : decrypt_filter,
|
||||||
|
&dfparm);
|
||||||
|
|
||||||
if (dfparm.is_de_vs
|
if (dfparm.is_de_vs
|
||||||
&& gnupg_gcrypt_is_compliant (CO_DE_VS))
|
&& gnupg_gcrypt_is_compliant (CO_DE_VS))
|
||||||
|
@ -1028,7 +1077,11 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, estream_t out_fp)
|
||||||
else if (stopreason == KSBA_SR_END_DATA)
|
else if (stopreason == KSBA_SR_END_DATA)
|
||||||
{
|
{
|
||||||
ksba_writer_set_filter (writer, NULL, NULL);
|
ksba_writer_set_filter (writer, NULL, NULL);
|
||||||
if (dfparm.any_data)
|
if (dfparm.mode == GCRY_CIPHER_MODE_GCM)
|
||||||
|
{
|
||||||
|
/* Nothing yet to do. We wait for the ready event. */
|
||||||
|
}
|
||||||
|
else if (dfparm.any_data )
|
||||||
{ /* write the last block with padding removed */
|
{ /* write the last block with padding removed */
|
||||||
int i, npadding = dfparm.lastblock[dfparm.blklen-1];
|
int i, npadding = dfparm.lastblock[dfparm.blklen-1];
|
||||||
if (!npadding || npadding > dfparm.blklen)
|
if (!npadding || npadding > dfparm.blklen)
|
||||||
|
@ -1054,7 +1107,28 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, estream_t out_fp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (stopreason == KSBA_SR_READY)
|
||||||
|
{
|
||||||
|
if (dfparm.mode == GCRY_CIPHER_MODE_GCM)
|
||||||
|
{
|
||||||
|
char *authtag;
|
||||||
|
size_t authtaglen;
|
||||||
|
|
||||||
|
rc = ksba_cms_get_message_digest (cms, 0, &authtag, &authtaglen);
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
log_error ("error getting authtag: %s\n", gpg_strerror (rc));
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
if (DBG_CRYPTO)
|
||||||
|
log_printhex (authtag, authtaglen, "Authtag ...:");
|
||||||
|
rc = gcry_cipher_checktag (dfparm.hd, authtag, authtaglen);
|
||||||
|
xfree (authtag);
|
||||||
|
if (rc)
|
||||||
|
log_error ("data is not authentic: %s\n", gpg_strerror (rc));
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
while (stopreason != KSBA_SR_READY);
|
while (stopreason != KSBA_SR_READY);
|
||||||
|
|
||||||
|
|
12
sm/gpgsm.c
12
sm/gpgsm.c
|
@ -1825,16 +1825,22 @@ main ( int argc, char **argv)
|
||||||
case aDecrypt:
|
case aDecrypt:
|
||||||
{
|
{
|
||||||
estream_t fp = open_es_fwrite (opt.outfile?opt.outfile:"-");
|
estream_t fp = open_es_fwrite (opt.outfile?opt.outfile:"-");
|
||||||
|
gpg_error_t err;
|
||||||
|
|
||||||
set_binary (stdin);
|
set_binary (stdin);
|
||||||
if (!argc)
|
if (!argc)
|
||||||
gpgsm_decrypt (&ctrl, 0, fp); /* from stdin */
|
err = gpgsm_decrypt (&ctrl, 0, fp); /* from stdin */
|
||||||
else if (argc == 1)
|
else if (argc == 1)
|
||||||
gpgsm_decrypt (&ctrl, open_read (*argv), fp); /* from file */
|
err = gpgsm_decrypt (&ctrl, open_read (*argv), fp); /* from file */
|
||||||
else
|
else
|
||||||
wrong_args ("--decrypt [filename]");
|
wrong_args ("--decrypt [filename]");
|
||||||
|
|
||||||
es_fclose (fp);
|
#if GPGRT_VERSION_NUMBER >= 0x012700 /* 1.39 */
|
||||||
|
if (err)
|
||||||
|
gpgrt_fcancel (fp);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
es_fclose (fp);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue