diff options
author | Werner Koch <wk@gnupg.org> | 2021-06-02 11:03:55 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2021-06-02 11:03:55 +0200 |
commit | 4980fb3c6dde8c1dda975e8a36d6086c8456a631 (patch) | |
tree | d5a1dd07d15256549159f8a20b1617fc6ee7122a | |
parent | tests: Rename subdir gpgsm to cms and move sample dirs. (diff) | |
download | gnupg2-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/DETAILS | 2 | ||||
-rw-r--r-- | sm/decrypt.c | 82 | ||||
-rw-r--r-- | sm/gpgsm.c | 9 | ||||
-rw-r--r-- | tests/cms/Makefile.am | 4 | ||||
-rw-r--r-- | tests/cms/samplemsgs/README | 6 | ||||
-rw-r--r-- | tests/cms/samplemsgs/pwri-sample.cbc-2.p7m | bin | 0 -> 346 bytes | |||
-rw-r--r-- | tests/cms/samplemsgs/pwri-sample.cbc.p7m | bin | 0 -> 350 bytes | |||
-rw-r--r-- | tests/cms/samplemsgs/pwri-sample.gcm.p7m | bin | 0 -> 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 Binary files differnew file mode 100644 index 000000000..a417b7aca --- /dev/null +++ b/tests/cms/samplemsgs/pwri-sample.cbc-2.p7m diff --git a/tests/cms/samplemsgs/pwri-sample.cbc.p7m b/tests/cms/samplemsgs/pwri-sample.cbc.p7m Binary files differnew file mode 100644 index 000000000..ba208d2e3 --- /dev/null +++ b/tests/cms/samplemsgs/pwri-sample.cbc.p7m diff --git a/tests/cms/samplemsgs/pwri-sample.gcm.p7m b/tests/cms/samplemsgs/pwri-sample.gcm.p7m Binary files differnew file mode 100644 index 000000000..7cf1f8542 --- /dev/null +++ b/tests/cms/samplemsgs/pwri-sample.gcm.p7m |