From jan.bilek at eftlab.com.au Sat Jan 4 11:33:36 2020 From: jan.bilek at eftlab.com.au (Jan Bilek) Date: Sat, 4 Jan 2020 10:33:36 +0000 Subject: Disable Weak cipher check for DES KCV In-Reply-To: References: Message-ID: Ping? On 2019-12-21 11:40:06+10:00 Jan Bilek wrote: Hi, We have a problem here where I need to encrypt a block of data with zeros. <> gcry_check_version (NULL); unsigned char key[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; unsigned char out[8]; unsigned char data[8]; gcry_error_t err = 0; gcry_cipher_hd_t hd = nullptr; err = gcry_cipher_open(&hd, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); //auto blklen = gcry_cipher_get_algo_blklen(GCRY_CIPHER_DES); //auto algolen = gcry_cipher_get_algo_keylen (GCRY_CIPHER_DES); err = gcry_cipher_setkey (hd, key, sizeof(key)); std::cerr << "gpg_err_code: " << gpg_err_code(err) << std::endl; std::cerr << "gpg_strerror: " << gpg_strerror(err) << std::endl; gcry_cipher_encrypt(hd, out, sizeof(key), data, 8); if (err) { std::cerr << "Failed to perform cryptography" << std::endl; std::cerr << " cipher: " << static_cast(GCRY_CIPHER_DES) << std::endl; std::cerr << " mode: " << static_cast(GCRY_CIPHER_MODE_ECB) << std::endl; //std::cerr << " keyBlock: " << BinToHex(key) << std::endl; //std::cerr << " out: " << BinToHex(out) << std::endl; //std::cerr << " data: " << BinToHex(encryptedData) << std::endl; } This blows on: gpg_err_code: 43 gpg_strerror: Weak encryption key cipher_encrypt: key not set Tracked back t in a source to libcrypt / cipher / des.c r. 1384 do_des_setkey r. 1021 is_weak_key if (is_weak_key (key)) { _gcry_burn_stack (64); return GPG_ERR_WEAK_KEY; } cipher.c r.797 rc = c->spec->setkey (&c->context.c, key, keylen, c); if (!rc) { } else c->marks.key = 0; ... then disallows weak key setting completely, resulting in a failure. This has quite an impact on multiple (still) in-use KCV operations (e.g. KCV_METHOD_VISA) where key needs to be encrypted with a zero key to get its KCV. May I propose a patch? (See in attachment). Thanks & Cheers, Jan -------------- next part -------------- An HTML attachment was scrubbed... URL: From jussi.kivilinna at iki.fi Sun Jan 5 15:36:08 2020 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sun, 5 Jan 2020 16:36:08 +0200 Subject: Disable Weak cipher check for DES KCV In-Reply-To: References: Message-ID: Hello, Apparently my first reply went only to the mailing list. There I wrote: "I tried to find KCV specification where zero key is used to encrypt actual key as input block for KCV value, but all KCV algorithms I managed to find encrypt zero input block with the actual key as key. Can you check your documentation for KCV if zero key is really used and give pointer/link to that spec for us?" -Jussi On 4.1.2020 12.33, Jan Bilek wrote: > Ping? > ? > > On 2019-12-21 11:40:06+10:00 Jan Bilek wrote: > > Hi, > > We have a problem here where I need to encrypt a block of data with zeros. > > <> > ??gcry_check_version (NULL); > ? unsigned char key[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; > ? unsigned char out[8]; > ? unsigned char data[8]; > ? gcry_error_t err = 0; > ? gcry_cipher_hd_t hd = nullptr; > ? err = gcry_cipher_open(&hd, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); > ? //auto blklen = gcry_cipher_get_algo_blklen(GCRY_CIPHER_DES); > ? //auto algolen = gcry_cipher_get_algo_keylen (GCRY_CIPHER_DES); > ? err = gcry_cipher_setkey (hd, key, sizeof(key)); > ? std::cerr << "gpg_err_code: " << gpg_err_code(err) << std::endl; > ? std::cerr << "gpg_strerror: " << gpg_strerror(err) << std::endl; > ? gcry_cipher_encrypt(hd, out, sizeof(key), data, 8); > ? if (err) { > ? ? std::cerr << "Failed to perform cryptography" << std::endl; > ? ? std::cerr << " ?cipher: ? ? " << static_cast(GCRY_CIPHER_DES) << std::endl; > ? ? std::cerr << " ?mode: ? ? ? " << static_cast(GCRY_CIPHER_MODE_ECB) << std::endl; > ? ? //std::cerr << " ?keyBlock: ? " << BinToHex(key) << std::endl; > ? ? //std::cerr << " ?out: ? ? ? ?" << BinToHex(out) << std::endl; > ? ? //std::cerr << " ?data: ? ? ? " << BinToHex(encryptedData) << std::endl; > ? } > > > This blows on: > > gpg_err_code: 43 > gpg_strerror: Weak encryption key > cipher_encrypt: key not set > > Tracked back t?in a source?to libcrypt / cipher / des.c > > r. 1384?do_des_setkey > r. 1021 is_weak_key > > ??if (is_weak_key (key)) { > ? ? _gcry_burn_stack (64); > ? ? return GPG_ERR_WEAK_KEY; > ? } > > cipher.c > r.797? > > ?rc = c->spec->setkey (&c->context.c, key, keylen, c); > ? if (!rc) { > > ??} else > ? ? c->marks.key = 0; > ? > ... then disallows weak key setting completely, resulting in a failure. > > This has quite an impact on multiple (still) in-use KCV operations (e.g. KCV_METHOD_VISA) where key needs to be encrypted with a zero key to get its KCV. > > May I propose a patch? (See in attachment). > > Thanks & Cheers, > Jan > > > _______________________________________________ > Gcrypt-devel mailing list > Gcrypt-devel at gnupg.org > http://lists.gnupg.org/mailman/listinfo/gcrypt-devel > From jussi.kivilinna at iki.fi Tue Jan 7 22:34:52 2020 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 7 Jan 2020 23:34:52 +0200 Subject: [PATCH] Fix three errors for ec algorithm In-Reply-To: <20191222091533.2587-1-tianjia.zhang@linux.alibaba.com> References: <20191222091533.2587-1-tianjia.zhang@linux.alibaba.com> Message-ID: Hello, On 22.12.2019 11.15, Tianjia Zhang via Gcrypt-devel wrote: > Fix three errors in EC alogrithm and mpi. > Thanks for your contributions. I'll leave some comments on the patches in few days but it would be better if someone more familiar with MPI/EC side of gcrypt checks the patches too. One thing for you to do is to send your signed DCO to this mailing-list (see 'License policy' in doc/HACKING). -Jussi > > > _______________________________________________ > Gcrypt-devel mailing list > Gcrypt-devel at gnupg.org > http://lists.gnupg.org/mailman/listinfo/gcrypt-devel > From jussi.kivilinna at iki.fi Tue Jan 7 22:35:40 2020 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 7 Jan 2020 23:35:40 +0200 Subject: [PATCH 1/3] Update .gitignore In-Reply-To: <20191222091533.2587-2-tianjia.zhang@linux.alibaba.com> References: <20191222091533.2587-1-tianjia.zhang@linux.alibaba.com> <20191222091533.2587-2-tianjia.zhang@linux.alibaba.com> Message-ID: <8b4f33ab-162b-3435-502a-b5d8c60d4a7f@iki.fi> Hello, On 22.12.2019 11.15, Tianjia Zhang via Gcrypt-devel wrote: > Signed-off-by: Tianjia Zhang > --- > .gitignore | 5 +++++ > 1 file changed, 5 insertions(+) > > diff --git a/.gitignore b/.gitignore > index 704d3ca0..99741c18 100644 > --- a/.gitignore > +++ b/.gitignore > @@ -32,6 +32,8 @@ cipher/libcipher.la > compat/Makefile > compat/libcompat.la > doc/gcrypt.info > +doc/gcrypt.info-1 > +doc/gcrypt.info-2 > doc/stamp-vti > doc/version.texi > doc/Makefile > @@ -65,6 +67,7 @@ src/gcrypt.h > src/hmac256 > src/libgcrypt-config > src/libgcrypt.la > +src/libgcrypt.pc > src/mpicalc > src/versioninfo.rc > src/*.exe > @@ -103,6 +106,8 @@ tests/t-lock > tests/t-mpi-bit > tests/t-mpi-point > tests/t-sexp > +tests/t-secmem > +tests/t-x448 > tests/tsexp > tests/version > tests/*.exe > Looks ok. -Jussi From jussi.kivilinna at iki.fi Tue Jan 7 22:36:34 2020 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 7 Jan 2020 23:36:34 +0200 Subject: [PATCH 3/3] ecc: Wrong flag and elements_enc fix. In-Reply-To: <20191222091533.2587-4-tianjia.zhang@linux.alibaba.com> References: <20191222091533.2587-1-tianjia.zhang@linux.alibaba.com> <20191222091533.2587-4-tianjia.zhang@linux.alibaba.com> Message-ID: <8367e139-f48d-d690-6dfa-286c8d53a8db@iki.fi> Hello, On 22.12.2019 11.15, Tianjia Zhang via Gcrypt-devel wrote: > * cipher/ecc.c (ecc_generate): Fix wrong flag and elements_enc. > > Signed-off-by: Tianjia Zhang > --- > cipher/ecc.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/cipher/ecc.c b/cipher/ecc.c > index 921510cc..10e11243 100644 > --- a/cipher/ecc.c > +++ b/cipher/ecc.c > @@ -577,7 +577,7 @@ ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey) > (&curve_flags, NULL, > ((flags & PUBKEY_FLAG_PARAM) && (flags & PUBKEY_FLAG_EDDSA))? > "(flags param eddsa)" : > - ((flags & PUBKEY_FLAG_PARAM) && (flags & PUBKEY_FLAG_EDDSA))? > + ((flags & PUBKEY_FLAG_PARAM) && (flags & PUBKEY_FLAG_DJB_TWEAK))? > "(flags param djb-tweak)" : > ((flags & PUBKEY_FLAG_PARAM))? > "(flags param)" : ((flags & PUBKEY_FLAG_EDDSA))? > @@ -1712,7 +1712,7 @@ gcry_pk_spec_t _gcry_pubkey_spec_ecc = > GCRY_PK_ECC, { 0, 1 }, > (GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR), > "ECC", ecc_names, > - "pabgnhq", "pabgnhqd", "sw", "rs", "pabgnhq", > + "pabgnhq", "pabgnhqd", "se", "rs", "pabgnhq", > ecc_generate, > ecc_check_secret_key, > ecc_encrypt_raw, > Looks ok. -Jussi From jussi.kivilinna at iki.fi Tue Jan 7 22:46:38 2020 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 7 Jan 2020 23:46:38 +0200 Subject: [PATCH 2/3] mpi: fix missing fields in an empty point and the mpi_clear requires a non-empty argument. In-Reply-To: <20191222091533.2587-3-tianjia.zhang@linux.alibaba.com> References: <20191222091533.2587-1-tianjia.zhang@linux.alibaba.com> <20191222091533.2587-3-tianjia.zhang@linux.alibaba.com> Message-ID: Hello, On 22.12.2019 11.15, Tianjia Zhang via Gcrypt-devel wrote: > * mpi/ec.c (_gcry_mpi_point_set): Assign value to missing fields. > > The problem is triggered when using the following code by > mpi_ec_get_elliptic_curve: > > elliptic_curve_t E; > memset (&E, 0, sizeof E); > mpi_point_set (&E->G, G->x, G->y, G->z); I think this issue should be fixed in 'mpi_ec_get_elliptic_curve' rather than in '_gcry_mpi_point_set'. '_gcry_mpi_point_set' expects POINT to be either properly initialized point structure or NULL. 'mpi_ec_get_elliptic_curve' however is passing point structure that has not been initialized with '_gcry_mpi_point_init'. So, I'd change { mpi_point_set (&E->G, G->x, G->y, G->z); mpi_point_set (G, NULL, NULL, NULL); mpi_point_release (G); } to { _gcry_mpi_point_init (&E->G); mpi_point_set (&E->G, G->x, G->y, G->z); mpi_point_set (G, NULL, NULL, NULL); mpi_point_release (G); } -Jussi > > Signed-off-by: Tianjia Zhang > --- > mpi/ec.c | 12 ++++++------ > 1 file changed, 6 insertions(+), 6 deletions(-) > > diff --git a/mpi/ec.c b/mpi/ec.c > index d4c4f953..94d93354 100644 > --- a/mpi/ec.c > +++ b/mpi/ec.c > @@ -224,16 +224,16 @@ _gcry_mpi_point_set (mpi_point_t point, > point = mpi_point_new (0); > > if (x) > - mpi_set (point->x, x); > - else > + point->x = mpi_set (point->x, x); > + else if (point->x) > mpi_clear (point->x); > if (y) > - mpi_set (point->y, y); > - else > + point->y = mpi_set (point->y, y); > + else if (point->y) > mpi_clear (point->y); > if (z) > - mpi_set (point->z, z); > - else > + point->z = mpi_set (point->z, z); > + else if (point->z) > mpi_clear (point->z); > > return point; > From tianjia.zhang at linux.alibaba.com Wed Jan 8 14:10:48 2020 From: tianjia.zhang at linux.alibaba.com (Tianjia Zhang) Date: Wed, 8 Jan 2020 21:10:48 +0800 Subject: Sign DCO from Tianjia Zhang Message-ID: -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA512 Libgcrypt Developer's Certificate of Origin.? Version 1.0 ========================================================= By making a contribution to the Libgcrypt project, I certify that: (a) The contribution was created in whole or in part by me and I ??? have the right to submit it under the free software license ??? indicated in the file; or (b) The contribution is based upon previous work that, to the ??? best of my knowledge, is covered under an appropriate free ??? software license and I have the right under that license to ??? submit that work with modifications, whether created in whole ??? or in part by me, under the same free software license ??? (unless I am permitted to submit under a different license), ??? as indicated in the file; or (c) The contribution was provided directly to me by some other ??? person who certified (a), (b) or (c) and I have not modified ??? it. (d) I understand and agree that this project and the contribution ??? are public and that a record of the contribution (including ??? all personal information I submit with it, including my ??? sign-off) is maintained indefinitely and may be redistributed ??? consistent with this project or the free software license(s) ??? involved. Signed-off-by: Tianjia Zhang -----BEGIN PGP SIGNATURE----- iQGzBAEBCgAdFiEEOxqBmMkQSfkUgZMrEYwPv7VKWxYFAl4V0x4ACgkQEYwPv7VK WxZSbAwAxuQY9HVBBgZnT2ZQwVXbetYh4TxRg0JCk0iIabnp9VsMh+FzKImOKzsJ jtcpMX8BIlSMh+O3Rh8VfA7obtHUS/Eh/KuePvptfhzW+KwOYHIQFPzMPDoSJbrt 212LIZaZ7PRdEKk74VwTMqTaFVZFB2BQnlpNnaRtgPjb5xM2Hxtk+45fC5ScVPEv cA5ti6PD52osdY4r/SS5HmTwNxyM5BxErQ8N606QYTcp+A9kprp1sEiigDUrKlTU 0kBAYF1RI8BhY7mCAovAzWUyLQfljJsjRWhn7e2UNvKjcV4at8LDekQB59P65Qhs a+k0lgc/0kBFwgUMhKo5QUB6ObxbK+zx28X9z1LwqcKj1RhYUfUquPw3STFu0WPC RX9DtoKjG5sM6vBoQARb7b9Fg3Wn+HmmySehIAKpStcoaJGt0ltZlcTe0zeM5+PZ whOBTayYXIwIWsnSpfWYzwfb4/BG0EyVpx2/NEKa7rPZ6taEof2oWeGBK7oYjhhM zaStF640 =jrd/ -----END PGP SIGNATURE----- -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 659 bytes Desc: OpenPGP digital signature URL: From tianjia.zhang at linux.alibaba.com Wed Jan 8 14:36:49 2020 From: tianjia.zhang at linux.alibaba.com (Tianjia Zhang) Date: Wed, 8 Jan 2020 21:36:49 +0800 Subject: [PATCH v2] mpi: Fix error that point not uninitialized Message-ID: <20200108133649.2375-1-tianjia.zhang@linux.alibaba.com> * cipher/ecc-curves.c (mpi_ec_get_elliptic_curve): Initialize E->G poing Signed-off-by: Tianjia Zhang --- cipher/ecc-curves.c | 1 + 1 file changed, 1 insertion(+) diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c index 1592d23a..92850ac7 100644 --- a/cipher/ecc-curves.c +++ b/cipher/ecc-curves.c @@ -1058,6 +1058,7 @@ mpi_ec_get_elliptic_curve (elliptic_curve_t *E, int *r_flags, goto leave; if (G) { + _gcry_mpi_point_init (&E->G); mpi_point_set (&E->G, G->x, G->y, G->z); mpi_point_set (G, NULL, NULL, NULL); mpi_point_release (G); -- 2.17.1 From gniibe at fsij.org Thu Jan 9 00:24:52 2020 From: gniibe at fsij.org (NIIBE Yutaka) Date: Thu, 09 Jan 2020 08:24:52 +0900 Subject: [PATCH] Fix three errors for ec algorithm In-Reply-To: References: <20191222091533.2587-1-tianjia.zhang@linux.alibaba.com> Message-ID: <87blrdbkfv.fsf@jumper.gniibe.org> Hello, Jussi Kivilinna via Gcrypt-devel wrote: > Thanks for your contributions. I'll leave some comments on the patches > in few days but it would be better if someone more familiar with > MPI/EC side of gcrypt checks the patches too. Acked by me for: [PATCH 1/3] Update .gitignore [PATCH v2] mpi: Fix error that point not uninitialized [PATCH 3/3] ecc: Wrong flag and elements_enc fix. To Tianjia Zhang: Thanks for your good catch. I just realized that you also sent me other patches directly to me for review. I'll do that soon. My excuse for 3/3 is that: the feature (flags param) is basically for classic ECC where (some) people want to define their own domain parameters, and it has been not used with modern ECC (which may have eddsa or djb-tweak flag). For the _gcry_pubkey_spec_ecc fix, I should have fixed the "sw" -> "se" when I touched other parameters. -- From jan.bilek at eftlab.com.au Thu Jan 9 02:57:53 2020 From: jan.bilek at eftlab.com.au (Jan Bilek) Date: Thu, 9 Jan 2020 01:57:53 +0000 Subject: Disable Weak cipher check for DES KCV In-Reply-To: References: , Message-ID: Hi Jussi, No problem and thanks for coming back on my email. You are right - "all KCV algorithms I managed to find encrypt zero input block with the actual key as key" - except cases where the key is a weak key. While this might sound ridiculous there are many cases like this - in production as well as in test environments. E.g. Thales HSM default-load key-set works with some weak keys and while doing symmetric crypto we need to support those as well (in testing / dev environments Thales HSM is almost always loaded with a default key set so crypto can be reproduced and validated). Hope it makes better sense now. Cheers, Jan On 2020-01-06 00:36:19+10:00 Jussi Kivilinna wrote: Hello, Apparently my first reply went only to the mailing list. There I wrote: "I tried to find KCV specification where zero key is used to encrypt actual key as input block for KCV value, but all KCV algorithms I managed to find encrypt zero input block with the actual key as key. Can you check your documentation for KCV if zero key is really used and give pointer/link to that spec for us?" -Jussi On 4.1.2020 12.33, Jan Bilek wrote: &gt; Ping? &gt; &nbsp; &gt; &gt; On 2019-12-21 11:40:06+10:00 Jan Bilek wrote: &gt; &gt; Hi, &gt; &gt; We have a problem here where I need to encrypt a block of data with zeros. &gt; &gt; &lt;&gt; &gt; &nbsp;&nbsp;gcry_check_version (NULL); &gt; &nbsp; unsigned char key[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; &gt; &nbsp; unsigned char out[8]; &gt; &nbsp; unsigned char data[8]; &gt; &nbsp; gcry_error_t err = 0; &gt; &nbsp; gcry_cipher_hd_t hd = nullptr; &gt; &nbsp; err = gcry_cipher_open(&amp;hd, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); &gt; &nbsp; //auto blklen = gcry_cipher_get_algo_blklen(GCRY_CIPHER_DES); &gt; &nbsp; //auto algolen = gcry_cipher_get_algo_keylen (GCRY_CIPHER_DES); &gt; &nbsp; err = gcry_cipher_setkey (hd, key, sizeof(key)); &gt; &nbsp; std::cerr &lt;&lt; "gpg_err_code: " &lt;&lt; gpg_err_code(err) &lt;&lt; std::endl; &gt; &nbsp; std::cerr &lt;&lt; "gpg_strerror: " &lt;&lt; gpg_strerror(err) &lt;&lt; std::endl; &gt; &nbsp; gcry_cipher_encrypt(hd, out, sizeof(key), data, 8); &gt; &nbsp; if (err) { &gt; &nbsp; &nbsp; std::cerr &lt;&lt; "Failed to perform cryptography" &lt;&lt; std::endl; &gt; &nbsp; &nbsp; std::cerr &lt;&lt; " &nbsp;cipher: &nbsp; &nbsp; " &lt;&lt; static_cast<int>(GCRY_CIPHER_DES) &lt;&lt; std::endl; &gt; &nbsp; &nbsp; std::cerr &lt;&lt; " &nbsp;mode: &nbsp; &nbsp; &nbsp; " &lt;&lt; static_cast<int>(GCRY_CIPHER_MODE_ECB) &lt;&lt; std::endl; &gt; &nbsp; &nbsp; //std::cerr &lt;&lt; " &nbsp;keyBlock: &nbsp; " &lt;&lt; BinToHex<std::string>(key) &lt;&lt; std::endl; &gt; &nbsp; &nbsp; //std::cerr &lt;&lt; " &nbsp;out: &nbsp; &nbsp; &nbsp; &nbsp;" &lt;&lt; BinToHex<std::string>(out) &lt;&lt; std::endl; &gt; &nbsp; &nbsp; //std::cerr &lt;&lt; " &nbsp;data: &nbsp; &nbsp; &nbsp; " &lt;&lt; BinToHex<std::string>(encryptedData) &lt;&lt; std::endl; &gt; &nbsp; } &gt; &gt; &gt; This blows on: &gt; &gt; gpg_err_code: 43 &gt; gpg_strerror: Weak encryption key &gt; cipher_encrypt: key not set &gt; &gt; Tracked back t&nbsp;in a source&nbsp;to libcrypt / cipher / des.c &gt; &gt; r. 1384&nbsp;do_des_setkey &gt; r. 1021 is_weak_key &gt; &gt; &nbsp;&nbsp;if (is_weak_key (key)) { &gt; &nbsp; &nbsp; _gcry_burn_stack (64); &gt; &nbsp; &nbsp; return GPG_ERR_WEAK_KEY; &gt; &nbsp; } &gt; &gt; cipher.c &gt; r.797&nbsp; &gt; &gt; &nbsp;rc = c-&gt;spec-&gt;setkey (&amp;c-&gt;context.c, key, keylen, c); &gt; &nbsp; if (!rc) { &gt; &gt; &nbsp;&nbsp;} else &gt; &nbsp; &nbsp; c-&gt;marks.key = 0; &gt; &nbsp; &gt; ... then disallows weak key setting completely, resulting in a failure. &gt; &gt; This has quite an impact on multiple (still) in-use KCV operations (e.g. KCV_METHOD_VISA) where key needs to be encrypted with a zero key to get its KCV. &gt; &gt; May I propose a patch? (See in attachment). &gt; &gt; Thanks &amp; Cheers, &gt; Jan &gt; &gt; &gt; _______________________________________________ &gt; Gcrypt-devel mailing list &gt; Gcrypt-devel at gnupg.org &gt; http://lists.gnupg.org/mailman/listinfo/gcrypt-devel &gt; </std::string></std::string></std::string></int></int> -------------- next part -------------- An HTML attachment was scrubbed... URL: From hjl.tools at gmail.com Fri Jan 17 18:29:53 2020 From: hjl.tools at gmail.com (H.J. Lu) Date: Fri, 17 Jan 2020 09:29:53 -0800 Subject: [PATCH 1/4] x86: Add .note.gnu.property section for Intel CET In-Reply-To: <20200117172956.3299-1-hjl.tools@gmail.com> References: <20200117172956.3299-1-hjl.tools@gmail.com> Message-ID: <20200117172956.3299-2-hjl.tools@gmail.com> When Intel CET is enabled, include in for assembly codes to mark Intel CET support. * configure.ac: Include in for assembly codes. Signed-off-by: H.J. Lu --- configure.ac | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/configure.ac b/configure.ac index 4d4fb49a..c3bcd74d 100644 --- a/configure.ac +++ b/configure.ac @@ -97,6 +97,12 @@ AH_TOP([ AH_BOTTOM([ #define _GCRYPT_IN_LIBGCRYPT 1 +/* Add .note.gnu.property section for Intel CET in assembler sources + when CET is enabled. */ +#if defined(__ASSEMBLER__) && defined(__CET__) +# include +#endif + /* If the configure check for endianness has been disabled, get it from OS macros. This is intended for making fat binary builds on OS X. */ #ifdef DISABLED_ENDIAN_CHECK -- 2.24.1 From hjl.tools at gmail.com Fri Jan 17 18:29:56 2020 From: hjl.tools at gmail.com (H.J. Lu) Date: Fri, 17 Jan 2020 09:29:56 -0800 Subject: [PATCH 4/4] i386: Add _CET_ENDBR to indirect jump targets In-Reply-To: <20200117172956.3299-1-hjl.tools@gmail.com> References: <20200117172956.3299-1-hjl.tools@gmail.com> Message-ID: <20200117172956.3299-5-hjl.tools@gmail.com> i386 mpih-add1.S and mpih-sub1.S use a trick to implment jump tables with LEA. We can't use conditional branches nor normal jump tables since jump table entries use EFLAGS set by jump table index. This patch adds _CET_ENDBR to indirect jump targets and adjust destination for _CET_ENDBR. * mpi/i386/mpih-add1.S (_gcry_mpih_add_n): Save and restore %ebx if IBT is enabed. Add _CET_ENDBR to indirect jump targets and adjust jump destination for _CET_ENDBR. * mpi/i386/mpih-sub1.S (_gcry_mpih_sub_n): Likewise. Signed-off-by: H.J. Lu --- mpi/i386/mpih-add1.S | 35 +++++++++++++++++++++++++++++++++++ mpi/i386/mpih-sub1.S | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/mpi/i386/mpih-add1.S b/mpi/i386/mpih-add1.S index 32091f34..ef6423d9 100644 --- a/mpi/i386/mpih-add1.S +++ b/mpi/i386/mpih-add1.S @@ -55,6 +55,10 @@ C_SYMBOL_NAME(_gcry_mpih_add_n:) movl 20(%esp),%edx /* s2_ptr */ movl 24(%esp),%ecx /* size */ +#if defined __CET__ && (__CET__ & 1) != 0 + pushl %ebx +#endif + movl %ecx,%eax shrl $3,%ecx /* compute count for unrolled loop */ negl %eax @@ -66,6 +70,9 @@ C_SYMBOL_NAME(_gcry_mpih_add_n:) subl %eax,%esi /* ... by a constant when we ... */ subl %eax,%edx /* ... enter the loop */ shrl $2,%eax /* restore previous value */ +#if defined __CET__ && (__CET__ & 1) != 0 + leal -4(,%eax,4),%ebx /* Count for 4-byte endbr32 */ +#endif #ifdef PIC /* Calculate start address in loop for PIC. Due to limitations in some assemblers, Loop-L0-3 cannot be put into the leal */ @@ -77,30 +84,54 @@ L0: leal (%eax,%eax,8),%eax #else /* Calculate start address in loop for non-PIC. */ leal (Loop - 3)(%eax,%eax,8),%eax +#endif +#if defined __CET__ && (__CET__ & 1) != 0 + addl %ebx,%eax /* Adjust for endbr32 */ #endif jmp *%eax /* jump into loop */ ALIGN (3) Loop: movl (%esi),%eax adcl (%edx),%eax movl %eax,(%edi) +#ifdef _CET_ENDBR + _CET_ENDBR +#endif movl 4(%esi),%eax adcl 4(%edx),%eax movl %eax,4(%edi) +#ifdef _CET_ENDBR + _CET_ENDBR +#endif movl 8(%esi),%eax adcl 8(%edx),%eax movl %eax,8(%edi) +#ifdef _CET_ENDBR + _CET_ENDBR +#endif movl 12(%esi),%eax adcl 12(%edx),%eax movl %eax,12(%edi) +#ifdef _CET_ENDBR + _CET_ENDBR +#endif movl 16(%esi),%eax adcl 16(%edx),%eax movl %eax,16(%edi) +#ifdef _CET_ENDBR + _CET_ENDBR +#endif movl 20(%esi),%eax adcl 20(%edx),%eax movl %eax,20(%edi) +#ifdef _CET_ENDBR + _CET_ENDBR +#endif movl 24(%esi),%eax adcl 24(%edx),%eax movl %eax,24(%edi) +#ifdef _CET_ENDBR + _CET_ENDBR +#endif movl 28(%esi),%eax adcl 28(%edx),%eax movl %eax,28(%edi) @@ -113,6 +144,10 @@ Loop: movl (%esi),%eax sbbl %eax,%eax negl %eax +#if defined __CET__ && (__CET__ & 1) != 0 + popl %ebx +#endif + popl %esi CFI_POP(%esi) popl %edi diff --git a/mpi/i386/mpih-sub1.S b/mpi/i386/mpih-sub1.S index 501c4a9f..86ab6725 100644 --- a/mpi/i386/mpih-sub1.S +++ b/mpi/i386/mpih-sub1.S @@ -56,6 +56,10 @@ C_SYMBOL_NAME(_gcry_mpih_sub_n:) movl 20(%esp),%edx /* s2_ptr */ movl 24(%esp),%ecx /* size */ +#if defined __CET__ && (__CET__ & 1) != 0 + pushl %ebx +#endif + movl %ecx,%eax shrl $3,%ecx /* compute count for unrolled loop */ negl %eax @@ -67,6 +71,9 @@ C_SYMBOL_NAME(_gcry_mpih_sub_n:) subl %eax,%esi /* ... by a constant when we ... */ subl %eax,%edx /* ... enter the loop */ shrl $2,%eax /* restore previous value */ +#if defined __CET__ && (__CET__ & 1) != 0 + leal -4(,%eax,4),%ebx /* Count for 4-byte endbr32 */ +#endif #ifdef PIC /* Calculate start address in loop for PIC. Due to limitations in some assemblers, Loop-L0-3 cannot be put into the leal */ @@ -78,30 +85,54 @@ L0: leal (%eax,%eax,8),%eax #else /* Calculate start address in loop for non-PIC. */ leal (Loop - 3)(%eax,%eax,8),%eax +#endif +#if defined __CET__ && (__CET__ & 1) != 0 + addl %ebx,%eax /* Adjust for endbr32 */ #endif jmp *%eax /* jump into loop */ ALIGN (3) Loop: movl (%esi),%eax sbbl (%edx),%eax movl %eax,(%edi) +#ifdef _CET_ENDBR + _CET_ENDBR +#endif movl 4(%esi),%eax sbbl 4(%edx),%eax movl %eax,4(%edi) +#ifdef _CET_ENDBR + _CET_ENDBR +#endif movl 8(%esi),%eax sbbl 8(%edx),%eax movl %eax,8(%edi) +#ifdef _CET_ENDBR + _CET_ENDBR +#endif movl 12(%esi),%eax sbbl 12(%edx),%eax movl %eax,12(%edi) +#ifdef _CET_ENDBR + _CET_ENDBR +#endif movl 16(%esi),%eax sbbl 16(%edx),%eax movl %eax,16(%edi) +#ifdef _CET_ENDBR + _CET_ENDBR +#endif movl 20(%esi),%eax sbbl 20(%edx),%eax movl %eax,20(%edi) +#ifdef _CET_ENDBR + _CET_ENDBR +#endif movl 24(%esi),%eax sbbl 24(%edx),%eax movl %eax,24(%edi) +#ifdef _CET_ENDBR + _CET_ENDBR +#endif movl 28(%esi),%eax sbbl 28(%edx),%eax movl %eax,28(%edi) @@ -114,6 +145,10 @@ Loop: movl (%esi),%eax sbbl %eax,%eax negl %eax +#if defined __CET__ && (__CET__ & 1) != 0 + popl %ebx +#endif + popl %esi CFI_POP(%esi) popl %edi -- 2.24.1 From hjl.tools at gmail.com Fri Jan 17 18:29:54 2020 From: hjl.tools at gmail.com (H.J. Lu) Date: Fri, 17 Jan 2020 09:29:54 -0800 Subject: [PATCH 2/4] mpi: Add .note.gnu.property section for Intel CET In-Reply-To: <20200117172956.3299-1-hjl.tools@gmail.com> References: <20200117172956.3299-1-hjl.tools@gmail.com> Message-ID: <20200117172956.3299-3-hjl.tools@gmail.com> When Intel CET is enabled, include in for assembly codes to mark Intel CET support. * mpi/config.links: Include in . Signed-off-by: H.J. Lu --- mpi/config.links | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/mpi/config.links b/mpi/config.links index 3ead4f08..4f43b732 100644 --- a/mpi/config.links +++ b/mpi/config.links @@ -382,6 +382,16 @@ if test x"$mpi_cpu_arch" = x ; then mpi_cpu_arch="unknown" fi +# Add .note.gnu.property section for Intel CET in assembler sources +# when CET is enabled. */ +if test x"$mpi_cpu_arch" = xx86 ; then + cat <> ./mpi/asm-syntax.h + +#if defined(__ASSEMBLER__) && defined(__CET__) +# include +#endif +EOF +fi # Make sysdep.h echo '/* created by config.links - do not edit */' >./mpi/sysdep.h -- 2.24.1 From hjl.tools at gmail.com Fri Jan 17 18:29:55 2020 From: hjl.tools at gmail.com (H.J. Lu) Date: Fri, 17 Jan 2020 09:29:55 -0800 Subject: [PATCH 3/4] amd64: Always include in cipher assembly codes In-Reply-To: <20200117172956.3299-1-hjl.tools@gmail.com> References: <20200117172956.3299-1-hjl.tools@gmail.com> Message-ID: <20200117172956.3299-4-hjl.tools@gmail.com> When Intel CET is enabled, we need to include in assembly codes to mark Intel CET support even if it is empty. We should always include in cipher amd64 assembly codes so that they will be marked for Intel CET support when compiling for i686. * cipher/camellia-aesni-avx-amd64.S: Always include . * cipher/camellia-aesni-avx2-amd64.S: Likewise. * cipher/serpent-avx2-amd64.S: Likewise. Signed-off-by: H.J. Lu --- cipher/camellia-aesni-avx-amd64.S | 3 ++- cipher/camellia-aesni-avx2-amd64.S | 3 ++- cipher/serpent-avx2-amd64.S | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/cipher/camellia-aesni-avx-amd64.S b/cipher/camellia-aesni-avx-amd64.S index e16d4f61..4671bcfe 100644 --- a/cipher/camellia-aesni-avx-amd64.S +++ b/cipher/camellia-aesni-avx-amd64.S @@ -18,8 +18,9 @@ * License along with this program; if not, see . */ -#ifdef __x86_64 #include + +#ifdef __x86_64 #if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \ defined(ENABLE_AESNI_SUPPORT) && defined(ENABLE_AVX_SUPPORT) diff --git a/cipher/camellia-aesni-avx2-amd64.S b/cipher/camellia-aesni-avx2-amd64.S index cc01c774..517e6880 100644 --- a/cipher/camellia-aesni-avx2-amd64.S +++ b/cipher/camellia-aesni-avx2-amd64.S @@ -18,8 +18,9 @@ * License along with this program; if not, see . */ -#ifdef __x86_64 #include + +#ifdef __x86_64 #if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \ defined(ENABLE_AESNI_SUPPORT) && defined(ENABLE_AVX2_SUPPORT) diff --git a/cipher/serpent-avx2-amd64.S b/cipher/serpent-avx2-amd64.S index 9b17c2bd..dcee9b62 100644 --- a/cipher/serpent-avx2-amd64.S +++ b/cipher/serpent-avx2-amd64.S @@ -18,8 +18,9 @@ * License along with this program; if not, see . */ -#ifdef __x86_64 #include + +#ifdef __x86_64 #if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && defined(USE_SERPENT) && \ defined(ENABLE_AVX2_SUPPORT) -- 2.24.1 From hjl.tools at gmail.com Fri Jan 17 18:29:52 2020 From: hjl.tools at gmail.com (H.J. Lu) Date: Fri, 17 Jan 2020 09:29:52 -0800 Subject: [PATCH 0/4] x86: Enable Intel Control-flow Enforcement Technology (CET) Message-ID: <20200117172956.3299-1-hjl.tools@gmail.com> Intel Control-flow Enforcement Technology (CET): https://software.intel.com/en-us/articles/intel-sdm contains shadow stack (SHSTK) and indirect branch tracking (IBT). When CET is enabled, ELF object files must be marked with .note.gnu.property section. CET enabled compiler provides which can be included in assembly sources to automatically generate .note.gnu.property section. Also when IBT is enabled, all indirect branch targets must start with ENDBR instruction. defines _CET_ENDBR to generate proper ENDBR instruction. Tested with $ CC="gcc -Wl,-z,cet-report=error -fcf-protection" ./configure in i686 and x86-64 modes on Linux CET machine. H.J. Lu (4): x86: Add .note.gnu.property section for Intel CET mpi: Add .note.gnu.property section for Intel CET amd64: Always include in cipher assembly codes i386: Add _CET_ENDBR to indirect jump targets cipher/camellia-aesni-avx-amd64.S | 3 ++- cipher/camellia-aesni-avx2-amd64.S | 3 ++- cipher/serpent-avx2-amd64.S | 3 ++- configure.ac | 6 +++++ mpi/config.links | 10 +++++++++ mpi/i386/mpih-add1.S | 35 ++++++++++++++++++++++++++++++ mpi/i386/mpih-sub1.S | 35 ++++++++++++++++++++++++++++++ 7 files changed, 92 insertions(+), 3 deletions(-) -- 2.24.1 From jussi.kivilinna at iki.fi Sun Jan 19 09:26:32 2020 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sun, 19 Jan 2020 10:26:32 +0200 Subject: [PATCH] gcrypt.texi: fix GCRYCTL_GET_ALGO_NENCR typo Message-ID: <157942239187.6560.13944694524499119012.stgit@localhost6.localdomain6> * doc/gcrypt.texi: Fix GCRYCTL_GET_ALGO_NENC to GCRYCTL_GET_ALGO_NENCR. -- Signed-off-by: Jussi Kivilinna --- doc/gcrypt.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index d7bfa4c27..091704de1 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -2824,7 +2824,7 @@ Return the number of elements a signature created with the algorithm @var{algo} consists of. Return 0 for an unknown algorithm or for an algorithm not capable of creating signatures. - at item GCRYCTL_GET_ALGO_NENC + at item GCRYCTL_GET_ALGO_NENCR Return the number of elements a encrypted message created with the algorithm @var{algo} consists of. Return 0 for an unknown algorithm or for an algorithm not capable of encryption. From jussi.kivilinna at iki.fi Sun Jan 19 09:27:10 2020 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sun, 19 Jan 2020 10:27:10 +0200 Subject: [PATCH] tests/basic: add vector cluttering to detect implementation bugs Message-ID: <157942243012.6894.17655631851985173631.stgit@localhost6.localdomain6> * src/global.c (_gcry_check_version): Fix missing newline. * src/basic.c (ALWAYS_INLINE, CLUTTER_REGISTER_*, prepare_vector_data) (clutter_vector_registers): New. (progress_handler): Make static function. (check_bulk_cipher_modes, check_one_cipher_core_reset) (check_one_cipher_core, check_one_md, check_one_md_multi) (check_one_md_final, check_one_mac): Clutter vector registers before gcry_* calls to cipher/md/mac algorithms. -- Signed-off-by: Jussi Kivilinna --- src/global.c | 3 - tests/basic.c | 288 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 288 insertions(+), 3 deletions(-) diff --git a/src/global.c b/src/global.c index d82c680a5..be65df54a 100644 --- a/src/global.c +++ b/src/global.c @@ -261,7 +261,8 @@ _gcry_check_version (const char *req_version) /* Compare version numbers. */ if ( my_major > rq_major || (my_major == rq_major && my_minor > rq_minor) - || (my_major == rq_major && my_minor == rq_minor && my_micro > rq_micro) + || (my_major == rq_major && my_minor == rq_minor + && my_micro > rq_micro) || (my_major == rq_major && my_minor == rq_minor && my_micro == rq_micro)) { diff --git a/tests/basic.c b/tests/basic.c index 8337bcfb7..71b2aa30f 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -33,6 +33,10 @@ #define PGM "basic" #include "t-common.h" +#if __GNUC__ >= 4 +# define ALWAYS_INLINE __attribute__((always_inline)) +#endif + typedef struct test_spec_pubkey_key { const char *secret; @@ -191,7 +195,7 @@ show_mac_not_available (int algo) -void +static void progress_handler (void *cb_data, const char *what, int printchar, int current, int total) { @@ -207,6 +211,237 @@ progress_handler (void *cb_data, const char *what, int printchar, fflush (stdout); } + +#if defined(__x86_64__) && defined(HAVE_GCC_INLINE_ASM_SSSE3) && \ + (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ + defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) +# define CLUTTER_VECTOR_REGISTER_AMD64 1 +# define CLUTTER_VECTOR_REGISTER_COUNT 16 +#elif defined(__i386__) && SIZEOF_UNSIGNED_LONG == 4 && __GNUC__ >= 4 && \ + defined(HAVE_GCC_INLINE_ASM_SSSE3) +# define CLUTTER_VECTOR_REGISTER_I386 1 +# define CLUTTER_VECTOR_REGISTER_COUNT 8 +#elif defined(HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS) && \ + defined(HAVE_GCC_INLINE_ASM_AARCH64_NEON) && \ + (defined(__ARM_FEATURE_SIMD32) || defined(__ARM_NEON)) +# define CLUTTER_VECTOR_REGISTER_AARCH64 1 +# define CLUTTER_VECTOR_REGISTER_COUNT 32 +#elif defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) && \ + defined(HAVE_GCC_INLINE_ASM_NEON) && \ + (defined(__ARM_FEATURE_SIMD32) || defined(__ARM_NEON)) +# define CLUTTER_VECTOR_REGISTER_NEON 1 +# define CLUTTER_VECTOR_REGISTER_COUNT 32 +#endif + + +#ifdef CLUTTER_VECTOR_REGISTER_COUNT +static void +prepare_vector_data(unsigned char data[CLUTTER_VECTOR_REGISTER_COUNT][16]) +{ + static unsigned char basedata[16] = + { + 0xd7, 0xfe, 0x5c, 0x4b, 0x58, 0xfe, 0xf4, 0xb6, + 0xed, 0x2f, 0x31, 0xc9, 0x1d, 0xd3, 0x62, 0x8d + }; + int j, i; + + for (i = 0; i < CLUTTER_VECTOR_REGISTER_COUNT; i++) + { + for (j = 0; j < 16; j++) + { + data[i][j] = basedata[(i + j) % 16]; + } + + for (j = 0; j < 16; j++) + { + basedata[j] -= j; + } + } +} +#endif + + +static inline ALWAYS_INLINE void +clutter_vector_registers(void) +{ +#ifdef CLUTTER_VECTOR_REGISTER_COUNT + unsigned char data[CLUTTER_VECTOR_REGISTER_COUNT][16]; +#if defined(CLUTTER_VECTOR_REGISTER_AARCH64) || \ + defined(CLUTTER_VECTOR_REGISTER_NEON) + static int init; + static int have_neon; + + if (!init) + { + char *string; + + string = gcry_get_config (0, "hwflist"); + if (string) + { + have_neon = (strstr(string, "arm-neon:") != NULL); + xfree(string); + } + init = 1; + } + + if (!have_neon) + return; +#elif defined(CLUTTER_VECTOR_REGISTER_I386) + static int init; + static int have_ssse3; + + if (!init) + { + char *string; + + string = gcry_get_config (0, "hwflist"); + if (string) + { + have_ssse3 = (strstr(string, "intel-ssse3:") != NULL); + xfree(string); + } + init = 1; + } + + if (!have_ssse3) + return; +#endif + + prepare_vector_data(data); + +#if defined(CLUTTER_VECTOR_REGISTER_AMD64) + asm volatile("movdqu %[data0], %%xmm0\n" + "movdqu %[data1], %%xmm1\n" + "movdqu %[data2], %%xmm2\n" + "movdqu %[data3], %%xmm3\n" + "movdqu %[data4], %%xmm4\n" + "movdqu %[data5], %%xmm5\n" + "movdqu %[data6], %%xmm6\n" + "movdqu %[data7], %%xmm7\n" + "movdqu %[data8], %%xmm8\n" + "movdqu %[data9], %%xmm9\n" + "movdqu %[data10], %%xmm10\n" + "movdqu %[data11], %%xmm11\n" + "movdqu %[data12], %%xmm12\n" + "movdqu %[data13], %%xmm13\n" + "movdqu %[data14], %%xmm14\n" + "movdqu %[data15], %%xmm15\n" + : + : [data0] "m" (*data[0]), + [data1] "m" (*data[1]), + [data2] "m" (*data[2]), + [data3] "m" (*data[3]), + [data4] "m" (*data[4]), + [data5] "m" (*data[5]), + [data6] "m" (*data[6]), + [data7] "m" (*data[7]), + [data8] "m" (*data[8]), + [data9] "m" (*data[9]), + [data10] "m" (*data[10]), + [data11] "m" (*data[11]), + [data12] "m" (*data[12]), + [data13] "m" (*data[13]), + [data14] "m" (*data[14]), + [data15] "m" (*data[15]) + : "memory" +#ifdef __SSE2__ + ,"xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", + "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", + "xmm15" +#endif + ); +#elif defined(CLUTTER_VECTOR_REGISTER_I386) + asm volatile("movdqu %[data0], %%xmm0\n" + "movdqu %[data1], %%xmm1\n" + "movdqu %[data2], %%xmm2\n" + "movdqu %[data3], %%xmm3\n" + "movdqu %[data4], %%xmm4\n" + "movdqu %[data5], %%xmm5\n" + "movdqu %[data6], %%xmm6\n" + "movdqu %[data7], %%xmm7\n" + : + : [data0] "m" (*data[0]), + [data1] "m" (*data[1]), + [data2] "m" (*data[2]), + [data3] "m" (*data[3]), + [data4] "m" (*data[4]), + [data5] "m" (*data[5]), + [data6] "m" (*data[6]), + [data7] "m" (*data[7]) + : "memory" +#ifdef __SSE2__ + ,"xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" +#endif + ); +#elif defined(CLUTTER_VECTOR_REGISTER_AARCH64) + asm volatile("mov x0, %[ptr]\n" + "ld1 {v0.16b}, [x0], #16\n" + "ld1 {v1.16b}, [x0], #16\n" + "ld1 {v2.16b}, [x0], #16\n" + "ld1 {v3.16b}, [x0], #16\n" + "ld1 {v4.16b}, [x0], #16\n" + "ld1 {v5.16b}, [x0], #16\n" + "ld1 {v6.16b}, [x0], #16\n" + "ld1 {v7.16b}, [x0], #16\n" + "ld1 {v8.16b}, [x0], #16\n" + "ld1 {v9.16b}, [x0], #16\n" + "ld1 {v10.16b}, [x0], #16\n" + "ld1 {v11.16b}, [x0], #16\n" + "ld1 {v12.16b}, [x0], #16\n" + "ld1 {v13.16b}, [x0], #16\n" + "ld1 {v14.16b}, [x0], #16\n" + "ld1 {v15.16b}, [x0], #16\n" + "ld1 {v16.16b}, [x0], #16\n" + "ld1 {v17.16b}, [x0], #16\n" + "ld1 {v18.16b}, [x0], #16\n" + "ld1 {v19.16b}, [x0], #16\n" + "ld1 {v20.16b}, [x0], #16\n" + "ld1 {v21.16b}, [x0], #16\n" + "ld1 {v22.16b}, [x0], #16\n" + "ld1 {v23.16b}, [x0], #16\n" + "ld1 {v24.16b}, [x0], #16\n" + "ld1 {v25.16b}, [x0], #16\n" + "ld1 {v26.16b}, [x0], #16\n" + "ld1 {v27.16b}, [x0], #16\n" + "ld1 {v28.16b}, [x0], #16\n" + "ld1 {v29.16b}, [x0], #16\n" + "ld1 {v30.16b}, [x0], #16\n" + "ld1 {v31.16b}, [x0], #16\n" + : + : [ptr] "r" (data) + : "x0", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", + "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", + "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", + "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"); +#elif defined(CLUTTER_VECTOR_REGISTER_NEON) + asm volatile("mov r0, %[ptr]\n" + "vld1.64 {q0}, [r0]!\n" + "vld1.64 {q1}, [r0]!\n" + "vld1.64 {q2}, [r0]!\n" + "vld1.64 {q3}, [r0]!\n" + "vld1.64 {q4}, [r0]!\n" + "vld1.64 {q5}, [r0]!\n" + "vld1.64 {q6}, [r0]!\n" + "vld1.64 {q7}, [r0]!\n" + "vld1.64 {q8}, [r0]!\n" + "vld1.64 {q9}, [r0]!\n" + "vld1.64 {q10}, [r0]!\n" + "vld1.64 {q11}, [r0]!\n" + "vld1.64 {q12}, [r0]!\n" + "vld1.64 {q13}, [r0]!\n" + "vld1.64 {q14}, [r0]!\n" + "vld1.64 {q15}, [r0]!\n" + : + : [ptr] "r" (data) + : "r0", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", + "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15"); +#endif + +#endif /* CLUTTER_VECTOR_REGISTER_COUNT */ +} + + + static void check_cbc_mac_cipher (void) { @@ -8280,7 +8515,9 @@ check_bulk_cipher_modes (void) goto leave; } + clutter_vector_registers(); err = gcry_cipher_setkey (hde, tv[i].key, tv[i].keylen); + clutter_vector_registers(); if (!err) err = gcry_cipher_setkey (hdd, tv[i].key, tv[i].keylen); if (err) @@ -8296,7 +8533,9 @@ check_bulk_cipher_modes (void) goto leave; } + clutter_vector_registers(); err = gcry_cipher_setiv (hde, tv[i].iv, tv[i].ivlen); + clutter_vector_registers(); if (!err) err = gcry_cipher_setiv (hdd, tv[i].iv, tv[i].ivlen); if (err) @@ -8309,6 +8548,7 @@ check_bulk_cipher_modes (void) for (j=0; j < buflen; j++) buffer[j] = ((j & 0xff) ^ ((j >> 8) & 0xff)); + clutter_vector_registers(); err = gcry_cipher_encrypt (hde, outbuf, buflen, buffer, buflen); if (err) { @@ -8330,6 +8570,7 @@ check_bulk_cipher_modes (void) fail ("encrypt mismatch (algo %d, mode %d)\n", tv[i].algo, tv[i].mode); + clutter_vector_registers(); err = gcry_cipher_decrypt (hdd, outbuf, buflen, NULL, 0); if (err) { @@ -8409,6 +8650,7 @@ check_one_cipher_core_reset (gcry_cipher_hd_t hd, int algo, int mode, int pass, if (mode == GCRY_CIPHER_MODE_OCB || mode == GCRY_CIPHER_MODE_CCM) { + clutter_vector_registers(); err = gcry_cipher_setiv (hd, iv, sizeof(iv)); if (err) { @@ -8535,6 +8777,7 @@ check_one_cipher_core (int algo, int mode, int flags, goto err_out_free; } + clutter_vector_registers(); err = gcry_cipher_setkey (hd, key, keylen); if (err) { @@ -8547,6 +8790,7 @@ check_one_cipher_core (int algo, int mode, int flags, if (check_one_cipher_core_reset (hd, algo, mode, pass, nplain) < 0) goto err_out_free; + clutter_vector_registers(); err = gcry_cipher_encrypt (hd, out, nplain, plain, nplain); if (err) { @@ -8558,6 +8802,7 @@ check_one_cipher_core (int algo, int mode, int flags, if (taglen > 0) { + clutter_vector_registers(); err = gcry_cipher_gettag (hd, tag, taglen); if (err) { @@ -8575,6 +8820,7 @@ check_one_cipher_core (int algo, int mode, int flags, if (check_one_cipher_core_reset (hd, algo, mode, pass, nplain) < 0) goto err_out_free; + clutter_vector_registers(); err = gcry_cipher_decrypt (hd, in, nplain, out, nplain); if (err) { @@ -8586,6 +8832,7 @@ check_one_cipher_core (int algo, int mode, int flags, if (taglen > 0) { + clutter_vector_registers(); err = gcry_cipher_checktag (hd, tag_result, taglen); if (err) { @@ -8605,6 +8852,7 @@ check_one_cipher_core (int algo, int mode, int flags, goto err_out_free; memcpy (out, plain, nplain); + clutter_vector_registers(); err = gcry_cipher_encrypt (hd, out, nplain, NULL, 0); if (err) { @@ -8639,6 +8887,7 @@ check_one_cipher_core (int algo, int mode, int flags, if (check_one_cipher_core_reset (hd, algo, mode, pass, nplain) < 0) goto err_out_free; + clutter_vector_registers(); err = gcry_cipher_decrypt (hd, out, nplain, NULL, 0); if (err) { @@ -8651,6 +8900,7 @@ check_one_cipher_core (int algo, int mode, int flags, if (taglen > 0) { + clutter_vector_registers(); err = gcry_cipher_checktag (hd, tag_result, taglen); if (err) { @@ -8677,6 +8927,7 @@ check_one_cipher_core (int algo, int mode, int flags, if (piecelen > nplain - pos) piecelen = nplain - pos; + clutter_vector_registers(); err = gcry_cipher_encrypt (hd, out + pos, piecelen, plain + pos, piecelen); if (err) @@ -8694,6 +8945,7 @@ check_one_cipher_core (int algo, int mode, int flags, if (taglen > 0) { + clutter_vector_registers(); err = gcry_cipher_gettag (hd, tag, taglen); if (err) { @@ -8723,6 +8975,7 @@ check_one_cipher_core (int algo, int mode, int flags, if (piecelen > nplain - pos) piecelen = nplain - pos; + clutter_vector_registers(); err = gcry_cipher_decrypt (hd, in + pos, piecelen, out + pos, piecelen); if (err) { @@ -8739,6 +8992,7 @@ check_one_cipher_core (int algo, int mode, int flags, if (taglen > 0) { + clutter_vector_registers(); err = gcry_cipher_checktag (hd, tag_result, taglen); if (err) { @@ -8767,6 +9021,7 @@ check_one_cipher_core (int algo, int mode, int flags, piecelen = nplain - pos; memcpy (out + pos, plain + pos, piecelen); + clutter_vector_registers(); err = gcry_cipher_encrypt (hd, out + pos, piecelen, NULL, 0); if (err) { @@ -8795,6 +9050,7 @@ check_one_cipher_core (int algo, int mode, int flags, if (piecelen > nplain - pos) piecelen = nplain - pos; + clutter_vector_registers(); err = gcry_cipher_decrypt (hd, out + pos, piecelen, NULL, 0); if (err) { @@ -9104,6 +9360,7 @@ check_one_md (int algo, const char *data, int len, const char *expect, int elen, if (key && klen) { + clutter_vector_registers(); err = gcry_md_setkey (hd, key, klen); if (err) { @@ -9131,6 +9388,7 @@ check_one_md (int algo, const char *data, int len, const char *expect, int elen, if (key && klen) { + clutter_vector_registers(); err = gcry_md_setkey (hd2, key, klen); if (err) { @@ -9149,10 +9407,12 @@ check_one_md (int algo, const char *data, int len, const char *expect, int elen, gcry_md_reset (hd); gcry_md_reset (hd2); + clutter_vector_registers(); gcry_md_write (hd, buf, i); for (j = 0; j < i; j++) gcry_md_write (hd2, &buf[j], 1); + clutter_vector_registers(); p1 = gcry_md_read (hd, algo); p2 = gcry_md_read (hd2, algo); if (memcmp (p1, p2, mdlen)) @@ -9196,6 +9456,7 @@ check_one_md (int algo, const char *data, int len, const char *expect, int elen, if (*data == '?') fillbuf_count(aaa, piecelen, 1000 * 1000 - left); + clutter_vector_registers(); gcry_md_write (hd, aaa, piecelen); left -= piecelen; @@ -9212,6 +9473,7 @@ check_one_md (int algo, const char *data, int len, const char *expect, int elen, if (*data == '?') fillbuf_count(aaa, piecelen, 1000 * 1000 - left); + clutter_vector_registers(); gcry_md_write (hd, aaa, piecelen); left -= piecelen; @@ -9223,8 +9485,12 @@ check_one_md (int algo, const char *data, int len, const char *expect, int elen, } } else - gcry_md_write (hd, data, len); + { + clutter_vector_registers(); + gcry_md_write (hd, data, len); + } + clutter_vector_registers(); err = gcry_md_copy (&hd2, hd); if (err) { @@ -9235,6 +9501,7 @@ check_one_md (int algo, const char *data, int len, const char *expect, int elen, if (!xof) { + clutter_vector_registers(); p = gcry_md_read (hd2, algo); if (memcmp (p, expect, mdlen)) @@ -9255,12 +9522,14 @@ check_one_md (int algo, const char *data, int len, const char *expect, int elen, char buf[1000]; int outmax = sizeof(buf) > elen ? elen : sizeof(buf); + clutter_vector_registers(); err = gcry_md_copy (&hd, hd2); if (err) { fail ("algo %d, gcry_md_copy failed: %s\n", algo, gpg_strerror (err)); } + clutter_vector_registers(); err = gcry_md_extract(hd2, algo, buf, outmax); if (err) { @@ -9283,6 +9552,7 @@ check_one_md (int algo, const char *data, int len, const char *expect, int elen, memset(buf, 0, sizeof(buf)); /* Extract one byte at time. */ + clutter_vector_registers(); for (i = 0; i < outmax && !err; i++) err = gcry_md_extract(hd, algo, &buf[i], 1); if (err) @@ -9334,6 +9604,7 @@ check_one_md (int algo, const char *data, int len, const char *expect, int elen, /* Extract large chucks, total 1000000 additional bytes. */ for (i = 0; i < 1000; i++) { + clutter_vector_registers(); err = gcry_md_extract(hd, algo, buf, 1000); if (!err) gcry_md_write(crc1, buf, 1000); @@ -9356,6 +9627,7 @@ check_one_md (int algo, const char *data, int len, const char *expect, int elen, if (piecelen > left) piecelen = left; + clutter_vector_registers(); err = gcry_md_extract (hd2, algo, buf, piecelen); if (!err) gcry_md_write(crc2, buf, piecelen); @@ -9373,7 +9645,9 @@ check_one_md (int algo, const char *data, int len, const char *expect, int elen, piecelen = piecelen * 2 - ((piecelen != startlen) ? startlen : 0); } + clutter_vector_registers(); p1 = gcry_md_read (crc1, crcalgo); + clutter_vector_registers(); p2 = gcry_md_read (crc2, crcalgo); if (memcmp (p1, p2, crclen)) @@ -9449,6 +9723,7 @@ check_one_md_multi (int algo, const char *data, int len, const char *expect) iovcnt++; assert (iovcnt <= DIM (iov)); + clutter_vector_registers(); err = gcry_md_hash_buffers (algo, 0, digest, iov, iovcnt); if (err) { @@ -9498,6 +9773,7 @@ check_one_md_final(int algo, const char *expect, unsigned int expectlen) for (i = 0; i < sizeof(inbuf); i++) inbuf[i] = i; + clutter_vector_registers(); gcry_md_hash_buffer (algo, xorbuf, NULL, 0); for (i = 1; i < sizeof(inbuf); i++) { @@ -11336,6 +11612,7 @@ check_one_mac (int algo, const char *data, int datalen, return; } + clutter_vector_registers(); err = gcry_mac_setkey (hd, key, keylen); if (err) fail("algo %d, mac gcry_mac_setkey failed: %s\n", algo, gpg_strerror (err)); @@ -11344,6 +11621,7 @@ check_one_mac (int algo, const char *data, int datalen, if (ivlen && iv) { + clutter_vector_registers(); err = gcry_mac_setiv (hd, iv, ivlen); if (err) fail("algo %d, mac gcry_mac_ivkey failed: %s\n", algo, @@ -11356,6 +11634,7 @@ check_one_mac (int algo, const char *data, int datalen, { for (i = 0; i < datalen; i++) { + clutter_vector_registers(); err = gcry_mac_write (hd, &data[i], 1); if (err) fail("algo %d, mac gcry_mac_write [buf-offset: %d] failed: %s\n", @@ -11389,6 +11668,7 @@ check_one_mac (int algo, const char *data, int datalen, if (*data == '?') fillbuf_count(aaa, piecelen, 1000 * 1000 - left); + clutter_vector_registers(); gcry_mac_write (hd, aaa, piecelen); left -= piecelen; @@ -11405,6 +11685,7 @@ check_one_mac (int algo, const char *data, int datalen, if (*data == '?') fillbuf_count(aaa, piecelen, 1000 * 1000 - left); + clutter_vector_registers(); gcry_mac_write (hd, aaa, piecelen); left -= piecelen; @@ -11417,6 +11698,7 @@ check_one_mac (int algo, const char *data, int datalen, } else { + clutter_vector_registers(); err = gcry_mac_write (hd, data, datalen); } @@ -11426,11 +11708,13 @@ check_one_mac (int algo, const char *data, int datalen, goto out; } + clutter_vector_registers(); err = gcry_mac_verify (hd, expect, maclen); if (err) fail("algo %d, mac gcry_mac_verify failed: %s\n", algo, gpg_strerror (err)); macoutlen = maclen; + clutter_vector_registers(); err = gcry_mac_read (hd, p, &macoutlen); if (err) fail("algo %d, mac gcry_mac_read failed: %s\n", algo, gpg_strerror (err)); From jussi.kivilinna at iki.fi Sun Jan 19 09:40:54 2020 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sun, 19 Jan 2020 10:40:54 +0200 Subject: [PATCH] Set vZZ.16b register to zero before use in armv8 gcm implementation Message-ID: <157942325445.11414.4589880665999427915.stgit@localhost6.localdomain6> * cipher/cipher-gcm-armv8-aarch64-ce.S (_gcry_ghash_setup_armv8_ce_pmull): Set vZZ to zero. -- Reported by: Marvin W. @ https://dev.gnupg.org/D497: > > The register vZZ.16b is expected to be always 0 throughout the macros > in cipher/cipher-gcm-armv8-aarch64-ce.S. The PMUL_128x128 and REDUCTION > macros are used in gcry_ghash_setup_armv8_ce_pmull function, however that > function does not set vZZ.16b to zero. If previous use left `vZZ.16b > non-zero before gcry_ghash_setup_armv8_ce_pmull is called, this will cause > invalid GCM auth tag results. > > The patch resets vZZ.16b to 0 at the beginning of > gcry_ghash_setup_armv8_ce_pmull. Signed-off-by: Jussi Kivilinna --- 0 files changed diff --git a/cipher/cipher-gcm-armv8-aarch64-ce.S b/cipher/cipher-gcm-armv8-aarch64-ce.S index b0c2cccc6..877207d3e 100644 --- a/cipher/cipher-gcm-armv8-aarch64-ce.S +++ b/cipher/cipher-gcm-armv8-aarch64-ce.S @@ -385,6 +385,8 @@ _gcry_ghash_setup_armv8_ce_pmull: GET_DATA_POINTER(x2, .Lrconst) + eor vZZ.16b, vZZ.16b, vZZ.16b + /* H? */ ld1 {rh1.16b}, [x0] rbit rh1.16b, rh1.16b From jussi.kivilinna at iki.fi Sun Jan 19 10:03:13 2020 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sun, 19 Jan 2020 11:03:13 +0200 Subject: [PATCH] Fix three errors for ec algorithm In-Reply-To: <87blrdbkfv.fsf@jumper.gniibe.org> References: <20191222091533.2587-1-tianjia.zhang@linux.alibaba.com> <87blrdbkfv.fsf@jumper.gniibe.org> Message-ID: On 9.1.2020 1.24, NIIBE Yutaka wrote: > Hello, > > Jussi Kivilinna via Gcrypt-devel wrote: >> Thanks for your contributions. I'll leave some comments on the patches >> in few days but it would be better if someone more familiar with >> MPI/EC side of gcrypt checks the patches too. > > Acked by me for: > [PATCH 1/3] Update .gitignore > [PATCH v2] mpi: Fix error that point not uninitialized > [PATCH 3/3] ecc: Wrong flag and elements_enc fix. > I've applied these now. -Jussi From jussi.kivilinna at iki.fi Sun Jan 19 10:20:58 2020 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sun, 19 Jan 2020 11:20:58 +0200 Subject: [PATCH 0/4] x86: Enable Intel Control-flow Enforcement Technology (CET) In-Reply-To: <20200117172956.3299-1-hjl.tools@gmail.com> References: <20200117172956.3299-1-hjl.tools@gmail.com> Message-ID: <8609b8e0-3fbf-a9ed-2e85-9af19b819396@iki.fi> Hello, On 17.1.2020 19.29, H.J. Lu via Gcrypt-devel wrote: > Intel Control-flow Enforcement Technology (CET): > > https://software.intel.com/en-us/articles/intel-sdm > > contains shadow stack (SHSTK) and indirect branch tracking (IBT). When > CET is enabled, ELF object files must be marked with .note.gnu.property > section. CET enabled compiler provides which can be included > in assembly sources to automatically generate .note.gnu.property section. > Also when IBT is enabled, all indirect branch targets must start with > ENDBR instruction. defines _CET_ENDBR to generate proper ENDBR > instruction. Thanks for your contribution. I've few generic comments. First, we need your signed DCO, please check 'License policy' in docs/HACKING. In each patch, commit log should start with ChangeLog entries without leading TABs followed by separator line with -- and then commit message. Check git history for examples. -Jussi > > Tested with > > $ CC="gcc -Wl,-z,cet-report=error -fcf-protection" ./configure > > in i686 and x86-64 modes on Linux CET machine. > > H.J. Lu (4): > x86: Add .note.gnu.property section for Intel CET > mpi: Add .note.gnu.property section for Intel CET > amd64: Always include in cipher assembly codes > i386: Add _CET_ENDBR to indirect jump targets > > cipher/camellia-aesni-avx-amd64.S | 3 ++- > cipher/camellia-aesni-avx2-amd64.S | 3 ++- > cipher/serpent-avx2-amd64.S | 3 ++- > configure.ac | 6 +++++ > mpi/config.links | 10 +++++++++ > mpi/i386/mpih-add1.S | 35 ++++++++++++++++++++++++++++++ > mpi/i386/mpih-sub1.S | 35 ++++++++++++++++++++++++++++++ > 7 files changed, 92 insertions(+), 3 deletions(-) > From jussi.kivilinna at iki.fi Sun Jan 19 10:22:52 2020 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sun, 19 Jan 2020 11:22:52 +0200 Subject: [PATCH 4/4] i386: Add _CET_ENDBR to indirect jump targets In-Reply-To: <20200117172956.3299-5-hjl.tools@gmail.com> References: <20200117172956.3299-1-hjl.tools@gmail.com> <20200117172956.3299-5-hjl.tools@gmail.com> Message-ID: Hello, On 17.1.2020 19.29, H.J. Lu via Gcrypt-devel wrote: > i386 mpih-add1.S and mpih-sub1.S use a trick to implment jump tables > with LEA. We can't use conditional branches nor normal jump tables > since jump table entries use EFLAGS set by jump table index. This > patch adds _CET_ENDBR to indirect jump targets and adjust destination > for _CET_ENDBR. > > * mpi/i386/mpih-add1.S (_gcry_mpih_add_n): Save and restore > %ebx if IBT is enabed. Add _CET_ENDBR to indirect jump targets > and adjust jump destination for _CET_ENDBR. > * mpi/i386/mpih-sub1.S (_gcry_mpih_sub_n): Likewise. > > Signed-off-by: H.J. Lu > --- > mpi/i386/mpih-add1.S | 35 +++++++++++++++++++++++++++++++++++ > mpi/i386/mpih-sub1.S | 35 +++++++++++++++++++++++++++++++++++ > 2 files changed, 70 insertions(+) > > diff --git a/mpi/i386/mpih-add1.S b/mpi/i386/mpih-add1.S > index 32091f34..ef6423d9 100644 > --- a/mpi/i386/mpih-add1.S > +++ b/mpi/i386/mpih-add1.S > @@ -55,6 +55,10 @@ C_SYMBOL_NAME(_gcry_mpih_add_n:) > movl 20(%esp),%edx /* s2_ptr */ > movl 24(%esp),%ecx /* size */ > > +#if defined __CET__ && (__CET__ & 1) != 0 > + pushl %ebx Please add CFI_PUSH(%ebx) after each pushl and also CFI_POP after popl. -Jussi From hjl.tools at gmail.com Sun Jan 19 14:52:41 2020 From: hjl.tools at gmail.com (H.J. Lu) Date: Sun, 19 Jan 2020 05:52:41 -0800 Subject: Signed DCO from H.J. Lu Message-ID: <20200119135241.GA4970@gmail.com> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 Libgcrypt Developer's Certificate of Origin. Version 1.0 ========================================================= By making a contribution to the Libgcrypt project, I certify that: (a) The contribution was created in whole or in part by me and I have the right to submit it under the free software license indicated in the file; or (b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate free software license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same free software license (unless I am permitted to submit under a different license), as indicated in the file; or (c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it. (d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the free software license(s) involved. Signed-off-by: H.J. Lu -----BEGIN PGP SIGNATURE----- iQIzBAEBCAAdFiEESBcVW22D4/86TifArSdE7lgCU5YFAl4kXq4ACgkQrSdE7lgC U5beXA/9GxlorLfHT0mSP7kMlu57Yj+kpRtY6Xy2GOT5z9VapFsG7NEVEr6d+Md7 ZcXKfl4a2hGk0ePWp0KTXzmbL+E/d8NVRA/PqRE7UPJz20Wv6oXtj1PALoRiUUe7 VbWXDJmdOSvFni3koYZs7vUgXd0hZL5igEXeoyxiiB/4YV6b9/O2IdEIVDV66Ia5 UY9vIfL0COEEpiVG5oui9Dg6yo6StFaMGloKfdT/bAb86jChU5XuP7onJN219lkP yyXn72qUZChRLs/QFooNrMIQ1VmSfeR4LEISInCGmkoCpfleHCAOX8zdsExqUIR6 qioM3n/jBmzOmuZNbcsNxRpWfV9lLmxO9DE1lwtVof4E3sdQ3QZVr51Ech8H+MWI Ph+6MUEP4laRpKcORDp0Bcs8jk3ugbMSQ2ycJleQ/9fUhNKRdjC84Vtv6AYouqAQ DX0MIp7vy6e+b09YwrNZwbrSlCpN9wlJSIS0XmZiXCP7t+OHITlLpxvdLbviB7Ik L+vtYJIJO29cyLPVtkKGmdEcGIBGGBtlA1E6N+Ns0a3IU4VigAFj8Fj5Q+cTPGC/ lgkbXN/sTO1JffHvRSC2vR9pEekymuG4xJvek7kdbSUerVLvuJvJ+DZCIkGOEtTZ vE/J9ypoSyujNTz2200dH47Xv/0+W88Mcocqaeid5DP39vqX/7M= =+aeI -----END PGP SIGNATURE----- From hjl.tools at gmail.com Sun Jan 19 15:40:24 2020 From: hjl.tools at gmail.com (H.J. Lu) Date: Sun, 19 Jan 2020 06:40:24 -0800 Subject: V2 [PATCH 3/4] amd64: Always include in cipher assembly codes In-Reply-To: <20200119144025.6551-1-hjl.tools@gmail.com> References: <20200119144025.6551-1-hjl.tools@gmail.com> Message-ID: <20200119144025.6551-4-hjl.tools@gmail.com> * cipher/camellia-aesni-avx-amd64.S: Always include . * cipher/camellia-aesni-avx2-amd64.S: Likewise. * cipher/serpent-avx2-amd64.S: Likewise. -- When Intel CET is enabled, we need to include in assembly codes to mark Intel CET support even if it is empty. We should always include in cipher amd64 assembly codes so that they will be marked for Intel CET support when compiling for i686. Signed-off-by: H.J. Lu --- cipher/camellia-aesni-avx-amd64.S | 3 ++- cipher/camellia-aesni-avx2-amd64.S | 3 ++- cipher/serpent-avx2-amd64.S | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/cipher/camellia-aesni-avx-amd64.S b/cipher/camellia-aesni-avx-amd64.S index e16d4f61..4671bcfe 100644 --- a/cipher/camellia-aesni-avx-amd64.S +++ b/cipher/camellia-aesni-avx-amd64.S @@ -18,8 +18,9 @@ * License along with this program; if not, see . */ -#ifdef __x86_64 #include + +#ifdef __x86_64 #if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \ defined(ENABLE_AESNI_SUPPORT) && defined(ENABLE_AVX_SUPPORT) diff --git a/cipher/camellia-aesni-avx2-amd64.S b/cipher/camellia-aesni-avx2-amd64.S index cc01c774..517e6880 100644 --- a/cipher/camellia-aesni-avx2-amd64.S +++ b/cipher/camellia-aesni-avx2-amd64.S @@ -18,8 +18,9 @@ * License along with this program; if not, see . */ -#ifdef __x86_64 #include + +#ifdef __x86_64 #if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \ defined(ENABLE_AESNI_SUPPORT) && defined(ENABLE_AVX2_SUPPORT) diff --git a/cipher/serpent-avx2-amd64.S b/cipher/serpent-avx2-amd64.S index 9b17c2bd..dcee9b62 100644 --- a/cipher/serpent-avx2-amd64.S +++ b/cipher/serpent-avx2-amd64.S @@ -18,8 +18,9 @@ * License along with this program; if not, see . */ -#ifdef __x86_64 #include + +#ifdef __x86_64 #if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && defined(USE_SERPENT) && \ defined(ENABLE_AVX2_SUPPORT) -- 2.24.1 From hjl.tools at gmail.com Sun Jan 19 15:40:21 2020 From: hjl.tools at gmail.com (H.J. Lu) Date: Sun, 19 Jan 2020 06:40:21 -0800 Subject: V2 [PATCH 0/4] x86: Enable Intel Control-flow Enforcement Technology (CET) Message-ID: <20200119144025.6551-1-hjl.tools@gmail.com> Intel Control-flow Enforcement Technology (CET): https://software.intel.com/en-us/articles/intel-sdm contains shadow stack (SHSTK) and indirect branch tracking (IBT). When CET is enabled, ELF object files must be marked with .note.gnu.property section. CET enabled compiler provides which can be included in assembly sources to automatically generate .note.gnu.property section. Also when IBT is enabled, all indirect branch targets must start with ENDBR instruction. defines _CET_ENDBR to generate proper ENDBR instruction. Tested with $ CC="gcc -Wl,-z,cet-report=error -fcf-protection" ./configure in i686 and x86-64 modes on Linux CET machine. H.J. Lu (4): x86: Add .note.gnu.property section for Intel CET mpi: Add .note.gnu.property section for Intel CET amd64: Always include in cipher assembly codes i386: Add _CET_ENDBR to indirect jump targets cipher/camellia-aesni-avx-amd64.S | 3 ++- cipher/camellia-aesni-avx2-amd64.S | 3 ++- cipher/serpent-avx2-amd64.S | 3 ++- configure.ac | 6 +++++ mpi/config.links | 10 ++++++++ mpi/i386/mpih-add1.S | 37 ++++++++++++++++++++++++++++++ mpi/i386/mpih-sub1.S | 37 ++++++++++++++++++++++++++++++ 7 files changed, 96 insertions(+), 3 deletions(-) -- 2.24.1 From hjl.tools at gmail.com Sun Jan 19 15:40:23 2020 From: hjl.tools at gmail.com (H.J. Lu) Date: Sun, 19 Jan 2020 06:40:23 -0800 Subject: V2 [PATCH 2/4] mpi: Add .note.gnu.property section for Intel CET In-Reply-To: <20200119144025.6551-1-hjl.tools@gmail.com> References: <20200119144025.6551-1-hjl.tools@gmail.com> Message-ID: <20200119144025.6551-3-hjl.tools@gmail.com> * mpi/config.links: Include in . -- When Intel CET is enabled, include in for assembly codes to mark Intel CET support. Signed-off-by: H.J. Lu --- mpi/config.links | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/mpi/config.links b/mpi/config.links index 3ead4f08..4f43b732 100644 --- a/mpi/config.links +++ b/mpi/config.links @@ -382,6 +382,16 @@ if test x"$mpi_cpu_arch" = x ; then mpi_cpu_arch="unknown" fi +# Add .note.gnu.property section for Intel CET in assembler sources +# when CET is enabled. */ +if test x"$mpi_cpu_arch" = xx86 ; then + cat <> ./mpi/asm-syntax.h + +#if defined(__ASSEMBLER__) && defined(__CET__) +# include +#endif +EOF +fi # Make sysdep.h echo '/* created by config.links - do not edit */' >./mpi/sysdep.h -- 2.24.1 From hjl.tools at gmail.com Sun Jan 19 15:40:22 2020 From: hjl.tools at gmail.com (H.J. Lu) Date: Sun, 19 Jan 2020 06:40:22 -0800 Subject: V2 [PATCH 1/4] x86: Add .note.gnu.property section for Intel CET In-Reply-To: <20200119144025.6551-1-hjl.tools@gmail.com> References: <20200119144025.6551-1-hjl.tools@gmail.com> Message-ID: <20200119144025.6551-2-hjl.tools@gmail.com> * configure.ac: Include in for assembly codes. -- When Intel CET is enabled, include in for assembly codes to mark Intel CET support. Signed-off-by: H.J. Lu --- configure.ac | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/configure.ac b/configure.ac index 4d4fb49a..c3bcd74d 100644 --- a/configure.ac +++ b/configure.ac @@ -97,6 +97,12 @@ AH_TOP([ AH_BOTTOM([ #define _GCRYPT_IN_LIBGCRYPT 1 +/* Add .note.gnu.property section for Intel CET in assembler sources + when CET is enabled. */ +#if defined(__ASSEMBLER__) && defined(__CET__) +# include +#endif + /* If the configure check for endianness has been disabled, get it from OS macros. This is intended for making fat binary builds on OS X. */ #ifdef DISABLED_ENDIAN_CHECK -- 2.24.1 From hjl.tools at gmail.com Sun Jan 19 15:40:25 2020 From: hjl.tools at gmail.com (H.J. Lu) Date: Sun, 19 Jan 2020 06:40:25 -0800 Subject: V2 [PATCH 4/4] i386: Add _CET_ENDBR to indirect jump targets In-Reply-To: <20200119144025.6551-1-hjl.tools@gmail.com> References: <20200119144025.6551-1-hjl.tools@gmail.com> Message-ID: <20200119144025.6551-5-hjl.tools@gmail.com> * mpi/i386/mpih-add1.S (_gcry_mpih_add_n): Save and restore %ebx if IBT is enabed. Add _CET_ENDBR to indirect jump targets and adjust jump destination for _CET_ENDBR. * mpi/i386/mpih-sub1.S (_gcry_mpih_sub_n): Likewise. -- i386 mpih-add1.S and mpih-sub1.S use a trick to implment jump tables with LEA. We can't use conditional branches nor normal jump tables since jump table entries use EFLAGS set by jump table index. This patch adds _CET_ENDBR to indirect jump targets and adjust destination for _CET_ENDBR. Signed-off-by: H.J. Lu --- mpi/i386/mpih-add1.S | 37 +++++++++++++++++++++++++++++++++++++ mpi/i386/mpih-sub1.S | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/mpi/i386/mpih-add1.S b/mpi/i386/mpih-add1.S index 32091f34..2f1ae931 100644 --- a/mpi/i386/mpih-add1.S +++ b/mpi/i386/mpih-add1.S @@ -55,6 +55,11 @@ C_SYMBOL_NAME(_gcry_mpih_add_n:) movl 20(%esp),%edx /* s2_ptr */ movl 24(%esp),%ecx /* size */ +#if defined __CET__ && (__CET__ & 1) != 0 + pushl %ebx + CFI_PUSH(%ebx) +#endif + movl %ecx,%eax shrl $3,%ecx /* compute count for unrolled loop */ negl %eax @@ -66,6 +71,9 @@ C_SYMBOL_NAME(_gcry_mpih_add_n:) subl %eax,%esi /* ... by a constant when we ... */ subl %eax,%edx /* ... enter the loop */ shrl $2,%eax /* restore previous value */ +#if defined __CET__ && (__CET__ & 1) != 0 + leal -4(,%eax,4),%ebx /* Count for 4-byte endbr32 */ +#endif #ifdef PIC /* Calculate start address in loop for PIC. Due to limitations in some assemblers, Loop-L0-3 cannot be put into the leal */ @@ -77,30 +85,54 @@ L0: leal (%eax,%eax,8),%eax #else /* Calculate start address in loop for non-PIC. */ leal (Loop - 3)(%eax,%eax,8),%eax +#endif +#if defined __CET__ && (__CET__ & 1) != 0 + addl %ebx,%eax /* Adjust for endbr32 */ #endif jmp *%eax /* jump into loop */ ALIGN (3) Loop: movl (%esi),%eax adcl (%edx),%eax movl %eax,(%edi) +#ifdef _CET_ENDBR + _CET_ENDBR +#endif movl 4(%esi),%eax adcl 4(%edx),%eax movl %eax,4(%edi) +#ifdef _CET_ENDBR + _CET_ENDBR +#endif movl 8(%esi),%eax adcl 8(%edx),%eax movl %eax,8(%edi) +#ifdef _CET_ENDBR + _CET_ENDBR +#endif movl 12(%esi),%eax adcl 12(%edx),%eax movl %eax,12(%edi) +#ifdef _CET_ENDBR + _CET_ENDBR +#endif movl 16(%esi),%eax adcl 16(%edx),%eax movl %eax,16(%edi) +#ifdef _CET_ENDBR + _CET_ENDBR +#endif movl 20(%esi),%eax adcl 20(%edx),%eax movl %eax,20(%edi) +#ifdef _CET_ENDBR + _CET_ENDBR +#endif movl 24(%esi),%eax adcl 24(%edx),%eax movl %eax,24(%edi) +#ifdef _CET_ENDBR + _CET_ENDBR +#endif movl 28(%esi),%eax adcl 28(%edx),%eax movl %eax,28(%edi) @@ -113,6 +145,11 @@ Loop: movl (%esi),%eax sbbl %eax,%eax negl %eax +#if defined __CET__ && (__CET__ & 1) != 0 + popl %ebx + CFI_POP(%ebx) +#endif + popl %esi CFI_POP(%esi) popl %edi diff --git a/mpi/i386/mpih-sub1.S b/mpi/i386/mpih-sub1.S index 501c4a9f..01e977e5 100644 --- a/mpi/i386/mpih-sub1.S +++ b/mpi/i386/mpih-sub1.S @@ -56,6 +56,11 @@ C_SYMBOL_NAME(_gcry_mpih_sub_n:) movl 20(%esp),%edx /* s2_ptr */ movl 24(%esp),%ecx /* size */ +#if defined __CET__ && (__CET__ & 1) != 0 + pushl %ebx + CFI_PUSH(%ebx) +#endif + movl %ecx,%eax shrl $3,%ecx /* compute count for unrolled loop */ negl %eax @@ -67,6 +72,9 @@ C_SYMBOL_NAME(_gcry_mpih_sub_n:) subl %eax,%esi /* ... by a constant when we ... */ subl %eax,%edx /* ... enter the loop */ shrl $2,%eax /* restore previous value */ +#if defined __CET__ && (__CET__ & 1) != 0 + leal -4(,%eax,4),%ebx /* Count for 4-byte endbr32 */ +#endif #ifdef PIC /* Calculate start address in loop for PIC. Due to limitations in some assemblers, Loop-L0-3 cannot be put into the leal */ @@ -78,30 +86,54 @@ L0: leal (%eax,%eax,8),%eax #else /* Calculate start address in loop for non-PIC. */ leal (Loop - 3)(%eax,%eax,8),%eax +#endif +#if defined __CET__ && (__CET__ & 1) != 0 + addl %ebx,%eax /* Adjust for endbr32 */ #endif jmp *%eax /* jump into loop */ ALIGN (3) Loop: movl (%esi),%eax sbbl (%edx),%eax movl %eax,(%edi) +#ifdef _CET_ENDBR + _CET_ENDBR +#endif movl 4(%esi),%eax sbbl 4(%edx),%eax movl %eax,4(%edi) +#ifdef _CET_ENDBR + _CET_ENDBR +#endif movl 8(%esi),%eax sbbl 8(%edx),%eax movl %eax,8(%edi) +#ifdef _CET_ENDBR + _CET_ENDBR +#endif movl 12(%esi),%eax sbbl 12(%edx),%eax movl %eax,12(%edi) +#ifdef _CET_ENDBR + _CET_ENDBR +#endif movl 16(%esi),%eax sbbl 16(%edx),%eax movl %eax,16(%edi) +#ifdef _CET_ENDBR + _CET_ENDBR +#endif movl 20(%esi),%eax sbbl 20(%edx),%eax movl %eax,20(%edi) +#ifdef _CET_ENDBR + _CET_ENDBR +#endif movl 24(%esi),%eax sbbl 24(%edx),%eax movl %eax,24(%edi) +#ifdef _CET_ENDBR + _CET_ENDBR +#endif movl 28(%esi),%eax sbbl 28(%edx),%eax movl %eax,28(%edi) @@ -114,6 +146,11 @@ Loop: movl (%esi),%eax sbbl %eax,%eax negl %eax +#if defined __CET__ && (__CET__ & 1) != 0 + popl %ebx + CFI_POP(%ebx) +#endif + popl %esi CFI_POP(%esi) popl %edi -- 2.24.1 From hjl.tools at gmail.com Sun Jan 19 15:42:21 2020 From: hjl.tools at gmail.com (H.J. Lu) Date: Sun, 19 Jan 2020 06:42:21 -0800 Subject: [PATCH 0/4] x86: Enable Intel Control-flow Enforcement Technology (CET) In-Reply-To: <8609b8e0-3fbf-a9ed-2e85-9af19b819396@iki.fi> References: <20200117172956.3299-1-hjl.tools@gmail.com> <8609b8e0-3fbf-a9ed-2e85-9af19b819396@iki.fi> Message-ID: On Sun, Jan 19, 2020 at 1:20 AM Jussi Kivilinna wrote: > > Hello, > > On 17.1.2020 19.29, H.J. Lu via Gcrypt-devel wrote: > > Intel Control-flow Enforcement Technology (CET): > > > > https://software.intel.com/en-us/articles/intel-sdm > > > > contains shadow stack (SHSTK) and indirect branch tracking (IBT). When > > CET is enabled, ELF object files must be marked with .note.gnu.property > > section. CET enabled compiler provides which can be included > > in assembly sources to automatically generate .note.gnu.property section. > > Also when IBT is enabled, all indirect branch targets must start with > > ENDBR instruction. defines _CET_ENDBR to generate proper ENDBR > > instruction. > > Thanks for your contribution. I've few generic comments. > > First, we need your signed DCO, please check 'License policy' in docs/HACKING. Done: https://lists.gnupg.org/pipermail/gcrypt-devel/2020-January/004889.html > In each patch, commit log should start with ChangeLog entries without leading > TABs followed by separator line with -- and then commit message. Check git > history for examples. > Done: https://lists.gnupg.org/pipermail/gcrypt-devel/2020-January/004891.html Thanks. -- H.J. From hjl.tools at gmail.com Sun Jan 19 15:42:56 2020 From: hjl.tools at gmail.com (H.J. Lu) Date: Sun, 19 Jan 2020 06:42:56 -0800 Subject: [PATCH 4/4] i386: Add _CET_ENDBR to indirect jump targets In-Reply-To: References: <20200117172956.3299-1-hjl.tools@gmail.com> <20200117172956.3299-5-hjl.tools@gmail.com> Message-ID: On Sun, Jan 19, 2020 at 1:22 AM Jussi Kivilinna wrote: > > Hello, > > On 17.1.2020 19.29, H.J. Lu via Gcrypt-devel wrote: > > i386 mpih-add1.S and mpih-sub1.S use a trick to implment jump tables > > with LEA. We can't use conditional branches nor normal jump tables > > since jump table entries use EFLAGS set by jump table index. This > > patch adds _CET_ENDBR to indirect jump targets and adjust destination > > for _CET_ENDBR. > > > > * mpi/i386/mpih-add1.S (_gcry_mpih_add_n): Save and restore > > %ebx if IBT is enabed. Add _CET_ENDBR to indirect jump targets > > and adjust jump destination for _CET_ENDBR. > > * mpi/i386/mpih-sub1.S (_gcry_mpih_sub_n): Likewise. > > > > Signed-off-by: H.J. Lu > > --- > > mpi/i386/mpih-add1.S | 35 +++++++++++++++++++++++++++++++++++ > > mpi/i386/mpih-sub1.S | 35 +++++++++++++++++++++++++++++++++++ > > 2 files changed, 70 insertions(+) > > > > diff --git a/mpi/i386/mpih-add1.S b/mpi/i386/mpih-add1.S > > index 32091f34..ef6423d9 100644 > > --- a/mpi/i386/mpih-add1.S > > +++ b/mpi/i386/mpih-add1.S > > @@ -55,6 +55,10 @@ C_SYMBOL_NAME(_gcry_mpih_add_n:) > > movl 20(%esp),%edx /* s2_ptr */ > > movl 24(%esp),%ecx /* size */ > > > > +#if defined __CET__ && (__CET__ & 1) != 0 > > + pushl %ebx > > Please add CFI_PUSH(%ebx) after each pushl and also CFI_POP after popl. > Done: https://lists.gnupg.org/pipermail/gcrypt-devel/2020-January/004894.html -- H.J. From tianjia.zhang at linux.alibaba.com Mon Jan 20 04:31:53 2020 From: tianjia.zhang at linux.alibaba.com (Tianjia Zhang) Date: Mon, 20 Jan 2020 11:31:53 +0800 Subject: [PATCH] tests: Fix typo missing commas Message-ID: <20200120033153.111736-1-tianjia.zhang@linux.alibaba.com> * tests/basic.c: Add missing commas. -- Signed-off-by: Tianjia Zhang --- tests/basic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/basic.c b/tests/basic.c index 8337bcfb..2a41fb82 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -13246,7 +13246,7 @@ check_pubkey (void) " 4DDFF75C45415C1D9DD9DD33612CD530EFE137C7C90CD4" " 0B0F5621DC3AC1B751CFA0E2634FA0503B3D52639F5D7F" " B72AFD61EA199441D943FFE7F0C70A2759A3CDB84C114E" - " 1F9339FDF27F35ECA93677BEEC#)))\n" + " 1F9339FDF27F35ECA93677BEEC#)))\n", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" } @@ -13268,7 +13268,7 @@ check_pubkey (void) " (curve secp256k1)\n" " (q #0439A36013301597DAEF41FBE593A02CC513D0B55527EC2D" " F1050E2E8FF49C85C23CBE7DED0E7CE6A594896B8F62888F" - " DBC5C8821305E2EA42BF01E37300116281#)))\n" + " DBC5C8821305E2EA42BF01E37300116281#)))\n", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" } -- 2.17.1 From tianjia.zhang at linux.alibaba.com Mon Jan 20 04:35:28 2020 From: tianjia.zhang at linux.alibaba.com (Tianjia Zhang) Date: Mon, 20 Jan 2020 11:35:28 +0800 Subject: [PATCH] ecc: Simplify signature code Message-ID: <20200120033528.111815-1-tianjia.zhang@linux.alibaba.com> * cipher/ecc-gost.c (_gcry_ecc_gost_sign): Use implemented function. * cipher/ecc.c (ecc_verify): Remove redundant code. -- Signed-off-by: Tianjia Zhang --- cipher/ecc-gost.c | 18 ++++-------------- cipher/ecc.c | 22 +--------------------- 2 files changed, 5 insertions(+), 35 deletions(-) diff --git a/cipher/ecc-gost.c b/cipher/ecc-gost.c index e9dfc597..44654a47 100644 --- a/cipher/ecc-gost.c +++ b/cipher/ecc-gost.c @@ -45,8 +45,7 @@ _gcry_ecc_gost_sign (gcry_mpi_t input, mpi_ec_t ec, gcry_mpi_t k, dr, sum, ke, x, e; mpi_point_struct I; gcry_mpi_t hash; - const void *abuf; - unsigned int abits, qbits; + unsigned int qbits; if (DBG_CIPHER) log_mpidump ("gost sign hash ", input ); @@ -54,18 +53,9 @@ _gcry_ecc_gost_sign (gcry_mpi_t input, mpi_ec_t ec, qbits = mpi_get_nbits (ec->n); /* Convert the INPUT into an MPI if needed. */ - if (mpi_is_opaque (input)) - { - abuf = mpi_get_opaque (input, &abits); - rc = _gcry_mpi_scan (&hash, GCRYMPI_FMT_USG, abuf, (abits+7)/8, NULL); - if (rc) - return rc; - if (abits > qbits) - mpi_rshift (hash, hash, abits - qbits); - } - else - hash = input; - + rc = _gcry_dsa_normalize_hash (input, &hash, qbits); + if (rc) + return rc; k = NULL; dr = mpi_alloc (0); diff --git a/cipher/ecc.c b/cipher/ecc.c index 10e11243..1195f5ec 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -813,27 +813,7 @@ ecc_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms) } else { - if (mpi_is_opaque (data)) - { - const void *abuf; - unsigned int abits, qbits; - gcry_mpi_t a; - - qbits = mpi_get_nbits (ec->n); - - abuf = mpi_get_opaque (data, &abits); - rc = _gcry_mpi_scan (&a, GCRYMPI_FMT_USG, abuf, (abits+7)/8, NULL); - if (!rc) - { - if (abits > qbits) - mpi_rshift (a, a, abits - qbits); - - rc = _gcry_ecc_ecdsa_verify (a, ec, sig_r, sig_s); - _gcry_mpi_release (a); - } - } - else - rc = _gcry_ecc_ecdsa_verify (data, ec, sig_r, sig_s); + rc = _gcry_ecc_ecdsa_verify (data, ec, sig_r, sig_s); } leave: -- 2.17.1 From tianjia.zhang at linux.alibaba.com Mon Jan 20 04:42:23 2020 From: tianjia.zhang at linux.alibaba.com (Tianjia Zhang) Date: Mon, 20 Jan 2020 11:42:23 +0800 Subject: [PATCH] Add elliptic curve SM2 implementation Message-ID: <20200120034225.111937-1-tianjia.zhang@linux.alibaba.com> This new module implement the SM2 elliptic curve algorithm. It was published by State Encryption Management Bureau, China. List of specifications for SM2 elliptic curve public key cryptography: * GM/T 0003.1-2012 * GM/T 0003.2-2012 * GM/T 0003.3-2012 * GM/T 0003.4-2012 * GM/T 0003.5-2012 IETF: https://tools.ietf.org/html/draft-shen-sm2-ecdsa-02 oscca: http://www.oscca.gov.cn/sca/xxgk/2010-12/17/content_1002386.shtml scctc: http://www.gmbz.org.cn/main/bzlb.html Signed-off-by: Tianjia Zhang Thanks, Tianjia From tianjia.zhang at linux.alibaba.com Mon Jan 20 04:42:24 2020 From: tianjia.zhang at linux.alibaba.com (Tianjia Zhang) Date: Mon, 20 Jan 2020 11:42:24 +0800 Subject: [PATCH 1/2] Add elliptic curve SM2 implementation. In-Reply-To: <20200120034225.111937-1-tianjia.zhang@linux.alibaba.com> References: <20200120034225.111937-1-tianjia.zhang@linux.alibaba.com> Message-ID: <20200120034225.111937-2-tianjia.zhang@linux.alibaba.com> * configure.ac (enabled_pubkey_ciphers): Add ecc-sm2. * cipher/Makefile.am (EXTRA_libcipher_la_SOURCES): Add ecc-sm2.c. * cipher/pubkey-util.c (_gcry_pk_util_parse_flaglist, _gcry_pk_util_preparse_sigval): Add sm2 flags. * cipher/ecc.c: Support ecc-sm2. * cipher/ecc-common.h: Add declarations for ecc-sm2. * cipher/ecc-sm2.c: New. * src/cipher.h: Define PUBKEY_FLAG_SM2. -- Signed-off-by: Tianjia Zhang --- cipher/Makefile.am | 2 +- cipher/ecc-common.h | 12 + cipher/ecc-sm2.c | 566 +++++++++++++++++++++++++++++++++++++++++++ cipher/ecc.c | 53 +++- cipher/pubkey-util.c | 7 + configure.ac | 3 +- src/cipher.h | 1 + 7 files changed, 630 insertions(+), 14 deletions(-) create mode 100644 cipher/ecc-sm2.c diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 020a9616..10a5ab62 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -87,7 +87,7 @@ EXTRA_libcipher_la_SOURCES = \ dsa.c \ elgamal.c \ ecc.c ecc-curves.c ecc-misc.c ecc-common.h \ - ecc-ecdh.c ecc-ecdsa.c ecc-eddsa.c ecc-gost.c \ + ecc-ecdh.c ecc-ecdsa.c ecc-eddsa.c ecc-gost.c ecc-sm2.c \ idea.c \ gost28147.c gost.h \ gostr3411-94.c \ diff --git a/cipher/ecc-common.h b/cipher/ecc-common.h index 7fbc950a..b8b7c763 100644 --- a/cipher/ecc-common.h +++ b/cipher/ecc-common.h @@ -125,4 +125,16 @@ gpg_err_code_t _gcry_ecc_gost_verify (gcry_mpi_t input, mpi_ec_t ec, gcry_mpi_t r, gcry_mpi_t s); +/*-- ecc-sm2.c --*/ +gpg_err_code_t _gcry_ecc_sm2_encrypt (gcry_sexp_t *r_ciph, + gcry_mpi_t input, mpi_ec_t ec); +gpg_err_code_t _gcry_ecc_sm2_decrypt (gcry_sexp_t *r_plain, + gcry_sexp_t data_list, mpi_ec_t ec); +gpg_err_code_t _gcry_ecc_sm2_sign (gcry_mpi_t input, mpi_ec_t ec, + gcry_mpi_t r, gcry_mpi_t s, + int flags, int hashalgo); +gpg_err_code_t _gcry_ecc_sm2_verify (gcry_mpi_t input, mpi_ec_t ec, + gcry_mpi_t r, gcry_mpi_t s); + + #endif /*GCRY_ECC_COMMON_H*/ diff --git a/cipher/ecc-sm2.c b/cipher/ecc-sm2.c new file mode 100644 index 00000000..a6341132 --- /dev/null +++ b/cipher/ecc-sm2.c @@ -0,0 +1,566 @@ +/* ecc-sm2.c - Elliptic Curve SM2 implementation + * Copyright (C) 2020 Tianjia Zhang + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#include +#include +#include +#include +#include + +#include "g10lib.h" +#include "bithelp.h" +#include "mpi.h" +#include "cipher.h" +#include "context.h" +#include "ec-context.h" +#include "pubkey-internal.h" +#include "ecc-common.h" + +#define MPI_NBYTES(m) ((mpi_get_nbits(m) + 7) / 8) + + +/* Key derivation function from X9.63/SECG */ +static gpg_err_code_t +kdf_x9_63 (int algo, const void *in, size_t inlen, void *out, size_t outlen) +{ + gpg_err_code_t rc; + gcry_md_hd_t hd; + int mdlen; + u32 counter = 1; + u32 counter_be; + unsigned char *dgst; + unsigned char *pout = out; + size_t rlen = outlen; + size_t len; + + rc = _gcry_md_open (&hd, algo, 0); + if (rc) + return rc; + + mdlen = _gcry_md_get_algo_dlen (algo); + + while (rlen > 0) + { + counter_be = be_bswap32 (counter); /* cpu_to_be32 */ + counter++; + + _gcry_md_write (hd, in, inlen); + _gcry_md_write (hd, &counter_be, sizeof(counter_be)); + + dgst = _gcry_md_read (hd, algo); + if (dgst == NULL) + { + rc = GPG_ERR_DIGEST_ALGO; + break; + } + + len = mdlen < rlen ? mdlen : rlen; /* min(mdlen, rlen) */ + memcpy (pout, dgst, len); + rlen -= len; + pout += len; + + _gcry_md_reset (hd); + } + + _gcry_md_close (hd); + return rc; +} + + +/* _gcry_ecc_sm2_encrypt description: + * input: + * data[0] : octet string + * output: A new S-expression with the parameters: + * a: c1 : generated ephemeral public key (kG) + * b: c3 : Hash(x2 || IN || y2) + * c: c2 : cipher + * + * sm2_decrypt description: + * in contrast to encrypt + */ +gpg_err_code_t +_gcry_ecc_sm2_encrypt (gcry_sexp_t *r_ciph, gcry_mpi_t input, mpi_ec_t ec) +{ + gpg_err_code_t rc; + const int algo = GCRY_MD_SM3; + gcry_md_hd_t md = NULL; + int mdlen; + unsigned char *dgst; + gcry_mpi_t k = NULL; + mpi_point_struct kG, kP; + gcry_mpi_t x1, y1; + gcry_mpi_t x2, y2; + gcry_mpi_t x2y2 = NULL; + unsigned char *in = NULL; + unsigned int inlen; + unsigned char *raw; + unsigned int rawlen; + unsigned char *cipher = NULL; + int i; + + point_init (&kG); + point_init (&kP); + x1 = mpi_new (0); + y1 = mpi_new (0); + x2 = mpi_new (0); + y2 = mpi_new (0); + + in = _gcry_mpi_get_buffer (input, 0, &inlen, NULL); + if (!in) + { + rc = gpg_err_code_from_syserror (); + goto leave; + } + + cipher = xtrymalloc (inlen); + if (!cipher) + { + rc = gpg_err_code_from_syserror (); + goto leave; + } + + /* rand k in [1, n-1] */ + k = _gcry_dsa_gen_k (ec->n, GCRY_VERY_STRONG_RANDOM); + + /* [k]G = (x1, y1) */ + _gcry_mpi_ec_mul_point (&kG, k, ec->G, ec); + if (_gcry_mpi_ec_get_affine (x1, y1, &kG, ec)) + { + if (DBG_CIPHER) + log_debug ("Bad check: kG can not be a Point at Infinity!\n"); + rc = GPG_ERR_INV_DATA; + goto leave; + } + + /* [k]P = (x2, y2) */ + _gcry_mpi_ec_mul_point (&kP, k, ec->Q, ec); + if (_gcry_mpi_ec_get_affine (x2, y2, &kP, ec)) + { + rc = GPG_ERR_INV_DATA; + goto leave; + } + + /* t = KDF(x2 || y2, klen) */ + x2y2 = _gcry_mpi_ec_ec2os (&kP, ec); + raw = mpi_get_opaque (x2y2, &rawlen); + rawlen = (rawlen + 7) / 8; + + /* skip the prefix '0x04' */ + raw += 1; + rawlen -= 1; + rc = kdf_x9_63 (algo, raw, rawlen, cipher, inlen); + if (rc) + goto leave; + + /* cipher = t xor in */ + for (i = 0; i < inlen; i++) + cipher[i] ^= in[i]; + + /* hash(x2 || IN || y2) */ + mdlen = _gcry_md_get_algo_dlen (algo); + rc = _gcry_md_open (&md, algo, 0); + if (rc) + goto leave; + _gcry_md_write (md, raw, MPI_NBYTES(x2)); + _gcry_md_write (md, in, inlen); + _gcry_md_write (md, raw + MPI_NBYTES(x2), MPI_NBYTES(y2)); + dgst = _gcry_md_read (md, algo); + if (dgst == NULL) + { + rc = GPG_ERR_DIGEST_ALGO; + goto leave; + } + + if (!rc) + { + gcry_mpi_t c1; + gcry_mpi_t c3; + gcry_mpi_t c2; + + c3 = mpi_new (0); + c2 = mpi_new (0); + + c1 = _gcry_ecc_ec2os (x1, y1, ec->p); + _gcry_mpi_set_opaque_copy (c3, dgst, mdlen * 8); + _gcry_mpi_set_opaque_copy (c2, cipher, inlen * 8); + + rc = sexp_build (r_ciph, NULL, + "(enc-val(flags sm2)(sm2(a%M)(b%M)(c%M)))", + c1, c3, c2); + + mpi_free (c1); + mpi_free (c3); + mpi_free (c2); + } + +leave: + _gcry_md_close (md); + mpi_free (x2y2); + mpi_free (k); + + point_free (&kG); + point_free (&kP); + mpi_free (x1); + mpi_free (y1); + mpi_free (x2); + mpi_free (y2); + + xfree (cipher); + xfree (in); + + return rc; +} + + +gpg_err_code_t +_gcry_ecc_sm2_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t data_list, mpi_ec_t ec) +{ + gpg_err_code_t rc; + gcry_mpi_t data_c1 = NULL; + gcry_mpi_t data_c3 = NULL; + gcry_mpi_t data_c2 = NULL; + + /* + * Extract the data. + */ + rc = sexp_extract_param (data_list, NULL, "/a/b/c", + &data_c1, &data_c3, &data_c2, NULL); + if (rc) + goto leave; + if (DBG_CIPHER) + { + log_printmpi ("ecc_decrypt d_c1", data_c1); + log_printmpi ("ecc_decrypt d_c3", data_c3); + log_printmpi ("ecc_decrypt d_c2", data_c2); + } + + { + const int algo = GCRY_MD_SM3; + gcry_md_hd_t md = NULL; + int mdlen; + unsigned char *dgst; + mpi_point_struct c1; + mpi_point_struct kP; + gcry_mpi_t x2, y2; + gcry_mpi_t x2y2 = NULL; + unsigned char *in = NULL; + unsigned int inlen; + unsigned char *plain = NULL; + unsigned char *raw; + unsigned int rawlen; + unsigned char *c3 = NULL; + unsigned int c3_len; + int i; + + point_init (&c1); + point_init (&kP); + x2 = mpi_new (0); + y2 = mpi_new (0); + + in = mpi_get_opaque (data_c2, &inlen); + inlen = (inlen + 7) / 8; + plain = xtrymalloc (inlen); + if (!plain) + { + rc = gpg_err_code_from_syserror (); + goto leave_main; + } + + rc = _gcry_ecc_os2ec (&c1, data_c1); + if (rc) + goto leave_main; + + if (!_gcry_mpi_ec_curve_point (&c1, ec)) + { + rc = GPG_ERR_INV_DATA; + goto leave_main; + } + + /* [d]C1 = (x2, y2), C1 = [k]G */ + _gcry_mpi_ec_mul_point (&kP, ec->d, &c1, ec); + if (_gcry_mpi_ec_get_affine (x2, y2, &kP, ec)) + { + rc = GPG_ERR_INV_DATA; + goto leave_main; + } + + /* t = KDF(x2 || y2, inlen) */ + x2y2 = _gcry_mpi_ec_ec2os (&kP, ec); + raw = mpi_get_opaque (x2y2, &rawlen); + rawlen = (rawlen + 7) / 8; + /* skip the prefix '0x04' */ + raw += 1; + rawlen -= 1; + rc = kdf_x9_63 (algo, raw, rawlen, plain, inlen); + if (rc) + goto leave_main; + + /* plain = C2 xor t */ + for (i = 0; i < inlen; i++) + plain[i] ^= in[i]; + + /* Hash(x2 || IN || y2) == C3 */ + mdlen = _gcry_md_get_algo_dlen (algo); + rc = _gcry_md_open (&md, algo, 0); + if (rc) + goto leave_main; + _gcry_md_write (md, raw, MPI_NBYTES(x2)); + _gcry_md_write (md, plain, inlen); + _gcry_md_write (md, raw + MPI_NBYTES(x2), MPI_NBYTES(y2)); + dgst = _gcry_md_read (md, algo); + if (dgst == NULL) + { + memset (plain, 0, inlen); + rc = GPG_ERR_DIGEST_ALGO; + goto leave_main; + } + c3 = mpi_get_opaque (data_c3, &c3_len); + c3_len = (c3_len + 7) / 8; + if (c3_len != mdlen || memcmp (dgst, c3, c3_len) != 0) + { + memset (plain, 0, inlen); + rc = GPG_ERR_INV_DATA; + goto leave_main; + } + + if (!rc) + { + gcry_mpi_t r; + + r = mpi_new (inlen * 8); + _gcry_mpi_set_buffer (r, plain, inlen, 0); + + rc = sexp_build (r_plain, NULL, "(value %m)", r); + + mpi_free (r); + } + + leave_main: + _gcry_md_close (md); + mpi_free (x2y2); + xfree (plain); + + point_free (&c1); + point_free (&kP); + mpi_free (x2); + mpi_free (y2); + } + + leave: + _gcry_mpi_release (data_c1); + _gcry_mpi_release (data_c3); + _gcry_mpi_release (data_c2); + + return rc; +} + + +/* Compute an SM2 signature. + * Return the signature struct (r,s) from the message hash. The caller + * must have allocated R and S. + */ +gpg_err_code_t +_gcry_ecc_sm2_sign (gcry_mpi_t input, mpi_ec_t ec, + gcry_mpi_t r, gcry_mpi_t s, + int flags, int hashalgo) +{ + gpg_err_code_t rc = 0; + int extraloops = 0; + gcry_mpi_t hash; + const void *abuf; + unsigned int abits, qbits; + gcry_mpi_t tmp = NULL; + gcry_mpi_t k = NULL; + gcry_mpi_t rk = NULL; + mpi_point_struct kG; + gcry_mpi_t x1; + + if (DBG_CIPHER) + log_mpidump ("sm2 sign hash ", input); + + qbits = mpi_get_nbits (ec->n); + + /* Convert the INPUT into an MPI if needed. */ + rc = _gcry_dsa_normalize_hash (input, &hash, qbits); + if (rc) + return rc; + + point_init (&kG); + x1 = mpi_new (0); + rk = mpi_new (0); + tmp = mpi_new (0); + + for (;;) + { + /* rand k in [1, n-1] */ + if ((flags & PUBKEY_FLAG_RFC6979) && hashalgo) + { + /* Use Pornin's method for deterministic DSA. If this + flag is set, it is expected that HASH is an opaque + MPI with the to be signed hash. That hash is also + used as h1 from 3.2.a. */ + if (!mpi_is_opaque (input)) + { + rc = GPG_ERR_CONFLICT; + goto leave; + } + + abuf = mpi_get_opaque (input, &abits); + rc = _gcry_dsa_gen_rfc6979_k (&k, ec->n, ec->d, + abuf, (abits+7)/8, + hashalgo, extraloops); + if (rc) + goto leave; + extraloops++; + } + else + k = _gcry_dsa_gen_k (ec->n, GCRY_VERY_STRONG_RANDOM); + + _gcry_dsa_modify_k (k, ec->n, qbits); + + /* [k]G = (x1, y1) */ + _gcry_mpi_ec_mul_point (&kG, k, ec->G, ec); + if (_gcry_mpi_ec_get_affine (x1, NULL, &kG, ec)) + { + rc = GPG_ERR_INV_DATA; + goto leave; + } + + /* r = (e + x1) % n */ + mpi_addm (r, hash, x1, ec->n); + + /* r != 0 && r + k != n */ + if (mpi_cmp_ui (r, 0) == 0) + continue; + mpi_add (rk, r, k); + if (mpi_cmp (rk, ec->n) == 0) + continue; + + /* s = ((d + 1)^-1 * (k - rd)) % n */ + mpi_addm (s, ec->d, GCRYMPI_CONST_ONE, ec->n); + mpi_invm (s, s, ec->n); + mpi_mulm (tmp, r, ec->d, ec->n); + mpi_subm (tmp, k, tmp, ec->n); + mpi_mulm (s, s, tmp, ec->n); + + /* s != 0 */ + if (mpi_cmp_ui (s, 0) == 0) + continue; + + break; /* Okay */ + } + + if (DBG_CIPHER) + { + log_mpidump ("sm2 sign result r ", r); + log_mpidump ("sm2 sign result s ", s); + } + +leave: + point_free (&kG); + mpi_free (k); + mpi_free (x1); + mpi_free (rk); + mpi_free (tmp); + + if (hash != input) + mpi_free (hash); + + return rc; +} + + +/* Verify an SM2 signature. + * Check if R and S verifies INPUT. + */ +gpg_err_code_t +_gcry_ecc_sm2_verify (gcry_mpi_t input, mpi_ec_t ec, + gcry_mpi_t r, gcry_mpi_t s) +{ + gpg_err_code_t err = 0; + gcry_mpi_t hash = NULL; + gcry_mpi_t t = NULL; + mpi_point_struct sG, tP; + gcry_mpi_t x1, y1; + unsigned int nbits; + + /* r, s within [1, n-1] */ + if (mpi_cmp_ui (r, 1) < 0 || mpi_cmp (r, ec->n) > 0) + return GPG_ERR_BAD_SIGNATURE; + if (mpi_cmp_ui (s, 1) < 0 || mpi_cmp (s, ec->n) > 0) + return GPG_ERR_BAD_SIGNATURE; + + nbits = mpi_get_nbits (ec->n); + err = _gcry_dsa_normalize_hash (input, &hash, nbits); + if (err) + return err; + + point_init (&sG); + point_init (&tP); + x1 = mpi_new (0); + y1 = mpi_new (0); + t = mpi_new (0); + + /* t = (r + s) % n, t != 0 */ + mpi_addm (t, r, s, ec->n); + if (mpi_cmp_ui (t, 0) == 0) + { + err = GPG_ERR_BAD_SIGNATURE; + goto leave; + } + + /* sG + tP = (x1, y1) */ + _gcry_mpi_ec_mul_point (&sG, s, ec->G, ec); + _gcry_mpi_ec_mul_point (&tP, t, ec->Q, ec); + _gcry_mpi_ec_add_points (&sG, &sG, &tP, ec); + if (_gcry_mpi_ec_get_affine (x1, y1, &sG, ec)) + { + err = GPG_ERR_INV_DATA; + goto leave; + } + + /* R = (e + x1) % n */ + mpi_addm (t, hash, x1, ec->n); + + /* check R == r */ + if (mpi_cmp (t, r)) + { + if (DBG_CIPHER) + { + log_mpidump (" R", t); + log_mpidump (" r", r); + log_mpidump (" s", s); + } + err = GPG_ERR_BAD_SIGNATURE; + goto leave; + } + if (DBG_CIPHER) + log_debug ("sm2 verify: Accepted\n"); + + leave: + point_free (&sG); + point_free (&tP); + mpi_free (x1); + mpi_free (y1); + mpi_free (t); + if (hash != input) + mpi_free (hash); + + return err; +} diff --git a/cipher/ecc.c b/cipher/ecc.c index 1195f5ec..49c2c0f6 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -69,6 +69,7 @@ static const char *ecc_names[] = "ecdh", "eddsa", "gost", + "sm2", NULL, }; @@ -723,6 +724,14 @@ ecc_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms) rc = sexp_build (r_sig, NULL, "(sig-val(gost(r%M)(s%M)))", sig_r, sig_s); } + else if ((ctx.flags & PUBKEY_FLAG_SM2)) + { + rc = _gcry_ecc_sm2_sign (data, ec, sig_r, sig_s, + ctx.flags, ctx.hash_algo); + if (!rc) + rc = sexp_build (r_sig, NULL, + "(sig-val(sm2(r%M)(s%M)))", sig_r, sig_s); + } else { rc = _gcry_ecc_ecdsa_sign (data, ec, sig_r, sig_s, @@ -811,6 +820,10 @@ ecc_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms) { rc = _gcry_ecc_gost_verify (data, ec, sig_r, sig_s); } + else if ((sigflags & PUBKEY_FLAG_SM2)) + { + rc = _gcry_ecc_sm2_verify (data, ec, sig_r, sig_s); + } else { rc = _gcry_ecc_ecdsa_verify (data, ec, sig_r, sig_s); @@ -918,6 +931,13 @@ ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms) goto leave; } + if ((ctx.flags & PUBKEY_FLAG_SM2)) + { + /* All encryption will be done, return it. */ + rc = _gcry_ecc_sm2_encrypt (r_ciph, data, ec); + goto leave; + } + /* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so */ { mpi_point_struct R; /* Result that we return. */ @@ -1041,18 +1061,6 @@ ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms) _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_DECRYPT, (nbits = ecc_get_nbits (keyparms))); - /* - * Extract the data. - */ - rc = _gcry_pk_util_preparse_encval (s_data, ecc_names, &l1, &ctx); - if (rc) - goto leave; - rc = sexp_extract_param (l1, NULL, "/e", &data_e, NULL); - if (rc) - goto leave; - if (DBG_CIPHER) - log_printmpi ("ecc_decrypt d_e", data_e); - /* * Extract the key. */ @@ -1066,6 +1074,27 @@ ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms) goto leave; } + /* + * Extract the data. + */ + rc = _gcry_pk_util_preparse_encval (s_data, ecc_names, &l1, &ctx); + if (rc) + goto leave; + if ((ctx.flags & PUBKEY_FLAG_SM2)) + { + /* All decryption will be done, return it. */ + rc = _gcry_ecc_sm2_decrypt (r_plain, l1, ec); + goto leave; + } + else + { + rc = sexp_extract_param (l1, NULL, "/e", &data_e, NULL); + if (rc) + goto leave; + if (DBG_CIPHER) + log_printmpi ("ecc_decrypt d_e", data_e); + } + if (ec->dialect == ECC_DIALECT_SAFECURVE || (flags & PUBKEY_FLAG_DJB_TWEAK)) enable_specific_point_validation = 1; else diff --git a/cipher/pubkey-util.c b/cipher/pubkey-util.c index 4a6bf462..c52185de 100644 --- a/cipher/pubkey-util.c +++ b/cipher/pubkey-util.c @@ -81,6 +81,11 @@ _gcry_pk_util_parse_flaglist (gcry_sexp_t list, encoding = PUBKEY_ENC_RAW; flags |= PUBKEY_FLAG_RAW_FLAG; /* Explicitly given. */ } + else if (!memcmp (s, "sm2", 3)) + { + encoding = PUBKEY_ENC_RAW; + flags |= PUBKEY_FLAG_SM2 | PUBKEY_FLAG_RAW_FLAG; + } else if (!igninvflag) rc = GPG_ERR_INV_FLAG; break; @@ -429,6 +434,8 @@ _gcry_pk_util_preparse_sigval (gcry_sexp_t s_sig, const char **algo_names, *r_eccflags = PUBKEY_FLAG_EDDSA; if (!strcmp (name, "gost")) *r_eccflags = PUBKEY_FLAG_GOST; + if (!strcmp (name, "sm2")) + *r_eccflags = PUBKEY_FLAG_SM2; } *r_parms = l2; diff --git a/configure.ac b/configure.ac index 4d4fb49a..e45452ee 100644 --- a/configure.ac +++ b/configure.ac @@ -2546,7 +2546,8 @@ LIST_MEMBER(ecc, $enabled_pubkey_ciphers) if test "$found" = "1" ; then GCRYPT_PUBKEY_CIPHERS="$GCRYPT_PUBKEY_CIPHERS \ ecc.lo ecc-curves.lo ecc-misc.lo \ - ecc-ecdh.lo ecc-ecdsa.lo ecc-eddsa.lo ecc-gost.lo" + ecc-ecdh.lo ecc-ecdsa.lo ecc-eddsa.lo ecc-gost.lo \ + ecc-sm2.lo" AC_DEFINE(USE_ECC, 1, [Defined if this module should be included]) fi diff --git a/src/cipher.h b/src/cipher.h index 5aac19f1..1fe50890 100644 --- a/src/cipher.h +++ b/src/cipher.h @@ -42,6 +42,7 @@ #define PUBKEY_FLAG_GOST (1 << 13) #define PUBKEY_FLAG_NO_KEYTEST (1 << 14) #define PUBKEY_FLAG_DJB_TWEAK (1 << 15) +#define PUBKEY_FLAG_SM2 (1 << 16) enum pk_operation -- 2.17.1 From tianjia.zhang at linux.alibaba.com Mon Jan 20 04:42:25 2020 From: tianjia.zhang at linux.alibaba.com (Tianjia Zhang) Date: Mon, 20 Jan 2020 11:42:25 +0800 Subject: [PATCH 2/2] tests: Add basic test cases for sm2 In-Reply-To: <20200120034225.111937-1-tianjia.zhang@linux.alibaba.com> References: <20200120034225.111937-1-tianjia.zhang@linux.alibaba.com> Message-ID: <20200120034225.111937-3-tianjia.zhang@linux.alibaba.com> * tests/basic.c (check_pubkey): Add test cases for ecc-sm2. -- Signed-off-by: Tianjia Zhang --- tests/basic.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/tests/basic.c b/tests/basic.c index 2a41fb82..82209b1b 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -12594,6 +12594,16 @@ check_pubkey_sign_ecdsa (int n, gcry_sexp_t skey, gcry_sexp_t pkey) /* */ "000102030405060708090A0B0C0D0E0F#))", 0 }, + { 256, + "(data (flags sm2)\n" + " (hash sm3 #112233445566778899AABBCCDDEEFF00" + /* */ "123456789ABCDEF0123456789ABCDEF0#))", + 0, + "(data (flags sm2)\n" + " (hash sm3 #B524F552CD82B8B028476E005C377FB1" + /* */ "9A87E6FC682D48BB5D42E3D9B9EFFE76#))", + 0 + }, { 0, NULL } }; @@ -12638,7 +12648,8 @@ check_pubkey_sign_ecdsa (int n, gcry_sexp_t skey, gcry_sexp_t pkey) static void -check_pubkey_crypt (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo) +check_pubkey_crypt (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo, + int exact_match) { gcry_error_t rc; gcry_sexp_t plain = NULL; @@ -12751,6 +12762,13 @@ check_pubkey_crypt (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo) NULL, 0, GPG_ERR_CONFLICT }, + { GCRY_PK_ECDSA, + "(data\n (flags sm2)\n (hash-algo sm3)\n" + " (value #1234567890ABCDEF1234567890ABCDEF#))\n", + NULL, + 1, + 0, + 0 }, { 0, NULL } }; @@ -12758,7 +12776,7 @@ check_pubkey_crypt (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo) for (dataidx = 0; datas[dataidx].data; dataidx++) { - if (datas[dataidx].algo && datas[dataidx].algo != algo) + if ((datas[dataidx].algo || exact_match) && datas[dataidx].algo != algo) continue; if (verbose) @@ -12908,7 +12926,12 @@ do_check_one_pubkey (int n, gcry_sexp_t skey, gcry_sexp_t pkey, check_pubkey_sign (n, skey, pkey, algo); } if (flags & FLAG_CRYPT) - check_pubkey_crypt (n, skey, pkey, algo); + { + if (algo == GCRY_PK_ECDSA) + check_pubkey_crypt (n, skey, pkey, algo, 1); + else + check_pubkey_crypt (n, skey, pkey, algo, 0); + } if (grip && (flags & FLAG_GRIP)) check_pubkey_grip (n, grip, skey, pkey, algo); } @@ -13270,6 +13293,29 @@ check_pubkey (void) " F1050E2E8FF49C85C23CBE7DED0E7CE6A594896B8F62888F" " DBC5C8821305E2EA42BF01E37300116281#)))\n", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" } + }, + { /* sm2 test */ + GCRY_PK_ECDSA, FLAG_CRYPT | FLAG_SIGN, + { + "(private-key\n" + " (ecc\n" + " (curve sm2p256v1)\n" + " (q #04" + " 8759389A34AAAD07ECF4E0C8C2650A4459C8D926EE2378324E0261C52538CB47" + " 7528106B1E0B7C8DD5FF29A9C86A89065656EB33154BC0556091EF8AC9D17D78#)" + " (d #41EBDBA9C98CBECCE7249CF18BFD427FF8EA0B2FAB7B9D305D9D9BF4DB6ADFC2#)" + "))", + + "(public-key\n" + " (ecc\n" + " (curve sm2p256v1)\n" + " (q #04" + " 8759389A34AAAD07ECF4E0C8C2650A4459C8D926EE2378324E0261C52538CB47" + " 7528106B1E0B7C8DD5FF29A9C86A89065656EB33154BC0556091EF8AC9D17D78#)" + "))", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" } } -- 2.17.1 From gniibe at fsij.org Tue Jan 21 06:20:50 2020 From: gniibe at fsij.org (NIIBE Yutaka) Date: Tue, 21 Jan 2020 14:20:50 +0900 Subject: [PATCH] tests: Fix typo missing commas In-Reply-To: <20200120033153.111736-1-tianjia.zhang@linux.alibaba.com> References: <20200120033153.111736-1-tianjia.zhang@linux.alibaba.com> Message-ID: <871rrtxu4t.fsf@iwagami.gniibe.org> Tianjia Zhang wrote: > * tests/basic.c: Add missing commas. Thanks. Good catch. I added missing FLAG_GRIP, and pushed the change. -- From gniibe at fsij.org Tue Jan 21 06:21:25 2020 From: gniibe at fsij.org (NIIBE Yutaka) Date: Tue, 21 Jan 2020 14:21:25 +0900 Subject: [PATCH] ecc: Simplify signature code In-Reply-To: <20200120033528.111815-1-tianjia.zhang@linux.alibaba.com> References: <20200120033528.111815-1-tianjia.zhang@linux.alibaba.com> Message-ID: <87y2u1wfje.fsf@iwagami.gniibe.org> Tianjia Zhang wrote: > * cipher/ecc-gost.c (_gcry_ecc_gost_sign): Use implemented function. > * cipher/ecc.c (ecc_verify): Remove redundant code. Thanks. Applied. -- From gniibe at fsij.org Tue Jan 21 06:28:55 2020 From: gniibe at fsij.org (NIIBE Yutaka) Date: Tue, 21 Jan 2020 14:28:55 +0900 Subject: [PATCH] Add elliptic curve SM2 implementation In-Reply-To: <20200120034225.111937-1-tianjia.zhang@linux.alibaba.com> References: <20200120034225.111937-1-tianjia.zhang@linux.alibaba.com> Message-ID: <87tv4pwf6w.fsf@iwagami.gniibe.org> Tianjia Zhang wrote: > This new module implement the SM2 elliptic curve algorithm. It was > published by State Encryption Management Bureau, China. Thanks. I applied: [PATCH 1/2] Add elliptic curve SM2 implementation. For another one: [PATCH 2/2] tests: Add basic test cases for sm2 While I understand your intention of testing SM2 also for encryption/decryption, the existing code is not good shape for that (thus, EXACT_MATCH was there in your patch). So, I only put tests for ECDSA with the SM2 curve. It's good if we have tests for GCRY_PK_ECC. We should do that in future. -- From tianjia.zhang at linux.alibaba.com Tue Jan 21 12:29:51 2020 From: tianjia.zhang at linux.alibaba.com (Tianjia Zhang) Date: Tue, 21 Jan 2020 19:29:51 +0800 Subject: =?UTF-8?B?5Zue5aSN77yaW1BBVENIXSBBZGQgZWxsaXB0aWMgY3VydmUgU00yIGltcGxlbWVudGF0aW9u?= In-Reply-To: <87tv4pwf6w.fsf@iwagami.gniibe.org> References: <20200120034225.111937-1-tianjia.zhang@linux.alibaba.com>, <87tv4pwf6w.fsf@iwagami.gniibe.org> Message-ID: <1f8a1c16-9cc4-4c19-9d2c-a4d9880c73a9.tianjia.zhang@linux.alibaba.com> That's right, if there is an encryption and decryption test for GCRY_PK_ECC, that would be great. Happy New Year. Thanks, Tianjia -------------- next part -------------- An HTML attachment was scrubbed... URL: From jussi.kivilinna at iki.fi Wed Jan 22 20:43:12 2020 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Wed, 22 Jan 2020 21:43:12 +0200 Subject: [PATCH] mpi/i386: fix DWARF CFI for _gcry_mpih_sub_n and _gcry_mpih_add_n Message-ID: <157972219236.15348.10638823411921801606.stgit@localhost6.localdomain6> * mpi/i386/mpih-add1.S (_gcry_mpih_add_n) [PIC]: Adjust CFI CFA offset when making call and restoring stack pointer. * mpi/i386/mpih-sub1.S (_gcry_mpih_sub_n) [PIC]: Ditto. -- Signed-off-by: Jussi Kivilinna --- mpi/i386/mpih-add1.S | 2 ++ mpi/i386/mpih-sub1.S | 2 ++ 2 files changed, 4 insertions(+) diff --git a/mpi/i386/mpih-add1.S b/mpi/i386/mpih-add1.S index 2f1ae931c..de78a0cb1 100644 --- a/mpi/i386/mpih-add1.S +++ b/mpi/i386/mpih-add1.S @@ -78,10 +78,12 @@ C_SYMBOL_NAME(_gcry_mpih_add_n:) /* Calculate start address in loop for PIC. Due to limitations in some assemblers, Loop-L0-3 cannot be put into the leal */ call L0 + CFI_ADJUST_CFA_OFFSET(4) L0: leal (%eax,%eax,8),%eax addl (%esp),%eax addl $(Loop-L0-3),%eax addl $4,%esp + CFI_ADJUST_CFA_OFFSET(-4) #else /* Calculate start address in loop for non-PIC. */ leal (Loop - 3)(%eax,%eax,8),%eax diff --git a/mpi/i386/mpih-sub1.S b/mpi/i386/mpih-sub1.S index 01e977e53..2bdc14386 100644 --- a/mpi/i386/mpih-sub1.S +++ b/mpi/i386/mpih-sub1.S @@ -79,10 +79,12 @@ C_SYMBOL_NAME(_gcry_mpih_sub_n:) /* Calculate start address in loop for PIC. Due to limitations in some assemblers, Loop-L0-3 cannot be put into the leal */ call L0 + CFI_ADJUST_CFA_OFFSET(4) L0: leal (%eax,%eax,8),%eax addl (%esp),%eax addl $(Loop-L0-3),%eax addl $4,%esp + CFI_ADJUST_CFA_OFFSET(-4) #else /* Calculate start address in loop for non-PIC. */ leal (Loop - 3)(%eax,%eax,8),%eax From jussi.kivilinna at iki.fi Wed Jan 22 21:42:50 2020 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Wed, 22 Jan 2020 22:42:50 +0200 Subject: [PATCH] sexp: fix cast from 'int' pointer to 'size_t' pointer Message-ID: <157972576990.4230.1351507697155074154.stgit@localhost6.localdomain6> * src/sexp.c (do_vsexp_sscan): Change 'datalen' from 'int' to 'size_t'; Remove &datalen pointer cast to 'size_t *' type. -- Signed-off-by: Jussi Kivilinna --- 0 files changed diff --git a/src/sexp.c b/src/sexp.c index 57d77d296..17341ba5e 100644 --- a/src/sexp.c +++ b/src/sexp.c @@ -1114,7 +1114,7 @@ do_vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff, int hexcount = 0; int b64count = 0; int quoted_esc = 0; - int datalen = 0; + size_t datalen = 0; size_t dummy_erroff; struct make_space_ctx c; int arg_counter = 0; @@ -1354,7 +1354,7 @@ do_vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff, goto leave; } err = gpgrt_b64dec_proc (b64state, b64buf, b64count, - (size_t *)&datalen); + &datalen); if (err && gpg_err_code (err) != GPG_ERR_EOF) { xfree (b64state); From jussi.kivilinna at iki.fi Wed Jan 22 22:08:52 2020 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Wed, 22 Jan 2020 23:08:52 +0200 Subject: Disable Weak cipher check for DES KCV In-Reply-To: References: Message-ID: Hello, On 9.1.2020 3.57, Jan Bilek wrote: > Hi Jussi, > > No problem and thanks for coming back on my email. > > You are right - "all KCV algorithms I managed to find encrypt zero input block with the actual key as key" - except cases where the key is a weak key. While this might sound ridiculous there are many cases like this - in production as well as in test environments. E.g. Thales HSM default-load key-set works with some weak keys and while doing symmetric crypto we need to support those as well (in testing / dev environments Thales HSM is almost always loaded with a default key set so crypto can be reproduced and validated). > > Hope it makes better sense now. Ok. I guess for such testing use-case, we could add new gcry_cipher_ctl command to allow weak-keys on cipher object. After command is given to cipher object, setkey would still return weak-key error code, but otherwise setup algorithm for encryption/decryption. Usage would be like this: err = gcry_cipher_open(&handle, algo, mode, 0) assert(err == 0) err = gcry_cipher_ctl(handle, GCRYCTL_ALLOW_WEAK_KEY, NULL, 1) assert(err == 0) err = gcry_cipher_setkey(handle, weak_key_buf, weak_key_len) assert(err == GPG_ERR_WEAK_KEY) err = gcry_cipher_encrypt(handle, out, outlen, in, inlen) assert(err == 0) err = gcry_cipher_close(handle) assert(err == 0) -Jussi From jussi.kivilinna at iki.fi Wed Jan 22 22:33:38 2020 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Wed, 22 Jan 2020 23:33:38 +0200 Subject: V2 [PATCH 0/4] x86: Enable Intel Control-flow Enforcement Technology (CET) In-Reply-To: <20200119144025.6551-1-hjl.tools@gmail.com> References: <20200119144025.6551-1-hjl.tools@gmail.com> Message-ID: <778f0645-fcef-cf3e-ed4a-bea233df3a3c@iki.fi> Hello, On 19.1.2020 16.40, H.J. Lu via Gcrypt-devel wrote: > Intel Control-flow Enforcement Technology (CET): > > https://software.intel.com/en-us/articles/intel-sdm > > contains shadow stack (SHSTK) and indirect branch tracking (IBT). When > CET is enabled, ELF object files must be marked with .note.gnu.property > section. CET enabled compiler provides which can be included > in assembly sources to automatically generate .note.gnu.property section. > Also when IBT is enabled, all indirect branch targets must start with > ENDBR instruction. defines _CET_ENDBR to generate proper ENDBR > instruction. > > Tested with > > $ CC="gcc -Wl,-z,cet-report=error -fcf-protection" ./configure > > in i686 and x86-64 modes on Linux CET machine. > > H.J. Lu (4): > x86: Add .note.gnu.property section for Intel CET > mpi: Add .note.gnu.property section for Intel CET > amd64: Always include in cipher assembly codes > i386: Add _CET_ENDBR to indirect jump targets > > cipher/camellia-aesni-avx-amd64.S | 3 ++- > cipher/camellia-aesni-avx2-amd64.S | 3 ++- > cipher/serpent-avx2-amd64.S | 3 ++- > configure.ac | 6 +++++ > mpi/config.links | 10 ++++++++ > mpi/i386/mpih-add1.S | 37 ++++++++++++++++++++++++++++++ > mpi/i386/mpih-sub1.S | 37 ++++++++++++++++++++++++++++++ > 7 files changed, 96 insertions(+), 3 deletions(-) > Patches have been applied to master. Thanks. -Jussi From hjl.tools at gmail.com Wed Jan 22 23:44:24 2020 From: hjl.tools at gmail.com (H.J. Lu) Date: Wed, 22 Jan 2020 14:44:24 -0800 Subject: V2 [PATCH 0/4] x86: Enable Intel Control-flow Enforcement Technology (CET) In-Reply-To: <778f0645-fcef-cf3e-ed4a-bea233df3a3c@iki.fi> References: <20200119144025.6551-1-hjl.tools@gmail.com> <778f0645-fcef-cf3e-ed4a-bea233df3a3c@iki.fi> Message-ID: On Wed, Jan 22, 2020 at 1:33 PM Jussi Kivilinna wrote: > > Hello, > > On 19.1.2020 16.40, H.J. Lu via Gcrypt-devel wrote: > > Intel Control-flow Enforcement Technology (CET): > > > > https://software.intel.com/en-us/articles/intel-sdm > > > > contains shadow stack (SHSTK) and indirect branch tracking (IBT). When > > CET is enabled, ELF object files must be marked with .note.gnu.property > > section. CET enabled compiler provides which can be included > > in assembly sources to automatically generate .note.gnu.property section. > > Also when IBT is enabled, all indirect branch targets must start with > > ENDBR instruction. defines _CET_ENDBR to generate proper ENDBR > > instruction. > > > > Tested with > > > > $ CC="gcc -Wl,-z,cet-report=error -fcf-protection" ./configure > > > > in i686 and x86-64 modes on Linux CET machine. > > > > H.J. Lu (4): > > x86: Add .note.gnu.property section for Intel CET > > mpi: Add .note.gnu.property section for Intel CET > > amd64: Always include in cipher assembly codes > > i386: Add _CET_ENDBR to indirect jump targets > > > > cipher/camellia-aesni-avx-amd64.S | 3 ++- > > cipher/camellia-aesni-avx2-amd64.S | 3 ++- > > cipher/serpent-avx2-amd64.S | 3 ++- > > configure.ac | 6 +++++ > > mpi/config.links | 10 ++++++++ > > mpi/i386/mpih-add1.S | 37 ++++++++++++++++++++++++++++++ > > mpi/i386/mpih-sub1.S | 37 ++++++++++++++++++++++++++++++ > > 7 files changed, 96 insertions(+), 3 deletions(-) > > > > Patches have been applied to master. Thanks. > Thanks. -- H.J. From jan.bilek at eftlab.com.au Wed Jan 22 23:57:02 2020 From: jan.bilek at eftlab.com.au (Jan Bilek) Date: Wed, 22 Jan 2020 22:57:02 +0000 Subject: Disable Weak cipher check for DES KCV In-Reply-To: References: , Message-ID: I love it! Let me know if we can support this somehow from our side. BR, Jan On 2020-01-23 07:09:02+10:00 Jussi Kivilinna wrote: Hello, On 9.1.2020 3.57, Jan Bilek wrote: &gt; Hi Jussi, &gt; &gt; No problem and thanks for coming back on my email. &gt; &gt; You are right - "all KCV algorithms I managed to find encrypt zero input block with the actual key as key" - except cases where the key is a weak key. While this might sound ridiculous there are many cases like this - in production as well as in test environments. E.g. Thales HSM default-load key-set works with some weak keys and while doing symmetric crypto we need to support those as well (in testing / dev environments Thales HSM is almost always loaded with a default key set so crypto can be reproduced and validated). &gt; &gt; Hope it makes better sense now. Ok. I guess for such testing use-case, we could add new gcry_cipher_ctl command to allow weak-keys on cipher object. After command is given to cipher object, setkey would still return weak-key error code, but otherwise setup algorithm for encryption/decryption. Usage would be like this: err = gcry_cipher_open(&amp;handle, algo, mode, 0) assert(err == 0) err = gcry_cipher_ctl(handle, GCRYCTL_ALLOW_WEAK_KEY, NULL, 1) assert(err == 0) err = gcry_cipher_setkey(handle, weak_key_buf, weak_key_len) assert(err == GPG_ERR_WEAK_KEY) err = gcry_cipher_encrypt(handle, out, outlen, in, inlen) assert(err == 0) err = gcry_cipher_close(handle) assert(err == 0) -Jussi -------------- next part -------------- An HTML attachment was scrubbed... URL: From jussi.kivilinna at iki.fi Sun Jan 26 19:54:46 2020 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sun, 26 Jan 2020 20:54:46 +0200 Subject: [PATCH] Add gcry_cipher_ctl command to allow weak keys in testing use-cases Message-ID: <158006488656.24795.12084595478500497720.stgit@localhost6.localdomain6> * cipher/cipher-internal.h (gcry_cipher_handle): Add 'marks.allow_weak_key' flag. * cipher/cipher.c (cipher_setkey): Do not handle weak key as error when weak keys are allowed. (cipher_reset): Preserve 'marks.allow_weak_key' flag on object reset. (_gcry_cipher_ctl): Add handling for GCRYCTL_SET_ALLOW_WEAK_KEY. * src/gcrypt.h.in (gcry_ctl_cmds): Add GCRYCTL_SET_ALLOW_WEAK_KEY. * tests/basic.c (check_ecb_cipher): Add tests for weak key errors and for GCRYCTL_SET_ALLOW_WEAK_KEY. -- Signed-off-by: Jussi Kivilinna --- 0 files changed diff --git a/cipher/cipher-internal.h b/cipher/cipher-internal.h index 47b7b6f9e..262ca9029 100644 --- a/cipher/cipher-internal.h +++ b/cipher/cipher-internal.h @@ -207,6 +207,7 @@ struct gcry_cipher_handle unsigned int iv:1; /* Set to 1 if a IV has been set. */ unsigned int tag:1; /* Set to 1 if a tag is finalized. */ unsigned int finalize:1; /* Next encrypt/decrypt has the final data. */ + unsigned int allow_weak_key:1; /* Set to 1 if weak keys are allowed. */ } marks; /* The initialization vector. For best performance we make sure diff --git a/cipher/cipher.c b/cipher/cipher.c index bd571367c..09b8d8299 100644 --- a/cipher/cipher.c +++ b/cipher/cipher.c @@ -794,7 +794,7 @@ cipher_setkey (gcry_cipher_hd_t c, byte *key, size_t keylen) } rc = c->spec->setkey (&c->context.c, key, keylen, c); - if (!rc) + if (!rc || (c->marks.allow_weak_key && rc == GPG_ERR_WEAK_KEY)) { /* Duplicate initial context. */ memcpy ((void *) ((char *) &c->context.c + c->spec->contextsize), @@ -828,7 +828,7 @@ cipher_setkey (gcry_cipher_hd_t c, byte *key, size_t keylen) /* Setup tweak cipher with second part of XTS key. */ rc = c->spec->setkey (c->u_mode.xts.tweak_context, key + keylen, keylen, c); - if (!rc) + if (!rc || (c->marks.allow_weak_key && rc == GPG_ERR_WEAK_KEY)) { /* Duplicate initial tweak context. */ memcpy (c->u_mode.xts.tweak_context + c->spec->contextsize, @@ -889,9 +889,10 @@ cipher_setiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen) static void cipher_reset (gcry_cipher_hd_t c) { - unsigned int marks_key; + unsigned int marks_key, marks_allow_weak_key; marks_key = c->marks.key; + marks_allow_weak_key = c->marks.allow_weak_key; memcpy (&c->context.c, (char *) &c->context.c + c->spec->contextsize, @@ -903,6 +904,7 @@ cipher_reset (gcry_cipher_hd_t c) c->unused = 0; c->marks.key = marks_key; + c->marks.allow_weak_key = marks_allow_weak_key; switch (c->mode) { @@ -1592,6 +1594,13 @@ _gcry_cipher_ctl (gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen) rc = GPG_ERR_NOT_SUPPORTED; break; + case GCRYCTL_SET_ALLOW_WEAK_KEY: + /* Expecting BUFFER to be NULL and buflen to be on/off flag (0 or 1). */ + if (!h || buffer || buflen > 1) + return GPG_ERR_CIPHER_ALGO; + h->marks.allow_weak_key = buflen ? 1 : 0; + break; + default: rc = GPG_ERR_INV_OP; } diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index c008f0a6d..46f92a91f 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -333,7 +333,8 @@ enum gcry_ctl_cmds GCRYCTL_SET_TAGLEN = 75, GCRYCTL_GET_TAGLEN = 76, GCRYCTL_REINIT_SYSCALL_CLAMP = 77, - GCRYCTL_AUTO_EXPAND_SECMEM = 78 + GCRYCTL_AUTO_EXPAND_SECMEM = 78, + GCRYCTL_SET_ALLOW_WEAK_KEY = 79 }; /* Perform various operations defined by CMD. */ diff --git a/tests/basic.c b/tests/basic.c index 812bd89d6..4e3589eea 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -691,6 +691,7 @@ check_ecb_cipher (void) { int algo; const char *key; + int is_weak_key; struct { const char *plaintext; @@ -704,6 +705,7 @@ check_ecb_cipher (void) { GCRY_CIPHER_BLOWFISH, "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87\x78\x69\x5a\x4b\x3c\x2d\x1e\x0f" "\x00\x11\x22\x33\x44\x55\x66\x77\x88", + 0, { { "\xfe\xdc\xba\x98\x76\x54\x32\x10", 1, 8, @@ -813,6 +815,7 @@ check_ecb_cipher (void) "\x00\x11\x22\x33\x44\x55\x66\x77\x04\x68\x91\x04\xc2\xfd\x3b\x2f" "\x58\x40\x23\x64\x1a\xba\x61\x76\x1f\x1f\x1f\x1f\x0e\x0e\x0e\x0e" "\xff\xff\xff\xff\xff\xff\xff\xff", + 0, { { "\xfe\xdc\xba\x98\x76\x54\x32\x10", 56, 8, @@ -820,6 +823,28 @@ check_ecb_cipher (void) { } } }, + /* Weak-key testing */ + { GCRY_CIPHER_DES, + "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe", + 1, + { { "\x00\x00\x00\x00\x00\x00\x00\x00", + 8, + 8, + "\xca\xaa\xaf\x4d\xea\xf1\xdb\xae" }, + { } + } + }, + /* Weak-key testing */ + { GCRY_CIPHER_DES, + "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe", + 2, + { { "\x00\x00\x00\x00\x00\x00\x00\x00", + 8, + 8, + "\xca\xaa\xaf\x4d\xea\xf1\xdb\xae" }, + { } + } + }, }; gcry_cipher_hd_t hde, hdd; unsigned char out[MAX_DATA_LEN]; @@ -858,6 +883,21 @@ check_ecb_cipher (void) return; } + if (tv[i].is_weak_key == 2) + { + err = gcry_cipher_ctl(hde, GCRYCTL_SET_ALLOW_WEAK_KEY, NULL, 1); + if (!err) + err = gcry_cipher_ctl(hdd, GCRYCTL_SET_ALLOW_WEAK_KEY, NULL, 1); + if (err) + { + fail ("ecb-algo:%d-tv:%d, gcry_cipher_ctl failed: %s\n", + algo, i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + } + for (j = 0; tv[i].data[j].inlen; j++) { keylen = tv[i].data[j].keylen; @@ -875,9 +915,36 @@ check_ecb_cipher (void) } err = gcry_cipher_setkey (hde, tv[i].key, keylen); - if (!err) + if (!err || (gcry_err_code(err) == GPG_ERR_WEAK_KEY + && tv[i].is_weak_key == 2)) err = gcry_cipher_setkey (hdd, tv[i].key, keylen); - if (err) + if (tv[i].is_weak_key == 1) + { + if (gcry_err_code(err) != GPG_ERR_WEAK_KEY) + { + fail ("ecb-algo:%d-tv:%d-data:%d, expected gcry_cipher_setkey to fail, but got: %s\n", + algo, i, j, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + else + { + continue; + } + } + else if (tv[i].is_weak_key == 2) + { + if (gcry_err_code(err) != GPG_ERR_WEAK_KEY) + { + fail ("ecb-algo:%d-tv:%d-data:%d, expected gcry_cipher_setkey to fail, but got: %s\n", + algo, i, j, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + } + else if (err) { fail ("ecb-algo:%d-tv:%d-data:%d, gcry_cipher_setkey failed: %s\n", algo, i, j, gpg_strerror (err));