From 4980fb3c6dde8c1dda975e8a36d6086c8456a631 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 2 Jun 2021 11:03:55 +0200 Subject: [PATCH] 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. --- doc/DETAILS | 2 + sm/decrypt.c | 82 ++++++++++++++++++++- sm/gpgsm.c | 9 ++- tests/cms/Makefile.am | 4 + tests/cms/samplemsgs/README | 6 ++ tests/cms/samplemsgs/pwri-sample.cbc-2.p7m | Bin 0 -> 346 bytes tests/cms/samplemsgs/pwri-sample.cbc.p7m | Bin 0 -> 350 bytes tests/cms/samplemsgs/pwri-sample.gcm.p7m | Bin 0 -> 375 bytes 8 files changed, 96 insertions(+), 7 deletions(-) create mode 100644 tests/cms/samplemsgs/README create mode 100644 tests/cms/samplemsgs/pwri-sample.cbc-2.p7m create mode 100644 tests/cms/samplemsgs/pwri-sample.cbc.p7m create mode 100644 tests/cms/samplemsgs/pwri-sample.gcm.p7m 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 0000000000000000000000000000000000000000..a417b7aca7e2f3bf61cc021f7e589c1d90623746 GIT binary patch literal 346 zcmXqLVB^$k^Jx3d%gD~WpuwPliIKsuapvO2X+XvTN4O*_kAVq`!u;Z&{tv&aAGv7q zcjDG_OQ)>u@e4O(V=^%6nq|`v|KTSS6URCO9ySh$iA>zA3fIK{Qjt#XE~#T26c2 zWj=3n&p-Xyp3_wZNbY4sGi^guP>TIhqbMVdCXuEf6^8{4ECq5hXKu+Z`V;YVxl`4H zbHSgNH1F-ayE{ga@Bi-2?gd(A)9hxvVmZ|D_0Ff}-|>@0_jf8q9J=Zzd!=4pRii4v z?p?Eu_(jcIyEvuK{VrUbkiJ^Z?gz8p3Y`g;mPahQcHrX|;|K5Ot#N4z&GI=janYk^ IM;YJ%08(m*ivR!s literal 0 HcmV?d00001 diff --git a/tests/cms/samplemsgs/pwri-sample.cbc.p7m b/tests/cms/samplemsgs/pwri-sample.cbc.p7m new file mode 100644 index 0000000000000000000000000000000000000000..ba208d2e3abf710a3294e64336027b8e77dfa436 GIT binary patch literal 350 zcmXqLVB^$k^Jx3d%gD~WpuwPliIKsuaqi;ASwO}DQ@A86kAVh@$os|2-*r|Rrp>kM zS7{2py|#Yytock#>H-ElY#b0%m^fJ(40PDIp=NRlFmoEnvT-J~c`&9jvoLD02rMgW zkF@x5*U9+nfAy`mZBkeaG`27Fd;cx{Vpmt z((}?eZ)V;v3W=$nrC4ErDlEZ8!MnXa7Os|j>QSKZ|M#}?&J(kemuIb-;-q2jyPYx2H!dr1Wyb{{LEma+ z-}>cR2j{(C(Ybc{$`#fdB_@}C)7jR~ywh@$$lHf{*5bS;4#*2F?`C_`q^7neHC9}@ L>HR@n1~>o!!(@dD literal 0 HcmV?d00001 diff --git a/tests/cms/samplemsgs/pwri-sample.gcm.p7m b/tests/cms/samplemsgs/pwri-sample.gcm.p7m new file mode 100644 index 0000000000000000000000000000000000000000..7cf1f8542458857f848601b756b3dff3e23a71b5 GIT binary patch literal 375 zcmXqLVB^+m^Jx3d%g8CfD88VKA(#sX6|PN+01kAVh@$UKHGEig!BQ>H-ElY#b1UOq{F?20BQlGIJWpvT-J~c`&9jvoLD02ryi@VsVx4VDcOZb|c z9lIf!W%K%%I`g&Jb}R@mXn;G5ozXxZVY;4y5Q_kNl1k^k(+&H~Hr#yA{l400K?6&< zKgSzYH%G>&;i0~F90liXiquNF&C6@e!hPOd