summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2021-06-02 11:03:55 +0200
committerWerner Koch <wk@gnupg.org>2021-06-02 11:03:55 +0200
commit4980fb3c6dde8c1dda975e8a36d6086c8456a631 (patch)
treed5a1dd07d15256549159f8a20b1617fc6ee7122a
parenttests: Rename subdir gpgsm to cms and move sample dirs. (diff)
downloadgnupg2-4980fb3c6dde8c1dda975e8a36d6086c8456a631.tar.xz
gnupg2-4980fb3c6dde8c1dda975e8a36d6086c8456a631.zip
sm: Support AES-GCM decryption.
* tests/cms/samplemsgs/: Add sample messages. * sm/gpgsm.c (main): Use gpgrt_fcancel on decryption error. * sm/decrypt.c (decrypt_gcm_filter): New. (gpgsm_decrypt): Use this filter if requested. Check authtag. -- Note that the sample message pwri-sample.gcm.p7m is broken: The authtag is duplicated to the authEncryptedContentInfo. I used a temporary code during testing hack to that test message out.
-rw-r--r--doc/DETAILS2
-rw-r--r--sm/decrypt.c82
-rw-r--r--sm/gpgsm.c9
-rw-r--r--tests/cms/Makefile.am4
-rw-r--r--tests/cms/samplemsgs/README6
-rw-r--r--tests/cms/samplemsgs/pwri-sample.cbc-2.p7mbin0 -> 346 bytes
-rw-r--r--tests/cms/samplemsgs/pwri-sample.cbc.p7mbin0 -> 350 bytes
-rw-r--r--tests/cms/samplemsgs/pwri-sample.gcm.p7mbin0 -> 375 bytes
8 files changed, 96 insertions, 7 deletions
diff --git a/doc/DETAILS b/doc/DETAILS
index bbe2ad5d5..b5b1bb7d5 100644
--- a/doc/DETAILS
+++ b/doc/DETAILS
@@ -1665,6 +1665,8 @@ Description of some debug flags:
** List of useful RFCs
- RFC-3447 :: PKCS #1: RSA Cryptography Specifications Version 2.1
- RFC-4880 :: OpenPGP
+ - RFC-5083 :: CMS - Authenticated-Enveloped-Data
+ - RFC-5084 :: CMS - AES-GCM
- RFC-5280 :: X.509 PKI Certificate and CRL Profile
- RFC-5652 :: CMS (STD0070)
- RFC-6818 :: Updates to the X.509 PKI Certificate and CRL Profile
diff --git a/sm/decrypt.c b/sm/decrypt.c
index c5f073190..6b3dd6661 100644
--- a/sm/decrypt.c
+++ b/sm/decrypt.c
@@ -37,6 +37,15 @@
#include "../common/tlv.h"
#include "../common/compliance.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
{
int algo;
@@ -911,6 +920,14 @@ prepare_decryption (ctrl_t ctrl, const char *hexkeygrip,
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:
xfree (seskey);
return rc;
@@ -1010,6 +1027,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. */
int
@@ -1332,9 +1379,11 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, estream_t out_fp)
else
{ /* setup the bulk decrypter */
any_key = 1;
- ksba_writer_set_filter (writer,
- decrypt_filter,
- &dfparm);
+ ksba_writer_set_filter
+ (writer,
+ dfparm.mode == GCRY_CIPHER_MODE_GCM?
+ decrypt_gcm_filter : decrypt_filter,
+ &dfparm);
if (dfparm.is_de_vs
&& gnupg_gcrypt_is_compliant (CO_DE_VS))
@@ -1389,7 +1438,11 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, estream_t out_fp)
else if (stopreason == KSBA_SR_END_DATA)
{
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 */
int i, npadding = dfparm.lastblock[dfparm.blklen-1];
if (!npadding || npadding > dfparm.blklen)
@@ -1415,7 +1468,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);
diff --git a/sm/gpgsm.c b/sm/gpgsm.c
index f488eb5e8..3c6fe9c76 100644
--- a/sm/gpgsm.c
+++ b/sm/gpgsm.c
@@ -2065,13 +2065,16 @@ main ( int argc, char **argv)
set_binary (stdin);
if (!argc)
- gpgsm_decrypt (&ctrl, 0, fp); /* from stdin */
+ err = gpgsm_decrypt (&ctrl, 0, fp); /* from stdin */
else if (argc == 1)
- gpgsm_decrypt (&ctrl, open_read (*argv), fp); /* from file */
+ err = gpgsm_decrypt (&ctrl, open_read (*argv), fp); /* from file */
else
wrong_args ("--decrypt [filename]");
- es_fclose (fp);
+ if (err)
+ gpgrt_fcancel (fp);
+ else
+ es_fclose (fp);
}
break;
diff --git a/tests/cms/Makefile.am b/tests/cms/Makefile.am
index 03c7d8d21..bc86acba2 100644
--- a/tests/cms/Makefile.am
+++ b/tests/cms/Makefile.am
@@ -86,6 +86,10 @@ EXTRA_DIST = $(XTESTS) $(KEYS) $(CERTS) $(TEST_FILES) \
samplekeys/cert_g10code_pete1.pem \
samplekeys/cert_g10code_test1.pem \
samplekeys/cert_g10code_theo1.pem \
+ samplemsgs/README \
+ samplemsgs/pwri-sample.cbc.p7m \
+ samplemsgs/pwri-sample.cbc-2.p7m \
+ samplemsgs/pwri-sample.gcm.p7m \
text-1.txt text-2.txt text-3.txt \
text-1.osig.pem text-1.dsig.pem text-1.osig-bad.pem \
text-2.osig.pem text-2.osig-bad.pem \
diff --git a/tests/cms/samplemsgs/README b/tests/cms/samplemsgs/README
new file mode 100644
index 000000000..a76b9457a
--- /dev/null
+++ b/tests/cms/samplemsgs/README
@@ -0,0 +1,6 @@
+Sample messages for CMS symmetric encryption.
+Password is "abc".
+
+pwri-sample.cbc.p7m - Using CBC Mode
+pwri-sample.cbc-2.p7m - Using CBC with a different iteration count
+pwri-sample.gcm.p7m - Using GCM (from a broken implementation)
diff --git a/tests/cms/samplemsgs/pwri-sample.cbc-2.p7m b/tests/cms/samplemsgs/pwri-sample.cbc-2.p7m
new file mode 100644
index 000000000..a417b7aca
--- /dev/null
+++ b/tests/cms/samplemsgs/pwri-sample.cbc-2.p7m
Binary files differ
diff --git a/tests/cms/samplemsgs/pwri-sample.cbc.p7m b/tests/cms/samplemsgs/pwri-sample.cbc.p7m
new file mode 100644
index 000000000..ba208d2e3
--- /dev/null
+++ b/tests/cms/samplemsgs/pwri-sample.cbc.p7m
Binary files differ
diff --git a/tests/cms/samplemsgs/pwri-sample.gcm.p7m b/tests/cms/samplemsgs/pwri-sample.gcm.p7m
new file mode 100644
index 000000000..7cf1f8542
--- /dev/null
+++ b/tests/cms/samplemsgs/pwri-sample.gcm.p7m
Binary files differ