From gniibe at fsij.org Tue Mar 1 01:06:41 2016 From: gniibe at fsij.org (NIIBE Yutaka) Date: Tue, 01 Mar 2016 09:06:41 +0900 Subject: Curve25519 ECDH with ephemeral key input O In-Reply-To: <20160229131700.GZ3611@yoink.cs.uwaterloo.ca> References: <56D3CD0F.3080707@fsij.org> <20160229131700.GZ3611@yoink.cs.uwaterloo.ca> Message-ID: <56D4DD11.9000703@fsij.org> On 02/29/2016 10:17 PM, Ian Goldberg wrote: > On Mon, Feb 29, 2016 at 01:46:07PM +0900, NIIBE Yutaka wrote: >> although any value of k to Curve25519(k, P) cannot produce O if P != >> O (because of the tweak). > > This line does not sound true to me. If k is the order of the point P > (or 0, for that matter?), why would Curve25519(k, P) not output O (or > more correctly, the all-0 string)? Sorry, I should have clarified the context. I am talking about Curve25519 specified in RFC 7748. It's not only a point multiplication of [k]P. Because of the function decodeScalar25519(k) which changes the bits (to be multiple of cofactor), the scalar can't be the order of the point P. More simply, my question is: When an implementation (GnuPG in our case) is offered the input of all-0 string as ephemeral key for Curve25519 ECDH, what should it do? The situation: * It can be decrypted by the recipient. * But it can be also decrypted by anyone. * It is not generated by the correct procedure. My opinion is that GnuPG should results an error as invalid input data, although the computation of Curve25519 itself is defined with such a data. I am not confident enough, because it seems for me that an implementation of Curve25519 should not validate the input. The second test vector in RFC 7748 is: Input u-coordinate: e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493 where the point (after decodeUCoordinate function) is not on the curve. I think it is OK (or it is the role) for upper layer to validate the input. -- From ian at cypherpunks.ca Tue Mar 1 07:26:27 2016 From: ian at cypherpunks.ca (Ian Goldberg) Date: Tue, 1 Mar 2016 01:26:27 -0500 Subject: Curve25519 ECDH with ephemeral key input O In-Reply-To: <56D4DD11.9000703@fsij.org> References: <56D3CD0F.3080707@fsij.org> <20160229131700.GZ3611@yoink.cs.uwaterloo.ca> <56D4DD11.9000703@fsij.org> Message-ID: <20160301062627.GF24749@thunk.cs.uwaterloo.ca> On Tue, Mar 01, 2016 at 09:06:41AM +0900, NIIBE Yutaka wrote: > On 02/29/2016 10:17 PM, Ian Goldberg wrote: > > On Mon, Feb 29, 2016 at 01:46:07PM +0900, NIIBE Yutaka wrote: > >> although any value of k to Curve25519(k, P) cannot produce O if P != > >> O (because of the tweak). > > > > This line does not sound true to me. If k is the order of the point P > > (or 0, for that matter?), why would Curve25519(k, P) not output O (or > > more correctly, the all-0 string)? > > Sorry, I should have clarified the context. I am talking about > Curve25519 specified in RFC 7748. It's not only a point > multiplication of [k]P. Because of the function decodeScalar25519(k) > which changes the bits (to be multiple of cofactor), the scalar can't > be the order of the point P. Sure it can. (Well, it can be 8 times the order, but that amounts to the same thing.) What happens if you feed in k = 8 * (2^252 + 27742317777372353535851937790883648493)? > > More simply, my question is: > > When an implementation (GnuPG in our case) is offered the input of > all-0 string as ephemeral key for Curve25519 ECDH, what should it > do? > > The situation: > > * It can be decrypted by the recipient. > * But it can be also decrypted by anyone. > * It is not generated by the correct procedure. > > My opinion is that GnuPG should results an error as invalid input data, > although the computation of Curve25519 itself is defined with such a > data. It's not just the all-0 string that is problematic in this way. From https://cr.yp.to/ecdh.html : There are some unusual non-Diffie-Hellman elliptic-curve protocols that need to ensure ``contributory'' behavior. In those protocols, you should reject the 32-byte strings that, in little-endian form, represent 0, 1, 325606250916557431795983626356110631294008115727848805560023387167927233504 (which has order 8), 39382357235489614581723060781553021112529911719440698176882885853963445705823 (which also has order 8), 2^255 - 19 - 1, 2^255 - 19, 2^255 - 19 + 1, 2^255 - 19 + 325606250916557431795983626356110631294008115727848805560023387167927233504, 2^255 - 19 + 39382357235489614581723060781553021112529911719440698176882885853963445705823, 2(2^255 - 19) - 1, 2(2^255 - 19), and 2(2^255 - 19) + 1. But these exclusions are unnecessary for Diffie-Hellman. If you're worried about contributory behaviour (if your side is behaving properly, then the session key is random, even if the other side is faulty), then you should worry about the above values as well. I don't think it's a big deal to worry about it with DH, but did I see you say that currently libgcrypt crashes on the all-0 input? That would be bad. - Ian From jussi.kivilinna at iki.fi Sat Mar 12 18:42:48 2016 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sat, 12 Mar 2016 19:42:48 +0200 Subject: [PATCH 1/2] Update .gitignore Message-ID: <20160312174248.12371.90456.stgit@localhost6.localdomain6> -- Signed-off-by: Jussi Kivilinna --- .gitignore | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/.gitignore b/.gitignore index b961614..3cd83a2 100644 --- a/.gitignore +++ b/.gitignore @@ -37,9 +37,12 @@ doc/Makefile doc/fips-fsm.eps doc/fips-fsm.pdf doc/fips-fsm.png +doc/hmac256.1 doc/libgcrypt-modules.eps doc/libgcrypt-modules.pdf doc/libgcrypt-modules.png +doc/yat2m +doc/yat2m-stamp mpi/Makefile mpi/asm-syntax.h mpi/libmpi.la @@ -61,27 +64,43 @@ src/gcrypt.h src/hmac256 src/libgcrypt-config src/libgcrypt.la +src/mpicalc src/versioninfo.rc +src/*.exe tests/Makefile tests/ac tests/ac-data tests/ac-schemes tests/aeswrap tests/basic +tests/bench-slope tests/benchmark +tests/curves +tests/dsa-rfc6979 tests/fips186-dsa tests/fipsdrv tests/gchash +tests/genhashdata +tests/hashtest tests/hashtest-256g tests/hmac tests/keygen tests/keygrip tests/mpitests +tests/pkcs1v2 tests/prime tests/pubkey tests/random tests/register tests/rsacvt +tests/t-convert +tests/t-cv25519 +tests/t-ed25519 +tests/t-kdf +tests/t-lock tests/t-mpi-bit +tests/t-mpi-point +tests/t-sexp tests/tsexp tests/version +tests/*.exe From jussi.kivilinna at iki.fi Sat Mar 12 18:42:53 2016 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sat, 12 Mar 2016 19:42:53 +0200 Subject: [PATCH 2/2] Add Intel PCLMUL implementations of CRC algorithms In-Reply-To: <20160312174248.12371.90456.stgit@localhost6.localdomain6> References: <20160312174248.12371.90456.stgit@localhost6.localdomain6> Message-ID: <20160312174253.12371.96469.stgit@localhost6.localdomain6> * cipher/Makefile.am: Add 'crc-intel-pclmul.c'. * cipher/crc-intel-pclmul.c: New. * cipher/crc.c (USE_INTEL_PCLMUL): New macro. (CRC_CONTEXT) [USE_INTEL_PCLMUL]: Add 'use_pclmul'. [USE_INTEL_PCLMUL] (_gcry_crc32_intel_pclmul) (gcry_crc24rfc2440_intel_pclmul): New. (crc32_init, crc32rfc1510_init, crc24rfc2440_init) [USE_INTEL_PCLMUL]: Select PCLMUL implementation if SSE4.1 and PCLMUL HW features detected. (crc32_write, crc24rfc2440_write) [USE_INTEL_PCLMUL]: Use PCLMUL implementation if enabled. (crc24_init): Document storage format of 24-bit CRC. (crc24_next4): Use only 'data' for last table look-up. * configure.ac: Add 'crc-intel-pclmul.lo'. * src/g10lib.h (HWF_*, HWF_INTEL_SSE4_1): Update HWF flags to include Intel SSE4.1. * src/hwf-x86.c (detect_x86_gnuc): Add SSE4.1 detection. * src/hwfeatures.c (hwflist): Add 'intel-sse4.1'. * tests/basic.c (fillbuf_count): New. (check_one_md): Add "?" check (million byte data-set with byte pattern 0x00,0x01,0x02,...); Test all buffer sizes 1 to 1000, for "!" and "?" checks. (check_one_md_multi): Skip "?". (check_digests): Add "?" test-vectors for MD5, SHA1, SHA224, SHA256, SHA384, SHA512, SHA3_224, SHA3_256, SHA3_384, SHA3_512, RIPEMD160, CRC32, CRC32_RFC1510, CRC24_RFC2440, TIGER1 and WHIRLPOOL; Add "!" test-vectors for CRC32_RFC1510 and CRC24_RFC2440. -- Add Intel PCLMUL accelerated implmentations of CRC algorithms. CRC performance is improved ~11x on x86_64 and i386 on Intel Haswell, and ~2.7x on Intel Sandy-bridge. Benchmark on Intel Core i5-4570 (x86_64, 3.2 Ghz): Before: | nanosecs/byte mebibytes/sec cycles/byte CRC32 | 0.865 ns/B 1103.0 MiB/s 2.77 c/B CRC32RFC1510 | 0.865 ns/B 1102.7 MiB/s 2.77 c/B CRC24RFC2440 | 0.865 ns/B 1103.0 MiB/s 2.77 c/B After: | nanosecs/byte mebibytes/sec cycles/byte CRC32 | 0.079 ns/B 12051.7 MiB/s 0.253 c/B CRC32RFC1510 | 0.079 ns/B 12050.6 MiB/s 0.253 c/B CRC24RFC2440 | 0.079 ns/B 12100.0 MiB/s 0.252 c/B Benchmark on Intel Core i5-4570 (i386, 3.2 Ghz): Before: | nanosecs/byte mebibytes/sec cycles/byte CRC32 | 0.860 ns/B 1109.0 MiB/s 2.75 c/B CRC32RFC1510 | 0.861 ns/B 1108.3 MiB/s 2.75 c/B CRC24RFC2440 | 0.860 ns/B 1108.6 MiB/s 2.75 c/B After: | nanosecs/byte mebibytes/sec cycles/byte CRC32 | 0.078 ns/B 12207.0 MiB/s 0.250 c/B CRC32RFC1510 | 0.078 ns/B 12207.0 MiB/s 0.250 c/B CRC24RFC2440 | 0.080 ns/B 11925.6 MiB/s 0.256 c/B Benchmark on Intel Core i5-2450M (x86_64, 2.5 Ghz): Before: | nanosecs/byte mebibytes/sec cycles/byte CRC32 | 1.25 ns/B 762.3 MiB/s 3.13 c/B CRC32RFC1510 | 1.26 ns/B 759.1 MiB/s 3.14 c/B CRC24RFC2440 | 1.25 ns/B 764.9 MiB/s 3.12 c/B After: | nanosecs/byte mebibytes/sec cycles/byte CRC32 | 0.451 ns/B 2114.3 MiB/s 1.13 c/B CRC32RFC1510 | 0.451 ns/B 2114.6 MiB/s 1.13 c/B CRC24RFC2440 | 0.457 ns/B 2085.0 MiB/s 1.14 c/B Signed-off-by: Jussi Kivilinna --- cipher/Makefile.am | 1 cipher/crc-intel-pclmul.c | 912 +++++++++++++++++++++++++++++++++++++++++++++ cipher/crc.c | 59 +++ configure.ac | 7 src/g10lib.h | 34 +- src/hwf-x86.c | 3 src/hwfeatures.c | 1 tests/basic.c | 95 ++++- 8 files changed, 1084 insertions(+), 28 deletions(-) create mode 100644 cipher/crc-intel-pclmul.c diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 65d7afb..ab71fa7 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -66,6 +66,7 @@ cast5.c cast5-amd64.S cast5-arm.S \ chacha20.c chacha20-sse2-amd64.S chacha20-ssse3-amd64.S chacha20-avx2-amd64.S \ chacha20-armv7-neon.S \ crc.c \ + crc-intel-pclmul.c \ des.c des-amd64.S \ dsa.c \ elgamal.c \ diff --git a/cipher/crc-intel-pclmul.c b/cipher/crc-intel-pclmul.c new file mode 100644 index 0000000..1b2da1a --- /dev/null +++ b/cipher/crc-intel-pclmul.c @@ -0,0 +1,912 @@ +/* crc.c - Cyclic redundancy checks. + * Copyright (C) 2003 Free Software Foundation, Inc. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + */ + +#include +#include +#include +#include + +#include "g10lib.h" + +#include "bithelp.h" +#include "bufhelp.h" + + +#if defined(ENABLE_PCLMUL_SUPPORT) && __GNUC__ >= 4 && \ + ((defined(__i386__) && SIZEOF_UNSIGNED_LONG == 4) || defined(__x86_64__)) + + +#if _GCRY_GCC_VERSION >= 40400 /* 4.4 */ +/* Prevent compiler from issuing SSE instructions between asm blocks. */ +# pragma GCC target("no-sse") +#endif + + +#define ALIGNED_16 __attribute__ ((aligned (16))) + + +/* Constants structure for generic reflected/non-reflected CRC32 CLMUL + * functions. */ +struct crc32_consts_s +{ + /* k: { x^(32*17), x^(32*15), x^(32*5), x^(32*3), x^(32*2), 0 } mod P(x) */ + u64 k[6]; + /* my_p: { floor(x^64 / P(x)), P(x) } */ + u64 my_p[2]; +}; + + +/* CLMUL constants for CRC32 and CRC32RFC1510. */ +static const struct crc32_consts_s crc32_consts ALIGNED_16 = +{ + { /* k[6] = reverse_33bits( x^(32*y) mod P(x) ) */ + U64_C(0x154442bd4), U64_C(0x1c6e41596), /* y = { 17, 15 } */ + U64_C(0x1751997d0), U64_C(0x0ccaa009e), /* y = { 5, 3 } */ + U64_C(0x163cd6124), 0 /* y = 2 */ + }, + { /* my_p[2] = reverse_33bits ( { floor(x^64 / P(x)), P(x) } ) */ + U64_C(0x1f7011641), U64_C(0x1db710641) + } +}; + +/* CLMUL constants for CRC24RFC2440 (polynomial multiplied with x?). */ +static const struct crc32_consts_s crc24rfc2440_consts ALIGNED_16 = +{ + { /* k[6] = x^(32*y) mod P(x) << 32*/ + U64_C(0x08289a00) << 32, U64_C(0x74b44a00) << 32, /* y = { 17, 15 } */ + U64_C(0xc4b14d00) << 32, U64_C(0xfd7e0c00) << 32, /* y = { 5, 3 } */ + U64_C(0xd9fe8c00) << 32, 0 /* y = 2 */ + }, + { /* my_p[2] = { floor(x^64 / P(x)), P(x) } */ + U64_C(0x1f845fe24), U64_C(0x1864cfb00) + } +}; + +/* Common constants for CRC32 algorithms. */ +static const byte crc32_refl_shuf_shift[3 * 16] ALIGNED_16 = + { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + }; +static const byte crc32_shuf_shift[3 * 16] ALIGNED_16 = + { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + }; +static const byte *crc32_bswap_shuf = &crc32_shuf_shift[16]; +static const byte crc32_partial_fold_input_mask[16 + 16] ALIGNED_16 = + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + }; +static const u64 crc32_merge9to15_shuf[15 - 9 + 1][2] ALIGNED_16 = + { + { U64_C(0x0706050403020100), U64_C(0xffffffffffffff0f) }, /* 9 */ + { U64_C(0x0706050403020100), U64_C(0xffffffffffff0f0e) }, + { U64_C(0x0706050403020100), U64_C(0xffffffffff0f0e0d) }, + { U64_C(0x0706050403020100), U64_C(0xffffffff0f0e0d0c) }, + { U64_C(0x0706050403020100), U64_C(0xffffff0f0e0d0c0b) }, + { U64_C(0x0706050403020100), U64_C(0xffff0f0e0d0c0b0a) }, + { U64_C(0x0706050403020100), U64_C(0xff0f0e0d0c0b0a09) }, /* 15 */ + }; +static const u64 crc32_merge5to7_shuf[7 - 5 + 1][2] ALIGNED_16 = + { + { U64_C(0xffffff0703020100), U64_C(0xffffffffffffffff) }, /* 5 */ + { U64_C(0xffff070603020100), U64_C(0xffffffffffffffff) }, + { U64_C(0xff07060503020100), U64_C(0xffffffffffffffff) }, /* 7 */ + }; + +/* PCLMUL functions for reflected CRC32. */ +static inline void +crc32_reflected_bulk (u32 *pcrc, const byte *inbuf, size_t inlen, + const struct crc32_consts_s *consts) +{ + if (inlen >= 8 * 16) + { + asm volatile ("movd %[crc], %%xmm4\n\t" + "movdqu %[inbuf_0], %%xmm0\n\t" + "movdqu %[inbuf_1], %%xmm1\n\t" + "movdqu %[inbuf_2], %%xmm2\n\t" + "movdqu %[inbuf_3], %%xmm3\n\t" + "pxor %%xmm4, %%xmm0\n\t" + : + : [inbuf_0] "m" (inbuf[0 * 16]), + [inbuf_1] "m" (inbuf[1 * 16]), + [inbuf_2] "m" (inbuf[2 * 16]), + [inbuf_3] "m" (inbuf[3 * 16]), + [crc] "m" (*pcrc) + : ); + + inbuf += 4 * 16; + inlen -= 4 * 16; + + asm volatile ("movdqa %[k1k2], %%xmm4\n\t" + : + : [k1k2] "m" (consts->k[1 - 1]) + : ); + + /* Fold by 4. */ + while (inlen >= 4 * 16) + { + asm volatile ("movdqu %[inbuf_0], %%xmm5\n\t" + "movdqa %%xmm0, %%xmm6\n\t" + "pclmulqdq $0x00, %%xmm4, %%xmm0\n\t" + "pclmulqdq $0x11, %%xmm4, %%xmm6\n\t" + "pxor %%xmm5, %%xmm0\n\t" + "pxor %%xmm6, %%xmm0\n\t" + + "movdqu %[inbuf_1], %%xmm5\n\t" + "movdqa %%xmm1, %%xmm6\n\t" + "pclmulqdq $0x00, %%xmm4, %%xmm1\n\t" + "pclmulqdq $0x11, %%xmm4, %%xmm6\n\t" + "pxor %%xmm5, %%xmm1\n\t" + "pxor %%xmm6, %%xmm1\n\t" + + "movdqu %[inbuf_2], %%xmm5\n\t" + "movdqa %%xmm2, %%xmm6\n\t" + "pclmulqdq $0x00, %%xmm4, %%xmm2\n\t" + "pclmulqdq $0x11, %%xmm4, %%xmm6\n\t" + "pxor %%xmm5, %%xmm2\n\t" + "pxor %%xmm6, %%xmm2\n\t" + + "movdqu %[inbuf_3], %%xmm5\n\t" + "movdqa %%xmm3, %%xmm6\n\t" + "pclmulqdq $0x00, %%xmm4, %%xmm3\n\t" + "pclmulqdq $0x11, %%xmm4, %%xmm6\n\t" + "pxor %%xmm5, %%xmm3\n\t" + "pxor %%xmm6, %%xmm3\n\t" + : + : [inbuf_0] "m" (inbuf[0 * 16]), + [inbuf_1] "m" (inbuf[1 * 16]), + [inbuf_2] "m" (inbuf[2 * 16]), + [inbuf_3] "m" (inbuf[3 * 16]) + : ); + + inbuf += 4 * 16; + inlen -= 4 * 16; + } + + asm volatile ("movdqa %[k3k4], %%xmm6\n\t" + "movdqa %[my_p], %%xmm5\n\t" + : + : [k3k4] "m" (consts->k[3 - 1]), + [my_p] "m" (consts->my_p[0]) + : ); + + /* Fold 4 to 1. */ + + asm volatile ("movdqa %%xmm0, %%xmm4\n\t" + "pclmulqdq $0x00, %%xmm6, %%xmm0\n\t" + "pclmulqdq $0x11, %%xmm6, %%xmm4\n\t" + "pxor %%xmm1, %%xmm0\n\t" + "pxor %%xmm4, %%xmm0\n\t" + + "movdqa %%xmm0, %%xmm4\n\t" + "pclmulqdq $0x00, %%xmm6, %%xmm0\n\t" + "pclmulqdq $0x11, %%xmm6, %%xmm4\n\t" + "pxor %%xmm2, %%xmm0\n\t" + "pxor %%xmm4, %%xmm0\n\t" + + "movdqa %%xmm0, %%xmm4\n\t" + "pclmulqdq $0x00, %%xmm6, %%xmm0\n\t" + "pclmulqdq $0x11, %%xmm6, %%xmm4\n\t" + "pxor %%xmm3, %%xmm0\n\t" + "pxor %%xmm4, %%xmm0\n\t" + : + : + : ); + } + else + { + asm volatile ("movd %[crc], %%xmm1\n\t" + "movdqu %[inbuf], %%xmm0\n\t" + "movdqa %[k3k4], %%xmm6\n\t" + "pxor %%xmm1, %%xmm0\n\t" + "movdqa %[my_p], %%xmm5\n\t" + : + : [inbuf] "m" (*inbuf), + [crc] "m" (*pcrc), + [k3k4] "m" (consts->k[3 - 1]), + [my_p] "m" (consts->my_p[0]) + : ); + + inbuf += 16; + inlen -= 16; + } + + /* Fold by 1. */ + if (inlen >= 16) + { + while (inlen >= 16) + { + /* Load next block to XMM2. Fold XMM0 to XMM0:XMM1. */ + asm volatile ("movdqu %[inbuf], %%xmm2\n\t" + "movdqa %%xmm0, %%xmm1\n\t" + "pclmulqdq $0x00, %%xmm6, %%xmm0\n\t" + "pclmulqdq $0x11, %%xmm6, %%xmm1\n\t" + "pxor %%xmm2, %%xmm0\n\t" + "pxor %%xmm1, %%xmm0\n\t" + : + : [inbuf] "m" (*inbuf) + : ); + + inbuf += 16; + inlen -= 16; + } + } + + /* Partial fold. */ + if (inlen) + { + /* Load last input and add padding zeros. */ + asm volatile ("movdqu %[shr_shuf], %%xmm3\n\t" + "movdqu %[shl_shuf], %%xmm4\n\t" + "movdqu %[mask], %%xmm2\n\t" + + "movdqa %%xmm0, %%xmm1\n\t" + "pshufb %%xmm4, %%xmm0\n\t" + "movdqu %[inbuf], %%xmm4\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "por %%xmm1, %%xmm2\n\t" + + "movdqa %%xmm0, %%xmm1\n\t" + "pclmulqdq $0x00, %%xmm6, %%xmm0\n\t" + "pclmulqdq $0x11, %%xmm6, %%xmm1\n\t" + "pxor %%xmm2, %%xmm0\n\t" + "pxor %%xmm1, %%xmm0\n\t" + : + : [inbuf] "m" (*(inbuf - 16 + inlen)), + [mask] "m" (crc32_partial_fold_input_mask[inlen]), + [shl_shuf] "m" (crc32_refl_shuf_shift[inlen]), + [shr_shuf] "m" (crc32_refl_shuf_shift[inlen + 16]) + : ); + + inbuf += inlen; + inlen -= inlen; + } + + /* Final fold. */ + asm volatile (/* reduce 128-bits to 96-bits */ + "movdqa %%xmm0, %%xmm1\n\t" + "pclmulqdq $0x10, %%xmm6, %%xmm0\n\t" + "psrldq $8, %%xmm1\n\t" + "pxor %%xmm1, %%xmm0\n\t" + + /* reduce 96-bits to 64-bits */ + "pshufd $0xfc, %%xmm0, %%xmm1\n\t" /* [00][00][00][x] */ + "pshufd $0xf9, %%xmm0, %%xmm0\n\t" /* [00][00][x>>64][x>>32] */ + "pclmulqdq $0x00, %[k5], %%xmm1\n\t" /* [00][00][xx][xx] */ + "pxor %%xmm1, %%xmm0\n\t" /* top 64-bit are zero */ + + /* barrett reduction */ + "pshufd $0xf3, %%xmm0, %%xmm1\n\t" /* [00][00][x>>32][00] */ + "pslldq $4, %%xmm0\n\t" /* [??][x>>32][??][??] */ + "pclmulqdq $0x00, %%xmm5, %%xmm1\n\t" /* [00][xx][xx][00] */ + "pclmulqdq $0x10, %%xmm5, %%xmm1\n\t" /* [00][xx][xx][00] */ + "pxor %%xmm1, %%xmm0\n\t" + + /* store CRC */ + "pextrd $2, %%xmm0, %[out]\n\t" + : [out] "=m" (*pcrc) + : [k5] "m" (consts->k[5 - 1]) + : ); +} + +static inline void +crc32_reflected_less_than_16 (u32 *pcrc, const byte *inbuf, size_t inlen, + const struct crc32_consts_s *consts) +{ + if (inlen < 4) + { + u32 crc = *pcrc; + u32 data; + + asm volatile ("movdqa %[my_p], %%xmm5\n\t" + : + : [my_p] "m" (consts->my_p[0]) + : ); + + if (inlen == 1) + { + data = inbuf[0]; + data ^= crc; + data <<= 24; + crc >>= 8; + } + else if (inlen == 2) + { + data = *((const u16 *)inbuf); + data ^= crc; + data <<= 16; + crc >>= 16; + } + else + { + data = *((const u16 *)inbuf); + data |= inbuf[2] << 16; + data ^= crc; + data <<= 8; + crc >>= 24; + } + + /* Barrett reduction */ + asm volatile ("movd %[in], %%xmm0\n\t" + "movd %[crc], %%xmm1\n\t" + + "pclmulqdq $0x00, %%xmm5, %%xmm0\n\t" /* [00][00][xx][xx] */ + "psllq $32, %%xmm1\n\t" + "pshufd $0xfc, %%xmm0, %%xmm0\n\t" /* [00][00][00][x] */ + "pclmulqdq $0x10, %%xmm5, %%xmm0\n\t" /* [00][00][xx][xx] */ + "pxor %%xmm1, %%xmm0\n\t" + + "pextrd $1, %%xmm0, %[out]\n\t" + : [out] "=m" (*pcrc) + : [in] "rm" (data), + [crc] "rm" (crc) + : ); + } + else if (inlen == 4) + { + /* Barrett reduction */ + asm volatile ("movd %[crc], %%xmm1\n\t" + "movd %[in], %%xmm0\n\t" + "movdqa %[my_p], %%xmm5\n\t" + "pxor %%xmm1, %%xmm0\n\t" + + "pclmulqdq $0x00, %%xmm5, %%xmm0\n\t" /* [00][00][xx][xx] */ + "pshufd $0xfc, %%xmm0, %%xmm0\n\t" /* [00][00][00][x] */ + "pclmulqdq $0x10, %%xmm5, %%xmm0\n\t" /* [00][00][xx][xx] */ + + "pextrd $1, %%xmm0, %[out]\n\t" + : [out] "=m" (*pcrc) + : [in] "m" (*inbuf), + [crc] "m" (*pcrc), + [my_p] "m" (consts->my_p[0]) + : ); + } + else + { + asm volatile ("movdqu %[shuf], %%xmm4\n\t" + "movd %[crc], %%xmm1\n\t" + "movdqa %[my_p], %%xmm5\n\t" + "movdqa %[k3k4], %%xmm6\n\t" + : + : [shuf] "m" (crc32_refl_shuf_shift[inlen]), + [crc] "m" (*pcrc), + [my_p] "m" (consts->my_p[0]), + [k3k4] "m" (consts->k[3 - 1]) + : ); + + if (inlen >= 8) + { + asm volatile ("movq %[inbuf], %%xmm0\n\t" + : + : [inbuf] "m" (*inbuf) + : ); + if (inlen > 8) + { + asm volatile (/*"pinsrq $1, %[inbuf_tail], %%xmm0\n\t"*/ + "movq %[inbuf_tail], %%xmm2\n\t" + "punpcklqdq %%xmm2, %%xmm0\n\t" + "pshufb %[merge_shuf], %%xmm0\n\t" + : + : [inbuf_tail] "m" (inbuf[inlen - 8]), + [merge_shuf] "m" + (*crc32_merge9to15_shuf[inlen - 9]) + : ); + } + } + else + { + asm volatile ("movd %[inbuf], %%xmm0\n\t" + "pinsrd $1, %[inbuf_tail], %%xmm0\n\t" + "pshufb %[merge_shuf], %%xmm0\n\t" + : + : [inbuf] "m" (*inbuf), + [inbuf_tail] "m" (inbuf[inlen - 4]), + [merge_shuf] "m" + (*crc32_merge5to7_shuf[inlen - 5]) + : ); + } + + /* Final fold. */ + asm volatile ("pxor %%xmm1, %%xmm0\n\t" + "pshufb %%xmm4, %%xmm0\n\t" + + /* reduce 128-bits to 96-bits */ + "movdqa %%xmm0, %%xmm1\n\t" + "pclmulqdq $0x10, %%xmm6, %%xmm0\n\t" + "psrldq $8, %%xmm1\n\t" + "pxor %%xmm1, %%xmm0\n\t" /* top 32-bit are zero */ + + /* reduce 96-bits to 64-bits */ + "pshufd $0xfc, %%xmm0, %%xmm1\n\t" /* [00][00][00][x] */ + "pshufd $0xf9, %%xmm0, %%xmm0\n\t" /* [00][00][x>>64][x>>32] */ + "pclmulqdq $0x00, %[k5], %%xmm1\n\t" /* [00][00][xx][xx] */ + "pxor %%xmm1, %%xmm0\n\t" /* top 64-bit are zero */ + + /* barrett reduction */ + "pshufd $0xf3, %%xmm0, %%xmm1\n\t" /* [00][00][x>>32][00] */ + "pslldq $4, %%xmm0\n\t" /* [??][x>>32][??][??] */ + "pclmulqdq $0x00, %%xmm5, %%xmm1\n\t" /* [00][xx][xx][00] */ + "pclmulqdq $0x10, %%xmm5, %%xmm1\n\t" /* [00][xx][xx][00] */ + "pxor %%xmm1, %%xmm0\n\t" + + /* store CRC */ + "pextrd $2, %%xmm0, %[out]\n\t" + : [out] "=m" (*pcrc) + : [k5] "m" (consts->k[5 - 1]) + : ); + } +} + +/* PCLMUL functions for non-reflected CRC32. */ +static inline void +crc32_bulk (u32 *pcrc, const byte *inbuf, size_t inlen, + const struct crc32_consts_s *consts) +{ + asm volatile ("movdqa %[bswap], %%xmm7\n\t" + : + : [bswap] "m" (*crc32_bswap_shuf) + : ); + + if (inlen >= 8 * 16) + { + asm volatile ("movd %[crc], %%xmm4\n\t" + "movdqu %[inbuf_0], %%xmm0\n\t" + "movdqu %[inbuf_1], %%xmm1\n\t" + "movdqu %[inbuf_2], %%xmm2\n\t" + "pxor %%xmm4, %%xmm0\n\t" + "movdqu %[inbuf_3], %%xmm3\n\t" + "pshufb %%xmm7, %%xmm0\n\t" + "pshufb %%xmm7, %%xmm1\n\t" + "pshufb %%xmm7, %%xmm2\n\t" + "pshufb %%xmm7, %%xmm3\n\t" + : + : [inbuf_0] "m" (inbuf[0 * 16]), + [inbuf_1] "m" (inbuf[1 * 16]), + [inbuf_2] "m" (inbuf[2 * 16]), + [inbuf_3] "m" (inbuf[3 * 16]), + [crc] "m" (*pcrc) + : ); + + inbuf += 4 * 16; + inlen -= 4 * 16; + + asm volatile ("movdqa %[k1k2], %%xmm4\n\t" + : + : [k1k2] "m" (consts->k[1 - 1]) + : ); + + /* Fold by 4. */ + while (inlen >= 4 * 16) + { + asm volatile ("movdqu %[inbuf_0], %%xmm5\n\t" + "movdqa %%xmm0, %%xmm6\n\t" + "pshufb %%xmm7, %%xmm5\n\t" + "pclmulqdq $0x01, %%xmm4, %%xmm0\n\t" + "pclmulqdq $0x10, %%xmm4, %%xmm6\n\t" + "pxor %%xmm5, %%xmm0\n\t" + "pxor %%xmm6, %%xmm0\n\t" + + "movdqu %[inbuf_1], %%xmm5\n\t" + "movdqa %%xmm1, %%xmm6\n\t" + "pshufb %%xmm7, %%xmm5\n\t" + "pclmulqdq $0x01, %%xmm4, %%xmm1\n\t" + "pclmulqdq $0x10, %%xmm4, %%xmm6\n\t" + "pxor %%xmm5, %%xmm1\n\t" + "pxor %%xmm6, %%xmm1\n\t" + + "movdqu %[inbuf_2], %%xmm5\n\t" + "movdqa %%xmm2, %%xmm6\n\t" + "pshufb %%xmm7, %%xmm5\n\t" + "pclmulqdq $0x01, %%xmm4, %%xmm2\n\t" + "pclmulqdq $0x10, %%xmm4, %%xmm6\n\t" + "pxor %%xmm5, %%xmm2\n\t" + "pxor %%xmm6, %%xmm2\n\t" + + "movdqu %[inbuf_3], %%xmm5\n\t" + "movdqa %%xmm3, %%xmm6\n\t" + "pshufb %%xmm7, %%xmm5\n\t" + "pclmulqdq $0x01, %%xmm4, %%xmm3\n\t" + "pclmulqdq $0x10, %%xmm4, %%xmm6\n\t" + "pxor %%xmm5, %%xmm3\n\t" + "pxor %%xmm6, %%xmm3\n\t" + : + : [inbuf_0] "m" (inbuf[0 * 16]), + [inbuf_1] "m" (inbuf[1 * 16]), + [inbuf_2] "m" (inbuf[2 * 16]), + [inbuf_3] "m" (inbuf[3 * 16]) + : ); + + inbuf += 4 * 16; + inlen -= 4 * 16; + } + + asm volatile ("movdqa %[k3k4], %%xmm6\n\t" + "movdqa %[my_p], %%xmm5\n\t" + : + : [k3k4] "m" (consts->k[3 - 1]), + [my_p] "m" (consts->my_p[0]) + : ); + + /* Fold 4 to 1. */ + + asm volatile ("movdqa %%xmm0, %%xmm4\n\t" + "pclmulqdq $0x01, %%xmm6, %%xmm0\n\t" + "pclmulqdq $0x10, %%xmm6, %%xmm4\n\t" + "pxor %%xmm1, %%xmm0\n\t" + "pxor %%xmm4, %%xmm0\n\t" + + "movdqa %%xmm0, %%xmm4\n\t" + "pclmulqdq $0x01, %%xmm6, %%xmm0\n\t" + "pclmulqdq $0x10, %%xmm6, %%xmm4\n\t" + "pxor %%xmm2, %%xmm0\n\t" + "pxor %%xmm4, %%xmm0\n\t" + + "movdqa %%xmm0, %%xmm4\n\t" + "pclmulqdq $0x01, %%xmm6, %%xmm0\n\t" + "pclmulqdq $0x10, %%xmm6, %%xmm4\n\t" + "pxor %%xmm3, %%xmm0\n\t" + "pxor %%xmm4, %%xmm0\n\t" + : + : + : ); + } + else + { + asm volatile ("movd %[crc], %%xmm1\n\t" + "movdqu %[inbuf], %%xmm0\n\t" + "movdqa %[k3k4], %%xmm6\n\t" + "pxor %%xmm1, %%xmm0\n\t" + "movdqa %[my_p], %%xmm5\n\t" + "pshufb %%xmm7, %%xmm0\n\t" + : + : [inbuf] "m" (*inbuf), + [crc] "m" (*pcrc), + [k3k4] "m" (consts->k[3 - 1]), + [my_p] "m" (consts->my_p[0]) + : ); + + inbuf += 16; + inlen -= 16; + } + + /* Fold by 1. */ + if (inlen >= 16) + { + while (inlen >= 16) + { + /* Load next block to XMM2. Fold XMM0 to XMM0:XMM1. */ + asm volatile ("movdqu %[inbuf], %%xmm2\n\t" + "movdqa %%xmm0, %%xmm1\n\t" + "pclmulqdq $0x01, %%xmm6, %%xmm0\n\t" + "pshufb %%xmm7, %%xmm2\n\t" + "pclmulqdq $0x10, %%xmm6, %%xmm1\n\t" + "pxor %%xmm2, %%xmm0\n\t" + "pxor %%xmm1, %%xmm0\n\t" + : + : [inbuf] "m" (*inbuf) + : ); + + inbuf += 16; + inlen -= 16; + } + } + + /* Partial fold. */ + if (inlen) + { + /* Load last input and add padding zeros. */ + asm volatile ("movdqu %[shl_shuf], %%xmm4\n\t" + "movdqu %[shr_shuf], %%xmm3\n\t" + "movdqu %[mask], %%xmm2\n\t" + + "movdqa %%xmm0, %%xmm1\n\t" + "pshufb %%xmm4, %%xmm0\n\t" + "movdqu %[inbuf], %%xmm4\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "por %%xmm1, %%xmm2\n\t" + + "pshufb %%xmm7, %%xmm2\n\t" + + "movdqa %%xmm0, %%xmm1\n\t" + "pclmulqdq $0x01, %%xmm6, %%xmm0\n\t" + "pclmulqdq $0x10, %%xmm6, %%xmm1\n\t" + "pxor %%xmm2, %%xmm0\n\t" + "pxor %%xmm1, %%xmm0\n\t" + : + : [inbuf] "m" (*(inbuf - 16 + inlen)), + [mask] "m" (crc32_partial_fold_input_mask[inlen]), + [shl_shuf] "m" (crc32_refl_shuf_shift[32 - inlen]), + [shr_shuf] "m" (crc32_shuf_shift[inlen + 16]) + : ); + + inbuf += inlen; + inlen -= inlen; + } + + /* Final fold. */ + asm volatile (/* reduce 128-bits to 96-bits */ + "movdqa %%xmm0, %%xmm1\n\t" + "pclmulqdq $0x11, %%xmm6, %%xmm0\n\t" + "pslldq $8, %%xmm1\n\t" + "pxor %%xmm1, %%xmm0\n\t" /* bottom 32-bit are zero */ + + /* reduce 96-bits to 64-bits */ + "pshufd $0x30, %%xmm0, %%xmm1\n\t" /* [00][x>>96][00][00] */ + "pshufd $0x24, %%xmm0, %%xmm0\n\t" /* [00][xx][xx][00] */ + "pclmulqdq $0x01, %[k5], %%xmm1\n\t" /* [00][xx][xx][00] */ + "pxor %%xmm1, %%xmm0\n\t" /* top and bottom 32-bit are zero */ + + /* barrett reduction */ + "pshufd $0x01, %%xmm0, %%xmm1\n\t" /* [00][00][00][x>>32] */ + "pclmulqdq $0x01, %%xmm5, %%xmm0\n\t" /* [00][xx][xx][xx] */ + "psrldq $4, %%xmm0\n\t" /* [00][00][xx][xx] */ + "pclmulqdq $0x10, %%xmm5, %%xmm0\n\t" + "pxor %%xmm1, %%xmm0\n\t" + + /* store CRC in input endian */ + "movd %%xmm0, %%eax\n\t" + "bswapl %%eax\n\t" + "movl %%eax, %[out]\n\t" + : [out] "=m" (*pcrc) + : [k5] "m" (consts->k[5 - 1]) + : "eax" ); +} + +static inline void +crc32_less_than_16 (u32 *pcrc, const byte *inbuf, size_t inlen, + const struct crc32_consts_s *consts) +{ + if (inlen < 4) + { + u32 crc = *pcrc; + u32 data; + + asm volatile ("movdqa %[my_p], %%xmm5\n\t" + : + : [my_p] "m" (consts->my_p[0]) + : ); + + if (inlen == 1) + { + data = inbuf[0]; + data ^= crc; + data = _gcry_bswap32(data << 24); + crc = _gcry_bswap32(crc >> 8); + } + else if (inlen == 2) + { + data = *((const u16 *)inbuf); + data ^= crc; + data = _gcry_bswap32(data << 16); + crc = _gcry_bswap32(crc >> 16); + } + else + { + data = *((const u16 *)inbuf); + data |= inbuf[2] << 16; + data ^= crc; + data = _gcry_bswap32(data << 8); + crc = _gcry_bswap32(crc >> 24); + } + + /* Barrett reduction */ + asm volatile ("movd %[in], %%xmm0\n\t" + "psllq $32, %%xmm0\n\t" /* [00][00][xx][00] */ + "movd %[crc], %%xmm1\n\t" + + "pclmulqdq $0x00, %%xmm5, %%xmm0\n\t" /* [00][xx][xx][00] */ + "pclmulqdq $0x11, %%xmm5, %%xmm0\n\t" /* [00][00][xx][xx] */ + "pxor %%xmm1, %%xmm0\n\t" + + /* store CRC in input endian */ + "movd %%xmm0, %%eax\n\t" + "bswapl %%eax\n\t" + "movl %%eax, %[out]\n\t" + : [out] "=m" (*pcrc) + : [in] "r" (data), + [crc] "r" (crc) + : "eax" ); + } + else if (inlen == 4) + { + /* Barrett reduction */ + asm volatile ("movd %[crc], %%xmm0\n\t" + "movd %[in], %%xmm1\n\t" + "movdqa %[my_p], %%xmm5\n\t" + "pxor %%xmm1, %%xmm0\n\t" + "pshufb %[bswap], %%xmm0\n\t" /* [xx][00][00][00] */ + + "pclmulqdq $0x01, %%xmm5, %%xmm0\n\t" /* [00][xx][xx][00] */ + "pclmulqdq $0x11, %%xmm5, %%xmm0\n\t" /* [00][00][xx][xx] */ + + /* store CRC in input endian */ + "movd %%xmm0, %%eax\n\t" + "bswapl %%eax\n\t" + "movl %%eax, %[out]\n\t" + : [out] "=m" (*pcrc) + : [in] "m" (*inbuf), + [crc] "m" (*pcrc), + [my_p] "m" (consts->my_p[0]), + [bswap] "m" (*crc32_bswap_shuf) + : "eax" ); + } + else + { + asm volatile ("movdqu %[shuf], %%xmm7\n\t" + "movd %[crc], %%xmm1\n\t" + "movdqa %[my_p], %%xmm5\n\t" + "movdqa %[k3k4], %%xmm6\n\t" + : + : [shuf] "m" (crc32_shuf_shift[32 - inlen]), + [crc] "m" (*pcrc), + [my_p] "m" (consts->my_p[0]), + [k3k4] "m" (consts->k[3 - 1]) + : ); + + if (inlen >= 8) + { + asm volatile ("movq %[inbuf], %%xmm0\n\t" + : + : [inbuf] "m" (*inbuf) + : ); + if (inlen > 8) + { + asm volatile (/*"pinsrq $1, %[inbuf_tail], %%xmm0\n\t"*/ + "movq %[inbuf_tail], %%xmm2\n\t" + "punpcklqdq %%xmm2, %%xmm0\n\t" + "pshufb %[merge_shuf], %%xmm0\n\t" + : + : [inbuf_tail] "m" (inbuf[inlen - 8]), + [merge_shuf] "m" + (*crc32_merge9to15_shuf[inlen - 9]) + : ); + } + } + else + { + asm volatile ("movd %[inbuf], %%xmm0\n\t" + "pinsrd $1, %[inbuf_tail], %%xmm0\n\t" + "pshufb %[merge_shuf], %%xmm0\n\t" + : + : [inbuf] "m" (*inbuf), + [inbuf_tail] "m" (inbuf[inlen - 4]), + [merge_shuf] "m" + (*crc32_merge5to7_shuf[inlen - 5]) + : ); + } + + /* Final fold. */ + asm volatile ("pxor %%xmm1, %%xmm0\n\t" + "pshufb %%xmm7, %%xmm0\n\t" + + /* reduce 128-bits to 96-bits */ + "movdqa %%xmm0, %%xmm1\n\t" + "pclmulqdq $0x11, %%xmm6, %%xmm0\n\t" + "pslldq $8, %%xmm1\n\t" + "pxor %%xmm1, %%xmm0\n\t" /* bottom 32-bit are zero */ + + /* reduce 96-bits to 64-bits */ + "pshufd $0x30, %%xmm0, %%xmm1\n\t" /* [00][x>>96][00][00] */ + "pshufd $0x24, %%xmm0, %%xmm0\n\t" /* [00][xx][xx][00] */ + "pclmulqdq $0x01, %[k5], %%xmm1\n\t" /* [00][xx][xx][00] */ + "pxor %%xmm1, %%xmm0\n\t" /* top and bottom 32-bit are zero */ + + /* barrett reduction */ + "pshufd $0x01, %%xmm0, %%xmm1\n\t" /* [00][00][00][x>>32] */ + "pclmulqdq $0x01, %%xmm5, %%xmm0\n\t" /* [00][xx][xx][xx] */ + "psrldq $4, %%xmm0\n\t" /* [00][00][xx][xx] */ + "pclmulqdq $0x10, %%xmm5, %%xmm0\n\t" + "pxor %%xmm1, %%xmm0\n\t" + + /* store CRC in input endian */ + "movd %%xmm0, %%eax\n\t" + "bswapl %%eax\n\t" + "movl %%eax, %[out]\n\t" + : [out] "=m" (*pcrc) + : [k5] "m" (consts->k[5 - 1]) + : "eax" ); + } +} + +void +_gcry_crc32_intel_pclmul (u32 *pcrc, const byte *inbuf, size_t inlen) +{ + const struct crc32_consts_s *consts = &crc32_consts; +#if defined(__x86_64__) && defined(__WIN64__) + char win64tmp[2 * 16]; + + /* XMM6-XMM7 need to be restored after use. */ + asm volatile ("movdqu %%xmm6, 0*16(%0)\n\t" + "movdqu %%xmm7, 1*16(%0)\n\t" + : + : "r" (win64tmp) + : "memory"); +#endif + + if (!inlen) + return; + + if (inlen >= 16) + crc32_reflected_bulk(pcrc, inbuf, inlen, consts); + else + crc32_reflected_less_than_16(pcrc, inbuf, inlen, consts); + +#if defined(__x86_64__) && defined(__WIN64__) + /* Restore used registers. */ + asm volatile("movdqu 0*16(%0), %%xmm6\n\t" + "movdqu 1*16(%0), %%xmm7\n\t" + : + : "r" (win64tmp) + : "memory"); +#endif +} + +void +_gcry_crc24rfc2440_intel_pclmul (u32 *pcrc, const byte *inbuf, size_t inlen) +{ + const struct crc32_consts_s *consts = &crc24rfc2440_consts; +#if defined(__x86_64__) && defined(__WIN64__) + char win64tmp[2 * 16]; + + /* XMM6-XMM7 need to be restored after use. */ + asm volatile ("movdqu %%xmm6, 0*16(%0)\n\t" + "movdqu %%xmm7, 1*16(%0)\n\t" + : + : "r" (win64tmp) + : "memory"); +#endif + + if (!inlen) + return; + + /* Note: *pcrc in input endian. */ + + if (inlen >= 16) + crc32_bulk(pcrc, inbuf, inlen, consts); + else + crc32_less_than_16(pcrc, inbuf, inlen, consts); + +#if defined(__x86_64__) && defined(__WIN64__) + /* Restore used registers. */ + asm volatile("movdqu 0*16(%0), %%xmm6\n\t" + "movdqu 1*16(%0), %%xmm7\n\t" + : + : "r" (win64tmp) + : "memory"); +#endif +} + +#endif /* USE_INTEL_PCLMUL */ diff --git a/cipher/crc.c b/cipher/crc.c index 46a185a..ee0e4e2 100644 --- a/cipher/crc.c +++ b/cipher/crc.c @@ -31,14 +31,37 @@ #include "bufhelp.h" +/* USE_INTEL_PCLMUL indicates whether to compile CRC with Intel PCLMUL + * code. */ +#undef USE_INTEL_PCLMUL +#ifdef ENABLE_PCLMUL_SUPPORT +# if ((defined(__i386__) && SIZEOF_UNSIGNED_LONG == 4) || defined(__x86_64__)) +# if __GNUC__ >= 4 +# define USE_INTEL_PCLMUL 1 +# endif +# endif +#endif /* USE_INTEL_PCLMUL */ + + typedef struct { u32 CRC; +#ifdef USE_INTEL_PCLMUL + unsigned int use_pclmul:1; /* Intel PCLMUL shall be used. */ +#endif byte buf[4]; } CRC_CONTEXT; +#ifdef USE_INTEL_PCLMUL +/*-- crc-intel-pclmul.c --*/ +void _gcry_crc32_intel_pclmul (u32 *pcrc, const byte *inbuf, size_t inlen); +void _gcry_crc24rfc2440_intel_pclmul (u32 *pcrc, const byte *inbuf, + size_t inlen); +#endif + + /* * Code generated by universal_crc by Danjel McGougan * @@ -338,6 +361,11 @@ static void crc32_init (void *context, unsigned int flags) { CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; +#ifdef USE_INTEL_PCLMUL + u32 hwf = _gcry_get_hw_features (); + + ctx->use_pclmul = (hwf & HWF_INTEL_SSE4_1) && (hwf & HWF_INTEL_PCLMUL); +#endif (void)flags; @@ -351,6 +379,14 @@ crc32_write (void *context, const void *inbuf_arg, size_t inlen) const byte *inbuf = inbuf_arg; u32 crc; +#ifdef USE_INTEL_PCLMUL + if (ctx->use_pclmul) + { + _gcry_crc32_intel_pclmul(&ctx->CRC, inbuf, inlen); + return; + } +#endif + if (!inbuf || !inlen) return; @@ -403,6 +439,11 @@ static void crc32rfc1510_init (void *context, unsigned int flags) { CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; +#ifdef USE_INTEL_PCLMUL + u32 hwf = _gcry_get_hw_features (); + + ctx->use_pclmul = (hwf & HWF_INTEL_SSE4_1) && (hwf & HWF_INTEL_PCLMUL); +#endif (void)flags; @@ -694,7 +735,8 @@ static const u32 crc24_table[1024] = static inline u32 crc24_init (void) { - return 0xce04b7; + /* Transformed to 32-bit CRC by multiplied by x? and then byte swapped. */ + return 0xce04b7; /* _gcry_bswap(0xb704ce << 8) */ } static inline @@ -713,7 +755,7 @@ u32 crc24_next4 (u32 crc, u32 data) crc = crc24_table[(crc & 0xff) + 0x300] ^ crc24_table[((crc >> 8) & 0xff) + 0x200] ^ crc24_table[((crc >> 16) & 0xff) + 0x100] ^ - crc24_table[(crc >> 24) & 0xff]; + crc24_table[(data >> 24) & 0xff]; return crc; } @@ -727,6 +769,11 @@ static void crc24rfc2440_init (void *context, unsigned int flags) { CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; +#ifdef USE_INTEL_PCLMUL + u32 hwf = _gcry_get_hw_features (); + + ctx->use_pclmul = (hwf & HWF_INTEL_SSE4_1) && (hwf & HWF_INTEL_PCLMUL); +#endif (void)flags; @@ -740,6 +787,14 @@ crc24rfc2440_write (void *context, const void *inbuf_arg, size_t inlen) CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; u32 crc; +#ifdef USE_INTEL_PCLMUL + if (ctx->use_pclmul) + { + _gcry_crc24rfc2440_intel_pclmul(&ctx->CRC, inbuf, inlen); + return; + } +#endif + if (!inbuf || !inlen) return; diff --git a/configure.ac b/configure.ac index 8b50360..ff72e3f 100644 --- a/configure.ac +++ b/configure.ac @@ -2023,6 +2023,13 @@ LIST_MEMBER(crc, $enabled_digests) if test "$found" = "1" ; then GCRYPT_DIGESTS="$GCRYPT_DIGESTS crc.lo" AC_DEFINE(USE_CRC, 1, [Defined if this module should be included]) + + case "${host}" in + i?86-*-* | x86_64-*-*) + # Build with the assembly implementation + GCRYPT_DIGESTS="$GCRYPT_DIGESTS crc-intel-pclmul.lo" + ;; + esac fi LIST_MEMBER(gostr3411-94, $enabled_digests) diff --git a/src/g10lib.h b/src/g10lib.h index 9d2ece9..7352556 100644 --- a/src/g10lib.h +++ b/src/g10lib.h @@ -194,23 +194,23 @@ char **_gcry_strtokenize (const char *string, const char *delim); /*-- src/hwfeatures.c --*/ -/* (Do not change these values unless synced with the asm code.) */ -#define HWF_PADLOCK_RNG 1 -#define HWF_PADLOCK_AES 2 -#define HWF_PADLOCK_SHA 4 -#define HWF_PADLOCK_MMUL 8 - -#define HWF_INTEL_CPU 16 -#define HWF_INTEL_FAST_SHLD 32 -#define HWF_INTEL_BMI2 64 -#define HWF_INTEL_SSSE3 128 -#define HWF_INTEL_PCLMUL 256 -#define HWF_INTEL_AESNI 512 -#define HWF_INTEL_RDRAND 1024 -#define HWF_INTEL_AVX 2048 -#define HWF_INTEL_AVX2 4096 - -#define HWF_ARM_NEON 8192 +#define HWF_PADLOCK_RNG (1 << 0) +#define HWF_PADLOCK_AES (1 << 1) +#define HWF_PADLOCK_SHA (1 << 2) +#define HWF_PADLOCK_MMUL (1 << 3) + +#define HWF_INTEL_CPU (1 << 4) +#define HWF_INTEL_FAST_SHLD (1 << 5) +#define HWF_INTEL_BMI2 (1 << 6) +#define HWF_INTEL_SSSE3 (1 << 7) +#define HWF_INTEL_SSE4_1 (1 << 8) +#define HWF_INTEL_PCLMUL (1 << 9) +#define HWF_INTEL_AESNI (1 << 10) +#define HWF_INTEL_RDRAND (1 << 11) +#define HWF_INTEL_AVX (1 << 12) +#define HWF_INTEL_AVX2 (1 << 13) + +#define HWF_ARM_NEON (1 << 14) gpg_err_code_t _gcry_disable_hw_feature (const char *name); diff --git a/src/hwf-x86.c b/src/hwf-x86.c index fbd6331..eeacccb 100644 --- a/src/hwf-x86.c +++ b/src/hwf-x86.c @@ -277,6 +277,9 @@ detect_x86_gnuc (void) /* Test bit 9 for SSSE3. */ if (features & 0x00000200) result |= HWF_INTEL_SSSE3; + /* Test bit 19 for SSE4.1. */ + if (features & 0x00080000) + result |= HWF_INTEL_SSE4_1; #ifdef ENABLE_AESNI_SUPPORT /* Test bit 25 for AES-NI. */ if (features & 0x02000000) diff --git a/src/hwfeatures.c b/src/hwfeatures.c index e7c55cc..4cafae1 100644 --- a/src/hwfeatures.c +++ b/src/hwfeatures.c @@ -50,6 +50,7 @@ static struct { HWF_INTEL_FAST_SHLD, "intel-fast-shld" }, { HWF_INTEL_BMI2, "intel-bmi2" }, { HWF_INTEL_SSSE3, "intel-ssse3" }, + { HWF_INTEL_SSE4_1, "intel-sse4.1" }, { HWF_INTEL_PCLMUL, "intel-pclmul" }, { HWF_INTEL_AESNI, "intel-aesni" }, { HWF_INTEL_RDRAND, "intel-rdrand" }, diff --git a/tests/basic.c b/tests/basic.c index 7d5de00..3d2db64 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -5267,6 +5267,14 @@ check_cipher_modes(void) static void +fillbuf_count (char *buf, size_t buflen, unsigned char pos) +{ + while (buflen--) + *((unsigned char *)(buf++)) = pos++; +} + + +static void check_one_md (int algo, const char *data, int len, const char *expect, int elen) { gcry_md_hd_t hd, hd2; @@ -5297,14 +5305,33 @@ check_one_md (int algo, const char *data, int len, const char *expect, int elen) } } - if (*data == '!' && !data[1]) - { /* hash one million times a "a" */ + if ((*data == '!' && !data[1]) || /* hash one million times a "a" */ + (*data == '?' && !data[1])) /* hash million byte data-set with byte pattern 0x00,0x01,0x02,... */ + { char aaa[1000]; size_t left = 1000 * 1000; size_t startlen = 1; size_t piecelen = startlen; - memset (aaa, 'a', 1000); + if (*data == '!') + memset (aaa, 'a', 1000); + + /* Write in chuck with all sizes 1 to 1000 (500500 bytes) */ + for (i = 1; i <= 1000 && left > 0; i++) + { + piecelen = i; + if (piecelen > sizeof(aaa)) + piecelen = sizeof(aaa); + if (piecelen > left) + piecelen = left; + + if (*data == '?') + fillbuf_count(aaa, piecelen, 1000 * 1000 - left); + + gcry_md_write (hd, aaa, piecelen); + + left -= piecelen; + } /* Write in odd size chunks so that we test the buffering. */ while (left > 0) @@ -5314,6 +5341,9 @@ check_one_md (int algo, const char *data, int len, const char *expect, int elen) if (piecelen > left) piecelen = left; + if (*data == '?') + fillbuf_count(aaa, piecelen, 1000 * 1000 - left); + gcry_md_write (hd, aaa, piecelen); left -= piecelen; @@ -5526,6 +5556,8 @@ check_one_md_multi (int algo, const char *data, int len, const char *expect) if (*data == '!' && !data[1]) return; /* We can't do that here. */ + if (*data == '?' && !data[1]) + return; /* We can't do that here. */ memset (iov, 0, sizeof iov); @@ -5616,6 +5648,8 @@ check_digests (void) "\xc4\x1a\x5c\x0b\x44\x5f\xba\x1a\xda\xbc\xc0\x38\x0e\x0c\x9e\x33" }, { GCRY_MD_MD5, "!", "\x77\x07\xd6\xae\x4e\x02\x7c\x70\xee\xa2\xa9\x35\xc2\x29\x6f\x21" }, + { GCRY_MD_MD5, "?", + "\x5c\x72\x5c\xbc\x2d\xbb\xe1\x14\x81\x59\xe9\xd9\xcf\x90\x64\x8f" }, { GCRY_MD_SHA1, "abc", "\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E" "\x25\x71\x78\x50\xC2\x6C\x9C\xD0\xD8\x9D" }, @@ -5626,6 +5660,9 @@ check_digests (void) { GCRY_MD_SHA1, "!" /* kludge for "a"*1000000 */ , "\x34\xAA\x97\x3C\xD4\xC4\xDA\xA4\xF6\x1E" "\xEB\x2B\xDB\xAD\x27\x31\x65\x34\x01\x6F" }, + { GCRY_MD_SHA1, "?" /* kludge for "\x00\x01\x02"..."\xfe\xff\x00\x01"... (length 1000000) */ , + "\x5f\x8d\x3c\x4f\x12\xf0\x49\x9e\x28\x73" + "\x79\xec\x97\x3b\x98\x4c\x94\x75\xaa\x8f" }, { GCRY_MD_SHA1, "Libgcrypt is free software; you can redistribute it and/or modif" "y it under the terms of the GNU Lesser general Public License as" @@ -5648,6 +5685,9 @@ check_digests (void) { GCRY_MD_SHA224, "!", "\x20\x79\x46\x55\x98\x0c\x91\xd8\xbb\xb4\xc1\xea\x97\x61\x8a\x4b" "\xf0\x3f\x42\x58\x19\x48\xb2\xee\x4e\xe7\xad\x67" }, + { GCRY_MD_SHA224, "?", + "\xfa\xb9\xf0\xdf\x12\xfe\xa1\x1a\x34\x78\x96\x31\xe6\x53\x48\xbf" + "\x3b\xca\x70\x78\xf2\x44\xdf\x62\xab\x27\xb8\xda" }, { GCRY_MD_SHA224, "Libgcrypt is free software; you can redistribute it and/or modif" "y it under the terms of the GNU Lesser general Public License as" @@ -5669,6 +5709,9 @@ check_digests (void) { GCRY_MD_SHA256, "!", "\xcd\xc7\x6e\x5c\x99\x14\xfb\x92\x81\xa1\xc7\xe2\x84\xd7\x3e\x67" "\xf1\x80\x9a\x48\xa4\x97\x20\x0e\x04\x6d\x39\xcc\xc7\x11\x2c\xd0" }, + { GCRY_MD_SHA256, "?", + "\x67\x87\x0d\xfc\x9c\x64\xe7\xaa\x27\x0a\x3f\x7e\x80\x51\xae\x65" + "\xd2\x07\xf9\x3f\xc3\xdf\x04\xd7\x57\x2e\x63\x65\xaf\x69\xcd\x0d" }, { GCRY_MD_SHA256, "Libgcrypt is free software; you can redistribute it and/or modif" "y it under the terms of the GNU Lesser general Public License as" @@ -5700,6 +5743,10 @@ check_digests (void) "\x9d\x0e\x18\x09\x71\x64\x74\xcb\x08\x6e\x83\x4e\x31\x0a\x4a\x1c" "\xed\x14\x9e\x9c\x00\xf2\x48\x52\x79\x72\xce\xc5\x70\x4c\x2a\x5b" "\x07\xb8\xb3\xdc\x38\xec\xc4\xeb\xae\x97\xdd\xd8\x7f\x3d\x89\x85" }, + { GCRY_MD_SHA384, "?", + "\xfa\x77\xbb\x86\x3a\xd5\xae\x88\xa9\x9c\x5e\xda\xb5\xc7\xcb\x40" + "\xcd\xf4\x30\xef\xa8\x1b\x23\x7b\xa9\xde\xfd\x81\x12\xf6\x7e\xed" + "\xa7\xd2\x27\x91\xd1\xbc\x76\x44\x57\x59\x71\x11\xe6\x8a\x2c\xde" }, { GCRY_MD_SHA512, "abc", "\xDD\xAF\x35\xA1\x93\x61\x7A\xBA\xCC\x41\x73\x49\xAE\x20\x41\x31" "\x12\xE6\xFA\x4E\x89\xA9\x7E\xA2\x0A\x9E\xEE\xE6\x4B\x55\xD3\x9A" @@ -5723,6 +5770,11 @@ check_digests (void) "\x8e\x1f\x98\xb1\x3b\x20\x44\x28\x56\x32\xa8\x03\xaf\xa9\x73\xeb" "\xde\x0f\xf2\x44\x87\x7e\xa6\x0a\x4c\xb0\x43\x2c\xe5\x77\xc3\x1b" "\xeb\x00\x9c\x5c\x2c\x49\xaa\x2e\x4e\xad\xb2\x17\xad\x8c\xc0\x9b" }, + { GCRY_MD_SHA512, "?", + "\x91\xe9\x42\x4e\xa9\xdc\x44\x01\x40\x64\xa4\x5a\x69\xcc\xac\xa3" + "\x74\xee\x78\xeb\x79\x1f\x94\x38\x5b\x73\xef\xf8\xfd\x5d\x74\xd8" + "\x51\x36\xfe\x63\x52\xde\x07\x70\x95\xd6\x78\x2b\x7b\x46\x8a\x2c" + "\x30\x0f\x48\x0c\x74\x43\x06\xdb\xa3\x8d\x64\x3d\xe9\xa1\xa7\x72" }, { GCRY_MD_SHA3_224, "abc", "\xe6\x42\x82\x4c\x3f\x8c\xf2\x4a\xd0\x92\x34\xee\x7d\x3c\x76\x6f" "\xc9\xa3\xa5\x16\x8d\x0c\x94\xad\x73\xb4\x6f\xdf" }, @@ -5806,6 +5858,21 @@ check_digests (void) "\x12\x0a\x2a\x53\x70\x21\x2d\xff\xb3\x38\x5a\x18\xd4\xf3\x88\x59" "\xed\x31\x1d\x0a\x9d\x51\x41\xce\x9c\xc5\xc6\x6e\xe6\x89\xb2\x66" "\xa8\xaa\x18\xac\xe8\x28\x2a\x0e\x0d\xb5\x96\xc9\x0b\x0a\x7b\x87" }, + { GCRY_MD_SHA3_224, "?", + "\x1b\xd1\xc6\x12\x02\x35\x52\x8b\x44\x7e\x16\x39\x20\x05\xec\x67" + "\x2d\x57\x20\xe0\x90\xc9\x78\x08\x86\x4f\x1b\xd0" }, + { GCRY_MD_SHA3_256, "?", + "\xfe\xb7\xf4\x76\x78\x97\x48\x2f\xe2\x29\x1b\x66\x85\xc1\x7b\x45" + "\xc5\x08\xed\x82\x50\xcc\x5d\x99\x96\xd2\xc3\x82\x1a\xa8\xd4\xa7" }, + { GCRY_MD_SHA3_384, "?", + "\x45\x1f\x0b\x93\x4b\xca\x3e\x65\x93\xd4\xaa\x8c\x18\xc1\x04\x84" + "\x12\xd5\x1e\x35\xe1\x05\xd9\x77\x3f\xc1\x08\x8b\x77\x36\xad\x4a" + "\x33\x70\xaf\x49\x8b\xea\x4c\x5c\x52\xe7\x5b\xed\x31\x74\x57\x12" }, + { GCRY_MD_SHA3_512, "?", + "\xa2\xee\xb5\x6f\x2a\x87\xa5\xb3\x9b\xd9\x1c\xf0\xaa\xdf\xb1\xd5" + "\xad\x0a\x1a\xaa\xd3\x63\x81\xcf\xb8\x7c\x36\xa7\x80\x3b\x03\xd6" + "\x31\x5c\x5d\x33\x8e\x52\xb1\x42\x4d\x27\x1c\xa2\xa5\xf2\xc5\x97" + "\x10\x12\xe5\xee\x86\xa3\xcc\xaf\x91\x7a\x94\x28\x65\xea\x66\xe3" }, { GCRY_MD_RMD160, "", "\x9c\x11\x85\xa5\xc5\xe9\xfc\x54\x61\x28" "\x08\x97\x7e\xe8\xf5\x48\xb2\x25\x8d\x31" }, @@ -5832,6 +5899,9 @@ check_digests (void) { GCRY_MD_RMD160, "!", "\x52\x78\x32\x43\xc1\x69\x7b\xdb\xe1\x6d\x37\xf9\x7f\x68\xf0\x83" "\x25\xdc\x15\x28" }, + { GCRY_MD_RMD160, "?", + "\x68\x14\x86\x70\x3d\x51\x4e\x36\x68\x50\xf8\xb3\x00\x75\xda\x49" + "\x0a\xaa\x2c\xf6" }, { GCRY_MD_CRC32, "", "\x00\x00\x00\x00" }, { GCRY_MD_CRC32, "foo", "\x8c\x73\x65\x21" }, { GCRY_MD_CRC32, @@ -5846,6 +5916,7 @@ check_digests (void) "\x4A\x53\x7D\x67" }, { GCRY_MD_CRC32, "123456789", "\xcb\xf4\x39\x26" }, { GCRY_MD_CRC32, "!", "\xdc\x25\xbf\xbc" }, + { GCRY_MD_CRC32, "?", "\x61\x82\x29\x1B" }, { GCRY_MD_CRC32_RFC1510, "", "\x00\x00\x00\x00" }, { GCRY_MD_CRC32_RFC1510, "foo", "\x73\x32\xbc\x33" }, { GCRY_MD_CRC32_RFC1510, "test0123456789", "\xb8\x3e\x88\xd6" }, @@ -5858,9 +5929,12 @@ check_digests (void) { GCRY_MD_CRC32_RFC1510, "\x80\x00\x00\x00", "\xed\x59\xb6\x3b", 4 }, { GCRY_MD_CRC32_RFC1510, "\x00\x00\x00\x01", "\x77\x07\x30\x96", 4 }, { GCRY_MD_CRC32_RFC1510, "123456789", "\x2d\xfd\x2d\x88" }, - { GCRY_MD_CRC24_RFC2440, "", "\xb7\x04\xce" }, + { GCRY_MD_CRC32_RFC1510, "!", "\xce\x5c\x74\x22" }, + { GCRY_MD_CRC32_RFC1510, "?", "\x73\xfb\xe2\x85" }, { GCRY_MD_CRC24_RFC2440, "foo", "\x4f\xc2\x55" }, { GCRY_MD_CRC24_RFC2440, "123456789", "\x21\xcf\x02" }, + { GCRY_MD_CRC24_RFC2440, "!", "\xa5\xcb\x6b" }, + { GCRY_MD_CRC24_RFC2440, "?", "\x7f\x67\x03" }, { GCRY_MD_TIGER, "", "\x24\xF0\x13\x0C\x63\xAC\x93\x32\x16\x16\x6E\x76" @@ -5942,6 +6016,9 @@ check_digests (void) "ral Public License for more details.", "\x60\xee\xdf\x95\x39\xc8\x44\x94\x64\xdc\xdf\x3d\x2e\x1c\xe5\x79" "\x6a\x95\xbd\x30\x68\x8c\x7e\xb8" }, + { GCRY_MD_TIGER1, "?", + "\x4b\xe2\x3f\x23\xf5\x34\xbe\xbf\x97\x42\x95\x80" + "\x54\xe4\x6c\x12\x64\x85\x44\x0a\xa9\x49\x9b\x65" }, { GCRY_MD_TIGER2, "", "\x44\x41\xBE\x75\xF6\x01\x87\x73\xC2\x06\xC2\x27" @@ -5986,11 +6063,11 @@ check_digests (void) "\xF0\xDF\xF5\x94\x13\x14\x5E\x69\x73\xC4\x50\x01\xD0\x08\x7B\x42" "\xD1\x1B\xC6\x45\x41\x3A\xEF\xF6\x3A\x42\x39\x1A\x39\x14\x5A\x59" "\x1A\x92\x20\x0D\x56\x01\x95\xE5\x3B\x47\x85\x84\xFD\xAE\x23\x1A" }, - { GCRY_MD_WHIRLPOOL, "a", - "\x8A\xCA\x26\x02\x79\x2A\xEC\x6F\x11\xA6\x72\x06\x53\x1F\xB7\xD7" - "\xF0\xDF\xF5\x94\x13\x14\x5E\x69\x73\xC4\x50\x01\xD0\x08\x7B\x42" - "\xD1\x1B\xC6\x45\x41\x3A\xEF\xF6\x3A\x42\x39\x1A\x39\x14\x5A\x59" - "\x1A\x92\x20\x0D\x56\x01\x95\xE5\x3B\x47\x85\x84\xFD\xAE\x23\x1A" }, + { GCRY_MD_WHIRLPOOL, "?", + "\x88\xf0\x78\x6d\x0d\x47\xe5\x32\x1f\x88\xb1\x48\x05\x53\x58\x7d" + "\x19\x4b\x32\x9b\xf1\xfb\x17\xc5\x98\x3a\x87\xa2\x48\x61\x3d\x2b" + "\xb2\xbc\x9f\x0d\xd2\x14\x37\x30\x55\x30\x91\xa7\xb8\x0c\x0f\x80" + "\x7c\x7b\x94\xf6\x55\xf6\x0b\x12\x85\x0c\x8e\x6d\x17\x5b\x1e\x71" }, { GCRY_MD_WHIRLPOOL, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "\xDC\x37\xE0\x08\xCF\x9E\xE6\x9B\xF1\x1F\x00\xED\x9A\xBA\x26\x90" From wk at gnupg.org Mon Mar 14 11:58:35 2016 From: wk at gnupg.org (Werner Koch) Date: Mon, 14 Mar 2016 11:58:35 +0100 Subject: [PATCH 1/2] Update .gitignore In-Reply-To: <20160312174248.12371.90456.stgit@localhost6.localdomain6> (Jussi Kivilinna's message of "Sat, 12 Mar 2016 19:42:48 +0200") References: <20160312174248.12371.90456.stgit@localhost6.localdomain6> Message-ID: <878u1lpbqc.fsf@wheatstone.g10code.de> > .gitignore | 19 +++++++++++++++++++ > 1 file changed, 19 insertions(+) Ha, I caught you as not using VPATH builds ;-) (feel free to push) Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From cvs at cvs.gnupg.org Mon Mar 14 19:14:39 2016 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Mon, 14 Mar 2016 19:14:39 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-337-g5d601dd Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via 5d601dd57fcb41aa2015ab655fd6fc51537da667 (commit) via a8b803d9e4bea2b779385ec9e9a579acc64431e9 (commit) from fdfa5bfefdde316688a3c8021bd3528c5273b0f4 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 5d601dd57fcb41aa2015ab655fd6fc51537da667 Author: Jussi Kivilinna Date: Sat Mar 12 17:07:21 2016 +0200 Add Intel PCLMUL implementations of CRC algorithms * cipher/Makefile.am: Add 'crc-intel-pclmul.c'. * cipher/crc-intel-pclmul.c: New. * cipher/crc.c (USE_INTEL_PCLMUL): New macro. (CRC_CONTEXT) [USE_INTEL_PCLMUL]: Add 'use_pclmul'. [USE_INTEL_PCLMUL] (_gcry_crc32_intel_pclmul) (gcry_crc24rfc2440_intel_pclmul): New. (crc32_init, crc32rfc1510_init, crc24rfc2440_init) [USE_INTEL_PCLMUL]: Select PCLMUL implementation if SSE4.1 and PCLMUL HW features detected. (crc32_write, crc24rfc2440_write) [USE_INTEL_PCLMUL]: Use PCLMUL implementation if enabled. (crc24_init): Document storage format of 24-bit CRC. (crc24_next4): Use only 'data' for last table look-up. * configure.ac: Add 'crc-intel-pclmul.lo'. * src/g10lib.h (HWF_*, HWF_INTEL_SSE4_1): Update HWF flags to include Intel SSE4.1. * src/hwf-x86.c (detect_x86_gnuc): Add SSE4.1 detection. * src/hwfeatures.c (hwflist): Add 'intel-sse4.1'. * tests/basic.c (fillbuf_count): New. (check_one_md): Add "?" check (million byte data-set with byte pattern 0x00,0x01,0x02,...); Test all buffer sizes 1 to 1000, for "!" and "?" checks. (check_one_md_multi): Skip "?". (check_digests): Add "?" test-vectors for MD5, SHA1, SHA224, SHA256, SHA384, SHA512, SHA3_224, SHA3_256, SHA3_384, SHA3_512, RIPEMD160, CRC32, CRC32_RFC1510, CRC24_RFC2440, TIGER1 and WHIRLPOOL; Add "!" test-vectors for CRC32_RFC1510 and CRC24_RFC2440. -- Add Intel PCLMUL accelerated implmentations of CRC algorithms. CRC performance is improved ~11x on x86_64 and i386 on Intel Haswell, and ~2.7x on Intel Sandy-bridge. Benchmark on Intel Core i5-4570 (x86_64, 3.2 Ghz): Before: | nanosecs/byte mebibytes/sec cycles/byte CRC32 | 0.865 ns/B 1103.0 MiB/s 2.77 c/B CRC32RFC1510 | 0.865 ns/B 1102.7 MiB/s 2.77 c/B CRC24RFC2440 | 0.865 ns/B 1103.0 MiB/s 2.77 c/B After: | nanosecs/byte mebibytes/sec cycles/byte CRC32 | 0.079 ns/B 12051.7 MiB/s 0.253 c/B CRC32RFC1510 | 0.079 ns/B 12050.6 MiB/s 0.253 c/B CRC24RFC2440 | 0.079 ns/B 12100.0 MiB/s 0.252 c/B Benchmark on Intel Core i5-4570 (i386, 3.2 Ghz): Before: | nanosecs/byte mebibytes/sec cycles/byte CRC32 | 0.860 ns/B 1109.0 MiB/s 2.75 c/B CRC32RFC1510 | 0.861 ns/B 1108.3 MiB/s 2.75 c/B CRC24RFC2440 | 0.860 ns/B 1108.6 MiB/s 2.75 c/B After: | nanosecs/byte mebibytes/sec cycles/byte CRC32 | 0.078 ns/B 12207.0 MiB/s 0.250 c/B CRC32RFC1510 | 0.078 ns/B 12207.0 MiB/s 0.250 c/B CRC24RFC2440 | 0.080 ns/B 11925.6 MiB/s 0.256 c/B Benchmark on Intel Core i5-2450M (x86_64, 2.5 Ghz): Before: | nanosecs/byte mebibytes/sec cycles/byte CRC32 | 1.25 ns/B 762.3 MiB/s 3.13 c/B CRC32RFC1510 | 1.26 ns/B 759.1 MiB/s 3.14 c/B CRC24RFC2440 | 1.25 ns/B 764.9 MiB/s 3.12 c/B After: | nanosecs/byte mebibytes/sec cycles/byte CRC32 | 0.451 ns/B 2114.3 MiB/s 1.13 c/B CRC32RFC1510 | 0.451 ns/B 2114.6 MiB/s 1.13 c/B CRC24RFC2440 | 0.457 ns/B 2085.0 MiB/s 1.14 c/B Signed-off-by: Jussi Kivilinna diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 65d7afb..ab71fa7 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -66,6 +66,7 @@ cast5.c cast5-amd64.S cast5-arm.S \ chacha20.c chacha20-sse2-amd64.S chacha20-ssse3-amd64.S chacha20-avx2-amd64.S \ chacha20-armv7-neon.S \ crc.c \ + crc-intel-pclmul.c \ des.c des-amd64.S \ dsa.c \ elgamal.c \ diff --git a/cipher/crc-intel-pclmul.c b/cipher/crc-intel-pclmul.c new file mode 100644 index 0000000..5002f80 --- /dev/null +++ b/cipher/crc-intel-pclmul.c @@ -0,0 +1,912 @@ +/* crc-intel-pclmul.c - Intel PCLMUL accelerated CRC implementation + * Copyright (C) 2016 Jussi Kivilinna + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + */ + +#include +#include +#include +#include + +#include "g10lib.h" + +#include "bithelp.h" +#include "bufhelp.h" + + +#if defined(ENABLE_PCLMUL_SUPPORT) && __GNUC__ >= 4 && \ + ((defined(__i386__) && SIZEOF_UNSIGNED_LONG == 4) || defined(__x86_64__)) + + +#if _GCRY_GCC_VERSION >= 40400 /* 4.4 */ +/* Prevent compiler from issuing SSE instructions between asm blocks. */ +# pragma GCC target("no-sse") +#endif + + +#define ALIGNED_16 __attribute__ ((aligned (16))) + + +/* Constants structure for generic reflected/non-reflected CRC32 CLMUL + * functions. */ +struct crc32_consts_s +{ + /* k: { x^(32*17), x^(32*15), x^(32*5), x^(32*3), x^(32*2), 0 } mod P(x) */ + u64 k[6]; + /* my_p: { floor(x^64 / P(x)), P(x) } */ + u64 my_p[2]; +}; + + +/* CLMUL constants for CRC32 and CRC32RFC1510. */ +static const struct crc32_consts_s crc32_consts ALIGNED_16 = +{ + { /* k[6] = reverse_33bits( x^(32*y) mod P(x) ) */ + U64_C(0x154442bd4), U64_C(0x1c6e41596), /* y = { 17, 15 } */ + U64_C(0x1751997d0), U64_C(0x0ccaa009e), /* y = { 5, 3 } */ + U64_C(0x163cd6124), 0 /* y = 2 */ + }, + { /* my_p[2] = reverse_33bits ( { floor(x^64 / P(x)), P(x) } ) */ + U64_C(0x1f7011641), U64_C(0x1db710641) + } +}; + +/* CLMUL constants for CRC24RFC2440 (polynomial multiplied with x?). */ +static const struct crc32_consts_s crc24rfc2440_consts ALIGNED_16 = +{ + { /* k[6] = x^(32*y) mod P(x) << 32*/ + U64_C(0x08289a00) << 32, U64_C(0x74b44a00) << 32, /* y = { 17, 15 } */ + U64_C(0xc4b14d00) << 32, U64_C(0xfd7e0c00) << 32, /* y = { 5, 3 } */ + U64_C(0xd9fe8c00) << 32, 0 /* y = 2 */ + }, + { /* my_p[2] = { floor(x^64 / P(x)), P(x) } */ + U64_C(0x1f845fe24), U64_C(0x1864cfb00) + } +}; + +/* Common constants for CRC32 algorithms. */ +static const byte crc32_refl_shuf_shift[3 * 16] ALIGNED_16 = + { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + }; +static const byte crc32_shuf_shift[3 * 16] ALIGNED_16 = + { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + }; +static const byte *crc32_bswap_shuf = &crc32_shuf_shift[16]; +static const byte crc32_partial_fold_input_mask[16 + 16] ALIGNED_16 = + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + }; +static const u64 crc32_merge9to15_shuf[15 - 9 + 1][2] ALIGNED_16 = + { + { U64_C(0x0706050403020100), U64_C(0xffffffffffffff0f) }, /* 9 */ + { U64_C(0x0706050403020100), U64_C(0xffffffffffff0f0e) }, + { U64_C(0x0706050403020100), U64_C(0xffffffffff0f0e0d) }, + { U64_C(0x0706050403020100), U64_C(0xffffffff0f0e0d0c) }, + { U64_C(0x0706050403020100), U64_C(0xffffff0f0e0d0c0b) }, + { U64_C(0x0706050403020100), U64_C(0xffff0f0e0d0c0b0a) }, + { U64_C(0x0706050403020100), U64_C(0xff0f0e0d0c0b0a09) }, /* 15 */ + }; +static const u64 crc32_merge5to7_shuf[7 - 5 + 1][2] ALIGNED_16 = + { + { U64_C(0xffffff0703020100), U64_C(0xffffffffffffffff) }, /* 5 */ + { U64_C(0xffff070603020100), U64_C(0xffffffffffffffff) }, + { U64_C(0xff07060503020100), U64_C(0xffffffffffffffff) }, /* 7 */ + }; + +/* PCLMUL functions for reflected CRC32. */ +static inline void +crc32_reflected_bulk (u32 *pcrc, const byte *inbuf, size_t inlen, + const struct crc32_consts_s *consts) +{ + if (inlen >= 8 * 16) + { + asm volatile ("movd %[crc], %%xmm4\n\t" + "movdqu %[inbuf_0], %%xmm0\n\t" + "movdqu %[inbuf_1], %%xmm1\n\t" + "movdqu %[inbuf_2], %%xmm2\n\t" + "movdqu %[inbuf_3], %%xmm3\n\t" + "pxor %%xmm4, %%xmm0\n\t" + : + : [inbuf_0] "m" (inbuf[0 * 16]), + [inbuf_1] "m" (inbuf[1 * 16]), + [inbuf_2] "m" (inbuf[2 * 16]), + [inbuf_3] "m" (inbuf[3 * 16]), + [crc] "m" (*pcrc) + : ); + + inbuf += 4 * 16; + inlen -= 4 * 16; + + asm volatile ("movdqa %[k1k2], %%xmm4\n\t" + : + : [k1k2] "m" (consts->k[1 - 1]) + : ); + + /* Fold by 4. */ + while (inlen >= 4 * 16) + { + asm volatile ("movdqu %[inbuf_0], %%xmm5\n\t" + "movdqa %%xmm0, %%xmm6\n\t" + "pclmulqdq $0x00, %%xmm4, %%xmm0\n\t" + "pclmulqdq $0x11, %%xmm4, %%xmm6\n\t" + "pxor %%xmm5, %%xmm0\n\t" + "pxor %%xmm6, %%xmm0\n\t" + + "movdqu %[inbuf_1], %%xmm5\n\t" + "movdqa %%xmm1, %%xmm6\n\t" + "pclmulqdq $0x00, %%xmm4, %%xmm1\n\t" + "pclmulqdq $0x11, %%xmm4, %%xmm6\n\t" + "pxor %%xmm5, %%xmm1\n\t" + "pxor %%xmm6, %%xmm1\n\t" + + "movdqu %[inbuf_2], %%xmm5\n\t" + "movdqa %%xmm2, %%xmm6\n\t" + "pclmulqdq $0x00, %%xmm4, %%xmm2\n\t" + "pclmulqdq $0x11, %%xmm4, %%xmm6\n\t" + "pxor %%xmm5, %%xmm2\n\t" + "pxor %%xmm6, %%xmm2\n\t" + + "movdqu %[inbuf_3], %%xmm5\n\t" + "movdqa %%xmm3, %%xmm6\n\t" + "pclmulqdq $0x00, %%xmm4, %%xmm3\n\t" + "pclmulqdq $0x11, %%xmm4, %%xmm6\n\t" + "pxor %%xmm5, %%xmm3\n\t" + "pxor %%xmm6, %%xmm3\n\t" + : + : [inbuf_0] "m" (inbuf[0 * 16]), + [inbuf_1] "m" (inbuf[1 * 16]), + [inbuf_2] "m" (inbuf[2 * 16]), + [inbuf_3] "m" (inbuf[3 * 16]) + : ); + + inbuf += 4 * 16; + inlen -= 4 * 16; + } + + asm volatile ("movdqa %[k3k4], %%xmm6\n\t" + "movdqa %[my_p], %%xmm5\n\t" + : + : [k3k4] "m" (consts->k[3 - 1]), + [my_p] "m" (consts->my_p[0]) + : ); + + /* Fold 4 to 1. */ + + asm volatile ("movdqa %%xmm0, %%xmm4\n\t" + "pclmulqdq $0x00, %%xmm6, %%xmm0\n\t" + "pclmulqdq $0x11, %%xmm6, %%xmm4\n\t" + "pxor %%xmm1, %%xmm0\n\t" + "pxor %%xmm4, %%xmm0\n\t" + + "movdqa %%xmm0, %%xmm4\n\t" + "pclmulqdq $0x00, %%xmm6, %%xmm0\n\t" + "pclmulqdq $0x11, %%xmm6, %%xmm4\n\t" + "pxor %%xmm2, %%xmm0\n\t" + "pxor %%xmm4, %%xmm0\n\t" + + "movdqa %%xmm0, %%xmm4\n\t" + "pclmulqdq $0x00, %%xmm6, %%xmm0\n\t" + "pclmulqdq $0x11, %%xmm6, %%xmm4\n\t" + "pxor %%xmm3, %%xmm0\n\t" + "pxor %%xmm4, %%xmm0\n\t" + : + : + : ); + } + else + { + asm volatile ("movd %[crc], %%xmm1\n\t" + "movdqu %[inbuf], %%xmm0\n\t" + "movdqa %[k3k4], %%xmm6\n\t" + "pxor %%xmm1, %%xmm0\n\t" + "movdqa %[my_p], %%xmm5\n\t" + : + : [inbuf] "m" (*inbuf), + [crc] "m" (*pcrc), + [k3k4] "m" (consts->k[3 - 1]), + [my_p] "m" (consts->my_p[0]) + : ); + + inbuf += 16; + inlen -= 16; + } + + /* Fold by 1. */ + if (inlen >= 16) + { + while (inlen >= 16) + { + /* Load next block to XMM2. Fold XMM0 to XMM0:XMM1. */ + asm volatile ("movdqu %[inbuf], %%xmm2\n\t" + "movdqa %%xmm0, %%xmm1\n\t" + "pclmulqdq $0x00, %%xmm6, %%xmm0\n\t" + "pclmulqdq $0x11, %%xmm6, %%xmm1\n\t" + "pxor %%xmm2, %%xmm0\n\t" + "pxor %%xmm1, %%xmm0\n\t" + : + : [inbuf] "m" (*inbuf) + : ); + + inbuf += 16; + inlen -= 16; + } + } + + /* Partial fold. */ + if (inlen) + { + /* Load last input and add padding zeros. */ + asm volatile ("movdqu %[shr_shuf], %%xmm3\n\t" + "movdqu %[shl_shuf], %%xmm4\n\t" + "movdqu %[mask], %%xmm2\n\t" + + "movdqa %%xmm0, %%xmm1\n\t" + "pshufb %%xmm4, %%xmm0\n\t" + "movdqu %[inbuf], %%xmm4\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "por %%xmm1, %%xmm2\n\t" + + "movdqa %%xmm0, %%xmm1\n\t" + "pclmulqdq $0x00, %%xmm6, %%xmm0\n\t" + "pclmulqdq $0x11, %%xmm6, %%xmm1\n\t" + "pxor %%xmm2, %%xmm0\n\t" + "pxor %%xmm1, %%xmm0\n\t" + : + : [inbuf] "m" (*(inbuf - 16 + inlen)), + [mask] "m" (crc32_partial_fold_input_mask[inlen]), + [shl_shuf] "m" (crc32_refl_shuf_shift[inlen]), + [shr_shuf] "m" (crc32_refl_shuf_shift[inlen + 16]) + : ); + + inbuf += inlen; + inlen -= inlen; + } + + /* Final fold. */ + asm volatile (/* reduce 128-bits to 96-bits */ + "movdqa %%xmm0, %%xmm1\n\t" + "pclmulqdq $0x10, %%xmm6, %%xmm0\n\t" + "psrldq $8, %%xmm1\n\t" + "pxor %%xmm1, %%xmm0\n\t" + + /* reduce 96-bits to 64-bits */ + "pshufd $0xfc, %%xmm0, %%xmm1\n\t" /* [00][00][00][x] */ + "pshufd $0xf9, %%xmm0, %%xmm0\n\t" /* [00][00][x>>64][x>>32] */ + "pclmulqdq $0x00, %[k5], %%xmm1\n\t" /* [00][00][xx][xx] */ + "pxor %%xmm1, %%xmm0\n\t" /* top 64-bit are zero */ + + /* barrett reduction */ + "pshufd $0xf3, %%xmm0, %%xmm1\n\t" /* [00][00][x>>32][00] */ + "pslldq $4, %%xmm0\n\t" /* [??][x>>32][??][??] */ + "pclmulqdq $0x00, %%xmm5, %%xmm1\n\t" /* [00][xx][xx][00] */ + "pclmulqdq $0x10, %%xmm5, %%xmm1\n\t" /* [00][xx][xx][00] */ + "pxor %%xmm1, %%xmm0\n\t" + + /* store CRC */ + "pextrd $2, %%xmm0, %[out]\n\t" + : [out] "=m" (*pcrc) + : [k5] "m" (consts->k[5 - 1]) + : ); +} + +static inline void +crc32_reflected_less_than_16 (u32 *pcrc, const byte *inbuf, size_t inlen, + const struct crc32_consts_s *consts) +{ + if (inlen < 4) + { + u32 crc = *pcrc; + u32 data; + + asm volatile ("movdqa %[my_p], %%xmm5\n\t" + : + : [my_p] "m" (consts->my_p[0]) + : ); + + if (inlen == 1) + { + data = inbuf[0]; + data ^= crc; + data <<= 24; + crc >>= 8; + } + else if (inlen == 2) + { + data = *((const u16 *)inbuf); + data ^= crc; + data <<= 16; + crc >>= 16; + } + else + { + data = *((const u16 *)inbuf); + data |= inbuf[2] << 16; + data ^= crc; + data <<= 8; + crc >>= 24; + } + + /* Barrett reduction */ + asm volatile ("movd %[in], %%xmm0\n\t" + "movd %[crc], %%xmm1\n\t" + + "pclmulqdq $0x00, %%xmm5, %%xmm0\n\t" /* [00][00][xx][xx] */ + "psllq $32, %%xmm1\n\t" + "pshufd $0xfc, %%xmm0, %%xmm0\n\t" /* [00][00][00][x] */ + "pclmulqdq $0x10, %%xmm5, %%xmm0\n\t" /* [00][00][xx][xx] */ + "pxor %%xmm1, %%xmm0\n\t" + + "pextrd $1, %%xmm0, %[out]\n\t" + : [out] "=m" (*pcrc) + : [in] "rm" (data), + [crc] "rm" (crc) + : ); + } + else if (inlen == 4) + { + /* Barrett reduction */ + asm volatile ("movd %[crc], %%xmm1\n\t" + "movd %[in], %%xmm0\n\t" + "movdqa %[my_p], %%xmm5\n\t" + "pxor %%xmm1, %%xmm0\n\t" + + "pclmulqdq $0x00, %%xmm5, %%xmm0\n\t" /* [00][00][xx][xx] */ + "pshufd $0xfc, %%xmm0, %%xmm0\n\t" /* [00][00][00][x] */ + "pclmulqdq $0x10, %%xmm5, %%xmm0\n\t" /* [00][00][xx][xx] */ + + "pextrd $1, %%xmm0, %[out]\n\t" + : [out] "=m" (*pcrc) + : [in] "m" (*inbuf), + [crc] "m" (*pcrc), + [my_p] "m" (consts->my_p[0]) + : ); + } + else + { + asm volatile ("movdqu %[shuf], %%xmm4\n\t" + "movd %[crc], %%xmm1\n\t" + "movdqa %[my_p], %%xmm5\n\t" + "movdqa %[k3k4], %%xmm6\n\t" + : + : [shuf] "m" (crc32_refl_shuf_shift[inlen]), + [crc] "m" (*pcrc), + [my_p] "m" (consts->my_p[0]), + [k3k4] "m" (consts->k[3 - 1]) + : ); + + if (inlen >= 8) + { + asm volatile ("movq %[inbuf], %%xmm0\n\t" + : + : [inbuf] "m" (*inbuf) + : ); + if (inlen > 8) + { + asm volatile (/*"pinsrq $1, %[inbuf_tail], %%xmm0\n\t"*/ + "movq %[inbuf_tail], %%xmm2\n\t" + "punpcklqdq %%xmm2, %%xmm0\n\t" + "pshufb %[merge_shuf], %%xmm0\n\t" + : + : [inbuf_tail] "m" (inbuf[inlen - 8]), + [merge_shuf] "m" + (*crc32_merge9to15_shuf[inlen - 9]) + : ); + } + } + else + { + asm volatile ("movd %[inbuf], %%xmm0\n\t" + "pinsrd $1, %[inbuf_tail], %%xmm0\n\t" + "pshufb %[merge_shuf], %%xmm0\n\t" + : + : [inbuf] "m" (*inbuf), + [inbuf_tail] "m" (inbuf[inlen - 4]), + [merge_shuf] "m" + (*crc32_merge5to7_shuf[inlen - 5]) + : ); + } + + /* Final fold. */ + asm volatile ("pxor %%xmm1, %%xmm0\n\t" + "pshufb %%xmm4, %%xmm0\n\t" + + /* reduce 128-bits to 96-bits */ + "movdqa %%xmm0, %%xmm1\n\t" + "pclmulqdq $0x10, %%xmm6, %%xmm0\n\t" + "psrldq $8, %%xmm1\n\t" + "pxor %%xmm1, %%xmm0\n\t" /* top 32-bit are zero */ + + /* reduce 96-bits to 64-bits */ + "pshufd $0xfc, %%xmm0, %%xmm1\n\t" /* [00][00][00][x] */ + "pshufd $0xf9, %%xmm0, %%xmm0\n\t" /* [00][00][x>>64][x>>32] */ + "pclmulqdq $0x00, %[k5], %%xmm1\n\t" /* [00][00][xx][xx] */ + "pxor %%xmm1, %%xmm0\n\t" /* top 64-bit are zero */ + + /* barrett reduction */ + "pshufd $0xf3, %%xmm0, %%xmm1\n\t" /* [00][00][x>>32][00] */ + "pslldq $4, %%xmm0\n\t" /* [??][x>>32][??][??] */ + "pclmulqdq $0x00, %%xmm5, %%xmm1\n\t" /* [00][xx][xx][00] */ + "pclmulqdq $0x10, %%xmm5, %%xmm1\n\t" /* [00][xx][xx][00] */ + "pxor %%xmm1, %%xmm0\n\t" + + /* store CRC */ + "pextrd $2, %%xmm0, %[out]\n\t" + : [out] "=m" (*pcrc) + : [k5] "m" (consts->k[5 - 1]) + : ); + } +} + +/* PCLMUL functions for non-reflected CRC32. */ +static inline void +crc32_bulk (u32 *pcrc, const byte *inbuf, size_t inlen, + const struct crc32_consts_s *consts) +{ + asm volatile ("movdqa %[bswap], %%xmm7\n\t" + : + : [bswap] "m" (*crc32_bswap_shuf) + : ); + + if (inlen >= 8 * 16) + { + asm volatile ("movd %[crc], %%xmm4\n\t" + "movdqu %[inbuf_0], %%xmm0\n\t" + "movdqu %[inbuf_1], %%xmm1\n\t" + "movdqu %[inbuf_2], %%xmm2\n\t" + "pxor %%xmm4, %%xmm0\n\t" + "movdqu %[inbuf_3], %%xmm3\n\t" + "pshufb %%xmm7, %%xmm0\n\t" + "pshufb %%xmm7, %%xmm1\n\t" + "pshufb %%xmm7, %%xmm2\n\t" + "pshufb %%xmm7, %%xmm3\n\t" + : + : [inbuf_0] "m" (inbuf[0 * 16]), + [inbuf_1] "m" (inbuf[1 * 16]), + [inbuf_2] "m" (inbuf[2 * 16]), + [inbuf_3] "m" (inbuf[3 * 16]), + [crc] "m" (*pcrc) + : ); + + inbuf += 4 * 16; + inlen -= 4 * 16; + + asm volatile ("movdqa %[k1k2], %%xmm4\n\t" + : + : [k1k2] "m" (consts->k[1 - 1]) + : ); + + /* Fold by 4. */ + while (inlen >= 4 * 16) + { + asm volatile ("movdqu %[inbuf_0], %%xmm5\n\t" + "movdqa %%xmm0, %%xmm6\n\t" + "pshufb %%xmm7, %%xmm5\n\t" + "pclmulqdq $0x01, %%xmm4, %%xmm0\n\t" + "pclmulqdq $0x10, %%xmm4, %%xmm6\n\t" + "pxor %%xmm5, %%xmm0\n\t" + "pxor %%xmm6, %%xmm0\n\t" + + "movdqu %[inbuf_1], %%xmm5\n\t" + "movdqa %%xmm1, %%xmm6\n\t" + "pshufb %%xmm7, %%xmm5\n\t" + "pclmulqdq $0x01, %%xmm4, %%xmm1\n\t" + "pclmulqdq $0x10, %%xmm4, %%xmm6\n\t" + "pxor %%xmm5, %%xmm1\n\t" + "pxor %%xmm6, %%xmm1\n\t" + + "movdqu %[inbuf_2], %%xmm5\n\t" + "movdqa %%xmm2, %%xmm6\n\t" + "pshufb %%xmm7, %%xmm5\n\t" + "pclmulqdq $0x01, %%xmm4, %%xmm2\n\t" + "pclmulqdq $0x10, %%xmm4, %%xmm6\n\t" + "pxor %%xmm5, %%xmm2\n\t" + "pxor %%xmm6, %%xmm2\n\t" + + "movdqu %[inbuf_3], %%xmm5\n\t" + "movdqa %%xmm3, %%xmm6\n\t" + "pshufb %%xmm7, %%xmm5\n\t" + "pclmulqdq $0x01, %%xmm4, %%xmm3\n\t" + "pclmulqdq $0x10, %%xmm4, %%xmm6\n\t" + "pxor %%xmm5, %%xmm3\n\t" + "pxor %%xmm6, %%xmm3\n\t" + : + : [inbuf_0] "m" (inbuf[0 * 16]), + [inbuf_1] "m" (inbuf[1 * 16]), + [inbuf_2] "m" (inbuf[2 * 16]), + [inbuf_3] "m" (inbuf[3 * 16]) + : ); + + inbuf += 4 * 16; + inlen -= 4 * 16; + } + + asm volatile ("movdqa %[k3k4], %%xmm6\n\t" + "movdqa %[my_p], %%xmm5\n\t" + : + : [k3k4] "m" (consts->k[3 - 1]), + [my_p] "m" (consts->my_p[0]) + : ); + + /* Fold 4 to 1. */ + + asm volatile ("movdqa %%xmm0, %%xmm4\n\t" + "pclmulqdq $0x01, %%xmm6, %%xmm0\n\t" + "pclmulqdq $0x10, %%xmm6, %%xmm4\n\t" + "pxor %%xmm1, %%xmm0\n\t" + "pxor %%xmm4, %%xmm0\n\t" + + "movdqa %%xmm0, %%xmm4\n\t" + "pclmulqdq $0x01, %%xmm6, %%xmm0\n\t" + "pclmulqdq $0x10, %%xmm6, %%xmm4\n\t" + "pxor %%xmm2, %%xmm0\n\t" + "pxor %%xmm4, %%xmm0\n\t" + + "movdqa %%xmm0, %%xmm4\n\t" + "pclmulqdq $0x01, %%xmm6, %%xmm0\n\t" + "pclmulqdq $0x10, %%xmm6, %%xmm4\n\t" + "pxor %%xmm3, %%xmm0\n\t" + "pxor %%xmm4, %%xmm0\n\t" + : + : + : ); + } + else + { + asm volatile ("movd %[crc], %%xmm1\n\t" + "movdqu %[inbuf], %%xmm0\n\t" + "movdqa %[k3k4], %%xmm6\n\t" + "pxor %%xmm1, %%xmm0\n\t" + "movdqa %[my_p], %%xmm5\n\t" + "pshufb %%xmm7, %%xmm0\n\t" + : + : [inbuf] "m" (*inbuf), + [crc] "m" (*pcrc), + [k3k4] "m" (consts->k[3 - 1]), + [my_p] "m" (consts->my_p[0]) + : ); + + inbuf += 16; + inlen -= 16; + } + + /* Fold by 1. */ + if (inlen >= 16) + { + while (inlen >= 16) + { + /* Load next block to XMM2. Fold XMM0 to XMM0:XMM1. */ + asm volatile ("movdqu %[inbuf], %%xmm2\n\t" + "movdqa %%xmm0, %%xmm1\n\t" + "pclmulqdq $0x01, %%xmm6, %%xmm0\n\t" + "pshufb %%xmm7, %%xmm2\n\t" + "pclmulqdq $0x10, %%xmm6, %%xmm1\n\t" + "pxor %%xmm2, %%xmm0\n\t" + "pxor %%xmm1, %%xmm0\n\t" + : + : [inbuf] "m" (*inbuf) + : ); + + inbuf += 16; + inlen -= 16; + } + } + + /* Partial fold. */ + if (inlen) + { + /* Load last input and add padding zeros. */ + asm volatile ("movdqu %[shl_shuf], %%xmm4\n\t" + "movdqu %[shr_shuf], %%xmm3\n\t" + "movdqu %[mask], %%xmm2\n\t" + + "movdqa %%xmm0, %%xmm1\n\t" + "pshufb %%xmm4, %%xmm0\n\t" + "movdqu %[inbuf], %%xmm4\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "por %%xmm1, %%xmm2\n\t" + + "pshufb %%xmm7, %%xmm2\n\t" + + "movdqa %%xmm0, %%xmm1\n\t" + "pclmulqdq $0x01, %%xmm6, %%xmm0\n\t" + "pclmulqdq $0x10, %%xmm6, %%xmm1\n\t" + "pxor %%xmm2, %%xmm0\n\t" + "pxor %%xmm1, %%xmm0\n\t" + : + : [inbuf] "m" (*(inbuf - 16 + inlen)), + [mask] "m" (crc32_partial_fold_input_mask[inlen]), + [shl_shuf] "m" (crc32_refl_shuf_shift[32 - inlen]), + [shr_shuf] "m" (crc32_shuf_shift[inlen + 16]) + : ); + + inbuf += inlen; + inlen -= inlen; + } + + /* Final fold. */ + asm volatile (/* reduce 128-bits to 96-bits */ + "movdqa %%xmm0, %%xmm1\n\t" + "pclmulqdq $0x11, %%xmm6, %%xmm0\n\t" + "pslldq $8, %%xmm1\n\t" + "pxor %%xmm1, %%xmm0\n\t" /* bottom 32-bit are zero */ + + /* reduce 96-bits to 64-bits */ + "pshufd $0x30, %%xmm0, %%xmm1\n\t" /* [00][x>>96][00][00] */ + "pshufd $0x24, %%xmm0, %%xmm0\n\t" /* [00][xx][xx][00] */ + "pclmulqdq $0x01, %[k5], %%xmm1\n\t" /* [00][xx][xx][00] */ + "pxor %%xmm1, %%xmm0\n\t" /* top and bottom 32-bit are zero */ + + /* barrett reduction */ + "pshufd $0x01, %%xmm0, %%xmm1\n\t" /* [00][00][00][x>>32] */ + "pclmulqdq $0x01, %%xmm5, %%xmm0\n\t" /* [00][xx][xx][xx] */ + "psrldq $4, %%xmm0\n\t" /* [00][00][xx][xx] */ + "pclmulqdq $0x10, %%xmm5, %%xmm0\n\t" + "pxor %%xmm1, %%xmm0\n\t" + + /* store CRC in input endian */ + "movd %%xmm0, %%eax\n\t" + "bswapl %%eax\n\t" + "movl %%eax, %[out]\n\t" + : [out] "=m" (*pcrc) + : [k5] "m" (consts->k[5 - 1]) + : "eax" ); +} + +static inline void +crc32_less_than_16 (u32 *pcrc, const byte *inbuf, size_t inlen, + const struct crc32_consts_s *consts) +{ + if (inlen < 4) + { + u32 crc = *pcrc; + u32 data; + + asm volatile ("movdqa %[my_p], %%xmm5\n\t" + : + : [my_p] "m" (consts->my_p[0]) + : ); + + if (inlen == 1) + { + data = inbuf[0]; + data ^= crc; + data = _gcry_bswap32(data << 24); + crc = _gcry_bswap32(crc >> 8); + } + else if (inlen == 2) + { + data = *((const u16 *)inbuf); + data ^= crc; + data = _gcry_bswap32(data << 16); + crc = _gcry_bswap32(crc >> 16); + } + else + { + data = *((const u16 *)inbuf); + data |= inbuf[2] << 16; + data ^= crc; + data = _gcry_bswap32(data << 8); + crc = _gcry_bswap32(crc >> 24); + } + + /* Barrett reduction */ + asm volatile ("movd %[in], %%xmm0\n\t" + "psllq $32, %%xmm0\n\t" /* [00][00][xx][00] */ + "movd %[crc], %%xmm1\n\t" + + "pclmulqdq $0x00, %%xmm5, %%xmm0\n\t" /* [00][xx][xx][00] */ + "pclmulqdq $0x11, %%xmm5, %%xmm0\n\t" /* [00][00][xx][xx] */ + "pxor %%xmm1, %%xmm0\n\t" + + /* store CRC in input endian */ + "movd %%xmm0, %%eax\n\t" + "bswapl %%eax\n\t" + "movl %%eax, %[out]\n\t" + : [out] "=m" (*pcrc) + : [in] "r" (data), + [crc] "r" (crc) + : "eax" ); + } + else if (inlen == 4) + { + /* Barrett reduction */ + asm volatile ("movd %[crc], %%xmm0\n\t" + "movd %[in], %%xmm1\n\t" + "movdqa %[my_p], %%xmm5\n\t" + "pxor %%xmm1, %%xmm0\n\t" + "pshufb %[bswap], %%xmm0\n\t" /* [xx][00][00][00] */ + + "pclmulqdq $0x01, %%xmm5, %%xmm0\n\t" /* [00][xx][xx][00] */ + "pclmulqdq $0x11, %%xmm5, %%xmm0\n\t" /* [00][00][xx][xx] */ + + /* store CRC in input endian */ + "movd %%xmm0, %%eax\n\t" + "bswapl %%eax\n\t" + "movl %%eax, %[out]\n\t" + : [out] "=m" (*pcrc) + : [in] "m" (*inbuf), + [crc] "m" (*pcrc), + [my_p] "m" (consts->my_p[0]), + [bswap] "m" (*crc32_bswap_shuf) + : "eax" ); + } + else + { + asm volatile ("movdqu %[shuf], %%xmm7\n\t" + "movd %[crc], %%xmm1\n\t" + "movdqa %[my_p], %%xmm5\n\t" + "movdqa %[k3k4], %%xmm6\n\t" + : + : [shuf] "m" (crc32_shuf_shift[32 - inlen]), + [crc] "m" (*pcrc), + [my_p] "m" (consts->my_p[0]), + [k3k4] "m" (consts->k[3 - 1]) + : ); + + if (inlen >= 8) + { + asm volatile ("movq %[inbuf], %%xmm0\n\t" + : + : [inbuf] "m" (*inbuf) + : ); + if (inlen > 8) + { + asm volatile (/*"pinsrq $1, %[inbuf_tail], %%xmm0\n\t"*/ + "movq %[inbuf_tail], %%xmm2\n\t" + "punpcklqdq %%xmm2, %%xmm0\n\t" + "pshufb %[merge_shuf], %%xmm0\n\t" + : + : [inbuf_tail] "m" (inbuf[inlen - 8]), + [merge_shuf] "m" + (*crc32_merge9to15_shuf[inlen - 9]) + : ); + } + } + else + { + asm volatile ("movd %[inbuf], %%xmm0\n\t" + "pinsrd $1, %[inbuf_tail], %%xmm0\n\t" + "pshufb %[merge_shuf], %%xmm0\n\t" + : + : [inbuf] "m" (*inbuf), + [inbuf_tail] "m" (inbuf[inlen - 4]), + [merge_shuf] "m" + (*crc32_merge5to7_shuf[inlen - 5]) + : ); + } + + /* Final fold. */ + asm volatile ("pxor %%xmm1, %%xmm0\n\t" + "pshufb %%xmm7, %%xmm0\n\t" + + /* reduce 128-bits to 96-bits */ + "movdqa %%xmm0, %%xmm1\n\t" + "pclmulqdq $0x11, %%xmm6, %%xmm0\n\t" + "pslldq $8, %%xmm1\n\t" + "pxor %%xmm1, %%xmm0\n\t" /* bottom 32-bit are zero */ + + /* reduce 96-bits to 64-bits */ + "pshufd $0x30, %%xmm0, %%xmm1\n\t" /* [00][x>>96][00][00] */ + "pshufd $0x24, %%xmm0, %%xmm0\n\t" /* [00][xx][xx][00] */ + "pclmulqdq $0x01, %[k5], %%xmm1\n\t" /* [00][xx][xx][00] */ + "pxor %%xmm1, %%xmm0\n\t" /* top and bottom 32-bit are zero */ + + /* barrett reduction */ + "pshufd $0x01, %%xmm0, %%xmm1\n\t" /* [00][00][00][x>>32] */ + "pclmulqdq $0x01, %%xmm5, %%xmm0\n\t" /* [00][xx][xx][xx] */ + "psrldq $4, %%xmm0\n\t" /* [00][00][xx][xx] */ + "pclmulqdq $0x10, %%xmm5, %%xmm0\n\t" + "pxor %%xmm1, %%xmm0\n\t" + + /* store CRC in input endian */ + "movd %%xmm0, %%eax\n\t" + "bswapl %%eax\n\t" + "movl %%eax, %[out]\n\t" + : [out] "=m" (*pcrc) + : [k5] "m" (consts->k[5 - 1]) + : "eax" ); + } +} + +void +_gcry_crc32_intel_pclmul (u32 *pcrc, const byte *inbuf, size_t inlen) +{ + const struct crc32_consts_s *consts = &crc32_consts; +#if defined(__x86_64__) && defined(__WIN64__) + char win64tmp[2 * 16]; + + /* XMM6-XMM7 need to be restored after use. */ + asm volatile ("movdqu %%xmm6, 0*16(%0)\n\t" + "movdqu %%xmm7, 1*16(%0)\n\t" + : + : "r" (win64tmp) + : "memory"); +#endif + + if (!inlen) + return; + + if (inlen >= 16) + crc32_reflected_bulk(pcrc, inbuf, inlen, consts); + else + crc32_reflected_less_than_16(pcrc, inbuf, inlen, consts); + +#if defined(__x86_64__) && defined(__WIN64__) + /* Restore used registers. */ + asm volatile("movdqu 0*16(%0), %%xmm6\n\t" + "movdqu 1*16(%0), %%xmm7\n\t" + : + : "r" (win64tmp) + : "memory"); +#endif +} + +void +_gcry_crc24rfc2440_intel_pclmul (u32 *pcrc, const byte *inbuf, size_t inlen) +{ + const struct crc32_consts_s *consts = &crc24rfc2440_consts; +#if defined(__x86_64__) && defined(__WIN64__) + char win64tmp[2 * 16]; + + /* XMM6-XMM7 need to be restored after use. */ + asm volatile ("movdqu %%xmm6, 0*16(%0)\n\t" + "movdqu %%xmm7, 1*16(%0)\n\t" + : + : "r" (win64tmp) + : "memory"); +#endif + + if (!inlen) + return; + + /* Note: *pcrc in input endian. */ + + if (inlen >= 16) + crc32_bulk(pcrc, inbuf, inlen, consts); + else + crc32_less_than_16(pcrc, inbuf, inlen, consts); + +#if defined(__x86_64__) && defined(__WIN64__) + /* Restore used registers. */ + asm volatile("movdqu 0*16(%0), %%xmm6\n\t" + "movdqu 1*16(%0), %%xmm7\n\t" + : + : "r" (win64tmp) + : "memory"); +#endif +} + +#endif /* USE_INTEL_PCLMUL */ diff --git a/cipher/crc.c b/cipher/crc.c index 46a185a..ee0e4e2 100644 --- a/cipher/crc.c +++ b/cipher/crc.c @@ -31,14 +31,37 @@ #include "bufhelp.h" +/* USE_INTEL_PCLMUL indicates whether to compile CRC with Intel PCLMUL + * code. */ +#undef USE_INTEL_PCLMUL +#ifdef ENABLE_PCLMUL_SUPPORT +# if ((defined(__i386__) && SIZEOF_UNSIGNED_LONG == 4) || defined(__x86_64__)) +# if __GNUC__ >= 4 +# define USE_INTEL_PCLMUL 1 +# endif +# endif +#endif /* USE_INTEL_PCLMUL */ + + typedef struct { u32 CRC; +#ifdef USE_INTEL_PCLMUL + unsigned int use_pclmul:1; /* Intel PCLMUL shall be used. */ +#endif byte buf[4]; } CRC_CONTEXT; +#ifdef USE_INTEL_PCLMUL +/*-- crc-intel-pclmul.c --*/ +void _gcry_crc32_intel_pclmul (u32 *pcrc, const byte *inbuf, size_t inlen); +void _gcry_crc24rfc2440_intel_pclmul (u32 *pcrc, const byte *inbuf, + size_t inlen); +#endif + + /* * Code generated by universal_crc by Danjel McGougan * @@ -338,6 +361,11 @@ static void crc32_init (void *context, unsigned int flags) { CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; +#ifdef USE_INTEL_PCLMUL + u32 hwf = _gcry_get_hw_features (); + + ctx->use_pclmul = (hwf & HWF_INTEL_SSE4_1) && (hwf & HWF_INTEL_PCLMUL); +#endif (void)flags; @@ -351,6 +379,14 @@ crc32_write (void *context, const void *inbuf_arg, size_t inlen) const byte *inbuf = inbuf_arg; u32 crc; +#ifdef USE_INTEL_PCLMUL + if (ctx->use_pclmul) + { + _gcry_crc32_intel_pclmul(&ctx->CRC, inbuf, inlen); + return; + } +#endif + if (!inbuf || !inlen) return; @@ -403,6 +439,11 @@ static void crc32rfc1510_init (void *context, unsigned int flags) { CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; +#ifdef USE_INTEL_PCLMUL + u32 hwf = _gcry_get_hw_features (); + + ctx->use_pclmul = (hwf & HWF_INTEL_SSE4_1) && (hwf & HWF_INTEL_PCLMUL); +#endif (void)flags; @@ -694,7 +735,8 @@ static const u32 crc24_table[1024] = static inline u32 crc24_init (void) { - return 0xce04b7; + /* Transformed to 32-bit CRC by multiplied by x? and then byte swapped. */ + return 0xce04b7; /* _gcry_bswap(0xb704ce << 8) */ } static inline @@ -713,7 +755,7 @@ u32 crc24_next4 (u32 crc, u32 data) crc = crc24_table[(crc & 0xff) + 0x300] ^ crc24_table[((crc >> 8) & 0xff) + 0x200] ^ crc24_table[((crc >> 16) & 0xff) + 0x100] ^ - crc24_table[(crc >> 24) & 0xff]; + crc24_table[(data >> 24) & 0xff]; return crc; } @@ -727,6 +769,11 @@ static void crc24rfc2440_init (void *context, unsigned int flags) { CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; +#ifdef USE_INTEL_PCLMUL + u32 hwf = _gcry_get_hw_features (); + + ctx->use_pclmul = (hwf & HWF_INTEL_SSE4_1) && (hwf & HWF_INTEL_PCLMUL); +#endif (void)flags; @@ -740,6 +787,14 @@ crc24rfc2440_write (void *context, const void *inbuf_arg, size_t inlen) CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; u32 crc; +#ifdef USE_INTEL_PCLMUL + if (ctx->use_pclmul) + { + _gcry_crc24rfc2440_intel_pclmul(&ctx->CRC, inbuf, inlen); + return; + } +#endif + if (!inbuf || !inlen) return; diff --git a/configure.ac b/configure.ac index 8b50360..ff72e3f 100644 --- a/configure.ac +++ b/configure.ac @@ -2023,6 +2023,13 @@ LIST_MEMBER(crc, $enabled_digests) if test "$found" = "1" ; then GCRYPT_DIGESTS="$GCRYPT_DIGESTS crc.lo" AC_DEFINE(USE_CRC, 1, [Defined if this module should be included]) + + case "${host}" in + i?86-*-* | x86_64-*-*) + # Build with the assembly implementation + GCRYPT_DIGESTS="$GCRYPT_DIGESTS crc-intel-pclmul.lo" + ;; + esac fi LIST_MEMBER(gostr3411-94, $enabled_digests) diff --git a/src/g10lib.h b/src/g10lib.h index 9d2ece9..7352556 100644 --- a/src/g10lib.h +++ b/src/g10lib.h @@ -194,23 +194,23 @@ char **_gcry_strtokenize (const char *string, const char *delim); /*-- src/hwfeatures.c --*/ -/* (Do not change these values unless synced with the asm code.) */ -#define HWF_PADLOCK_RNG 1 -#define HWF_PADLOCK_AES 2 -#define HWF_PADLOCK_SHA 4 -#define HWF_PADLOCK_MMUL 8 - -#define HWF_INTEL_CPU 16 -#define HWF_INTEL_FAST_SHLD 32 -#define HWF_INTEL_BMI2 64 -#define HWF_INTEL_SSSE3 128 -#define HWF_INTEL_PCLMUL 256 -#define HWF_INTEL_AESNI 512 -#define HWF_INTEL_RDRAND 1024 -#define HWF_INTEL_AVX 2048 -#define HWF_INTEL_AVX2 4096 - -#define HWF_ARM_NEON 8192 +#define HWF_PADLOCK_RNG (1 << 0) +#define HWF_PADLOCK_AES (1 << 1) +#define HWF_PADLOCK_SHA (1 << 2) +#define HWF_PADLOCK_MMUL (1 << 3) + +#define HWF_INTEL_CPU (1 << 4) +#define HWF_INTEL_FAST_SHLD (1 << 5) +#define HWF_INTEL_BMI2 (1 << 6) +#define HWF_INTEL_SSSE3 (1 << 7) +#define HWF_INTEL_SSE4_1 (1 << 8) +#define HWF_INTEL_PCLMUL (1 << 9) +#define HWF_INTEL_AESNI (1 << 10) +#define HWF_INTEL_RDRAND (1 << 11) +#define HWF_INTEL_AVX (1 << 12) +#define HWF_INTEL_AVX2 (1 << 13) + +#define HWF_ARM_NEON (1 << 14) gpg_err_code_t _gcry_disable_hw_feature (const char *name); diff --git a/src/hwf-x86.c b/src/hwf-x86.c index fbd6331..eeacccb 100644 --- a/src/hwf-x86.c +++ b/src/hwf-x86.c @@ -277,6 +277,9 @@ detect_x86_gnuc (void) /* Test bit 9 for SSSE3. */ if (features & 0x00000200) result |= HWF_INTEL_SSSE3; + /* Test bit 19 for SSE4.1. */ + if (features & 0x00080000) + result |= HWF_INTEL_SSE4_1; #ifdef ENABLE_AESNI_SUPPORT /* Test bit 25 for AES-NI. */ if (features & 0x02000000) diff --git a/src/hwfeatures.c b/src/hwfeatures.c index e7c55cc..4cafae1 100644 --- a/src/hwfeatures.c +++ b/src/hwfeatures.c @@ -50,6 +50,7 @@ static struct { HWF_INTEL_FAST_SHLD, "intel-fast-shld" }, { HWF_INTEL_BMI2, "intel-bmi2" }, { HWF_INTEL_SSSE3, "intel-ssse3" }, + { HWF_INTEL_SSE4_1, "intel-sse4.1" }, { HWF_INTEL_PCLMUL, "intel-pclmul" }, { HWF_INTEL_AESNI, "intel-aesni" }, { HWF_INTEL_RDRAND, "intel-rdrand" }, diff --git a/tests/basic.c b/tests/basic.c index 7d5de00..5e7ee44 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -5267,6 +5267,14 @@ check_cipher_modes(void) static void +fillbuf_count (char *buf, size_t buflen, unsigned char pos) +{ + while (buflen--) + *((unsigned char *)(buf++)) = pos++; +} + + +static void check_one_md (int algo, const char *data, int len, const char *expect, int elen) { gcry_md_hd_t hd, hd2; @@ -5297,14 +5305,33 @@ check_one_md (int algo, const char *data, int len, const char *expect, int elen) } } - if (*data == '!' && !data[1]) - { /* hash one million times a "a" */ + if ((*data == '!' && !data[1]) || /* hash one million times a "a" */ + (*data == '?' && !data[1])) /* hash million byte data-set with byte pattern 0x00,0x01,0x02,... */ + { char aaa[1000]; size_t left = 1000 * 1000; size_t startlen = 1; size_t piecelen = startlen; - memset (aaa, 'a', 1000); + if (*data == '!') + memset (aaa, 'a', 1000); + + /* Write in chuck with all sizes 1 to 1000 (500500 bytes) */ + for (i = 1; i <= 1000 && left > 0; i++) + { + piecelen = i; + if (piecelen > sizeof(aaa)) + piecelen = sizeof(aaa); + if (piecelen > left) + piecelen = left; + + if (*data == '?') + fillbuf_count(aaa, piecelen, 1000 * 1000 - left); + + gcry_md_write (hd, aaa, piecelen); + + left -= piecelen; + } /* Write in odd size chunks so that we test the buffering. */ while (left > 0) @@ -5314,6 +5341,9 @@ check_one_md (int algo, const char *data, int len, const char *expect, int elen) if (piecelen > left) piecelen = left; + if (*data == '?') + fillbuf_count(aaa, piecelen, 1000 * 1000 - left); + gcry_md_write (hd, aaa, piecelen); left -= piecelen; @@ -5526,6 +5556,8 @@ check_one_md_multi (int algo, const char *data, int len, const char *expect) if (*data == '!' && !data[1]) return; /* We can't do that here. */ + if (*data == '?' && !data[1]) + return; /* We can't do that here. */ memset (iov, 0, sizeof iov); @@ -5616,6 +5648,8 @@ check_digests (void) "\xc4\x1a\x5c\x0b\x44\x5f\xba\x1a\xda\xbc\xc0\x38\x0e\x0c\x9e\x33" }, { GCRY_MD_MD5, "!", "\x77\x07\xd6\xae\x4e\x02\x7c\x70\xee\xa2\xa9\x35\xc2\x29\x6f\x21" }, + { GCRY_MD_MD5, "?", + "\x5c\x72\x5c\xbc\x2d\xbb\xe1\x14\x81\x59\xe9\xd9\xcf\x90\x64\x8f" }, { GCRY_MD_SHA1, "abc", "\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E" "\x25\x71\x78\x50\xC2\x6C\x9C\xD0\xD8\x9D" }, @@ -5626,6 +5660,9 @@ check_digests (void) { GCRY_MD_SHA1, "!" /* kludge for "a"*1000000 */ , "\x34\xAA\x97\x3C\xD4\xC4\xDA\xA4\xF6\x1E" "\xEB\x2B\xDB\xAD\x27\x31\x65\x34\x01\x6F" }, + { GCRY_MD_SHA1, "?" /* kludge for "\x00\x01\x02"..."\xfe\xff\x00\x01"... (length 1000000) */ , + "\x5f\x8d\x3c\x4f\x12\xf0\x49\x9e\x28\x73" + "\x79\xec\x97\x3b\x98\x4c\x94\x75\xaa\x8f" }, { GCRY_MD_SHA1, "Libgcrypt is free software; you can redistribute it and/or modif" "y it under the terms of the GNU Lesser general Public License as" @@ -5648,6 +5685,9 @@ check_digests (void) { GCRY_MD_SHA224, "!", "\x20\x79\x46\x55\x98\x0c\x91\xd8\xbb\xb4\xc1\xea\x97\x61\x8a\x4b" "\xf0\x3f\x42\x58\x19\x48\xb2\xee\x4e\xe7\xad\x67" }, + { GCRY_MD_SHA224, "?", + "\xfa\xb9\xf0\xdf\x12\xfe\xa1\x1a\x34\x78\x96\x31\xe6\x53\x48\xbf" + "\x3b\xca\x70\x78\xf2\x44\xdf\x62\xab\x27\xb8\xda" }, { GCRY_MD_SHA224, "Libgcrypt is free software; you can redistribute it and/or modif" "y it under the terms of the GNU Lesser general Public License as" @@ -5669,6 +5709,9 @@ check_digests (void) { GCRY_MD_SHA256, "!", "\xcd\xc7\x6e\x5c\x99\x14\xfb\x92\x81\xa1\xc7\xe2\x84\xd7\x3e\x67" "\xf1\x80\x9a\x48\xa4\x97\x20\x0e\x04\x6d\x39\xcc\xc7\x11\x2c\xd0" }, + { GCRY_MD_SHA256, "?", + "\x67\x87\x0d\xfc\x9c\x64\xe7\xaa\x27\x0a\x3f\x7e\x80\x51\xae\x65" + "\xd2\x07\xf9\x3f\xc3\xdf\x04\xd7\x57\x2e\x63\x65\xaf\x69\xcd\x0d" }, { GCRY_MD_SHA256, "Libgcrypt is free software; you can redistribute it and/or modif" "y it under the terms of the GNU Lesser general Public License as" @@ -5700,6 +5743,10 @@ check_digests (void) "\x9d\x0e\x18\x09\x71\x64\x74\xcb\x08\x6e\x83\x4e\x31\x0a\x4a\x1c" "\xed\x14\x9e\x9c\x00\xf2\x48\x52\x79\x72\xce\xc5\x70\x4c\x2a\x5b" "\x07\xb8\xb3\xdc\x38\xec\xc4\xeb\xae\x97\xdd\xd8\x7f\x3d\x89\x85" }, + { GCRY_MD_SHA384, "?", + "\xfa\x77\xbb\x86\x3a\xd5\xae\x88\xa9\x9c\x5e\xda\xb5\xc7\xcb\x40" + "\xcd\xf4\x30\xef\xa8\x1b\x23\x7b\xa9\xde\xfd\x81\x12\xf6\x7e\xed" + "\xa7\xd2\x27\x91\xd1\xbc\x76\x44\x57\x59\x71\x11\xe6\x8a\x2c\xde" }, { GCRY_MD_SHA512, "abc", "\xDD\xAF\x35\xA1\x93\x61\x7A\xBA\xCC\x41\x73\x49\xAE\x20\x41\x31" "\x12\xE6\xFA\x4E\x89\xA9\x7E\xA2\x0A\x9E\xEE\xE6\x4B\x55\xD3\x9A" @@ -5723,6 +5770,11 @@ check_digests (void) "\x8e\x1f\x98\xb1\x3b\x20\x44\x28\x56\x32\xa8\x03\xaf\xa9\x73\xeb" "\xde\x0f\xf2\x44\x87\x7e\xa6\x0a\x4c\xb0\x43\x2c\xe5\x77\xc3\x1b" "\xeb\x00\x9c\x5c\x2c\x49\xaa\x2e\x4e\xad\xb2\x17\xad\x8c\xc0\x9b" }, + { GCRY_MD_SHA512, "?", + "\x91\xe9\x42\x4e\xa9\xdc\x44\x01\x40\x64\xa4\x5a\x69\xcc\xac\xa3" + "\x74\xee\x78\xeb\x79\x1f\x94\x38\x5b\x73\xef\xf8\xfd\x5d\x74\xd8" + "\x51\x36\xfe\x63\x52\xde\x07\x70\x95\xd6\x78\x2b\x7b\x46\x8a\x2c" + "\x30\x0f\x48\x0c\x74\x43\x06\xdb\xa3\x8d\x64\x3d\xe9\xa1\xa7\x72" }, { GCRY_MD_SHA3_224, "abc", "\xe6\x42\x82\x4c\x3f\x8c\xf2\x4a\xd0\x92\x34\xee\x7d\x3c\x76\x6f" "\xc9\xa3\xa5\x16\x8d\x0c\x94\xad\x73\xb4\x6f\xdf" }, @@ -5806,6 +5858,21 @@ check_digests (void) "\x12\x0a\x2a\x53\x70\x21\x2d\xff\xb3\x38\x5a\x18\xd4\xf3\x88\x59" "\xed\x31\x1d\x0a\x9d\x51\x41\xce\x9c\xc5\xc6\x6e\xe6\x89\xb2\x66" "\xa8\xaa\x18\xac\xe8\x28\x2a\x0e\x0d\xb5\x96\xc9\x0b\x0a\x7b\x87" }, + { GCRY_MD_SHA3_224, "?", + "\x1b\xd1\xc6\x12\x02\x35\x52\x8b\x44\x7e\x16\x39\x20\x05\xec\x67" + "\x2d\x57\x20\xe0\x90\xc9\x78\x08\x86\x4f\x1b\xd0" }, + { GCRY_MD_SHA3_256, "?", + "\xfe\xb7\xf4\x76\x78\x97\x48\x2f\xe2\x29\x1b\x66\x85\xc1\x7b\x45" + "\xc5\x08\xed\x82\x50\xcc\x5d\x99\x96\xd2\xc3\x82\x1a\xa8\xd4\xa7" }, + { GCRY_MD_SHA3_384, "?", + "\x45\x1f\x0b\x93\x4b\xca\x3e\x65\x93\xd4\xaa\x8c\x18\xc1\x04\x84" + "\x12\xd5\x1e\x35\xe1\x05\xd9\x77\x3f\xc1\x08\x8b\x77\x36\xad\x4a" + "\x33\x70\xaf\x49\x8b\xea\x4c\x5c\x52\xe7\x5b\xed\x31\x74\x57\x12" }, + { GCRY_MD_SHA3_512, "?", + "\xa2\xee\xb5\x6f\x2a\x87\xa5\xb3\x9b\xd9\x1c\xf0\xaa\xdf\xb1\xd5" + "\xad\x0a\x1a\xaa\xd3\x63\x81\xcf\xb8\x7c\x36\xa7\x80\x3b\x03\xd6" + "\x31\x5c\x5d\x33\x8e\x52\xb1\x42\x4d\x27\x1c\xa2\xa5\xf2\xc5\x97" + "\x10\x12\xe5\xee\x86\xa3\xcc\xaf\x91\x7a\x94\x28\x65\xea\x66\xe3" }, { GCRY_MD_RMD160, "", "\x9c\x11\x85\xa5\xc5\xe9\xfc\x54\x61\x28" "\x08\x97\x7e\xe8\xf5\x48\xb2\x25\x8d\x31" }, @@ -5832,6 +5899,9 @@ check_digests (void) { GCRY_MD_RMD160, "!", "\x52\x78\x32\x43\xc1\x69\x7b\xdb\xe1\x6d\x37\xf9\x7f\x68\xf0\x83" "\x25\xdc\x15\x28" }, + { GCRY_MD_RMD160, "?", + "\x68\x14\x86\x70\x3d\x51\x4e\x36\x68\x50\xf8\xb3\x00\x75\xda\x49" + "\x0a\xaa\x2c\xf6" }, { GCRY_MD_CRC32, "", "\x00\x00\x00\x00" }, { GCRY_MD_CRC32, "foo", "\x8c\x73\x65\x21" }, { GCRY_MD_CRC32, @@ -5846,6 +5916,7 @@ check_digests (void) "\x4A\x53\x7D\x67" }, { GCRY_MD_CRC32, "123456789", "\xcb\xf4\x39\x26" }, { GCRY_MD_CRC32, "!", "\xdc\x25\xbf\xbc" }, + { GCRY_MD_CRC32, "?", "\x61\x82\x29\x1B" }, { GCRY_MD_CRC32_RFC1510, "", "\x00\x00\x00\x00" }, { GCRY_MD_CRC32_RFC1510, "foo", "\x73\x32\xbc\x33" }, { GCRY_MD_CRC32_RFC1510, "test0123456789", "\xb8\x3e\x88\xd6" }, @@ -5858,9 +5929,13 @@ check_digests (void) { GCRY_MD_CRC32_RFC1510, "\x80\x00\x00\x00", "\xed\x59\xb6\x3b", 4 }, { GCRY_MD_CRC32_RFC1510, "\x00\x00\x00\x01", "\x77\x07\x30\x96", 4 }, { GCRY_MD_CRC32_RFC1510, "123456789", "\x2d\xfd\x2d\x88" }, + { GCRY_MD_CRC32_RFC1510, "!", "\xce\x5c\x74\x22" }, + { GCRY_MD_CRC32_RFC1510, "?", "\x73\xfb\xe2\x85" }, { GCRY_MD_CRC24_RFC2440, "", "\xb7\x04\xce" }, { GCRY_MD_CRC24_RFC2440, "foo", "\x4f\xc2\x55" }, { GCRY_MD_CRC24_RFC2440, "123456789", "\x21\xcf\x02" }, + { GCRY_MD_CRC24_RFC2440, "!", "\xa5\xcb\x6b" }, + { GCRY_MD_CRC24_RFC2440, "?", "\x7f\x67\x03" }, { GCRY_MD_TIGER, "", "\x24\xF0\x13\x0C\x63\xAC\x93\x32\x16\x16\x6E\x76" @@ -5942,6 +6017,9 @@ check_digests (void) "ral Public License for more details.", "\x60\xee\xdf\x95\x39\xc8\x44\x94\x64\xdc\xdf\x3d\x2e\x1c\xe5\x79" "\x6a\x95\xbd\x30\x68\x8c\x7e\xb8" }, + { GCRY_MD_TIGER1, "?", + "\x4b\xe2\x3f\x23\xf5\x34\xbe\xbf\x97\x42\x95\x80" + "\x54\xe4\x6c\x12\x64\x85\x44\x0a\xa9\x49\x9b\x65" }, { GCRY_MD_TIGER2, "", "\x44\x41\xBE\x75\xF6\x01\x87\x73\xC2\x06\xC2\x27" @@ -5986,11 +6064,11 @@ check_digests (void) "\xF0\xDF\xF5\x94\x13\x14\x5E\x69\x73\xC4\x50\x01\xD0\x08\x7B\x42" "\xD1\x1B\xC6\x45\x41\x3A\xEF\xF6\x3A\x42\x39\x1A\x39\x14\x5A\x59" "\x1A\x92\x20\x0D\x56\x01\x95\xE5\x3B\x47\x85\x84\xFD\xAE\x23\x1A" }, - { GCRY_MD_WHIRLPOOL, "a", - "\x8A\xCA\x26\x02\x79\x2A\xEC\x6F\x11\xA6\x72\x06\x53\x1F\xB7\xD7" - "\xF0\xDF\xF5\x94\x13\x14\x5E\x69\x73\xC4\x50\x01\xD0\x08\x7B\x42" - "\xD1\x1B\xC6\x45\x41\x3A\xEF\xF6\x3A\x42\x39\x1A\x39\x14\x5A\x59" - "\x1A\x92\x20\x0D\x56\x01\x95\xE5\x3B\x47\x85\x84\xFD\xAE\x23\x1A" }, + { GCRY_MD_WHIRLPOOL, "?", + "\x88\xf0\x78\x6d\x0d\x47\xe5\x32\x1f\x88\xb1\x48\x05\x53\x58\x7d" + "\x19\x4b\x32\x9b\xf1\xfb\x17\xc5\x98\x3a\x87\xa2\x48\x61\x3d\x2b" + "\xb2\xbc\x9f\x0d\xd2\x14\x37\x30\x55\x30\x91\xa7\xb8\x0c\x0f\x80" + "\x7c\x7b\x94\xf6\x55\xf6\x0b\x12\x85\x0c\x8e\x6d\x17\x5b\x1e\x71" }, { GCRY_MD_WHIRLPOOL, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "\xDC\x37\xE0\x08\xCF\x9E\xE6\x9B\xF1\x1F\x00\xED\x9A\xBA\x26\x90" commit a8b803d9e4bea2b779385ec9e9a579acc64431e9 Author: Jussi Kivilinna Date: Sat Mar 12 17:10:30 2016 +0200 Update .gitignore -- Signed-off-by: Jussi Kivilinna diff --git a/.gitignore b/.gitignore index b961614..3cd83a2 100644 --- a/.gitignore +++ b/.gitignore @@ -37,9 +37,12 @@ doc/Makefile doc/fips-fsm.eps doc/fips-fsm.pdf doc/fips-fsm.png +doc/hmac256.1 doc/libgcrypt-modules.eps doc/libgcrypt-modules.pdf doc/libgcrypt-modules.png +doc/yat2m +doc/yat2m-stamp mpi/Makefile mpi/asm-syntax.h mpi/libmpi.la @@ -61,27 +64,43 @@ src/gcrypt.h src/hmac256 src/libgcrypt-config src/libgcrypt.la +src/mpicalc src/versioninfo.rc +src/*.exe tests/Makefile tests/ac tests/ac-data tests/ac-schemes tests/aeswrap tests/basic +tests/bench-slope tests/benchmark +tests/curves +tests/dsa-rfc6979 tests/fips186-dsa tests/fipsdrv tests/gchash +tests/genhashdata +tests/hashtest tests/hashtest-256g tests/hmac tests/keygen tests/keygrip tests/mpitests +tests/pkcs1v2 tests/prime tests/pubkey tests/random tests/register tests/rsacvt +tests/t-convert +tests/t-cv25519 +tests/t-ed25519 +tests/t-kdf +tests/t-lock tests/t-mpi-bit +tests/t-mpi-point +tests/t-sexp tests/tsexp tests/version +tests/*.exe ----------------------------------------------------------------------- Summary of changes: .gitignore | 19 + cipher/Makefile.am | 1 + cipher/crc-intel-pclmul.c | 912 ++++++++++++++++++++++++++++++++++++++++++++++ cipher/crc.c | 59 ++- configure.ac | 7 + src/g10lib.h | 34 +- src/hwf-x86.c | 3 + src/hwfeatures.c | 1 + tests/basic.c | 94 ++++- 9 files changed, 1103 insertions(+), 27 deletions(-) create mode 100644 cipher/crc-intel-pclmul.c hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From jussi.kivilinna at iki.fi Tue Mar 15 21:48:25 2016 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 15 Mar 2016 22:48:25 +0200 Subject: [PATCH 1/2] Update .gitignore In-Reply-To: <878u1lpbqc.fsf@wheatstone.g10code.de> References: <20160312174248.12371.90456.stgit@localhost6.localdomain6> <878u1lpbqc.fsf@wheatstone.g10code.de> Message-ID: <56E87519.40908@iki.fi> On 14.03.2016 12:58, Werner Koch wrote: > >> .gitignore | 19 +++++++++++++++++++ >> 1 file changed, 19 insertions(+) > > Ha, I caught you as not using VPATH builds ;-) Well well.. these VPATH builds seems to be awfully useful. > > (feel free to push) Done. I think commit 2cba0dbda462237f55438d4199eccd10c5e3f6ca (salsa20: fix alignment of self-test context) should be cherry-picked to libgcrypt 1.6 branch. It fixes the crashes with FreeBSD/clang. -Jussi > > > Shalom-Salam, > > Werner > From cvs at cvs.gnupg.org Wed Mar 16 13:59:09 2016 From: cvs at cvs.gnupg.org (by Justus Winter) Date: Wed, 16 Mar 2016 13:59:09 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-339-g4051fe7 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via 4051fe7fec6ffdc7a2f5c3856665478866991ee7 (commit) via fcf4358a7a7ba8d32bf385ea99ced5f47cbd3ae2 (commit) from 5d601dd57fcb41aa2015ab655fd6fc51537da667 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 4051fe7fec6ffdc7a2f5c3856665478866991ee7 Author: Justus Winter Date: Wed Mar 16 13:35:37 2016 +0100 Update documentation for 'gcry_sexp_extract_param'. * doc/gcrypt.texi (gcry_sexp_extract_param): Mention that all MIPs must be set to NULL first, and document how the function behaves in case of errors. * src/sexp.c (_gcry_sexp_extract_param): Likewise. * src/gcrypt.h.in (gcry_sexp_extract_param): Copy the comment from '_gcry_sexp_extract_param'. Signed-off-by: Justus Winter diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index 23b1f79..3265a70 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -4336,8 +4336,10 @@ In general parameter names are single letters. To use a string for a parameter name, enclose the name in single quotes. Unless in buffer descriptor mode for each parameter name a pointer to -an @code{gcry_mpi_t} variable is expected finally followed by a @code{NULL}. -For example +an @code{gcry_mpi_t} variable is expected that must be set to + at code{NULL} prior to invoking this function, and finally a @code{NULL} +is expected. For example + @example _gcry_sexp_extract_param (key, NULL, "n/x+e d-'foo'", &mpi_n, &mpi_x, &mpi_e, &mpi_foo, NULL) @@ -4366,8 +4368,11 @@ number of bytes copied to that buffer; in case the buffer is too small, the function immediately returns with an error code (and @var{len} is set to 0). -The function returns NULL on success. On error an error code is -returned and the passed MPIs are either unchanged or set to NULL. +The function returns 0 on success. On error an error code is +returned, all passed MPIs that might have been allocated up to this +point are deallocated and set to @code{NULL}, and all passed buffers +are either truncated if the caller supplied the buffer, or deallocated +if the function allocated the buffer. @end deftypefun diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index f48f04f..797da2e 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -473,8 +473,51 @@ char *gcry_sexp_nth_string (gcry_sexp_t list, int number); value can't be converted to an MPI, `NULL' is returned. */ gcry_mpi_t gcry_sexp_nth_mpi (gcry_sexp_t list, int number, int mpifmt); -/* Convenience function to extract parameters from an S-expression - * using a list of single letter parameters. */ +/* Extract MPIs from an s-expression using a list of parameters. The + * names of these parameters are given by the string LIST. Some + * special characters may be given to control the conversion: + * + * + :: Switch to unsigned integer format (default). + * - :: Switch to standard signed format. + * / :: Switch to opaque format. + * & :: Switch to buffer descriptor mode - see below. + * ? :: The previous parameter is optional. + * + * In general parameter names are single letters. To use a string for + * a parameter name, enclose the name in single quotes. + * + * Unless in gcry_buffer_t mode for each parameter name a pointer to + * an MPI variable is expected that must be set to NULL prior to + * invoking this function, and finally a NULL is expected. Example: + * + * _gcry_sexp_extract_param (key, NULL, "n/x+ed", + * &mpi_n, &mpi_x, &mpi_e, NULL) + * + * This stores the parameter "N" from KEY as an unsigned MPI into + * MPI_N, the parameter "X" as an opaque MPI into MPI_X, and the + * parameter "E" again as an unsigned MPI into MPI_E. + * + * If in buffer descriptor mode a pointer to gcry_buffer_t descriptor + * is expected instead of a pointer to an MPI. The caller may use two + * different operation modes: If the DATA field of the provided buffer + * descriptor is NULL, the function allocates a new buffer and stores + * it at DATA; the other fields are set accordingly with OFF being 0. + * If DATA is not NULL, the function assumes that DATA, SIZE, and OFF + * describe a buffer where to but the data; on return the LEN field + * receives the number of bytes copied to that buffer; if the buffer + * is too small, the function immediately returns with an error code + * (and LEN set to 0). + * + * PATH is an optional string used to locate a token. The exclamation + * mark separated tokens are used to via gcry_sexp_find_token to find + * a start point inside SEXP. + * + * The function returns 0 on success. On error an error code is + * returned, all passed MPIs that might have been allocated up to this + * point are deallocated and set to NULL, and all passed buffers are + * either truncated if the caller supplied the buffer, or deallocated + * if the function allocated the buffer. + */ gpg_error_t gcry_sexp_extract_param (gcry_sexp_t sexp, const char *path, const char *list, diff --git a/src/sexp.c b/src/sexp.c index d063962..636f922 100644 --- a/src/sexp.c +++ b/src/sexp.c @@ -2183,8 +2183,8 @@ _gcry_sexp_canon_len (const unsigned char *buffer, size_t length, * a parameter name, enclose the name in single quotes. * * Unless in gcry_buffer_t mode for each parameter name a pointer to - * an MPI variable is expected and finally a NULL is expected. - * Example: + * an MPI variable is expected that must be set to NULL prior to + * invoking this function, and finally a NULL is expected. Example: * * _gcry_sexp_extract_param (key, NULL, "n/x+ed", * &mpi_n, &mpi_x, &mpi_e, NULL) @@ -2208,8 +2208,11 @@ _gcry_sexp_canon_len (const unsigned char *buffer, size_t length, * mark separated tokens are used to via gcry_sexp_find_token to find * a start point inside SEXP. * - * The function returns NULL on success. On error an error code is - * returned and the passed MPIs are either unchanged or set to NULL. + * The function returns 0 on success. On error an error code is + * returned, all passed MPIs that might have been allocated up to this + * point are deallocated and set to NULL, and all passed buffers are + * either truncated if the caller supplied the buffer, or deallocated + * if the function allocated the buffer. */ gpg_err_code_t _gcry_sexp_vextract_param (gcry_sexp_t sexp, const char *path, commit fcf4358a7a7ba8d32bf385ea99ced5f47cbd3ae2 Author: Justus Winter Date: Wed Mar 16 12:49:26 2016 +0100 cipher: Update comment. * cipher/ecc.c (ecc_get_nbits): Update comment to reflect the fact that a curve parameter can be given. Signed-off-by: Justus Winter diff --git a/cipher/ecc.c b/cipher/ecc.c index 4cdbb14..f65203f 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -1657,6 +1657,7 @@ ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms) * for example: * * (ecc + * (curve ) * (p ) * (a ) * (b ) @@ -1664,8 +1665,7 @@ ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms) * (n ) * (q )) * - * More parameters may be given currently P is needed. FIXME: We - * need allow for a "curve" parameter. + * More parameters may be given. Either P or CURVE is needed. */ static unsigned int ecc_get_nbits (gcry_sexp_t parms) ----------------------------------------------------------------------- Summary of changes: cipher/ecc.c | 4 ++-- doc/gcrypt.texi | 13 +++++++++---- src/gcrypt.h.in | 47 +++++++++++++++++++++++++++++++++++++++++++++-- src/sexp.c | 11 +++++++---- 4 files changed, 63 insertions(+), 12 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From jussi.kivilinna at iki.fi Wed Mar 16 20:24:54 2016 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Wed, 16 Mar 2016 21:24:54 +0200 Subject: [PATCH] Fix ARM NEON support detection on ARMv6 target Message-ID: <20160316192454.13294.65181.stgit@localhost6.localdomain6> * configure.ac (gcry_cv_gcc_inline_asm_neon): Use '.arm' directive instead of '.thumb'. -- Fix allows building ARM NEON assembly implementations when compiler target is ARMv6. This enables NEON implementations on ARMv7+NEON CPUs running on ARMv6 OS (for example, Raspbian on Raspberry Pi 2/3). Signed-off-by: Jussi Kivilinna --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index ff72e3f..f76e875 100644 --- a/configure.ac +++ b/configure.ac @@ -1487,7 +1487,7 @@ AC_CACHE_CHECK([whether GCC inline assembler supports NEON instructions], AC_COMPILE_IFELSE([AC_LANG_SOURCE( [[__asm__( ".syntax unified\n\t" - ".thumb\n\t" + ".arm\n\t" ".fpu neon\n\t" "vld1.64 {%q0-%q1}, [%r0]!;\n\t" "vrev64.8 %q0, %q3;\n\t" From burts at us.ibm.com Fri Mar 18 02:09:39 2016 From: burts at us.ibm.com (Burt Silverman) Date: Thu, 17 Mar 2016 20:09:39 -0500 Subject: dladdr() in fips.c and --enable-hmac-binary-check and --enable-static Message-ID: <201603180109.u2I19Pxt017884@d03av05.boulder.ibm.com> One of our team members decided that he needed to create a program binary using static libraries, and he also decided to use the --enable-hmac-binary-check option. This combination of configure options will not work, because it exposes the dladdr() function call, and the dladdr() function is incompatible with static libraries. My teammate's initial problem was that dladdr() was not found. He thought he could solve the issue by linking in -ldl. That solved his build problem, and I had to point out to him that his solution will fail at run time. Can you eliminate the use of dladdr(), or come up with something that is less likely to trip up a novice? Perhaps it is ridiculous for him to be building a static library, but the configure.ac does not prevent him from doing that. Honestly, his own autoconf/automake files apparently have some bug that led him to consider static libraries. But those files are owned by a different company, so there are non-technical hurdles involved. What can you do or recommend? Thank you, Werner. Burt Silverman -------------- next part -------------- An HTML attachment was scrubbed... URL: From wk at gnupg.org Fri Mar 18 10:21:17 2016 From: wk at gnupg.org (Werner Koch) Date: Fri, 18 Mar 2016 10:21:17 +0100 Subject: version 1.7 In-Reply-To: <20160212131505.GA1242@argenau.bebt.de> (Andreas Metzler's message of "Fri, 12 Feb 2016 14:15:05 +0100") References: <20160128170750.23462.38269.stgit@localhost6.localdomain6> <87io2cn41i.fsf@vigenere.g10code.de> <6bakoc-207.ln1@argenau.bebt.de> <87twlgb9uv.fsf@vigenere.g10code.de> <20160212131505.GA1242@argenau.bebt.de> Message-ID: <87vb4kgn02.fsf@wheatstone.g10code.de> On Fri, 12 Feb 2016 14:15, ametzler at bebt.de said: > Out of the yet tried builds only one failed, PPC64: > selftest for CFB failed - see syslog for details > pass 0, algo 4, mode 1, gcry_cipher_setkey failed: Selftest failed > This is also present in 1.6 where we work around it with > http://sources.debian.net/src/libgcrypt20/1.6.5-2/debian/patches/20_fedora_libgcrypt-1.6.3-aliasing.patch/ which adds __attribute__ ((optimize("no-strict-aliasing"))) to the inline functions of bufhelp.h. @jussi: I recall that you fixed some alignment problems - might that problem be related? Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From cvs at cvs.gnupg.org Fri Mar 18 17:56:27 2016 From: cvs at cvs.gnupg.org (by Vitezslav Cizek) Date: Fri, 18 Mar 2016 17:56:27 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-352-g9ecc269 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via 9ecc2690181ba0bb44f66451a7dce2fc19965793 (commit) via 1a02d741cacc3b57fe3d6ffebd794d53a60c9e97 (commit) from 0bd8137e68c201b6c2290710e348aaf57efa2b2e (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 9ecc2690181ba0bb44f66451a7dce2fc19965793 Author: Vitezslav Cizek Date: Fri Mar 18 17:54:36 2016 +0100 tests: Fix testsuite after the FIPS adjustments. * tests/benchmark.c (ecc_bench): Avoid not approved curves in FIPS. * tests/curves.c (check_get_params): Skip Brainpool curves in FIPS. * tests/keygen.c (check_dsa_keys): Generate 2048 and 3072 bits keys. (check_ecc_keys): Skip Ed25519 in FIPS mode. * tests/random.c (main): Don't switch DRBG in FIPS mode. * tests/t-ed25519.c (main): Ed25519 isn't supported in FIPS mode. * tests/t-kdf.c (check_openpgp): Skip vectors using md5 in FIPS. * tests/t-mpi-point.c (context_param): Skip P-192 and Ed25519 in FIPS. (main): Skip math tests that use P-192 and Ed25519 in FIPS. -- Fix the testsuite to make it pass after the FIPS adjustmens. This consists mostly of disabling the tests that use not approved curves and algorithms as well as increasing the keysizes. Signed-off-by: Vitezslav Cizek Additional changes by wk: - Removed changes already done with commit e40939b. The original patch had these chnages: * tests/fips186-dsa.c (main): Merely suggest a future improvement. * tests/pubkey.c (get_dsa_key_*new): Increase keysizes. (check_run): Skip tests with small domain in FIPS. (main): Skip Ed25519 sample key test in FIPS. Noet that get_dsa_key_fips186_with_seed_new was not changed from 1024 to 3072 but to 2048 bit. - Return with 77 (skip) from t-ed25519.c in FIPS mode. - Some code style changes. Signed-off-by: Werner Koch diff --git a/tests/benchmark.c b/tests/benchmark.c index c748dac..1258b81 100644 --- a/tests/benchmark.c +++ b/tests/benchmark.c @@ -1434,6 +1434,12 @@ ecc_bench (int iterations, int print_header) is_ed25519 = !strcmp (p_sizes[testno], "Ed25519"); is_gost = !strncmp (p_sizes[testno], "gost", 4); + + /* Only P-{224,256,384,521} are allowed in fips mode */ + if (gcry_fips_mode_active() + && (is_ed25519 || is_gost || !strcmp (p_sizes[testno], "192"))) + continue; + if (is_ed25519) { p_size = 256; diff --git a/tests/curves.c b/tests/curves.c index bec48e9..2732bbd 100644 --- a/tests/curves.c +++ b/tests/curves.c @@ -171,6 +171,9 @@ check_get_params (void) gcry_sexp_release (param); + /* Brainpool curves are not supported in fips mode */ + if (gcry_fips_mode_active()) + return; param = gcry_pk_get_param (GCRY_PK_ECDSA, sample_key_2_curve); if (!param) diff --git a/tests/keygen.c b/tests/keygen.c index 7afa76c..dcb59e4 100644 --- a/tests/keygen.c +++ b/tests/keygen.c @@ -329,7 +329,7 @@ check_dsa_keys (void) if (rc && !in_fips_mode) die ("error generating DSA key: %s\n", gpg_strerror (rc)); else if (!rc && in_fips_mode) - die ("generating 512 bit DSA key must not work!"); + die ("generating 1024 bit DSA key must not work!"); if (!i && verbose > 1) show_sexp ("1024 bit DSA key:\n", key); gcry_sexp_release (key); @@ -354,6 +354,60 @@ check_dsa_keys (void) if (verbose > 1) show_sexp ("1536 bit DSA key:\n", key); gcry_sexp_release (key); + + if (verbose) + show ("creating 3072 bit DSA key\n"); + rc = gcry_sexp_new (&keyparm, + "(genkey\n" + " (dsa\n" + " (nbits 4:3072)\n" + " (qbits 3:256)\n" + " ))", 0, 1); + if (rc) + die ("error creating S-expression: %s\n", gpg_strerror (rc)); + rc = gcry_pk_genkey (&key, keyparm); + gcry_sexp_release (keyparm); + if (rc) + die ("error generating DSA key: %s\n", gpg_strerror (rc)); + if (verbose > 1) + show_sexp ("3072 bit DSA key:\n", key); + gcry_sexp_release (key); + + if (verbose) + show ("creating 2048/256 bit DSA key\n"); + rc = gcry_sexp_new (&keyparm, + "(genkey\n" + " (dsa\n" + " (nbits 4:2048)\n" + " (qbits 3:256)\n" + " ))", 0, 1); + if (rc) + die ("error creating S-expression: %s\n", gpg_strerror (rc)); + rc = gcry_pk_genkey (&key, keyparm); + gcry_sexp_release (keyparm); + if (rc) + die ("error generating DSA key: %s\n", gpg_strerror (rc)); + if (verbose > 1) + show_sexp ("2048 bit DSA key:\n", key); + gcry_sexp_release (key); + + if (verbose) + show ("creating 2048/224 bit DSA key\n"); + rc = gcry_sexp_new (&keyparm, + "(genkey\n" + " (dsa\n" + " (nbits 4:2048)\n" + " (qbits 3:224)\n" + " ))", 0, 1); + if (rc) + die ("error creating S-expression: %s\n", gpg_strerror (rc)); + rc = gcry_pk_genkey (&key, keyparm); + gcry_sexp_release (keyparm); + if (rc) + die ("error generating DSA key: %s\n", gpg_strerror (rc)); + if (verbose > 1) + show_sexp ("2048 bit DSA key:\n", key); + gcry_sexp_release (key); } @@ -406,9 +460,14 @@ check_ecc_keys (void) if (verbose) show ("creating ECC key using curve %s\n", curves[testno]); if (!strcmp (curves[testno], "Ed25519")) - rc = gcry_sexp_build (&keyparm, NULL, - "(genkey(ecc(curve %s)(flags param eddsa)))", - curves[testno]); + { + /* Ed25519 isn't allowed in fips mode */ + if (in_fips_mode) + continue; + rc = gcry_sexp_build (&keyparm, NULL, + "(genkey(ecc(curve %s)(flags param eddsa)))", + curves[testno]); + } else rc = gcry_sexp_build (&keyparm, NULL, "(genkey(ecc(curve %s)(flags param)))", @@ -459,6 +518,40 @@ check_ecc_keys (void) " (nocomp): %s\n", gpg_strerror (rc)); + if (verbose) + show ("creating ECC key using curve NIST P-384 for ECDSA\n"); + + /* Must be specified as nistp384 (one word), because ecc_generate + * uses _gcry_sexp_nth_string which takes the first word of the name + * and thus libgcrypt can't find it later in its curves table. */ + rc = gcry_sexp_build (&keyparm, NULL, "(genkey(ecc(curve nistp384)))"); + if (rc) + die ("error creating S-expression: %s\n", gpg_strerror (rc)); + rc = gcry_pk_genkey (&key, keyparm); + gcry_sexp_release (keyparm); + if (rc) + die ("error generating ECC key using curve NIST P-384 for ECDSA: %s\n", + gpg_strerror (rc)); + + if (verbose > 1) + show_sexp ("ECC key:\n", key); + + check_generated_ecc_key (key); + gcry_sexp_release (key); + + if (verbose) + show ("creating ECC key using curve NIST P-384 for ECDSA (nocomp)\n"); + rc = gcry_sexp_build (&keyparm, NULL, + "(genkey(ecc(curve nistp384)(flags nocomp)))"); + if (rc) + die ("error creating S-expression: %s\n", gpg_strerror (rc)); + rc = gcry_pk_genkey (&key, keyparm); + gcry_sexp_release (keyparm); + if (rc) + die ("error generating ECC key using curve NIST P-384 for ECDSA" + " (nocomp): %s\n", + gpg_strerror (rc)); + if (verbose > 1) show_sexp ("ECC key:\n", key); diff --git a/tests/pubkey.c b/tests/pubkey.c index 5ed6ca1..b691913 100644 --- a/tests/pubkey.c +++ b/tests/pubkey.c @@ -483,8 +483,8 @@ get_dsa_key_new (gcry_sexp_t *pkey, gcry_sexp_t *skey, int transient_key) rc = gcry_sexp_new (&key_spec, transient_key - ? "(genkey (dsa (nbits 4:1024)(transient-key)))" - : "(genkey (dsa (nbits 4:1024)))", + ? "(genkey (dsa (nbits 4:2048)(transient-key)))" + : "(genkey (dsa (nbits 4:2048)))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gcry_strerror (rc)); @@ -1243,7 +1243,8 @@ main (int argc, char **argv) check_x931_derived_key (i); check_ecc_sample_key (); - check_ed25519ecdsa_sample_key (); + if (!gcry_fips_mode_active ()) + check_ed25519ecdsa_sample_key (); return !!error_count; } diff --git a/tests/random.c b/tests/random.c index 2a4b698..3c08726 100644 --- a/tests/random.c +++ b/tests/random.c @@ -647,7 +647,11 @@ main (int argc, char **argv) #endif if (early_rng) - check_early_rng_type_switching (); + { + /* Don't switch RNG in fips mode. */ + if (!gcry_fips_mode_active()) + check_early_rng_type_switching (); + } gcry_control (GCRYCTL_DISABLE_SECMEM, 0); if (!gcry_check_version (GCRYPT_VERSION)) @@ -670,7 +674,10 @@ main (int argc, char **argv) to its high requirement for entropy. */ if (!getenv ("GCRYPT_IN_REGRESSION_TEST")) check_drbg_reinit (); - check_rng_type_switching (); + + /* Don't switch RNG in fips mode. */ + if (!gcry_fips_mode_active()) + check_rng_type_switching (); if (!in_recursion) run_all_rng_tests (program); diff --git a/tests/t-ed25519.c b/tests/t-ed25519.c index 38e154d..d63c145 100644 --- a/tests/t-ed25519.c +++ b/tests/t-ed25519.c @@ -548,6 +548,10 @@ main (int argc, char **argv) gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); + /* Ed25519 isn't supported in fips mode */ + if (gcry_fips_mode_active()) + return 77; + start_timer (); check_ed25519 (fname); stop_timer (); diff --git a/tests/t-kdf.c b/tests/t-kdf.c index 18c8357..bf31c83 100644 --- a/tests/t-kdf.c +++ b/tests/t-kdf.c @@ -888,6 +888,10 @@ check_openpgp (void) { if (tv[tvidx].disabled) continue; + /* MD5 isn't supported in fips mode */ + if (gcry_fips_mode_active() + && tv[tvidx].hashalgo == GCRY_MD_MD5) + continue; if (verbose) fprintf (stderr, "checking S2K test vector %d\n", tvidx); assert (tv[tvidx].dklen <= sizeof outbuf); diff --git a/tests/t-mpi-point.c b/tests/t-mpi-point.c index d72cd27..55c6b66 100644 --- a/tests/t-mpi-point.c +++ b/tests/t-mpi-point.c @@ -540,6 +540,17 @@ context_param (void) show ("checking standard curves\n"); for (idx=0; test_curve[idx].desc; idx++) { + /* P-192 and Ed25519 are not supported in fips mode */ + if (gcry_fips_mode_active()) + { + if (!strcmp(test_curve[idx].desc, "NIST P-192") + || !strcmp(test_curve[idx].desc, "Ed25519")) + { + show("skipping %s in fips mode\n", test_curve[idx].desc ); + continue; + } + } + gcry_ctx_release (ctx); err = gcry_mpi_ec_new (&ctx, NULL, test_curve[idx].desc); if (err) @@ -635,6 +646,10 @@ context_param (void) gcry_sexp_release (sexp); } + /* Skipping Ed25519 if in FIPS mode (it isn't supported) */ + if (gcry_fips_mode_active()) + goto cleanup; + show ("checking sample public key (Ed25519)\n"); q = hex2mpi (sample_ed25519_q); gcry_sexp_release (keyparam); @@ -722,6 +737,7 @@ context_param (void) } + cleanup: gcry_ctx_release (ctx); gcry_sexp_release (keyparam); } @@ -1101,8 +1117,14 @@ main (int argc, char **argv) context_alloc (); context_param (); basic_ec_math (); - basic_ec_math_simplified (); - twistededwards_math (); + + /* The tests are for P-192 and ed25519 which are not supported in + FIPS mode. */ + if (!gcry_fips_mode_active()) + { + basic_ec_math_simplified (); + twistededwards_math (); + } show ("All tests completed. Errors: %d\n", error_count); return error_count ? 1 : 0; commit 1a02d741cacc3b57fe3d6ffebd794d53a60c9e97 Author: Vitezslav Cizek Date: Fri Oct 30 17:36:03 2015 +0100 tests: Add new --pss option to fipsdrv * tests/fipsdrv.c (run_rsa_sign, run_rsa_verify): Set salt-length to 0 for PSS. -- Add new --pss option to fipsdrv to specify RSA-PSS signature encoding. Signed-off-by: Vitezslav Cizek Added by wk: - Help string for --pss - Check that only --pss or --pkcs1 is given. Signed-off-by: Werner Koch diff --git a/tests/fipsdrv.c b/tests/fipsdrv.c index bcc56d1..49253cb 100644 --- a/tests/fipsdrv.c +++ b/tests/fipsdrv.c @@ -1583,7 +1583,7 @@ run_rsa_gen (int keysize, int pubexp) encoded KEYFILE and the hash algorithm HASHALGO. */ static void run_rsa_sign (const void *data, size_t datalen, - int hashalgo, int pkcs1, const char *keyfile) + int hashalgo, int pkcs1, int pss, const char *keyfile) { gpg_error_t err; @@ -1607,6 +1607,20 @@ run_rsa_sign (const void *data, size_t datalen, gcry_md_algo_name (hashalgo), (int)hashsize, hash); } + else if (pss) + { + unsigned char hash[64]; + unsigned int hashsize; + + hashsize = gcry_md_get_algo_dlen (hashalgo); + if (!hashsize || hashsize > sizeof hash) + die ("digest too long for buffer or unknown hash algorithm\n"); + gcry_md_hash_buffer (hashalgo, hash, data, datalen); + err = gcry_sexp_build (&s_data, NULL, + "(data (flags pss)(salt-length #00#)(hash %s %b))", + gcry_md_algo_name (hashalgo), + (int)hashsize, hash); + } else { gcry_mpi_t tmp; @@ -1674,7 +1688,7 @@ run_rsa_sign (const void *data, size_t datalen, binary signature in SIGFILE. */ static void run_rsa_verify (const void *data, size_t datalen, int hashalgo, int pkcs1, - const char *keyfile, const char *sigfile) + int pss, const char *keyfile, const char *sigfile) { gpg_error_t err; @@ -1694,6 +1708,20 @@ run_rsa_verify (const void *data, size_t datalen, int hashalgo, int pkcs1, gcry_md_algo_name (hashalgo), (int)hashsize, hash); } + else if (pss) + { + unsigned char hash[64]; + unsigned int hashsize; + + hashsize = gcry_md_get_algo_dlen (hashalgo); + if (!hashsize || hashsize > sizeof hash) + die ("digest too long for buffer or unknown hash algorithm\n"); + gcry_md_hash_buffer (hashalgo, hash, data, datalen); + err = gcry_sexp_build (&s_data, NULL, + "(data (flags pss)(salt-length #00#)(hash %s %b))", + gcry_md_algo_name (hashalgo), + (int)hashsize, hash); + } else { gcry_mpi_t tmp; @@ -2285,6 +2313,7 @@ usage (int show_help) " --signature NAME Take signature from file NAME\n" " --chunk N Read in chunks of N bytes (implies --binary)\n" " --pkcs1 Use PKCS#1 encoding\n" + " --pss Use PSS encoding with a zero length salt\n" " --mct-server Run a monte carlo test server\n" " --loop Enable random loop mode\n" " --progress Print pogress indicators\n" @@ -2302,6 +2331,7 @@ main (int argc, char **argv) int no_fips = 0; int progress = 0; int use_pkcs1 = 0; + int use_pss = 0; const char *mode_string; const char *curve_string = NULL; const char *key_string = NULL; @@ -2432,6 +2462,11 @@ main (int argc, char **argv) use_pkcs1 = 1; argc--; argv++; } + else if (!strcmp (*argv, "--pss")) + { + use_pss = 1; + argc--; argv++; + } else if (!strcmp (*argv, "--mct-server")) { mct_server = 1; @@ -2446,8 +2481,12 @@ main (int argc, char **argv) if (!argc || argc > 2) usage (0); + mode_string = *argv; + if (use_pkcs1 && use_pss) + die ("Only one of --pkcs or --pss may be given\n"); + if (!strcmp (mode_string, "rsa-derive")) binary_input = 1; @@ -2718,7 +2757,7 @@ main (int argc, char **argv) if (!data) die ("no data available (do not use --chunk)\n"); - run_rsa_sign (data, datalen, algo, use_pkcs1, key_string); + run_rsa_sign (data, datalen, algo, use_pkcs1, use_pss, key_string); } else if (!strcmp (mode_string, "rsa-verify")) @@ -2741,7 +2780,7 @@ main (int argc, char **argv) if (access (signature_string, R_OK)) die ("option --signature needs to specify an existing file\n"); - run_rsa_verify (data, datalen, algo, use_pkcs1, key_string, + run_rsa_verify (data, datalen, algo, use_pkcs1, use_pss, key_string, signature_string); } ----------------------------------------------------------------------- Summary of changes: tests/benchmark.c | 6 ++++ tests/curves.c | 3 ++ tests/fipsdrv.c | 47 +++++++++++++++++++++--- tests/keygen.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++--- tests/pubkey.c | 7 ++-- tests/random.c | 11 ++++-- tests/t-ed25519.c | 4 +++ tests/t-kdf.c | 4 +++ tests/t-mpi-point.c | 26 ++++++++++++-- 9 files changed, 194 insertions(+), 15 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From cvs at cvs.gnupg.org Fri Mar 18 19:04:46 2016 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Fri, 18 Mar 2016 19:04:46 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-353-g897ccd2 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via 897ccd21b7221982806b5c024518f4e989152f14 (commit) from 9ecc2690181ba0bb44f66451a7dce2fc19965793 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 897ccd21b7221982806b5c024518f4e989152f14 Author: Werner Koch Date: Fri Mar 18 18:57:19 2016 +0100 Always require a 64 bit integer type * configure.ac (available_digests_64): Merge with available_digests. (available_kdfs_64): Merge with available_kdfs. <64 bit datatype test>: Bail out if no such type is available. * src/types.h: Emit #error if no u64 can be defined. (PROPERLY_ALIGNED_TYPE): Always add u64 type. * cipher/bithelp.h: Remove all code paths which handle the case of !HAVE_U64_TYPEDEF. * cipher/bufhelp.h: Ditto. * cipher/cipher-ccm.c: Ditto. * cipher/cipher-gcm.c: Ditto. * cipher/cipher-internal.h: Ditto. * cipher/cipher.c: Ditto. * cipher/hash-common.h: Ditto. * cipher/md.c: Ditto. * cipher/poly1305.c: Ditto. * cipher/scrypt.c: Ditto. * cipher/tiger.c: Ditto. * src/g10lib.h: Ditto. * tests/basic.c: Ditto. * tests/bench-slope.c: Ditto. * tests/benchmark.c: Ditto. -- Given that SHA-2 and some other algorithms require a 64 bit type it does not make anymore sense to conditionally compile some part when the platform does not provide such a type. GnuPG-bug-id: 1815. Signed-off-by: Werner Koch diff --git a/cipher/bithelp.h b/cipher/bithelp.h index 258ab2f..4575380 100644 --- a/cipher/bithelp.h +++ b/cipher/bithelp.h @@ -47,33 +47,27 @@ _gcry_bswap32(u32 x) } #endif -#ifdef HAVE_U64_TYPEDEF -# ifdef HAVE_BUILTIN_BSWAP64 -# define _gcry_bswap64 __builtin_bswap64 -# else +#ifdef HAVE_BUILTIN_BSWAP64 +# define _gcry_bswap64 __builtin_bswap64 +#else static inline u64 _gcry_bswap64(u64 x) { return ((u64)_gcry_bswap32(x) << 32) | (_gcry_bswap32(x >> 32)); } -# endif #endif /* Endian dependent byte swap operations. */ #ifdef WORDS_BIGENDIAN # define le_bswap32(x) _gcry_bswap32(x) # define be_bswap32(x) ((u32)(x)) -# ifdef HAVE_U64_TYPEDEF -# define le_bswap64(x) _gcry_bswap64(x) -# define be_bswap64(x) ((u64)(x)) -# endif +# define le_bswap64(x) _gcry_bswap64(x) +# define be_bswap64(x) ((u64)(x)) #else # define le_bswap32(x) ((u32)(x)) # define be_bswap32(x) _gcry_bswap32(x) -# ifdef HAVE_U64_TYPEDEF -# define le_bswap64(x) ((u64)(x)) -# define be_bswap64(x) _gcry_bswap64(x) -# endif +# define le_bswap64(x) ((u64)(x)) +# define be_bswap64(x) _gcry_bswap64(x) #endif @@ -104,7 +98,6 @@ _gcry_ctz (unsigned int x) /* Count trailing zero bits in an u64. We return an int because that is what gcc's builtin does. Returns the number of bits in X if X is 0. */ -#ifdef HAVE_U64_TYPEDEF static inline int _gcry_ctz64(u64 x) { @@ -118,7 +111,6 @@ _gcry_ctz64(u64 x) return 32 + _gcry_ctz (x >> 32); #endif } -#endif /*HAVE_U64_TYPEDEF*/ #endif /*GCRYPT_BITHELP_H*/ diff --git a/cipher/bufhelp.h b/cipher/bufhelp.h index aec4f1c..df35594 100644 --- a/cipher/bufhelp.h +++ b/cipher/bufhelp.h @@ -318,7 +318,7 @@ static inline void buf_put_le32(void *_buf, u32 val) out[0] = val; } -#ifdef HAVE_U64_TYPEDEF + /* Functions for loading and storing unaligned u64 values of different endianness. */ static inline u64 buf_get_be64(const void *_buf) @@ -364,7 +364,6 @@ static inline void buf_put_le64(void *_buf, u64 val) out[1] = val >> 8; out[0] = val; } -#endif /*HAVE_U64_TYPEDEF*/ #else /*BUFHELP_FAST_UNALIGNED_ACCESS*/ @@ -397,7 +396,6 @@ static inline void buf_put_le32(void *_buf, u32 val) out->a = le_bswap32(val); } -#ifdef HAVE_U64_TYPEDEF typedef struct bufhelp_u64_s { @@ -427,7 +425,7 @@ static inline void buf_put_le64(void *_buf, u64 val) bufhelp_u64_t *out = _buf; out->a = le_bswap64(val); } -#endif /*HAVE_U64_TYPEDEF*/ + #endif /*BUFHELP_FAST_UNALIGNED_ACCESS*/ diff --git a/cipher/cipher-ccm.c b/cipher/cipher-ccm.c index 3d5f220..4d8f816 100644 --- a/cipher/cipher-ccm.c +++ b/cipher/cipher-ccm.c @@ -28,9 +28,6 @@ #include "bufhelp.h" #include "./cipher-internal.h" -/* We need a 64 bit type for this code. */ -#ifdef HAVE_U64_TYPEDEF - #define set_burn(burn, nburn) do { \ unsigned int __nburn = (nburn); \ @@ -364,78 +361,3 @@ _gcry_cipher_ccm_decrypt (gcry_cipher_hd_t c, unsigned char *outbuf, return err; } - -#else - -/* - * Provide dummy functions so that we avoid adding too much #ifdefs in - * cipher.c. - */ - -gcry_err_code_t -_gcry_cipher_ccm_encrypt(gcry_cipher_hd_t c, unsigned char *outbuf, - size_t outbuflen, const unsigned char *inbuf, - size_t inbuflen) -{ - (void)c; - (void)outbuf; - (void)outbuflen; - (void)inbuf; - (void)inbuflen; - return GPG_ERR_NOT_SUPPORTED; -} - -gcry_err_code_t -_gcry_cipher_ccm_decrypt(gcry_cipher_hd_t c, unsigned char *outbuf, - size_t outbuflen, const unsigned char *inbuf, - size_t inbuflen) -{ - (void)c; - (void)outbuf; - (void)outbuflen; - (void)inbuf; - (void)inbuflen; - return GPG_ERR_NOT_SUPPORTED; -} - -gcry_err_code_t -_gcry_cipher_ccm_set_nonce(gcry_cipher_hd_t c, const unsigned char *nonce, - size_t noncelen) -{ - (void)c; - (void)nonce; - (void)noncelen; - return GPG_ERR_NOT_SUPPORTED; -} - -gcry_err_code_t -_gcry_cipher_ccm_authenticate(gcry_cipher_hd_t c, const unsigned char *abuf, - size_t abuflen) -{ - (void)c; - (void)abuf; - (void)abuflen; - return GPG_ERR_NOT_SUPPORTED; -} - -gcry_err_code_t -_gcry_cipher_ccm_get_tag(gcry_cipher_hd_t c, unsigned char *outtag, - size_t taglen) -{ - (void)c; - (void)outtag; - (void)taglen; - return GPG_ERR_NOT_SUPPORTED; -} - -gcry_err_code_t -_gcry_cipher_ccm_check_tag(gcry_cipher_hd_t c, const unsigned char *intag, - size_t taglen) -{ - (void)c; - (void)intag; - (void)taglen; - return GPG_ERR_NOT_SUPPORTED; -} - -#endif /*HAVE_U64_TYPEDEF*/ diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c index 3711a1d..d390ef8 100644 --- a/cipher/cipher-gcm.c +++ b/cipher/cipher-gcm.c @@ -171,7 +171,7 @@ do_ghash (unsigned char *result, const unsigned char *buf, const u64 *gcmM) sizeof(int)*2 + sizeof(void*)*5); } -#else +#else /*!GCM_TABLES_USE_U64*/ static void bshift (u32 * M, int i) @@ -284,7 +284,7 @@ do_ghash (unsigned char *result, const unsigned char *buf, const u32 *gcmM) return (sizeof(V) + sizeof(T) + sizeof(tmp) + sizeof(int)*2 + sizeof(void*)*6); } -#endif /* !HAVE_U64_TYPEDEF || SIZEOF_UNSIGNED_LONG != 8 */ +#endif /*!GCM_TABLES_USE_U64*/ #define fillM(c) \ do_fillM (c->u_mode.gcm.u_ghash_key.key, c->u_mode.gcm.gcm_table) diff --git a/cipher/cipher-internal.h b/cipher/cipher-internal.h index 29c6f33..80e7c09 100644 --- a/cipher/cipher-internal.h +++ b/cipher/cipher-internal.h @@ -168,7 +168,6 @@ struct gcry_cipher_handle int unused; /* Number of unused bytes in LASTIV. */ union { -#ifdef HAVE_U64_TYPEDEF /* Mode specific storage for CCM mode. */ struct { u64 encryptlen; @@ -185,7 +184,6 @@ struct gcry_cipher_handle unsigned int lengths:1; /* Set to 1 if CCM length parameters has been processed. */ } ccm; -#endif /* Mode specific storage for Poly1305 mode. */ struct { @@ -248,8 +246,7 @@ struct gcry_cipher_handle /* Pre-calculated table for GCM. */ #ifdef GCM_USE_TABLES - #if defined(HAVE_U64_TYPEDEF) && (SIZEOF_UNSIGNED_LONG == 8 \ - || defined(__x86_64__)) + #if (SIZEOF_UNSIGNED_LONG == 8 || defined(__x86_64__)) #define GCM_TABLES_USE_U64 1 u64 gcm_table[2 * 16]; #else @@ -362,10 +359,8 @@ gcry_err_code_t _gcry_cipher_ccm_set_nonce size_t noncelen); gcry_err_code_t _gcry_cipher_ccm_authenticate /* */ (gcry_cipher_hd_t c, const unsigned char *abuf, size_t abuflen); -#ifdef HAVE_U64_TYPEDEF gcry_err_code_t _gcry_cipher_ccm_set_lengths /* */ (gcry_cipher_hd_t c, u64 encryptedlen, u64 aadlen, u64 taglen); -#endif gcry_err_code_t _gcry_cipher_ccm_get_tag /* */ (gcry_cipher_hd_t c, unsigned char *outtag, size_t taglen); diff --git a/cipher/cipher.c b/cipher/cipher.c index a013846..3a8597f 100644 --- a/cipher/cipher.c +++ b/cipher/cipher.c @@ -397,15 +397,11 @@ _gcry_cipher_open_internal (gcry_cipher_hd_t *handle, switch (mode) { case GCRY_CIPHER_MODE_CCM: -#ifdef HAVE_U64_TYPEDEF if (spec->blocksize != GCRY_CCM_BLOCK_LEN) err = GPG_ERR_INV_CIPHER_MODE; if (!spec->encrypt || !spec->decrypt) err = GPG_ERR_INV_CIPHER_MODE; break; -#else - err = GPG_ERR_NOT_SUPPORTED; -#endif case GCRY_CIPHER_MODE_ECB: case GCRY_CIPHER_MODE_CBC: @@ -743,11 +739,9 @@ cipher_reset (gcry_cipher_hd_t c) memset (&c->u_mode.poly1305, 0, sizeof c->u_mode.poly1305); break; -#ifdef HAVE_U64_TYPEDEF case GCRY_CIPHER_MODE_CCM: memset (&c->u_mode.ccm, 0, sizeof c->u_mode.ccm); break; -#endif case GCRY_CIPHER_MODE_OCB: memset (&c->u_mode.ocb, 0, sizeof c->u_mode.ocb); @@ -1264,7 +1258,6 @@ _gcry_cipher_ctl (gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen) break; case GCRYCTL_SET_CCM_LENGTHS: -#ifdef HAVE_U64_TYPEDEF { u64 params[3]; size_t encryptedlen; @@ -1286,9 +1279,6 @@ _gcry_cipher_ctl (gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen) rc = _gcry_cipher_ccm_set_lengths (h, encryptedlen, aadlen, authtaglen); } -#else - rc = GPG_ERR_NOT_SUPPORTED; -#endif break; case GCRYCTL_SET_TAGLEN: diff --git a/cipher/hash-common.h b/cipher/hash-common.h index 27d670d..23f81ed 100644 --- a/cipher/hash-common.h +++ b/cipher/hash-common.h @@ -33,7 +33,7 @@ typedef unsigned int (*_gcry_md_block_write_t) (void *c, const unsigned char *blks, size_t nblks); -#if defined(HAVE_U64_TYPEDEF) && (defined(USE_SHA512) || defined(USE_WHIRLPOOL)) +#if (defined(USE_SHA512) || defined(USE_WHIRLPOOL)) /* SHA-512 and Whirlpool needs u64. SHA-512 needs larger buffer. */ # define MD_BLOCK_MAX_BLOCKSIZE 128 # define MD_NBLOCKS_TYPE u64 diff --git a/cipher/md.c b/cipher/md.c index 281db12..5b4f0c1 100644 --- a/cipher/md.c +++ b/cipher/md.c @@ -1228,7 +1228,6 @@ md_stop_debug( gcry_md_hd_t md ) md->ctx->debug = NULL; } -#ifdef HAVE_U64_TYPEDEF { /* a kludge to pull in the __muldi3 for Solaris */ volatile u32 a = (u32)(uintptr_t)md; volatile u64 b = 42; @@ -1236,7 +1235,6 @@ md_stop_debug( gcry_md_hd_t md ) c = a * b; (void)c; } -#endif } diff --git a/cipher/poly1305.c b/cipher/poly1305.c index 1adf0e7..7ae3592 100644 --- a/cipher/poly1305.c +++ b/cipher/poly1305.c @@ -98,8 +98,6 @@ static const poly1305_ops_t poly1305_armv7_neon_ops = { #endif -#ifdef HAVE_U64_TYPEDEF - /* Reference unoptimized poly1305 implementation using 32 bit * 32 bit = 64 bit * multiplication and 64 bit addition. */ @@ -358,218 +356,6 @@ static const poly1305_ops_t poly1305_default_ops = { poly1305_finish_ext_ref32 }; -#else /* !HAVE_U64_TYPEDEF */ - -/* Reference unoptimized poly1305 implementation using 8 bit * 8 bit = 16 bit - * multiplication and 16 bit addition, used when we don't have 'u64'. - */ - -typedef struct poly1305_state_ref8_t -{ - byte h[17]; - byte r[17]; - byte pad[17]; - byte final; -} poly1305_state_ref8_t; - - -static OPS_FUNC_ABI void -poly1305_init_ext_ref8 (void *state, const poly1305_key_t * key) -{ - poly1305_state_ref8_t *st = (poly1305_state_ref8_t *) state; - size_t i; - - /* h = 0 */ - for (i = 0; i < 17; i++) - st->h[i] = 0; - - /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ - st->r[0] = key->b[0]; - st->r[1] = key->b[1]; - st->r[2] = key->b[2]; - st->r[3] = key->b[3] & 0x0f; - st->r[4] = key->b[4] & 0xfc; - st->r[5] = key->b[5]; - st->r[6] = key->b[6]; - st->r[7] = key->b[7] & 0x0f; - st->r[8] = key->b[8] & 0xfc; - st->r[9] = key->b[9]; - st->r[10] = key->b[10]; - st->r[11] = key->b[11] & 0x0f; - st->r[12] = key->b[12] & 0xfc; - st->r[13] = key->b[13]; - st->r[14] = key->b[14]; - st->r[15] = key->b[15] & 0x0f; - st->r[16] = 0; - - /* save pad for later */ - for (i = 0; i < 16; i++) - st->pad[i] = key->b[i + 16]; - st->pad[16] = 0; - - st->final = 0; -} - - -static void -poly1305_add_ref8 (byte h[17], const byte c[17]) -{ - u16 u; - unsigned int i; - for (u = 0, i = 0; i < 17; i++) - { - u += (u16) h[i] + (u16) c[i]; - h[i] = (byte) u & 0xff; - u >>= 8; - } -} - - -static void -poly1305_squeeze_ref8 (byte h[17], u32 hr[17]) -{ - u32 u; - unsigned int i; - u = 0; - for (i = 0; i < 16; i++) - { - u += hr[i]; - h[i] = (byte) u & 0xff; - u >>= 8; - } - u += hr[16]; - h[16] = (byte) u & 0x03; - u >>= 2; - u += (u << 2); /* u *= 5; */ - for (i = 0; i < 16; i++) - { - u += h[i]; - h[i] = (byte) u & 0xff; - u >>= 8; - } - h[16] += (byte) u; -} - - -static void -poly1305_freeze_ref8 (byte h[17]) -{ - static const byte minusp[17] = { - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xfc - }; - byte horig[17], negative; - unsigned int i; - - /* compute h + -p */ - for (i = 0; i < 17; i++) - horig[i] = h[i]; - poly1305_add_ref8 (h, minusp); - - /* select h if h < p, or h + -p if h >= p */ - negative = -(h[16] >> 7); - for (i = 0; i < 17; i++) - h[i] ^= negative & (horig[i] ^ h[i]); -} - - -static OPS_FUNC_ABI unsigned int -poly1305_blocks_ref8 (void *state, const byte * m, size_t bytes) -{ - poly1305_state_ref8_t *st = (poly1305_state_ref8_t *) state; - const byte hibit = st->final ^ 1; /* 1 << 128 */ - - while (bytes >= POLY1305_REF_BLOCKSIZE) - { - u32 hr[17], u; - byte c[17]; - unsigned int i, j; - - /* h += m */ - for (i = 0; i < 16; i++) - c[i] = m[i]; - c[16] = hibit; - poly1305_add_ref8 (st->h, c); - - /* h *= r */ - for (i = 0; i < 17; i++) - { - u = 0; - for (j = 0; j <= i; j++) - { - u += (u16) st->h[j] * st->r[i - j]; - } - for (j = i + 1; j < 17; j++) - { - u32 v = (u16) st->h[j] * st->r[i + 17 - j]; - v = ((v << 8) + (v << 6)); /* v *= (5 << 6); */ - u += v; - } - hr[i] = u; - } - - /* (partial) h %= p */ - poly1305_squeeze_ref8 (st->h, hr); - - m += POLY1305_REF_BLOCKSIZE; - bytes -= POLY1305_REF_BLOCKSIZE; - } - - /* burn_stack */ - return (18 + 2) * sizeof (u32) + 18 + 6 * sizeof (void *) + - 6 * sizeof (void *); -} - - -static OPS_FUNC_ABI unsigned int -poly1305_finish_ext_ref8 (void *state, const byte * m, size_t remaining, - byte mac[POLY1305_TAGLEN]) -{ - poly1305_state_ref8_t *st = (poly1305_state_ref8_t *) state; - size_t i; - unsigned int burn = 0; - - /* process the remaining block */ - if (remaining) - { - byte final[POLY1305_REF_BLOCKSIZE] = { 0 }; - for (i = 0; i < remaining; i++) - final[i] = m[i]; - final[remaining] = 1; - st->final = 1; - burn = poly1305_blocks_ref8 (st, final, POLY1305_REF_BLOCKSIZE); - } - - /* fully reduce h */ - poly1305_freeze_ref8 (st->h); - - /* h = (h + pad) % (1 << 128) */ - poly1305_add_ref8 (st->h, st->pad); - for (i = 0; i < 16; i++) - mac[i] = st->h[i]; - - /* zero out the state */ - for (i = 0; i < 17; i++) - st->h[i] = 0; - for (i = 0; i < 17; i++) - st->r[i] = 0; - for (i = 0; i < 17; i++) - st->pad[i] = 0; - - /* burn_stack */ - return POLY1305_REF_BLOCKSIZE + 18 + 16 * sizeof (void *) + burn; -} - - -static const poly1305_ops_t poly1305_default_ops = { - POLY1305_REF_BLOCKSIZE, - poly1305_init_ext_ref8, - poly1305_blocks_ref8, - poly1305_finish_ext_ref8 -}; - -#endif /* HAVE_U64_TYPEDEF */ diff --git a/cipher/scrypt.c b/cipher/scrypt.c index a05b5bf..13fd1cf 100644 --- a/cipher/scrypt.c +++ b/cipher/scrypt.c @@ -50,8 +50,6 @@ #include "bufhelp.h" /* We really need a 64 bit type for this code. */ -#ifdef HAVE_U64_TYPEDEF - #define SALSA20_INPUT_LENGTH 16 #define ROTL32(n,x) (((x)<<(n)) | ((x)>>(32-(n)))) @@ -322,6 +320,3 @@ _gcry_kdf_scrypt (const unsigned char *passwd, size_t passwdlen, return ec; } - - -#endif /* HAVE_U64_TYPEDEF */ diff --git a/cipher/tiger.c b/cipher/tiger.c index 516bd44..b60ec16 100644 --- a/cipher/tiger.c +++ b/cipher/tiger.c @@ -31,9 +31,6 @@ #include "bithelp.h" #include "bufhelp.h" -/* We really need a 64 bit type for this code. */ -#ifdef HAVE_U64_TYPEDEF - typedef struct { gcry_md_block_ctx_t bctx; @@ -853,5 +850,3 @@ gcry_md_spec_t _gcry_digest_spec_tiger2 = tiger2_init, _gcry_md_block_write, tiger_final, tiger_read, NULL, sizeof (TIGER_CONTEXT) }; - -#endif /* HAVE_U64_TYPEDEF */ diff --git a/configure.ac b/configure.ac index ff72e3f..8ed8d26 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ # Configure.ac script for Libgcrypt # Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006, # 2007, 2008, 2009, 2011 Free Software Foundation, Inc. -# Copyright (C) 2012, 2013 g10 Code GmbH +# Copyright (C) 2012, 2013, 2014, 2015 g10 Code GmbH # # This file is part of Libgcrypt. # @@ -198,12 +198,11 @@ enabled_pubkey_ciphers="" # Definitions for message digests. available_digests="crc gostr3411-94 md2 md4 md5 rmd160 sha1 sha256" -available_digests_64="sha512 sha3 tiger whirlpool stribog" +available_digests="$available_digests sha512 sha3 tiger whirlpool stribog" enabled_digests="" # Definitions for kdfs (optional ones) -available_kdfs="s2k pkdf2" -available_kdfs_64="scrypt" +available_kdfs="s2k pkdf2 scrypt" enabled_kdfs="" # Definitions for random modules. @@ -368,13 +367,14 @@ if test "$ac_cv_sizeof_unsigned_int" != "8" \ && test "$ac_cv_sizeof_unsigned_long" != "8" \ && test "$ac_cv_sizeof_unsigned_long_long" != "8" \ && test "$ac_cv_sizeof_uint64_t" != "8"; then - AC_MSG_WARN([No 64-bit types. Disabling TIGER/192, SCRYPT, SHA-384, \ - SHA-512 and GOST R 34.11-12]) -else - available_digests="$available_digests $available_digests_64" - available_kdfs="$available_kdfs $available_kdfs_64" + AC_MSG_ERROR([[ +*** +*** No 64-bit integer type available. +*** It is not possible to build Libgcrypt on this platform. +***]]) fi + # If not specified otherwise, all available algorithms will be # included. default_ciphers="$available_ciphers" diff --git a/src/g10lib.h b/src/g10lib.h index af68870..1070d9e 100644 --- a/src/g10lib.h +++ b/src/g10lib.h @@ -318,13 +318,8 @@ void __gcry_burn_stack (unsigned int bytes); } while(0) #define wipememory(_ptr,_len) wipememory2(_ptr,0,_len) -#ifdef HAVE_U64_TYPEDEF - #define FASTWIPE_T u64 - #define FASTWIPE_MULT (U64_C(0x0101010101010101)) -#else - #define FASTWIPE_T u32 - #define FASTWIPE_MULT (0x01010101U) -#endif +#define FASTWIPE_T u64 +#define FASTWIPE_MULT (U64_C(0x0101010101010101)) /* Following architectures can handle unaligned accesses fast. */ #if defined(HAVE_GCC_ATTRIBUTE_PACKED) && \ diff --git a/src/types.h b/src/types.h index dcdba4f..645ddd6 100644 --- a/src/types.h +++ b/src/types.h @@ -123,6 +123,8 @@ typedef uint64_t u64; # define U64_C(c) (UINT64_C(c)) # define HAVE_U64_TYPEDEF +# else +# error No way to declare a 64 bit integer type # endif #endif @@ -132,9 +134,7 @@ typedef union short b; char c[1]; long d; -#ifdef HAVE_U64_TYPEDEF u64 e; -#endif float f; double g; } PROPERLY_ALIGNED_TYPE; diff --git a/tests/basic.c b/tests/basic.c index 63fbcf6..c633ae9 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -2039,7 +2039,6 @@ check_poly1305_cipher (void) static void check_ccm_cipher (void) { -#ifdef HAVE_U64_TYPEDEF static const struct tv { int algo; @@ -2816,7 +2815,6 @@ check_ccm_cipher (void) if (verbose) fprintf (stderr, " Completed CCM checks.\n"); #endif -#endif /*HAVE_U64_TYPEDEF*/ } diff --git a/tests/bench-slope.c b/tests/bench-slope.c index 3a2aa38..8938f18 100644 --- a/tests/bench-slope.c +++ b/tests/bench-slope.c @@ -741,7 +741,6 @@ static struct bench_ops decrypt_ops = { }; -#ifdef HAVE_U64_TYPEDEF static void bench_ccm_encrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen) { @@ -904,7 +903,6 @@ static struct bench_ops ccm_authenticate_ops = { &bench_encrypt_free, &bench_ccm_authenticate_do_bench }; -#endif /*HAVE_U64_TYPEDEF*/ static void @@ -1167,11 +1165,9 @@ static struct bench_cipher_mode cipher_modes[] = { {GCRY_CIPHER_MODE_OFB, "OFB dec", &decrypt_ops}, {GCRY_CIPHER_MODE_CTR, "CTR enc", &encrypt_ops}, {GCRY_CIPHER_MODE_CTR, "CTR dec", &decrypt_ops}, -#ifdef HAVE_U64_TYPEDEF {GCRY_CIPHER_MODE_CCM, "CCM enc", &ccm_encrypt_ops}, {GCRY_CIPHER_MODE_CCM, "CCM dec", &ccm_decrypt_ops}, {GCRY_CIPHER_MODE_CCM, "CCM auth", &ccm_authenticate_ops}, -#endif {GCRY_CIPHER_MODE_GCM, "GCM enc", &gcm_encrypt_ops}, {GCRY_CIPHER_MODE_GCM, "GCM dec", &gcm_decrypt_ops}, {GCRY_CIPHER_MODE_GCM, "GCM auth", &gcm_authenticate_ops}, diff --git a/tests/benchmark.c b/tests/benchmark.c index 1258b81..53b83b1 100644 --- a/tests/benchmark.c +++ b/tests/benchmark.c @@ -724,7 +724,6 @@ mac_bench ( const char *algoname ) } -#ifdef HAVE_U64_TYPEDEF static void ccm_aead_init(gcry_cipher_hd_t hd, size_t buflen, int authlen) { const int _L = 4; @@ -756,7 +755,6 @@ static void ccm_aead_init(gcry_cipher_hd_t hd, size_t buflen, int authlen) exit (1); } } -#endif static void @@ -786,10 +784,8 @@ cipher_bench ( const char *algoname ) { GCRY_CIPHER_MODE_CFB, " CFB", 0 }, { GCRY_CIPHER_MODE_OFB, " OFB", 0 }, { GCRY_CIPHER_MODE_CTR, " CTR", 0 }, -#ifdef HAVE_U64_TYPEDEF { GCRY_CIPHER_MODE_CCM, " CCM", 0, ccm_aead_init, GCRY_CCM_BLOCK_LEN, 8 }, -#endif { GCRY_CIPHER_MODE_GCM, " GCM", 0, NULL, GCRY_GCM_BLOCK_LEN, GCRY_GCM_BLOCK_LEN }, { GCRY_CIPHER_MODE_OCB, " OCB", 1, ----------------------------------------------------------------------- Summary of changes: cipher/bithelp.h | 22 ++--- cipher/bufhelp.h | 6 +- cipher/cipher-ccm.c | 78 ----------------- cipher/cipher-gcm.c | 4 +- cipher/cipher-internal.h | 7 +- cipher/cipher.c | 10 --- cipher/hash-common.h | 2 +- cipher/md.c | 2 - cipher/poly1305.c | 214 ----------------------------------------------- cipher/scrypt.c | 5 -- cipher/tiger.c | 5 -- configure.ac | 18 ++-- src/g10lib.h | 9 +- src/types.h | 4 +- tests/basic.c | 2 - tests/bench-slope.c | 4 - tests/benchmark.c | 4 - 17 files changed, 26 insertions(+), 370 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From cvs at cvs.gnupg.org Fri Mar 18 16:54:53 2016 From: cvs at cvs.gnupg.org (by Vitezslav Cizek) Date: Fri, 18 Mar 2016 16:54:53 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-350-g0bd8137 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via 0bd8137e68c201b6c2290710e348aaf57efa2b2e (commit) via 2e139456369a834cf87d983da4f61241fda76efe (commit) via c690230af5a66b809f8f6fbab1a6262a5ba078cb (commit) via 78cec8b4754fdf774edb2d575000cb3e972e244c (commit) via ce1cbe16992a7340edcf8e6576973e3508267640 (commit) via c478cf175887c84dc071c4f73a7667603b354789 (commit) via 0f741b0704bac5c0e2d2a0c2b34b44b35baa76d6 (commit) via a242e3d9185e6e2dc13902ea9331131755bbba01 (commit) via e40939b2141306238cc30a340b867b60fa4dc2a3 (commit) via 80e9f95e6f419daa765e4876c858e3e36e808897 (commit) via 443bed836a4fd60217325789134f5a2dc2ec41ce (commit) from 4051fe7fec6ffdc7a2f5c3856665478866991ee7 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 0bd8137e68c201b6c2290710e348aaf57efa2b2e Author: Vitezslav Cizek Date: Fri Oct 30 17:34:04 2015 +0100 cipher: Add option to specify salt length for PSS verification. * cipher/pubkey-util.c (_gcry_pk_util_data_to_mpi): Check for salt-length token. -- Add possibility to use a different salt length for RSASSA-PSS verification instead of the default 20. Signed-off-by: Vitezslav Cizek Additional changes by wk: - Detect overlong salt-length - Release LIST on error. Signed-off-by: Werner Koch diff --git a/cipher/pubkey-util.c b/cipher/pubkey-util.c index 76d3923..c40ef97 100644 --- a/cipher/pubkey-util.c +++ b/cipher/pubkey-util.c @@ -665,7 +665,7 @@ _gcry_pk_util_free_encoding_ctx (struct pk_encoding_ctx *ctx) LABEL is specific to OAEP. - SALT-LENGTH is for PSS. + SALT-LENGTH is for PSS it is limited to 16384 bytes. RANDOM-OVERRIDE is used to replace random nonces for regression testing. */ @@ -1068,6 +1068,31 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi, rc = GPG_ERR_DIGEST_ALGO; else { + gcry_sexp_t list; + /* Get SALT-LENGTH. */ + list = sexp_find_token (ldata, "salt-length", 0); + if (list) + { + unsigned long ul; + + s = sexp_nth_data (list, 1, &n); + if (!s) + { + rc = GPG_ERR_NO_OBJ; + sexp_release (list); + goto leave; + } + ul = strtoul (s, NULL, 10); + if (ul > 16384) + { + rc = GPG_ERR_TOO_LARGE; + sexp_release (list); + goto leave; + } + ctx->saltlen = ul; + sexp_release (list); + } + *ret_mpi = sexp_nth_mpi (lhash, 2, GCRYMPI_FMT_USG); if (!*ret_mpi) rc = GPG_ERR_INV_OBJ; commit 2e139456369a834cf87d983da4f61241fda76efe Author: Vitezslav Cizek Date: Fri Oct 30 15:41:09 2015 +0100 tests: Add support for RSA keygen tests to fipsdrv. * tests/fipsdrv.c (run_rsa_keygen): New. (main): Support RSA keygen and RSA keygen KAT tests. -- In fipsdrv implement support for KeyGen_RandomProbablyPrime and Known Answer Test for probably primes RSA2VS tests. Signed-off-by: Vitezslav Cizek diff --git a/tests/fipsdrv.c b/tests/fipsdrv.c index b5962cf..bcc56d1 100644 --- a/tests/fipsdrv.c +++ b/tests/fipsdrv.c @@ -1340,6 +1340,69 @@ run_rsa_derive (const void *data, size_t datalen) } +/* Generate RSA key using the S-expression in (DATA,DATALEN). This + S-expression is used directly as input to gcry_pk_genkey. The + result is printed to stdout with one parameter per line in hex + format and in this order: e, p, q, n, d. */ +static void +run_rsa_keygen (const void *data, size_t datalen, int test) +{ + gpg_error_t err; + gcry_sexp_t s_keyspec, s_key, s_top, l1; + gcry_mpi_t mpi; + const char *parmlist; + int idx; + + if (!datalen) + err = gpg_error (GPG_ERR_NO_DATA); + else + err = gcry_sexp_new (&s_keyspec, data, datalen, 1); + if (err) + die ("gcry_sexp_new failed for RSA key generation: %s\n", + gpg_strerror (err)); + + err = gcry_pk_genkey (&s_key, s_keyspec); + + gcry_sexp_release (s_keyspec); + + if (test) { + if (err) + printf("F\n"); + else { + gcry_sexp_release (s_key); + printf("P\n"); + } + return; + } + + if (err) + die ("gcry_pk_genkey failed for RSA: %s\n", gpg_strerror (err)); + + parmlist = "epqnd"; + + /* Parse and print the parameters. */ + l1 = gcry_sexp_find_token (s_key, "private-key", 0); + s_top = gcry_sexp_find_token (l1, "rsa", 0); + gcry_sexp_release (l1); + if (!s_top) + die ("private-key part not found in result\n"); + + for (idx=0; parmlist[idx]; idx++) + { + l1 = gcry_sexp_find_token (s_top, parmlist+idx, 1); + mpi = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG); + gcry_sexp_release (l1); + if (!mpi) + die ("parameter %c missing in private-key\n", parmlist[idx]); + print_mpi_line (mpi, 1); + gcry_mpi_release (mpi); + } + + gcry_sexp_release (s_top); + gcry_sexp_release (s_key); +} + + static size_t compute_tag_length (size_t n) @@ -2421,6 +2484,8 @@ main (int argc, char **argv) && !mct_server && strcmp (mode_string, "random") && strcmp (mode_string, "rsa-gen") + && strcmp (mode_string, "rsa-keygen") + && strcmp (mode_string, "rsa-keygen-kat") && strcmp (mode_string, "dsa-gen") && strcmp (mode_string, "ecdsa-gen-key") ) { @@ -2611,6 +2676,20 @@ main (int argc, char **argv) die ("no data available (do not use --chunk)\n"); run_rsa_derive (data, datalen); } + else if (!strcmp (mode_string, "rsa-keygen")) + { + data = read_file (input, 0, &datalen); + if (!data) + die ("no data available (do not use --chunk)\n"); + run_rsa_keygen (data, datalen, 0); + } + else if (!strcmp (mode_string, "rsa-keygen-kat")) + { + data = read_file (input, 0, &datalen); + if (!data) + die ("no data available (do not use --chunk)\n"); + run_rsa_keygen (data, datalen, 1); + } else if (!strcmp (mode_string, "rsa-gen")) { int keysize; commit c690230af5a66b809f8f6fbab1a6262a5ba078cb Author: Vitezslav Cizek Date: Fri Oct 30 15:38:13 2015 +0100 tests: Fixes for RSA testsuite in FIPS mode * tests/basic.c (get_keys_new): Generate 2048 bit key. * tests/benchmark.c (rsa_bench): Skip keys of lengths different than 2048 and 3072 in FIPS mode. * tests/keygen.c (check_rsa_keys): Failure if short keys can be generated in FIPS mode. (check_dsa_keys): Ditto for DSA keys. * tests/pubkey.c (check_x931_derived_key): Skip keys < 2048 in FIPS. -- Thanks to Ludwig Nussel. Signed-off-by: Vitezslav Cizek Additional changes by wk: - Remove printing of "FAIL" in fail() because this is reserved for use by the test driver of the Makefile. - Move setting of IN_FIPS_MODE after gcry_check_version in keygen.c Signed-off-by: Werner Koch diff --git a/tests/basic.c b/tests/basic.c index 876ee2e..63fbcf6 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -8442,7 +8442,7 @@ get_keys_new (gcry_sexp_t *pkey, gcry_sexp_t *skey) if (verbose) fprintf (stderr, " generating RSA key:"); rc = gcry_sexp_new (&key_spec, - in_fips_mode ? "(genkey (rsa (nbits 4:1024)))" + in_fips_mode ? "(genkey (rsa (nbits 4:2048)))" : "(genkey (rsa (nbits 4:1024)(transient-key)))", 0, 1); if (rc) diff --git a/tests/benchmark.c b/tests/benchmark.c index b6cd7a8..c748dac 100644 --- a/tests/benchmark.c +++ b/tests/benchmark.c @@ -1085,15 +1085,22 @@ rsa_bench (int iterations, int print_header, int no_blinding) gcry_sexp_t data; gcry_sexp_t sig = NULL; int count; + unsigned nbits = p_sizes[testno]; - printf ("RSA %3d bit ", p_sizes[testno]); + printf ("RSA %3d bit ", nbits); fflush (stdout); + if (in_fips_mode && !(nbits == 2048 || nbits == 3072)) + { + puts ("[skipped in fips mode]"); + continue; + } + err = gcry_sexp_build (&key_spec, NULL, gcry_fips_mode_active () ? "(genkey (RSA (nbits %d)))" : "(genkey (RSA (nbits %d)(transient-key)))", - p_sizes[testno]); + nbits); if (err) die ("creating S-expression failed: %s\n", gcry_strerror (err)); @@ -1101,7 +1108,7 @@ rsa_bench (int iterations, int print_header, int no_blinding) err = gcry_pk_genkey (&key_pair, key_spec); if (err) die ("creating %d bit RSA key failed: %s\n", - p_sizes[testno], gcry_strerror (err)); + nbits, gcry_strerror (err)); pub_key = gcry_sexp_find_token (key_pair, "public-key", 0); if (! pub_key) @@ -1116,8 +1123,8 @@ rsa_bench (int iterations, int print_header, int no_blinding) printf (" %s", elapsed_time (1)); fflush (stdout); - x = gcry_mpi_new (p_sizes[testno]); - gcry_mpi_randomize (x, p_sizes[testno]-8, GCRY_WEAK_RANDOM); + x = gcry_mpi_new (nbits); + gcry_mpi_randomize (x, nbits-8, GCRY_WEAK_RANDOM); err = gcry_sexp_build (&data, NULL, "(data (flags raw) (value %m))", x); gcry_mpi_release (x); @@ -1155,8 +1162,8 @@ rsa_bench (int iterations, int print_header, int no_blinding) if (no_blinding) { fflush (stdout); - x = gcry_mpi_new (p_sizes[testno]); - gcry_mpi_randomize (x, p_sizes[testno]-8, GCRY_WEAK_RANDOM); + x = gcry_mpi_new (nbits); + gcry_mpi_randomize (x, nbits-8, GCRY_WEAK_RANDOM); err = gcry_sexp_build (&data, NULL, "(data (flags no-blinding) (value %m))", x); gcry_mpi_release (x); diff --git a/tests/keygen.c b/tests/keygen.c index 8b9a1d5..7afa76c 100644 --- a/tests/keygen.c +++ b/tests/keygen.c @@ -40,6 +40,7 @@ static int verbose; static int debug; static int error_count; +static int in_fips_mode; static void @@ -196,11 +197,11 @@ check_rsa_keys (void) int rc; if (verbose) - show ("creating 1024 bit RSA key\n"); + show ("creating 2048 bit RSA key\n"); rc = gcry_sexp_new (&keyparm, "(genkey\n" " (rsa\n" - " (nbits 4:1024)\n" + " (nbits 4:2048)\n" " ))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gpg_strerror (rc)); @@ -208,9 +209,29 @@ check_rsa_keys (void) gcry_sexp_release (keyparm); if (rc) die ("error generating RSA key: %s\n", gpg_strerror (rc)); - if (verbose > 1) - show_sexp ("1024 bit RSA key:\n", key); - check_generated_rsa_key (key, 65537); + + if (verbose) + show ("creating 1024 bit RSA key\n"); + rc = gcry_sexp_new (&keyparm, + "(genkey\n" + " (rsa\n" + " (nbits 4:1024)\n" + " ))", 0, 1); + if (rc) + die ("error creating S-expression: %s\n", gpg_strerror (rc)); + rc = gcry_pk_genkey (&key, keyparm); + gcry_sexp_release (keyparm); + if (rc && !in_fips_mode) + fail ("error generating RSA key: %s\n", gpg_strerror (rc)); + else if (!rc && in_fips_mode) + fail ("generating 1024 bit RSA key must not work!"); + + if (!rc) + { + if (verbose > 1) + show_sexp ("1024 bit RSA key:\n", key); + check_generated_rsa_key (key, 65537); + } gcry_sexp_release (key); @@ -226,10 +247,13 @@ check_rsa_keys (void) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); gcry_sexp_release (keyparm); - if (rc) - die ("error generating RSA key: %s\n", gpg_strerror (rc)); + if (rc && !in_fips_mode) + fail ("error generating RSA key: %s\n", gpg_strerror (rc)); + else if (!rc && in_fips_mode) + fail ("generating 512 bit RSA key must not work!"); - check_generated_rsa_key (key, 257); + if (!rc) + check_generated_rsa_key (key, 257); gcry_sexp_release (key); if (verbose) @@ -244,10 +268,13 @@ check_rsa_keys (void) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); gcry_sexp_release (keyparm); - if (rc) - die ("error generating RSA key: %s\n", gpg_strerror (rc)); + if (rc && !in_fips_mode) + fail ("error generating RSA key: %s\n", gpg_strerror (rc)); + else if (!rc && in_fips_mode) + fail ("generating 512 bit RSA key must not work!"); - check_generated_rsa_key (key, 0); /* We don't expect a constant exponent. */ + if (!rc) + check_generated_rsa_key (key, 0); /* We don't expect a constant exponent. */ gcry_sexp_release (key); } @@ -299,8 +326,10 @@ check_dsa_keys (void) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); gcry_sexp_release (keyparm); - if (rc) + if (rc && !in_fips_mode) die ("error generating DSA key: %s\n", gpg_strerror (rc)); + else if (!rc && in_fips_mode) + die ("generating 512 bit DSA key must not work!"); if (!i && verbose > 1) show_sexp ("1024 bit DSA key:\n", key); gcry_sexp_release (key); @@ -318,8 +347,10 @@ check_dsa_keys (void) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); gcry_sexp_release (keyparm); - if (rc) + if (rc && !in_fips_mode) die ("error generating DSA key: %s\n", gpg_strerror (rc)); + else if (!rc && in_fips_mode) + die ("generating 1536 bit DSA key must not work!"); if (verbose > 1) show_sexp ("1536 bit DSA key:\n", key); gcry_sexp_release (key); @@ -597,6 +628,9 @@ main (int argc, char **argv) if (with_progress) gcry_set_progress_handler (progress_cb, NULL); + if ( gcry_fips_mode_active () ) + in_fips_mode = 1; + if (!argc) { check_rsa_keys (); diff --git a/tests/pubkey.c b/tests/pubkey.c index 62dc0d6..5ed6ca1 100644 --- a/tests/pubkey.c +++ b/tests/pubkey.c @@ -165,6 +165,33 @@ show_sexp (const char *prefix, gcry_sexp_t a) gcry_free (buf); } +/* from ../cipher/pubkey-util.c */ +gpg_err_code_t +_gcry_pk_util_get_nbits (gcry_sexp_t list, unsigned int *r_nbits) +{ + char buf[50]; + const char *s; + size_t n; + + *r_nbits = 0; + + list = gcry_sexp_find_token (list, "nbits", 0); + if (!list) + return 0; /* No NBITS found. */ + + s = gcry_sexp_nth_data (list, 1, &n); + if (!s || n >= DIM (buf) - 1 ) + { + /* NBITS given without a cdr. */ + gcry_sexp_release (list); + return GPG_ERR_INV_OBJ; + } + memcpy (buf, s, n); + buf[n] = 0; + *r_nbits = (unsigned int)strtoul (buf, NULL, 0); + gcry_sexp_release (list); + return 0; +} /* Convert STRING consisting of hex characters into its binary representation and return it as an allocated buffer. The valid @@ -906,8 +933,8 @@ check_x931_derived_key (int what) } }; gpg_error_t err; - gcry_sexp_t key_spec, key, pub_key, sec_key; - gcry_mpi_t d_expected, d_have; + gcry_sexp_t key_spec = NULL, key = NULL, pub_key = NULL, sec_key = NULL; + gcry_mpi_t d_expected = NULL, d_have = NULL; if (what < 0 && what >= sizeof testtable) die ("invalid WHAT value\n"); @@ -916,10 +943,25 @@ check_x931_derived_key (int what) if (err) die ("error creating S-expression [%d]: %s\n", what, gpg_strerror (err)); + { + unsigned nbits; + err = _gcry_pk_util_get_nbits(key_spec, &nbits); + if (err) + die ("nbits not found\n"); + if (gcry_fips_mode_active() && nbits < 2048) + { + info("RSA key test with %d bits skipped in fips mode\n", nbits); + goto leave; + } + } + err = gcry_pk_genkey (&key, key_spec); gcry_sexp_release (key_spec); if (err) - die ("error generating RSA key [%d]: %s\n", what, gpg_strerror (err)); + { + fail ("error generating RSA key [%d]: %s\n", what, gpg_strerror (err)); + goto leave; + } pub_key = gcry_sexp_find_token (key, "public-key", 0); if (!pub_key) @@ -945,6 +987,7 @@ check_x931_derived_key (int what) show_sexp (NULL, sec_key); die ("parameter d does match expected value [%d]\n", what); } +leave: gcry_mpi_release (d_expected); gcry_mpi_release (d_have); commit 78cec8b4754fdf774edb2d575000cb3e972e244c Author: Vitezslav Cizek Date: Fri Oct 30 13:41:41 2015 +0100 rsa: Use 2048 bit RSA keys for selftest. * cipher/rsa.c (selftests_rsa): Use 2048 bit keys. (selftest_encr_1024): Replaced by selftest_encr_2048. (selftest_sign_1024): Replaced by selftest_sign_2048. (selftest_encr_2048): Add check against known ciphertext. (selftest_sign_2048): Add check against known signature. (selftest_sign_2048): Free SIG_MPI. * tests/pubkey.c (get_keys_new): Generate 2048 bit keys. -- Use a 2048 bit keys for RSA selftest. Check against the known signature/ciphertext after signing/encryption in the selftests. Also generate 2k keys in tests/pubkey. Thanks to Ludwig Nussel. Signed-off-by: Vitezslav Cizek Additional changes by wk: - Reformat some strings and comments. - Replace a free by xfree. - Free SIG_MPI. - Make two strings static. Signed-off-by: Werner Koch diff --git a/cipher/rsa.c b/cipher/rsa.c index 45a481b..787b14a 100644 --- a/cipher/rsa.c +++ b/cipher/rsa.c @@ -62,36 +62,53 @@ static const char *rsa_names[] = }; -/* A sample 1024 bit RSA key used for the selftests. */ +/* A sample 2048 bit RSA key used for the selftests. */ static const char sample_secret_key[] = -"(private-key" -" (rsa" -" (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa" -" 2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291" -" ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7" -" 891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)" -" (e #010001#)" -" (d #046129f2489d71579be0a75fe029bd6cdb574ebf57ea8a5b0fda942cab943b11" -" 7d7bb95e5d28875e0f9fc5fcc06a72f6d502464dabded78ef6b716177b83d5bd" -" c543dc5d3fed932e59f5897e92e6f58a0f33424106a3b6fa2cbf877510e4ac21" -" c3ee47851e97d12996222ac3566d4ccb0b83d164074abf7de655fc2446da1781#)" -" (p #00e861b700e17e8afe6837e7512e35b6ca11d0ae47d8b85161c67baf64377213" -" fe52d772f2035b3ca830af41d8a4120e1c1c70d12cc22f00d28d31dd48a8d424f1#)" -" (q #00f7a7ca5367c661f8e62df34f0d05c10c88e5492348dd7bddc942c9a8f369f9" -" 35a07785d2db805215ed786e4285df1658eed3ce84f469b81b50d358407b4ad361#)" -" (u #304559a9ead56d2309d203811a641bb1a09626bc8eb36fffa23c968ec5bd891e" -" ebbafc73ae666e01ba7c8990bae06cc2bbe10b75e69fcacb353a6473079d8e9b#)))"; -/* A sample 1024 bit RSA key used for the selftests (public only). */ +" (private-key" +" (rsa" +" (n #009F56231A3D82E3E7D613D59D53E9AB921BEF9F08A782AED0B6E46ADBC853EC" +" 7C71C422435A3CD8FA0DB9EFD55CD3295BADC4E8E2E2B94E15AE82866AB8ADE8" +" 7E469FAE76DC3577DE87F1F419C4EB41123DFAF8D16922D5EDBAD6E9076D5A1C" +" 958106F0AE5E2E9193C6B49124C64C2A241C4075D4AF16299EB87A6585BAE917" +" DEF27FCDD165764D069BC18D16527B29DAAB549F7BBED4A7C6A842D203ED6613" +" 6E2411744E432CD26D940132F25874483DCAEECDFD95744819CBCF1EA810681C" +" 42907EBCB1C7EAFBE75C87EC32C5413EA10476545D3FC7B2ADB1B66B7F200918" +" 664B0E5261C2895AA28B0DE321E921B3F877172CCCAB81F43EF98002916156F6CB#)" +" (e #010001#)" +" (d #07EF82500C403899934FE993AC5A36F14FF2DF38CF1EF315F205EE4C83EDAA19" +" 8890FC23DE9AA933CAFB37B6A8A8DBA675411958337287310D3FF2F1DDC0CB93" +" 7E70F57F75F833C021852B631D2B9A520E4431A03C5C3FCB5742DCD841D9FB12" +" 771AA1620DCEC3F1583426066ED9DC3F7028C5B59202C88FDF20396E2FA0EC4F" +" 5A22D9008F3043673931BC14A5046D6327398327900867E39CC61B2D1AFE2F48" +" EC8E1E3861C68D257D7425F4E6F99ABD77D61F10CA100EFC14389071831B33DD" +" 69CC8EABEF860D1DC2AAA84ABEAE5DFC91BC124DAF0F4C8EF5BBEA436751DE84" +" 3A8063E827A024466F44C28614F93B0732A100D4A0D86D532FE1E22C7725E401#)" +" (p #00C29D438F115825779631CD665A5739367F3E128ADC29766483A46CA80897E0" +" 79B32881860B8F9A6A04C2614A904F6F2578DAE13EA67CD60AE3D0AA00A1FF9B" +" 441485E44B2DC3D0B60260FBFE073B5AC72FAF67964DE15C8212C389D20DB9CF" +" 54AF6AEF5C4196EAA56495DD30CF709F499D5AB30CA35E086C2A1589D6283F1783#)" +" (q #00D1984135231CB243FE959C0CBEF551EDD986AD7BEDF71EDF447BE3DA27AF46" +" 79C974A6FA69E4D52FE796650623DE70622862713932AA2FD9F2EC856EAEAA77" +" 88B4EA6084DC81C902F014829B18EA8B2666EC41586818E0589E18876065F97E" +" 8D22CE2DA53A05951EC132DCEF41E70A9C35F4ACC268FFAC2ADF54FA1DA110B919#)" +" (u #67CF0FD7635205DD80FA814EE9E9C267C17376BF3209FB5D1BC42890D2822A04" +" 479DAF4D5B6ED69D0F8D1AF94164D07F8CD52ECEFE880641FA0F41DDAB1785E4" +" A37A32F997A516480B4CD4F6482B9466A1765093ED95023CA32D5EDC1E34CEE9" +" AF595BC51FE43C4BF810FA225AF697FB473B83815966188A4312C048B885E3F7#)))"; + +/* A sample 2048 bit RSA key used for the selftests (public only). */ static const char sample_public_key[] = -"(public-key" -" (rsa" -" (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa" -" 2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291" -" ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7" -" 891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)" -" (e #010001#)))"; - - +" (public-key" +" (rsa" +" (n #009F56231A3D82E3E7D613D59D53E9AB921BEF9F08A782AED0B6E46ADBC853EC" +" 7C71C422435A3CD8FA0DB9EFD55CD3295BADC4E8E2E2B94E15AE82866AB8ADE8" +" 7E469FAE76DC3577DE87F1F419C4EB41123DFAF8D16922D5EDBAD6E9076D5A1C" +" 958106F0AE5E2E9193C6B49124C64C2A241C4075D4AF16299EB87A6585BAE917" +" DEF27FCDD165764D069BC18D16527B29DAAB549F7BBED4A7C6A842D203ED6613" +" 6E2411744E432CD26D940132F25874483DCAEECDFD95744819CBCF1EA810681C" +" 42907EBCB1C7EAFBE75C87EC32C5413EA10476545D3FC7B2ADB1B66B7F200918" +" 664B0E5261C2895AA28B0DE321E921B3F877172CCCAB81F43EF98002916156F6CB#)" +" (e #010001#)))"; static int test_keys (RSA_secret_key *sk, unsigned nbits); @@ -1349,20 +1366,34 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) */ static const char * -selftest_sign_1024 (gcry_sexp_t pkey, gcry_sexp_t skey) +selftest_sign_2048 (gcry_sexp_t pkey, gcry_sexp_t skey) { static const char sample_data[] = "(data (flags pkcs1)" - " (hash sha1 #11223344556677889900aabbccddeeff10203040#))"; + " (hash sha256 #11223344556677889900aabbccddeeff" + /**/ "102030405060708090a0b0c0d0f01121#))"; static const char sample_data_bad[] = "(data (flags pkcs1)" - " (hash sha1 #11223344556677889900aabbccddeeff80203040#))"; + " (hash sha256 #11223344556677889900aabbccddeeff" + /**/ "802030405060708090a0b0c0d0f01121#))"; const char *errtxt = NULL; gcry_error_t err; gcry_sexp_t data = NULL; gcry_sexp_t data_bad = NULL; gcry_sexp_t sig = NULL; + /* raw signature data reference */ + const char ref_data[] = + "6252a19a11e1d5155ed9376036277193d644fa239397fff03e9b92d6f86415d6" + "d30da9273775f290e580d038295ff8ff89522becccfa6ae870bf76b76df402a8" + "54f69347e3db3de8e1e7d4dada281ec556810c7a8ecd0b5f51f9b1c0e7aa7557" + "61aa2b8ba5f811304acc6af0eca41fe49baf33bf34eddaf44e21e036ac7f0b68" + "03cdef1c60021fb7b5b97ebacdd88ab755ce29af568dbc5728cc6e6eff42618d" + "62a0386ca8beed46402bdeeef29b6a3feded906bace411a06a39192bf516ae10" + "67e4320fa8ea113968525f4574d022a3ceeaafdc41079efe1f22cc94bf59d8d3" + "328085da9674857db56de5978a62394aab48aa3b72e23a1b16260cfd9daafe65"; + gcry_mpi_t ref_mpi = NULL; + gcry_mpi_t sig_mpi = NULL; err = sexp_sscan (&data, NULL, sample_data, strlen (sample_data)); if (!err) @@ -1380,6 +1411,27 @@ selftest_sign_1024 (gcry_sexp_t pkey, gcry_sexp_t skey) errtxt = "signing failed"; goto leave; } + + err = _gcry_mpi_scan(&ref_mpi, GCRYMPI_FMT_HEX, ref_data, 0, NULL); + if (err) + { + errtxt = "converting ref_data to mpi failed"; + goto leave; + } + + err = _gcry_sexp_extract_param(sig, "sig-val!rsa", "s", &sig_mpi, NULL); + if (err) + { + errtxt = "extracting signature data failed"; + goto leave; + } + + if (mpi_cmp (sig_mpi, ref_mpi)) + { + errtxt = "signature does not match reference data"; + goto leave; + } + err = _gcry_pk_verify (sig, data, pkey); if (err) { @@ -1398,6 +1450,8 @@ selftest_sign_1024 (gcry_sexp_t pkey, gcry_sexp_t skey) sexp_release (sig); sexp_release (data_bad); sexp_release (data); + _gcry_mpi_release (ref_mpi); + _gcry_mpi_release (sig_mpi); return errtxt; } @@ -1436,25 +1490,33 @@ extract_a_from_sexp (gcry_sexp_t encr_data) static const char * -selftest_encr_1024 (gcry_sexp_t pkey, gcry_sexp_t skey) +selftest_encr_2048 (gcry_sexp_t pkey, gcry_sexp_t skey) { const char *errtxt = NULL; gcry_error_t err; - const unsigned int nbits = 1000; /* Encrypt 1000 random bits. */ - gcry_mpi_t plaintext = NULL; + static const char plaintext[] = + "Jim quickly realized that the beautiful gowns are expensive."; gcry_sexp_t plain = NULL; gcry_sexp_t encr = NULL; gcry_mpi_t ciphertext = NULL; gcry_sexp_t decr = NULL; - gcry_mpi_t decr_plaintext = NULL; + char *decr_plaintext = NULL; gcry_sexp_t tmplist = NULL; - - /* Create plaintext. The plaintext is actually a big integer number. */ - plaintext = mpi_new (nbits); - _gcry_mpi_randomize (plaintext, nbits, GCRY_WEAK_RANDOM); + /* expected result of encrypting the plaintext with sample_secret_key */ + static const char ref_data[] = + "18022e2593a402a737caaa93b4c7e750e20ca265452980e1d6b7710fbd3e" + "7dce72be5c2110fb47691cb38f42170ee3b4a37f2498d4a51567d762585e" + "4cb81d04fbc7df4144f8e5eac2d4b8688521b64011f11d7ad53f4c874004" + "819856f2e2a6f83d1c9c4e73ac26089789c14482b0b8d44139133c88c4a5" + "2dba9dd6d6ffc622666b7d129168333d999706af30a2d7d272db7734e5ed" + "fb8c64ea3018af3ad20f4a013a5060cb0f5e72753967bebe294280a6ed0d" + "dbd3c4f11d0a8696e9d32a0dc03deb0b5e49b2cbd1503392642d4e1211f3" + "e8e2ee38abaa3671ccd57fcde8ca76e85fd2cb77c35706a970a213a27352" + "cec92a9604d543ddb5fc478ff50e0622"; + gcry_mpi_t ref_mpi = NULL; /* Put the plaintext into an S-expression. */ - err = sexp_build (&plain, NULL, "(data (flags raw) (value %m))", plaintext); + err = sexp_build (&plain, NULL, "(data (flags raw) (value %s))", plaintext); if (err) { errtxt = "converting data failed"; @@ -1469,6 +1531,13 @@ selftest_encr_1024 (gcry_sexp_t pkey, gcry_sexp_t skey) goto leave; } + err = _gcry_mpi_scan(&ref_mpi, GCRYMPI_FMT_HEX, ref_data, 0, NULL); + if (err) + { + errtxt = "converting encrydata to mpi failed"; + goto leave; + } + /* Extraxt the ciphertext from the returned S-expression. */ /*sexp_dump (encr);*/ ciphertext = extract_a_from_sexp (encr); @@ -1481,9 +1550,9 @@ selftest_encr_1024 (gcry_sexp_t pkey, gcry_sexp_t skey) /* Check that the ciphertext does no match the plaintext. */ /* _gcry_log_printmpi ("plaintext", plaintext); */ /* _gcry_log_printmpi ("ciphertxt", ciphertext); */ - if (!mpi_cmp (plaintext, ciphertext)) + if (mpi_cmp (ref_mpi, ciphertext)) { - errtxt = "ciphertext matches plaintext"; + errtxt = "ciphertext doesn't match reference data"; goto leave; } @@ -1503,9 +1572,9 @@ selftest_encr_1024 (gcry_sexp_t pkey, gcry_sexp_t skey) take care of it anyway. */ tmplist = sexp_find_token (decr, "value", 0); if (tmplist) - decr_plaintext = sexp_nth_mpi (tmplist, 1, GCRYMPI_FMT_USG); + decr_plaintext = sexp_nth_string (tmplist, 1); else - decr_plaintext = sexp_nth_mpi (decr, 0, GCRYMPI_FMT_USG); + decr_plaintext = sexp_nth_string (decr, 0); if (!decr_plaintext) { errtxt = "decrypt returned no plaintext"; @@ -1513,7 +1582,7 @@ selftest_encr_1024 (gcry_sexp_t pkey, gcry_sexp_t skey) } /* Check that the decrypted plaintext matches the original plaintext. */ - if (mpi_cmp (plaintext, decr_plaintext)) + if (strcmp (plaintext, decr_plaintext)) { errtxt = "mismatch"; goto leave; @@ -1521,12 +1590,12 @@ selftest_encr_1024 (gcry_sexp_t pkey, gcry_sexp_t skey) leave: sexp_release (tmplist); - _gcry_mpi_release (decr_plaintext); + xfree (decr_plaintext); sexp_release (decr); _gcry_mpi_release (ciphertext); + _gcry_mpi_release (ref_mpi); sexp_release (encr); sexp_release (plain); - _gcry_mpi_release (plaintext); return errtxt; } @@ -1561,12 +1630,12 @@ selftests_rsa (selftest_report_func_t report) } what = "sign"; - errtxt = selftest_sign_1024 (pkey, skey); + errtxt = selftest_sign_2048 (pkey, skey); if (errtxt) goto failed; what = "encrypt"; - errtxt = selftest_encr_1024 (pkey, skey); + errtxt = selftest_encr_2048 (pkey, skey); if (errtxt) goto failed; diff --git a/tests/pubkey.c b/tests/pubkey.c index 26bd9e3..62dc0d6 100644 --- a/tests/pubkey.c +++ b/tests/pubkey.c @@ -354,7 +354,7 @@ get_keys_new (gcry_sexp_t *pkey, gcry_sexp_t *skey) int rc; rc = gcry_sexp_new (&key_spec, - "(genkey (rsa (nbits 4:1024)))", 0, 1); + "(genkey (rsa (nbits 4:2048)))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gcry_strerror (rc)); rc = gcry_pk_genkey (&key, key_spec); @@ -386,7 +386,7 @@ get_keys_x931_new (gcry_sexp_t *pkey, gcry_sexp_t *skey) int rc; rc = gcry_sexp_new (&key_spec, - "(genkey (rsa (nbits 4:1024)(use-x931)))", 0, 1); + "(genkey (rsa (nbits 4:2048)(use-x931)))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gcry_strerror (rc)); rc = gcry_pk_genkey (&key, key_spec); commit ce1cbe16992a7340edcf8e6576973e3508267640 Author: Vitezslav Cizek Date: Thu Oct 29 17:13:16 2015 +0100 Disable non-allowed algorithms in FIPS mode * cipher/cipher.c (_gcry_cipher_init), * cipher/mac.c (_gcry_mac_init), * cipher/md.c (_gcry_md_init), * cipher/pubkey.c (_gcry_pk_init): In the FIPS mode, disable all the non-allowed ciphers. * cipher/md5.c: Mark MD5 as not allowed in FIPS. * src/g10lib.h (_gcry_mac_init): New. * src/global.c (global_init): Call the new _gcry_mac_init. * tests/basic.c (check_ciphers): Fix a typo. -- When running in the FIPS mode, disable all the ciphers that don't have the fips flag set. Skip the non-allowed algos during testing in the FIPS mode. Thanks to Ludwig Nussel. Signed-off-by: Vitezslav Cizek Signed-off-by: Vitezslav Cizek diff --git a/cipher/cipher.c b/cipher/cipher.c index 802ffad..a013846 100644 --- a/cipher/cipher.c +++ b/cipher/cipher.c @@ -1514,6 +1514,17 @@ _gcry_cipher_get_algo_blklen (int algo) gcry_err_code_t _gcry_cipher_init (void) { + if (fips_mode()) + { + /* disable algorithms that are disallowed in fips */ + int idx; + gcry_cipher_spec_t *spec; + + for (idx = 0; (spec = cipher_list[idx]); idx++) + if (!spec->flags.fips) + spec->flags.disabled = 1; + } + return 0; } diff --git a/cipher/mac.c b/cipher/mac.c index b8a5534..46be7b7 100644 --- a/cipher/mac.c +++ b/cipher/mac.c @@ -116,6 +116,23 @@ static gcry_mac_spec_t *mac_list[] = { NULL, }; +/* Explicitly initialize this module. */ +gcry_err_code_t +_gcry_mac_init (void) +{ + if (fips_mode()) + { + /* disable algorithms that are disallowed in fips */ + int idx; + gcry_mac_spec_t *spec; + + for (idx = 0; (spec = mac_list[idx]); idx++) + if (!spec->flags.fips) + spec->flags.disabled = 1; + } + + return 0; +} /* Return the spec structure for the MAC algorithm ALGO. For an diff --git a/cipher/md.c b/cipher/md.c index 15d944d..281db12 100644 --- a/cipher/md.c +++ b/cipher/md.c @@ -1296,6 +1296,17 @@ _gcry_md_info (gcry_md_hd_t h, int cmd, void *buffer, size_t *nbytes) gcry_err_code_t _gcry_md_init (void) { + if (fips_mode()) + { + /* disable algorithms that are disallowed in fips */ + int idx; + gcry_md_spec_t *spec; + + for (idx = 0; (spec = digest_list[idx]); idx++) + if (!spec->flags.fips) + spec->flags.disabled = 1; + } + return 0; } diff --git a/cipher/md5.c b/cipher/md5.c index 66cc5f6..ed942cf 100644 --- a/cipher/md5.c +++ b/cipher/md5.c @@ -310,7 +310,7 @@ static gcry_md_oid_spec_t oid_spec_md5[] = gcry_md_spec_t _gcry_digest_spec_md5 = { - GCRY_MD_MD5, {0, 1}, + GCRY_MD_MD5, {0, 0}, "MD5", asn, DIM (asn), oid_spec_md5, 16, md5_init, _gcry_md_block_write, md5_final, md5_read, NULL, sizeof (MD5_CONTEXT) diff --git a/cipher/pubkey.c b/cipher/pubkey.c index b321a89..8ec15fd 100644 --- a/cipher/pubkey.c +++ b/cipher/pubkey.c @@ -926,6 +926,17 @@ _gcry_pubkey_get_sexp (gcry_sexp_t *r_sexp, int mode, gcry_ctx_t ctx) gcry_err_code_t _gcry_pk_init (void) { + if (fips_mode()) + { + /* disable algorithms that are disallowed in fips */ + int idx; + gcry_pk_spec_t *spec; + + for (idx = 0; (spec = pubkey_list[idx]); idx++) + if (!spec->flags.fips) + spec->flags.disabled = 1; + } + return 0; } diff --git a/src/g10lib.h b/src/g10lib.h index 7352556..af68870 100644 --- a/src/g10lib.h +++ b/src/g10lib.h @@ -381,6 +381,7 @@ typedef struct fast_wipememory_s gcry_err_code_t _gcry_cipher_init (void); gcry_err_code_t _gcry_md_init (void); +gcry_err_code_t _gcry_mac_init (void); gcry_err_code_t _gcry_pk_init (void); gcry_err_code_t _gcry_secmem_module_init (void); gcry_err_code_t _gcry_mpi_init (void); diff --git a/src/global.c b/src/global.c index 4d69b27..8669a46 100644 --- a/src/global.c +++ b/src/global.c @@ -105,6 +105,9 @@ global_init (void) err = _gcry_md_init (); if (err) goto fail; + err = _gcry_mac_init (); + if (err) + goto fail; err = _gcry_pk_init (); if (err) goto fail; diff --git a/tests/basic.c b/tests/basic.c index 5e7ee44..876ee2e 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -698,6 +698,14 @@ check_ctr_cipher (void) if (!tv[i].algo) continue; + if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode) + { + if (verbose) + fprintf (stderr, " algorithm %d not available in fips mode\n", + tv[i].algo); + continue; + } + err = gcry_cipher_open (&hde, tv[i].algo, GCRY_CIPHER_MODE_CTR, 0); if (!err) err = gcry_cipher_open (&hdd, tv[i].algo, GCRY_CIPHER_MODE_CTR, 0); @@ -929,6 +937,14 @@ check_cfb_cipher (void) for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++) { + if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode) + { + if (verbose) + fprintf (stderr, " algorithm %d not available in fips mode\n", + tv[i].algo); + continue; + } + if (verbose) fprintf (stderr, " checking CFB mode for %s [%i]\n", gcry_cipher_algo_name (tv[i].algo), @@ -1100,6 +1116,14 @@ check_ofb_cipher (void) for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++) { + if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode) + { + if (verbose) + fprintf (stderr, " algorithm %d not available in fips mode\n", + tv[i].algo); + continue; + } + if (verbose) fprintf (stderr, " checking OFB mode for %s [%i]\n", gcry_cipher_algo_name (tv[i].algo), @@ -1402,6 +1426,14 @@ _check_gcm_cipher (unsigned int step) for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++) { + if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode) + { + if (verbose) + fprintf (stderr, " algorithm %d not available in fips mode\n", + tv[i].algo); + continue; + } + if (verbose) fprintf (stderr, " checking GCM mode for %s [%i]\n", gcry_cipher_algo_name (tv[i].algo), @@ -2423,6 +2455,14 @@ check_ccm_cipher (void) for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++) { + if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode) + { + if (verbose) + fprintf (stderr, " algorithm %d not available in fips mode\n", + tv[i].algo); + continue; + } + if (verbose) fprintf (stderr, " checking CCM mode for %s [%i]\n", gcry_cipher_algo_name (tv[i].algo), @@ -3924,6 +3964,13 @@ check_stream_cipher (void) for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++) { + if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode) + { + if (verbose) + fprintf (stderr, " algorithm %d not available in fips mode\n", + tv[i].algo); + continue; + } if (verbose) fprintf (stderr, " checking stream mode for %s [%i] (%s)\n", gcry_cipher_algo_name (tv[i].algo), tv[i].algo, tv[i].name); @@ -4368,6 +4415,14 @@ check_stream_cipher_large_block (void) for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++) { + if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode) + { + if (verbose) + fprintf (stderr, " algorithm %d not available in fips mode\n", + tv[i].algo); + continue; + } + if (verbose) fprintf (stderr, " checking large block stream for %s [%i] (%s)\n", gcry_cipher_algo_name (tv[i].algo), tv[i].algo, tv[i].name); @@ -5219,11 +5274,11 @@ check_ciphers (void) for (i = 0; algos2[i]; i++) { - if (gcry_cipher_test_algo (algos[i]) && in_fips_mode) + if (gcry_cipher_test_algo (algos2[i]) && in_fips_mode) { if (verbose) fprintf (stderr, " algorithm %d not available in fips mode\n", - algos[i]); + algos2[i]); continue; } if (verbose) @@ -6399,8 +6454,7 @@ check_digests (void) show_md_not_available (algos[i].md); continue; } - if ((gcry_md_test_algo (algos[i].md) || algos[i].md == GCRY_MD_MD5) - && in_fips_mode) + if (gcry_md_test_algo (algos[i].md) && in_fips_mode) { if (verbose) fprintf (stderr, " algorithm %d not available in fips mode\n", @@ -6832,8 +6886,7 @@ check_hmac (void) show_old_hmac_not_available (algos[i].md); continue; } - if ((gcry_md_test_algo (algos[i].md) || algos[i].md == GCRY_MD_MD5) - && in_fips_mode) + if (gcry_md_test_algo (algos[i].md) && in_fips_mode) { if (verbose) fprintf (stderr, " algorithm %d not available in fips mode\n", @@ -7809,8 +7862,7 @@ check_mac (void) show_mac_not_available (algos[i].algo); continue; } - if ((gcry_mac_test_algo (algos[i].algo) - || algos[i].algo == GCRY_MAC_HMAC_MD5) && in_fips_mode) + if (gcry_mac_test_algo (algos[i].algo) && in_fips_mode) { if (verbose) fprintf (stderr, " algorithm %d not available in fips mode\n", commit c478cf175887c84dc071c4f73a7667603b354789 Author: Werner Koch Date: Fri Mar 18 15:38:26 2016 +0100 kdf: Make PBKDF2 check work on all platforms. * cipher/kdf.c (_gcry_kdf_pkdf2): Chnage DKLEN to unsigned long. -- The previous pacth has no effect because on almost all platformans an unsigned int is 32 bit and thus the 0xffffffff is anyway the largest value. This patch changes the variable to an unsigned long so that at least on common 64 bit Unix systems (but not on 64 bit Windows) there is an actual check. Signed-off-by: Werner Koch diff --git a/cipher/kdf.c b/cipher/kdf.c index 831edd2..27f5789 100644 --- a/cipher/kdf.c +++ b/cipher/kdf.c @@ -125,7 +125,7 @@ _gcry_kdf_pkdf2 (const void *passphrase, size_t passphraselen, gpg_err_code_t ec; gcry_md_hd_t md; int secmode; - unsigned int dklen = keysize; + unsigned long dklen = keysize; char *dk = keybuffer; unsigned int hlen; /* Output length of the digest function. */ unsigned int l; /* Rounded up number of blocks. */ @@ -151,11 +151,14 @@ _gcry_kdf_pkdf2 (const void *passphrase, size_t passphraselen, secmode = _gcry_is_secure (passphrase) || _gcry_is_secure (keybuffer); /* Step 1 */ - /* If dkLen > (2^32 - 1) * hLen, output "derived key too long" and stop. - We use a stronger inequality. */ + /* If dkLen > (2^32 - 1) * hLen, output "derived key too long" and + * stop. We use a stronger inequality but only if our type can hold + * a larger value. */ - if (dklen > 4294967295U) +#if SIZEOF_UNSIGNED_LONG > 4 + if (dklen > 0xffffffffU) return GPG_ERR_INV_VALUE; +#endif /* Step 2 */ commit 0f741b0704bac5c0e2d2a0c2b34b44b35baa76d6 Author: Vitezslav Cizek Date: Thu Oct 29 14:00:26 2015 +0100 kdf: Add upper bound for derived key length in PBKDF2. * cipher/kdf.c (_gcry_kdf_pkdf2): limit dkLen. -- Add a missing step 1 from PBKDF specification. Signed-off-by: Vitezslav Cizek diff --git a/cipher/kdf.c b/cipher/kdf.c index ad5c46e..831edd2 100644 --- a/cipher/kdf.c +++ b/cipher/kdf.c @@ -138,7 +138,7 @@ _gcry_kdf_pkdf2 (const void *passphrase, size_t passphraselen, unsigned long iter; /* Current iteration number. */ unsigned int i; - /* NWe allow for a saltlen of 0 here to support scrypt. It is not + /* We allow for a saltlen of 0 here to support scrypt. It is not clear whether rfc2898 allows for this this, thus we do a test on saltlen > 0 only in gcry_kdf_derive. */ if (!salt || !iterations || !dklen) @@ -150,8 +150,13 @@ _gcry_kdf_pkdf2 (const void *passphrase, size_t passphraselen, secmode = _gcry_is_secure (passphrase) || _gcry_is_secure (keybuffer); - /* We ignore step 1 from pksc5v2.1 which demands a check that dklen - is not larger that 0xffffffff * hlen. */ + /* Step 1 */ + /* If dkLen > (2^32 - 1) * hLen, output "derived key too long" and stop. + We use a stronger inequality. */ + + if (dklen > 4294967295U) + return GPG_ERR_INV_VALUE; + /* Step 2 */ l = ((dklen - 1)/ hlen) + 1; commit a242e3d9185e6e2dc13902ea9331131755bbba01 Author: Vitezslav Cizek Date: Tue Oct 27 14:29:11 2015 +0100 ecc: ECDSA adjustments for FIPS 186-4 * cipher/ecc-curves.c: Unmark curve P-192 for FIPS. * cipher/ecc.c: Add ECDSA self test. * cipher/pubkey-util.c (_gcry_pk_util_init_encoding_ctx): Use SHA-2 in FIPS mode. * tests/fipsdrv.c: Add support for ECDSA signatures. -- Enable ECC in FIPS mode. According to NIST SP 800-131A, curve P-192 and SHA-1 are disallowed for key pair generation and signature generation after 2013. Thanks to Jan Matejek for the patch. Signed-off-by: Vitezslav Cizek Minor source code re-formatting by -wk. diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c index a74501d..91f29cc 100644 --- a/cipher/ecc-curves.c +++ b/cipher/ecc-curves.c @@ -160,7 +160,7 @@ static const ecc_domain_parms_t domain_parms[] = }, #endif /*0*/ { - "NIST P-192", 192, 1, + "NIST P-192", 192, 0, MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD, "0xfffffffffffffffffffffffffffffffeffffffffffffffff", "0xfffffffffffffffffffffffffffffffefffffffffffffffc", diff --git a/cipher/ecc.c b/cipher/ecc.c index f65203f..5b03530 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -73,6 +73,25 @@ static const char *ecc_names[] = }; +/* Sample NIST P-256 key from RFC 6979 A.2.5 */ +static const char sample_public_key_secp256[] = + "(public-key" + " (ecc" + " (curve secp256r1)" + " (q #04" + /**/ "60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6" + /**/ "7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299#)))"; + +static const char sample_secret_key_secp256[] = + "(private-key" + " (ecc" + " (curve secp256r1)" + " (d #C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721#)" + " (q #04" + /**/ "60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6" + /**/ "7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299#)))"; + + /* Registered progress function and its callback value. */ static void (*progress_cb) (void *, const char*, int, int, int); static void *progress_cb_data; @@ -1956,23 +1975,165 @@ _gcry_pk_ecc_get_sexp (gcry_sexp_t *r_sexp, int mode, mpi_ec_t ec) Self-test section. */ +static const char * +selftest_sign (gcry_sexp_t pkey, gcry_sexp_t skey) +{ + /* Sample data from RFC 6979 section A.2.5, hash is of message "sample" */ + static const char sample_data[] = + "(data (flags rfc6979)" + " (hash sha256 #af2bdbe1aa9b6ec1e2ade1d694f41fc71a831d0268e98915" + /**/ "62113d8a62add1bf#))"; + static const char sample_data_bad[] = + "(data (flags rfc6979)" + " (hash sha256 #bf2bdbe1aa9b6ec1e2ade1d694f41fc71a831d0268e98915" + /**/ "62113d8a62add1bf#))"; + static const char signature_r[] = + "efd48b2aacb6a8fd1140dd9cd45e81d69d2c877b56aaf991c34d0ea84eaf3716"; + static const char signature_s[] = + "f7cb1c942d657c41d436c7a1b6e29f65f3e900dbb9aff4064dc4ab2f843acda8"; + + const char *errtxt = NULL; + gcry_error_t err; + gcry_sexp_t data = NULL; + gcry_sexp_t data_bad = NULL; + gcry_sexp_t sig = NULL; + gcry_sexp_t l1 = NULL; + gcry_sexp_t l2 = NULL; + gcry_mpi_t r = NULL; + gcry_mpi_t s = NULL; + gcry_mpi_t calculated_r = NULL; + gcry_mpi_t calculated_s = NULL; + int cmp; + + err = sexp_sscan (&data, NULL, sample_data, strlen (sample_data)); + if (!err) + err = sexp_sscan (&data_bad, NULL, + sample_data_bad, strlen (sample_data_bad)); + if (!err) + err = _gcry_mpi_scan (&r, GCRYMPI_FMT_HEX, signature_r, 0, NULL); + if (!err) + err = _gcry_mpi_scan (&s, GCRYMPI_FMT_HEX, signature_s, 0, NULL); + + if (err) + { + errtxt = "converting data failed"; + goto leave; + } + + err = _gcry_pk_sign (&sig, data, skey); + if (err) + { + errtxt = "signing failed"; + goto leave; + } + + /* check against known signature */ + errtxt = "signature validity failed"; + l1 = _gcry_sexp_find_token (sig, "sig-val", 0); + if (!l1) + goto leave; + l2 = _gcry_sexp_find_token (l1, "ecdsa", 0); + if (!l2) + goto leave; + + sexp_release (l1); + l1 = l2; + + l2 = _gcry_sexp_find_token (l1, "r", 0); + if (!l2) + goto leave; + calculated_r = _gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); + if (!calculated_r) + goto leave; + + l2 = _gcry_sexp_find_token (l1, "s", 0); + if (!l2) + goto leave; + calculated_s = _gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); + if (!calculated_s) + goto leave; + + errtxt = "known sig check failed"; + + cmp = _gcry_mpi_cmp (r, calculated_r); + if (cmp) + goto leave; + cmp = _gcry_mpi_cmp (s, calculated_s); + if (cmp) + goto leave; + + errtxt = NULL; + + /* verify generated signature */ + err = _gcry_pk_verify (sig, data, pkey); + if (err) + { + errtxt = "verify failed"; + goto leave; + } + err = _gcry_pk_verify (sig, data_bad, pkey); + if (gcry_err_code (err) != GPG_ERR_BAD_SIGNATURE) + { + errtxt = "bad signature not detected"; + goto leave; + } + + + leave: + sexp_release (sig); + sexp_release (data_bad); + sexp_release (data); + sexp_release (l1); + sexp_release (l2); + mpi_release (r); + mpi_release (s); + mpi_release (calculated_r); + mpi_release (calculated_s); + return errtxt; +} + static gpg_err_code_t selftests_ecdsa (selftest_report_func_t report) { const char *what; const char *errtxt; + gcry_error_t err; + gcry_sexp_t skey = NULL; + gcry_sexp_t pkey = NULL; + + what = "convert"; + err = sexp_sscan (&skey, NULL, sample_secret_key_secp256, + strlen (sample_secret_key_secp256)); + if (!err) + err = sexp_sscan (&pkey, NULL, sample_public_key_secp256, + strlen (sample_public_key_secp256)); + if (err) + { + errtxt = _gcry_strerror (err); + goto failed; + } + + what = "key consistency"; + err = ecc_check_secret_key(skey); + if (err) + { + errtxt = _gcry_strerror (err); + goto failed; + } - what = "low-level"; - errtxt = NULL; /*selftest ();*/ + what = "sign"; + errtxt = selftest_sign (pkey, skey); if (errtxt) goto failed; - /* FIXME: need more tests. */ - + sexp_release(pkey); + sexp_release(skey); return 0; /* Succeeded. */ failed: + sexp_release(pkey); + sexp_release(skey); if (report) report ("pubkey", GCRY_PK_ECC, what, errtxt); return GPG_ERR_SELFTEST_FAILED; @@ -1996,7 +2157,7 @@ run_selftests (int algo, int extended, selftest_report_func_t report) gcry_pk_spec_t _gcry_pubkey_spec_ecc = { - GCRY_PK_ECC, { 0, 0 }, + GCRY_PK_ECC, { 0, 1 }, (GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR), "ECC", ecc_names, "pabgnhq", "pabgnhqd", "sw", "rs", "pabgnhq", diff --git a/cipher/pubkey-util.c b/cipher/pubkey-util.c index d0d6003..76d3923 100644 --- a/cipher/pubkey-util.c +++ b/cipher/pubkey-util.c @@ -617,7 +617,14 @@ _gcry_pk_util_init_encoding_ctx (struct pk_encoding_ctx *ctx, ctx->nbits = nbits; ctx->encoding = PUBKEY_ENC_UNKNOWN; ctx->flags = 0; - ctx->hash_algo = GCRY_MD_SHA1; + if (fips_mode ()) + { + ctx->hash_algo = GCRY_MD_SHA256; + } + else + { + ctx->hash_algo = GCRY_MD_SHA1; + } ctx->label = NULL; ctx->labellen = 0; ctx->saltlen = 20; diff --git a/src/fips.c b/src/fips.c index edcbeac..3311ba2 100644 --- a/src/fips.c +++ b/src/fips.c @@ -549,7 +549,7 @@ run_pubkey_selftests (int extended) { GCRY_PK_RSA, GCRY_PK_DSA, - /* GCRY_PK_ECC is not enabled in fips mode. */ + GCRY_PK_ECC, 0 }; int idx; diff --git a/tests/fipsdrv.c b/tests/fipsdrv.c index d757420..b5962cf 100644 --- a/tests/fipsdrv.c +++ b/tests/fipsdrv.c @@ -1721,6 +1721,33 @@ dsa_gen_with_seed (int keysize, const void *seed, size_t seedlen) } +/* Generate an ECDSA key on the specified curve and return the complete + S-expression. */ +static gcry_sexp_t +ecdsa_gen_key (const char *curve) +{ + gpg_error_t err; + gcry_sexp_t keyspec, key; + + err = gcry_sexp_build (&keyspec, NULL, + "(genkey" + " (ecc" + " (use-fips186)" + " (curve %s)))", + curve); + if (err) + die ("gcry_sexp_build failed for ECDSA key generation: %s\n", + gpg_strerror (err)); + err = gcry_pk_genkey (&key, keyspec); + if (err) + die ("gcry_pk_genkey failed for ECDSA: %s\n", gpg_strerror (err)); + + gcry_sexp_release (keyspec); + + return key; +} + + /* Print the domain parameter as well as the derive information. KEY is the complete key as returned by dsa_gen. We print to stdout with one parameter per line in hex format using this order: p, q, @@ -1813,6 +1840,46 @@ print_dsa_domain_parameters (gcry_sexp_t key) } +/* Print public key Q (in octet-string format) and private key d. + KEY is the complete key as returned by ecdsa_gen_key. + with one parameter per line in hex format using this order: d, Q. */ +static void +print_ecdsa_dq (gcry_sexp_t key) +{ + gcry_sexp_t l1, l2; + gcry_mpi_t mpi; + int idx; + + l1 = gcry_sexp_find_token (key, "private-key", 0); + if (!l1) + die ("private key not found in genkey result\n"); + + l2 = gcry_sexp_find_token (l1, "ecc", 0); + if (!l2) + die ("returned private key not formed as expected\n"); + gcry_sexp_release (l1); + l1 = l2; + + /* Extract the parameters from the S-expression and print them to stdout. */ + for (idx=0; "dq"[idx]; idx++) + { + l2 = gcry_sexp_find_token (l1, "dq"+idx, 1); + if (!l2) + die ("no %c parameter in returned public key\n", "dq"[idx]); + mpi = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); + if (!mpi) + die ("no value for %c parameter in returned private key\n","dq"[idx]); + gcry_sexp_release (l2); + if (standalone_mode) + printf ("%c = ", "dQ"[idx]); + print_mpi_line (mpi, 1); + gcry_mpi_release (mpi); + } + + gcry_sexp_release (l1); +} + + /* Generate DSA domain parameters for a modulus size of KEYSIZE. The result is printed to stdout with one parameter per line in hex format and in this order: p, q, g, seed, counter, h. If SEED is @@ -1992,6 +2059,138 @@ run_dsa_verify (const void *data, size_t datalen, } + +/* Sign DATA of length DATALEN using the key taken from the S-expression + encoded KEYFILE. */ +static void +run_ecdsa_sign (const void *data, size_t datalen, + const char *keyfile, const int algo) + +{ + gpg_error_t err; + gcry_sexp_t s_data, s_key, s_sig, s_tmp; + char hash[128]; + gcry_mpi_t tmpmpi; + + s_key = read_sexp_from_file (keyfile); + + gcry_md_hash_buffer (algo, hash, data, datalen); + err = gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_USG, hash, + gcry_md_get_algo_dlen(algo), NULL); + if (!err) + { + err = gcry_sexp_build (&s_data, NULL, + "(data (flags raw)(hash %s %M))", + gcry_md_algo_name(algo), tmpmpi); + gcry_mpi_release (tmpmpi); + } + if (err) + die ("gcry_sexp_build failed for ECDSA data input: %s\n", + gpg_strerror (err)); + + err = gcry_pk_sign (&s_sig, s_data, s_key); + if (err) + { + die ("gcry_pk_signed failed: %s\n", gpg_strerror (err)); + } + gcry_sexp_release (s_data); + gcry_sexp_release (s_key); + + /* Now return the actual signature. */ + s_tmp = gcry_sexp_find_token (s_sig, "sig-val", 0); + if (!s_tmp) + die ("no sig-val element in returned S-expression\n"); + + gcry_sexp_release (s_sig); + s_sig = s_tmp; + s_tmp = gcry_sexp_find_token (s_sig, "ecdsa", 0); + if (!s_tmp) + die ("no ecdsa element in returned S-expression\n"); + + gcry_sexp_release (s_sig); + s_sig = s_tmp; + + s_tmp = gcry_sexp_find_token (s_sig, "r", 0); + tmpmpi = gcry_sexp_nth_mpi (s_tmp, 1, GCRYMPI_FMT_USG); + if (!tmpmpi) + die ("no r parameter in returned S-expression\n"); + print_mpi_line (tmpmpi, 1); + gcry_mpi_release (tmpmpi); + gcry_sexp_release (s_tmp); + + s_tmp = gcry_sexp_find_token (s_sig, "s", 0); + tmpmpi = gcry_sexp_nth_mpi (s_tmp, 1, GCRYMPI_FMT_USG); + if (!tmpmpi) + die ("no s parameter in returned S-expression\n"); + print_mpi_line (tmpmpi, 1); + gcry_mpi_release (tmpmpi); + gcry_sexp_release (s_tmp); + + gcry_sexp_release (s_sig); +} + + + +/* Verify DATA of length DATALEN using the public key taken from the + S-expression in KEYFILE against the S-expression formatted + signature in SIGFILE. */ +static void +run_ecdsa_verify (const void *data, size_t datalen, + const char *keyfile, const int algo, const char *sigfile) + +{ + gpg_error_t err; + gcry_sexp_t s_data, s_key, s_sig; + char hash[128]; + gcry_mpi_t tmpmpi; + + s_key = read_sexp_from_file (keyfile); + + gcry_md_hash_buffer (algo, hash, data, datalen); + /* Note that we can't simply use %b with HASH to build the + S-expression, because that might yield a negative value. */ + err = gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_USG, hash, + gcry_md_get_algo_dlen(algo), NULL); + if (!err) + { + err = gcry_sexp_build (&s_data, NULL, + "(data (flags raw)(hash %s %M))", + gcry_md_algo_name(algo), tmpmpi); + gcry_mpi_release (tmpmpi); + } + if (err) + die ("gcry_sexp_build failed for DSA data input: %s\n", + gpg_strerror (err)); + + s_sig = read_sexp_from_file (sigfile); + + err = gcry_pk_verify (s_sig, s_data, s_key); + if (!err) + puts ("GOOD signature"); + else if (gpg_err_code (err) == GPG_ERR_BAD_SIGNATURE) + puts ("BAD signature"); + else + printf ("ERROR (%s)\n", gpg_strerror (err)); + + gcry_sexp_release (s_sig); + gcry_sexp_release (s_key); + gcry_sexp_release (s_data); +} + + +/* Generate an ECDSA key with specified domain parameters + and print the d and Q values, in the standard octet-string format. */ +static void +run_ecdsa_gen_key (const char *curve) +{ + gcry_sexp_t key; + + key = ecdsa_gen_key (curve); + print_ecdsa_dq (key); + + gcry_sexp_release (key); +} + static void @@ -2008,7 +2207,8 @@ usage (int show_help) "Run a crypto operation using hex encoded input and output.\n" "MODE:\n" " encrypt, decrypt, digest, random, hmac-sha,\n" - " rsa-{derive,gen,sign,verify}, dsa-{pqg-gen,gen,sign,verify}\n" + " rsa-{derive,gen,sign,verify},\n" + " dsa-{pqg-gen,gen,sign,verify}, ecdsa-{gen-key,sign,verify}\n" "OPTIONS:\n" " --verbose Print additional information\n" " --binary Input and output is in binary form\n" @@ -2017,6 +2217,7 @@ usage (int show_help) " --iv IV Use the hex encoded IV\n" " --dt DT Use the hex encoded DT for the RNG\n" " --algo NAME Use algorithm NAME\n" + " --curve NAME Select ECC curve spec NAME\n" " --keysize N Use a keysize of N bits\n" " --signature NAME Take signature from file NAME\n" " --chunk N Read in chunks of N bytes (implies --binary)\n" @@ -2039,6 +2240,7 @@ main (int argc, char **argv) int progress = 0; int use_pkcs1 = 0; const char *mode_string; + const char *curve_string = NULL; const char *key_string = NULL; const char *iv_string = NULL; const char *dt_string = NULL; @@ -2154,6 +2356,14 @@ main (int argc, char **argv) binary_input = binary_output = 1; argc--; argv++; } + else if (!strcmp (*argv, "--curve")) + { + argc--; argv++; + if (!argc) + usage (0); + curve_string = *argv; + argc--; argv++; + } else if (!strcmp (*argv, "--pkcs1")) { use_pkcs1 = 1; @@ -2211,7 +2421,8 @@ main (int argc, char **argv) && !mct_server && strcmp (mode_string, "random") && strcmp (mode_string, "rsa-gen") - && strcmp (mode_string, "dsa-gen") ) + && strcmp (mode_string, "dsa-gen") + && strcmp (mode_string, "ecdsa-gen-key") ) { data = read_file (input, !binary_input, &datalen); if (!data) @@ -2501,6 +2712,53 @@ main (int argc, char **argv) run_dsa_verify (data, datalen, key_string, signature_string); } + else if (!strcmp (mode_string, "ecdsa-gen-key")) + { + if (!curve_string) + die ("option --curve containing name of the specified curve is required in this mode\n"); + run_ecdsa_gen_key (curve_string); + } + else if (!strcmp (mode_string, "ecdsa-sign")) + { + int algo; + + if (!key_string) + die ("option --key is required in this mode\n"); + if (access (key_string, R_OK)) + die ("option --key needs to specify an existing keyfile\n"); + if (!algo_string) + die ("use --algo to specify the digest algorithm\n"); + algo = gcry_md_map_name (algo_string); + if (!algo) + die ("digest algorithm `%s' is not supported\n", algo_string); + + if (!data) + die ("no data available (do not use --chunk)\n"); + + run_ecdsa_sign (data, datalen, key_string, algo); + } + else if (!strcmp (mode_string, "ecdsa-verify")) + { + int algo; + + if (!key_string) + die ("option --key is required in this mode\n"); + if (access (key_string, R_OK)) + die ("option --key needs to specify an existing keyfile\n"); + if (!algo_string) + die ("use --algo to specify the digest algorithm\n"); + algo = gcry_md_map_name (algo_string); + if (!algo) + die ("digest algorithm `%s' is not supported\n", algo_string); + if (!data) + die ("no data available (do not use --chunk)\n"); + if (!signature_string) + die ("option --signature is required in this mode\n"); + if (access (signature_string, R_OK)) + die ("option --signature needs to specify an existing file\n"); + + run_ecdsa_verify (data, datalen, key_string, algo, signature_string); + } else usage (0); commit e40939b2141306238cc30a340b867b60fa4dc2a3 Author: Werner Koch Date: Fri Mar 18 15:11:31 2016 +0100 dsa: Make regression tests work. * cipher/dsa.c (sample_secret_key_1024): Comment out unused constant. (ogenerate_fips186): Make it work with use-fips183-2 flag. * cipher/primegen.c (_gcry_generate_fips186_3_prime): Use Emacs standard comment out format. * tests/fips186-dsa.c (check_dsa_gen_186_3): New dummy fucntion. (main): Call it. (main): Compare against current version. * tests/pubkey.c (get_dsa_key_fips186_new): Create 2048 bit key. (get_dsa_key_fips186_with_seed_new): Ditto. (get_dsa_key_fips186_with_domain_new): Comment out. (check_run): Do not call that function. -- Signed-off-by: Werner Koch diff --git a/cipher/dsa.c b/cipher/dsa.c index 37c1b18..909a8ca 100644 --- a/cipher/dsa.c +++ b/cipher/dsa.c @@ -66,7 +66,9 @@ static const char *dsa_names[] = }; -/* A sample 1024 bit DSA key used for the selftests. */ +/* A sample 1024 bit DSA key used for the selftests. Not anymore + * used, kept only for reference. */ +#if 0 static const char sample_secret_key_1024[] = "(private-key" " (dsa" @@ -101,6 +103,7 @@ static const char sample_public_key_1024[] = " A1816A724C34F87330FC9E187C5D66897A04535CC2AC9164A7150ABFA8179827" " 6E45831AB811EEE848EBB24D9F5F2883B6E5DDC4C659DEF944DCFD80BF4D0A20" " 42CAA7DC289F0C5A9D155F02D3D551DB741A81695B74D4C8F477F9C7838EB0FB#)))"; +#endif /*0*/ /* 2048 DSA key from RFC 6979 A.2.2 */ static const char sample_public_key_2048[] = @@ -412,7 +415,9 @@ generate_fips186 (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits, /* Check that QBITS and NBITS match the standard. Note that FIPS 186-3 uses N for QBITS and L for NBITS. */ - if (nbits == 2048 && qbits == 224) + if (nbits == 1024 && qbits == 160 && use_fips186_2) + ; /* Allowed in FIPS 186-2 mode. */ + else if (nbits == 2048 && qbits == 224) ; else if (nbits == 2048 && qbits == 256) ; @@ -442,27 +447,28 @@ generate_fips186 (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits, initial_seed.sexp = sexp_find_token (deriveparms, "seed", 0); if (initial_seed.sexp) initial_seed.seed = sexp_nth_data (initial_seed.sexp, 1, - &initial_seed.seedlen); + &initial_seed.seedlen); } if (use_fips186_2) ec = _gcry_generate_fips186_2_prime (nbits, qbits, - initial_seed.seed, - initial_seed.seedlen, - &prime_q, &prime_p, - r_counter, - r_seed, r_seedlen); + initial_seed.seed, + initial_seed.seedlen, + &prime_q, &prime_p, + r_counter, + r_seed, r_seedlen); else ec = _gcry_generate_fips186_3_prime (nbits, qbits, NULL, 0, - &prime_q, &prime_p, - r_counter, - r_seed, r_seedlen, NULL); + &prime_q, &prime_p, + r_counter, + r_seed, r_seedlen, NULL); sexp_release (initial_seed.sexp); if (ec) goto leave; /* Find a generator g (h and e are helpers). - e = (p-1)/q */ + * e = (p-1)/q + */ value_e = mpi_alloc_like (prime_p); mpi_sub_ui (value_e, prime_p, 1); mpi_fdiv_q (value_e, value_e, prime_q ); diff --git a/cipher/primegen.c b/cipher/primegen.c index 9fd58d2..3ed432b 100644 --- a/cipher/primegen.c +++ b/cipher/primegen.c @@ -1612,23 +1612,21 @@ _gcry_generate_fips186_2_prime (unsigned int pbits, unsigned int qbits, -/* WARNING: The code below has not yet been tested! However, it is - not yet used. We need to wait for FIPS 186-3 final and for test - vectors. - - Generate the two prime used for DSA using the algorithm specified - in FIPS 186-3, A.1.1.2. PBITS is the desired length of the prime P - and a QBITS the length of the prime Q. If SEED is not supplied and - SEEDLEN is 0 the function generates an appropriate SEED. On - success the generated primes are stored at R_Q and R_P, the counter - value is stored at R_COUNTER and the seed actually used for - generation is stored at R_SEED and R_SEEDVALUE. The hash algorithm - used is stored at R_HASHALGO. - - Note that this function is very similar to the fips186_2 code. Due - to the minor differences, other buffer sizes and for documentarion, - we use a separate function. -*/ +/* WARNING: The code below has not yet been tested! + * + * Generate the two prime used for DSA using the algorithm specified + * in FIPS 186-3, A.1.1.2. PBITS is the desired length of the prime P + * and a QBITS the length of the prime Q. If SEED is not supplied and + * SEEDLEN is 0 the function generates an appropriate SEED. On + * success the generated primes are stored at R_Q and R_P, the counter + * value is stored at R_COUNTER and the seed actually used for + * generation is stored at R_SEED and R_SEEDVALUE. The hash algorithm + * used is stored at R_HASHALGO. + * + * Note that this function is very similar to the fips186_2 code. Due + * to the minor differences, other buffer sizes and for documentarion, + * we use a separate function. + */ gpg_err_code_t _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits, const void *seed, size_t seedlen, @@ -1813,13 +1811,12 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits, } /* Step 12: Save p, q, counter and seed. */ -/* - log_debug ("fips186-3 pbits p=%u q=%u counter=%d\n", - mpi_get_nbits (prime_p), mpi_get_nbits (prime_q), counter); - log_printhex ("fips186-3 seed", seed, seedlen); - log_printmpi ("fips186-3 p", prime_p); - log_printmpi ("fips186-3 q", prime_q); -*/ + /* log_debug ("fips186-3 pbits p=%u q=%u counter=%d\n", */ + /* mpi_get_nbits (prime_p), mpi_get_nbits (prime_q), counter); */ + /* log_printhex ("fips186-3 seed", seed, seedlen); */ + /* log_printmpi ("fips186-3 p", prime_p); */ + /* log_printmpi ("fips186-3 q", prime_q); */ + if (r_q) { *r_q = prime_q; diff --git a/tests/fips186-dsa.c b/tests/fips186-dsa.c index 10b18ab..5ee829e 100644 --- a/tests/fips186-dsa.c +++ b/tests/fips186-dsa.c @@ -434,6 +434,14 @@ check_dsa_gen_186_2 (void) } +static void +check_dsa_gen_186_3 (void) +{ + /* FIXME: Needs to be implemented. */ + if (verbose) + info ("generating FIPS 186-3 test keys - skipped\n"); +} + int main (int argc, char **argv) @@ -449,7 +457,7 @@ main (int argc, char **argv) } gcry_control (GCRYCTL_DISABLE_SECMEM, 0); - if (!gcry_check_version ("1.4.4")) + if (!gcry_check_version (GCRYPT_VERSION)) die ("version mismatch\n"); gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); if (debug) @@ -459,6 +467,7 @@ main (int argc, char **argv) check_dsa_gen_186_2 (); + check_dsa_gen_186_3 (); return error_count ? 1 : 0; diff --git a/tests/pubkey.c b/tests/pubkey.c index ae5eea2..26bd9e3 100644 --- a/tests/pubkey.c +++ b/tests/pubkey.c @@ -490,7 +490,7 @@ get_dsa_key_fips186_new (gcry_sexp_t *pkey, gcry_sexp_t *skey) int rc; rc = gcry_sexp_new - (&key_spec, "(genkey (dsa (nbits 4:1024)(use-fips186)))", 0, 1); + (&key_spec, "(genkey (dsa (nbits 4:2048)(use-fips186)))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gcry_strerror (rc)); rc = gcry_pk_genkey (&key, key_spec); @@ -557,6 +557,7 @@ get_dsa_key_with_domain_new (gcry_sexp_t *pkey, gcry_sexp_t *skey) *skey = sec_key; } +#if 0 static void get_dsa_key_fips186_with_domain_new (gcry_sexp_t *pkey, gcry_sexp_t *skey) { @@ -598,7 +599,7 @@ get_dsa_key_fips186_with_domain_new (gcry_sexp_t *pkey, gcry_sexp_t *skey) *pkey = pub_key; *skey = sec_key; } - +#endif /*0*/ static void get_dsa_key_fips186_with_seed_new (gcry_sexp_t *pkey, gcry_sexp_t *skey) @@ -610,7 +611,7 @@ get_dsa_key_fips186_with_seed_new (gcry_sexp_t *pkey, gcry_sexp_t *skey) (&key_spec, "(genkey" " (dsa" - " (nbits 4:1024)" + " (nbits 4:2048)" " (use-fips186)" " (transient-key)" " (derive-parms" @@ -722,12 +723,14 @@ check_run (void) gcry_sexp_release (pkey); gcry_sexp_release (skey); + /* We need new test vectors for get_dsa_key_fips186_with_domain_new. */ if (verbose) - fprintf (stderr, "Generating DSA key with given domain (FIPS 186).\n"); - get_dsa_key_fips186_with_domain_new (&pkey, &skey); - /* Fixme: Add a check function for DSA keys. */ - gcry_sexp_release (pkey); - gcry_sexp_release (skey); + fprintf (stderr, "Generating DSA key with given domain (FIPS 186)" + " - skipped.\n"); + /* get_dsa_key_fips186_with_domain_new (&pkey, &skey); */ + /* /\* Fixme: Add a check function for DSA keys. *\/ */ + /* gcry_sexp_release (pkey); */ + /* gcry_sexp_release (skey); */ if (verbose) fprintf (stderr, "Generating DSA key with given seed (FIPS 186).\n"); commit 80e9f95e6f419daa765e4876c858e3e36e808897 Author: Vitezslav Cizek Date: Tue Oct 27 12:46:30 2015 +0100 dsa: Adjustments to conform with FIPS 186-4. * cipher/dsa.c (generate_fips186): FIPS 186-4 adjustments. * cipher/primegen.c (_gcry_generate_fips186_3_prime): Fix incorrect buflen passed to _gcry_mpi_scan. -- Generate the DSA keypair by testing candidates. (FIPS 186-4 B.1.2) Use 2048 bit key for the selftest. Allow only 2048 and 3072 as pbits size. Signed-off-by: Vitezslav Cizek diff --git a/cipher/dsa.c b/cipher/dsa.c index 01d153f..37c1b18 100644 --- a/cipher/dsa.c +++ b/cipher/dsa.c @@ -67,7 +67,7 @@ static const char *dsa_names[] = /* A sample 1024 bit DSA key used for the selftests. */ -static const char sample_secret_key[] = +static const char sample_secret_key_1024[] = "(private-key" " (dsa" " (p #00AD7C0025BA1A15F775F3F2D673718391D00456978D347B33D7B49E7F32EDAB" @@ -85,7 +85,7 @@ static const char sample_secret_key[] = " 42CAA7DC289F0C5A9D155F02D3D551DB741A81695B74D4C8F477F9C7838EB0FB#)" " (x #11D54E4ADBD3034160F2CED4B7CD292A4EBF3EC0#)))"; /* A sample 1024 bit DSA key used for the selftests (public only). */ -static const char sample_public_key[] = +static const char sample_public_key_1024[] = "(public-key" " (dsa" " (p #00AD7C0025BA1A15F775F3F2D673718391D00456978D347B33D7B49E7F32EDAB" @@ -102,6 +102,23 @@ static const char sample_public_key[] = " 6E45831AB811EEE848EBB24D9F5F2883B6E5DDC4C659DEF944DCFD80BF4D0A20" " 42CAA7DC289F0C5A9D155F02D3D551DB741A81695B74D4C8F477F9C7838EB0FB#)))"; +/* 2048 DSA key from RFC 6979 A.2.2 */ +static const char sample_public_key_2048[] = +"(public-key" +" (dsa" +" (p #9DB6FB5951B66BB6FE1E140F1D2CE5502374161FD6538DF1648218642F0B5C48C8F7A41AADFA187324B87674FA1822B00F1ECF8136943D7C55757264E5A1A44FFE012E9936E00C1D3E9310B01C7D179805D3058B2A9F4BB6F9716BFE6117C6B5B3CC4D9BE341104AD4A80AD6C94E005F4B993E14F091EB51743BF33050C38DE235567E1B34C3D6A5C0CEAA1A0F368213C3D19843D0B4B09DCB9FC72D39C8DE41F1BF14D4BB4563CA28371621CAD3324B6A2D392145BEBFAC748805236F5CA2FE92B871CD8F9C36D3292B5509CA8CAA77A2ADFC7BFD77DDA6F71125A7456FEA153E433256A2261C6A06ED3693797E7995FAD5AABBCFBE3EDA2741E375404AE25B#)" +" (q #F2C3119374CE76C9356990B465374A17F23F9ED35089BD969F61C6DDE9998C1F#)" +" (g #5C7FF6B06F8F143FE8288433493E4769C4D988ACE5BE25A0E24809670716C613D7B0CEE6932F8FAA7C44D2CB24523DA53FBE4F6EC3595892D1AA58C4328A06C46A15662E7EAA703A1DECF8BBB2D05DBE2EB956C142A338661D10461C0D135472085057F3494309FFA73C611F78B32ADBB5740C361C9F35BE90997DB2014E2EF5AA61782F52ABEB8BD6432C4DD097BC5423B285DAFB60DC364E8161F4A2A35ACA3A10B1C4D203CC76A470A33AFDCBDD92959859ABD8B56E1725252D78EAC66E71BA9AE3F1DD2487199874393CD4D832186800654760E1E34C09E4D155179F9EC0DC4473F996BDCE6EED1CABED8B6F116F7AD9CF505DF0F998E34AB27514B0FFE7#)" +" (y #667098C654426C78D7F8201EAC6C203EF030D43605032C2F1FA937E5237DBD949F34A0A2564FE126DC8B715C5141802CE0979C8246463C40E6B6BDAA2513FA611728716C2E4FD53BC95B89E69949D96512E873B9C8F8DFD499CC312882561ADECB31F658E934C0C197F2C4D96B05CBAD67381E7B768891E4DA3843D24D94CDFB5126E9B8BF21E8358EE0E0A30EF13FD6A664C0DCE3731F7FB49A4845A4FD8254687972A2D382599C9BAC4E0ED7998193078913032558134976410B89D2C171D123AC35FD977219597AA7D15C1A9A428E59194F75C721EBCBCFAE44696A499AFA74E04299F132026601638CB87AB79190D4A0986315DA8EEC6561C938996BEADF#)))"; + +static const char sample_secret_key_2048[] = +"(private-key" +" (dsa" +" (p #9DB6FB5951B66BB6FE1E140F1D2CE5502374161FD6538DF1648218642F0B5C48C8F7A41AADFA187324B87674FA1822B00F1ECF8136943D7C55757264E5A1A44FFE012E9936E00C1D3E9310B01C7D179805D3058B2A9F4BB6F9716BFE6117C6B5B3CC4D9BE341104AD4A80AD6C94E005F4B993E14F091EB51743BF33050C38DE235567E1B34C3D6A5C0CEAA1A0F368213C3D19843D0B4B09DCB9FC72D39C8DE41F1BF14D4BB4563CA28371621CAD3324B6A2D392145BEBFAC748805236F5CA2FE92B871CD8F9C36D3292B5509CA8CAA77A2ADFC7BFD77DDA6F71125A7456FEA153E433256A2261C6A06ED3693797E7995FAD5AABBCFBE3EDA2741E375404AE25B#)" +" (q #F2C3119374CE76C9356990B465374A17F23F9ED35089BD969F61C6DDE9998C1F#)" +" (g #5C7FF6B06F8F143FE8288433493E4769C4D988ACE5BE25A0E24809670716C613D7B0CEE6932F8FAA7C44D2CB24523DA53FBE4F6EC3595892D1AA58C4328A06C46A15662E7EAA703A1DECF8BBB2D05DBE2EB956C142A338661D10461C0D135472085057F3494309FFA73C611F78B32ADBB5740C361C9F35BE90997DB2014E2EF5AA61782F52ABEB8BD6432C4DD097BC5423B285DAFB60DC364E8161F4A2A35ACA3A10B1C4D203CC76A470A33AFDCBDD92959859ABD8B56E1725252D78EAC66E71BA9AE3F1DD2487199874393CD4D832186800654760E1E34C09E4D155179F9EC0DC4473F996BDCE6EED1CABED8B6F116F7AD9CF505DF0F998E34AB27514B0FFE7#)" +" (y #667098C654426C78D7F8201EAC6C203EF030D43605032C2F1FA937E5237DBD949F34A0A2564FE126DC8B715C5141802CE0979C8246463C40E6B6BDAA2513FA611728716C2E4FD53BC95B89E69949D96512E873B9C8F8DFD499CC312882561ADECB31F658E934C0C197F2C4D96B05CBAD67381E7B768891E4DA3843D24D94CDFB5126E9B8BF21E8358EE0E0A30EF13FD6A664C0DCE3731F7FB49A4845A4FD8254687972A2D382599C9BAC4E0ED7998193078913032558134976410B89D2C171D123AC35FD977219597AA7D15C1A9A428E59194F75C721EBCBCFAE44696A499AFA74E04299F132026601638CB87AB79190D4A0986315DA8EEC6561C938996BEADF#)" +" (x #69C7548C21D0DFEA6B9A51C9EAD4E27C33D3B3F180316E5BCAB92C933F0E4DBC#)))"; @@ -373,6 +390,8 @@ generate_fips186 (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits, gcry_mpi_t value_x = NULL; /* The secret exponent. */ gcry_mpi_t value_h = NULL; /* Helper. */ gcry_mpi_t value_e = NULL; /* Helper. */ + gcry_mpi_t value_c = NULL; /* helper for x */ + gcry_mpi_t value_qm2 = NULL; /* q - 2 */ /* Preset return values. */ *r_counter = 0; @@ -393,9 +412,7 @@ generate_fips186 (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits, /* Check that QBITS and NBITS match the standard. Note that FIPS 186-3 uses N for QBITS and L for NBITS. */ - if (nbits == 1024 && qbits == 160) - ; - else if (nbits == 2048 && qbits == 224) + if (nbits == 2048 && qbits == 224) ; else if (nbits == 2048 && qbits == 256) ; @@ -428,21 +445,18 @@ generate_fips186 (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits, &initial_seed.seedlen); } - /* Fixme: Enable 186-3 after it has been approved and after fixing - the generation function. */ - /* if (use_fips186_2) */ - (void)use_fips186_2; - ec = _gcry_generate_fips186_2_prime (nbits, qbits, + if (use_fips186_2) + ec = _gcry_generate_fips186_2_prime (nbits, qbits, initial_seed.seed, initial_seed.seedlen, &prime_q, &prime_p, r_counter, r_seed, r_seedlen); - /* else */ - /* ec = _gcry_generate_fips186_3_prime (nbits, qbits, NULL, 0, */ - /* &prime_q, &prime_p, */ - /* r_counter, */ - /* r_seed, r_seedlen, NULL); */ + else + ec = _gcry_generate_fips186_3_prime (nbits, qbits, NULL, 0, + &prime_q, &prime_p, + r_counter, + r_seed, r_seedlen, NULL); sexp_release (initial_seed.sexp); if (ec) goto leave; @@ -463,17 +477,24 @@ generate_fips186 (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits, while (!mpi_cmp_ui (value_g, 1)); /* Continue until g != 1. */ } - - /* Select a random number x with: 0 < x < q */ + value_c = mpi_snew (qbits); value_x = mpi_snew (qbits); + value_qm2 = mpi_snew (qbits); + mpi_sub_ui (value_qm2, prime_q, 2); + + /* FIPS 186-4 B.1.2 steps 4-6 */ do { if( DBG_CIPHER ) progress('.'); - _gcry_mpi_randomize (value_x, qbits, GCRY_VERY_STRONG_RANDOM); - mpi_clear_highbit (value_x, qbits+1); + _gcry_mpi_randomize (value_c, qbits, GCRY_VERY_STRONG_RANDOM); + mpi_clear_highbit (value_c, qbits+1); } - while (!(mpi_cmp_ui (value_x, 0) > 0 && mpi_cmp (value_x, prime_q) < 0)); + while (!(mpi_cmp_ui (value_c, 0) > 0 && mpi_cmp (value_c, value_qm2) < 0)); + /* while (mpi_cmp (value_c, value_qm2) > 0); */ + + /* x = c + 1 */ + mpi_add_ui(value_x, value_c, 1); /* y = g^x mod p */ value_y = mpi_alloc_like (prime_p); @@ -506,6 +527,8 @@ generate_fips186 (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits, _gcry_mpi_release (value_x); _gcry_mpi_release (value_h); _gcry_mpi_release (value_e); + _gcry_mpi_release (value_c); + _gcry_mpi_release (value_qm2); /* As a last step test this keys (this should never fail of course). */ if (!ec && test_keys (sk, qbits) ) @@ -1158,25 +1181,42 @@ dsa_get_nbits (gcry_sexp_t parms) */ static const char * -selftest_sign_1024 (gcry_sexp_t pkey, gcry_sexp_t skey) +selftest_sign (gcry_sexp_t pkey, gcry_sexp_t skey) { + /* Sample data from RFC 6979 section A.2.2, hash is of message "sample" */ static const char sample_data[] = - "(data (flags raw)" - " (value #a0b1c2d3e4f500102030405060708090a1b2c3d4#))"; + "(data (flags rfc6979)" + " (hash sha256 #af2bdbe1aa9b6ec1e2ade1d694f41fc71a831d0268e9891562113d8a62add1bf#))"; static const char sample_data_bad[] = - "(data (flags raw)" - " (value #a0b1c2d3e4f510102030405060708090a1b2c3d4#))"; + "(data (flags rfc6979)" + " (hash sha256 #bf2bdbe1aa9b6ec1e2ade1d694f41fc71a831d0268e9891562113d8a62add1bf#))"; + static const char signature_r[] = + "eace8bdbbe353c432a795d9ec556c6d021f7a03f42c36e9bc87e4ac7932cc809"; + static const char signature_s[] = + "7081e175455f9247b812b74583e9e94f9ea79bd640dc962533b0680793a38d53"; const char *errtxt = NULL; gcry_error_t err; gcry_sexp_t data = NULL; gcry_sexp_t data_bad = NULL; gcry_sexp_t sig = NULL; + gcry_sexp_t l1 = NULL; + gcry_sexp_t l2 = NULL; + gcry_mpi_t r = NULL; + gcry_mpi_t s = NULL; + gcry_mpi_t calculated_r = NULL; + gcry_mpi_t calculated_s = NULL; + int cmp; err = sexp_sscan (&data, NULL, sample_data, strlen (sample_data)); if (!err) err = sexp_sscan (&data_bad, NULL, sample_data_bad, strlen (sample_data_bad)); + if (!err) + err = _gcry_mpi_scan (&r, GCRYMPI_FMT_HEX, signature_r, 0, NULL); + if (!err) + err = _gcry_mpi_scan (&s, GCRYMPI_FMT_HEX, signature_s, 0, NULL); + if (err) { errtxt = "converting data failed"; @@ -1189,6 +1229,45 @@ selftest_sign_1024 (gcry_sexp_t pkey, gcry_sexp_t skey) errtxt = "signing failed"; goto leave; } + + /* check against known signature */ + errtxt = "signature validity failed"; + l1 = _gcry_sexp_find_token (sig, "sig-val", 0); + if (!l1) + goto leave; + l2 = _gcry_sexp_find_token (l1, "dsa", 0); + if (!l2) + goto leave; + + sexp_release (l1); + l1 = l2; + + l2 = _gcry_sexp_find_token (l1, "r", 0); + if (!l2) + goto leave; + calculated_r = _gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); + if (!calculated_r) + goto leave; + + l2 = _gcry_sexp_find_token (l1, "s", 0); + if (!l2) + goto leave; + calculated_s = _gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); + if (!calculated_s) + goto leave; + + errtxt = "known sig check failed"; + + cmp = _gcry_mpi_cmp (r, calculated_r); + if (cmp) + goto leave; + cmp = _gcry_mpi_cmp (s, calculated_s); + if (cmp) + goto leave; + + errtxt = NULL; + + err = _gcry_pk_verify (sig, data, pkey); if (err) { @@ -1212,7 +1291,7 @@ selftest_sign_1024 (gcry_sexp_t pkey, gcry_sexp_t skey) static gpg_err_code_t -selftests_dsa (selftest_report_func_t report) +selftests_dsa_2048 (selftest_report_func_t report) { const char *what; const char *errtxt; @@ -1222,10 +1301,10 @@ selftests_dsa (selftest_report_func_t report) /* Convert the S-expressions into the internal representation. */ what = "convert"; - err = sexp_sscan (&skey, NULL, sample_secret_key, strlen (sample_secret_key)); + err = sexp_sscan (&skey, NULL, sample_secret_key_2048, strlen (sample_secret_key_2048)); if (!err) err = sexp_sscan (&pkey, NULL, - sample_public_key, strlen (sample_public_key)); + sample_public_key_2048, strlen (sample_public_key_2048)); if (err) { errtxt = _gcry_strerror (err); @@ -1241,7 +1320,7 @@ selftests_dsa (selftest_report_func_t report) } what = "sign"; - errtxt = selftest_sign_1024 (pkey, skey); + errtxt = selftest_sign (pkey, skey); if (errtxt) goto failed; @@ -1269,7 +1348,7 @@ run_selftests (int algo, int extended, selftest_report_func_t report) switch (algo) { case GCRY_PK_DSA: - ec = selftests_dsa (report); + ec = selftests_dsa_2048 (report); break; default: ec = GPG_ERR_PUBKEY_ALGO; @@ -1280,7 +1359,6 @@ run_selftests (int algo, int extended, selftest_report_func_t report) } - gcry_pk_spec_t _gcry_pubkey_spec_dsa = { diff --git a/cipher/primegen.c b/cipher/primegen.c index 2a702a7..9fd58d2 100644 --- a/cipher/primegen.c +++ b/cipher/primegen.c @@ -1640,7 +1640,7 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits, gpg_err_code_t ec; unsigned char seed_help_buffer[256/8]; /* Used to hold a generated SEED. */ unsigned char *seed_plus; /* Malloced buffer to hold SEED+x. */ - unsigned char digest[256/8]; /* Helper buffer for SHA-1 digest. */ + unsigned char digest[256/8]; /* Helper buffer for SHA-2 digest. */ gcry_mpi_t val_2 = NULL; /* Helper for the prime test. */ gcry_mpi_t tmpval = NULL; /* Helper variable. */ int hashalgo; /* The id of the Approved Hash Function. */ @@ -1659,9 +1659,7 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits, /* Step 1: Check the requested prime lengths. */ /* Note that due to the size of our buffers QBITS is limited to 256. */ - if (pbits == 1024 && qbits == 160) - hashalgo = GCRY_MD_SHA1; - else if (pbits == 2048 && qbits == 224) + if (pbits == 2048 && qbits == 224) hashalgo = GCRY_MD_SHA224; else if (pbits == 2048 && qbits == 256) hashalgo = GCRY_MD_SHA256; @@ -1730,7 +1728,7 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits, } _gcry_mpi_release (prime_q); prime_q = NULL; ec = _gcry_mpi_scan (&prime_q, GCRYMPI_FMT_USG, - value_u, sizeof value_u, NULL); + value_u, qbits/8, NULL); if (ec) goto leave; mpi_set_highbit (prime_q, qbits-1 ); @@ -1775,11 +1773,11 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits, if (seed_plus[i]) break; } - _gcry_md_hash_buffer (GCRY_MD_SHA1, digest, seed_plus, seedlen); + _gcry_md_hash_buffer (hashalgo, digest, seed_plus, seedlen); _gcry_mpi_release (tmpval); tmpval = NULL; ec = _gcry_mpi_scan (&tmpval, GCRYMPI_FMT_USG, - digest, sizeof digest, NULL); + digest, qbits/8, NULL); if (ec) goto leave; if (value_j == value_n) @@ -1815,11 +1813,13 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits, } /* Step 12: Save p, q, counter and seed. */ +/* log_debug ("fips186-3 pbits p=%u q=%u counter=%d\n", mpi_get_nbits (prime_p), mpi_get_nbits (prime_q), counter); log_printhex ("fips186-3 seed", seed, seedlen); log_printmpi ("fips186-3 p", prime_p); log_printmpi ("fips186-3 q", prime_q); +*/ if (r_q) { *r_q = prime_q; commit 443bed836a4fd60217325789134f5a2dc2ec41ce Author: Werner Koch Date: Fri Mar 18 13:05:34 2016 +0100 Register DCO for Vitezslav Cizek. -- Signed-off-by: Werner Koch diff --git a/AUTHORS b/AUTHORS index 42d5ee6..b19612b 100644 --- a/AUTHORS +++ b/AUTHORS @@ -180,6 +180,9 @@ Stephan Mueller Tom?? Mr?z 2012-04-16:1334571250.5056.52.camel at vespa.frost.loc: +Vitezslav Cizek +2015-11-05:20151105131424.GA32700 at kolac.suse.cz: + Werner Koch (g10 Code GmbH) 2012-12-05:87obi8u4h2.fsf at vigenere.g10code.de: ----------------------------------------------------------------------- Summary of changes: AUTHORS | 3 + cipher/cipher.c | 11 ++ cipher/dsa.c | 160 ++++++++++++++++++------ cipher/ecc-curves.c | 2 +- cipher/ecc.c | 171 +++++++++++++++++++++++++- cipher/kdf.c | 16 ++- cipher/mac.c | 17 +++ cipher/md.c | 11 ++ cipher/md5.c | 2 +- cipher/primegen.c | 55 ++++----- cipher/pubkey-util.c | 36 +++++- cipher/pubkey.c | 11 ++ cipher/rsa.c | 167 +++++++++++++++++-------- src/fips.c | 2 +- src/g10lib.h | 1 + src/global.c | 3 + tests/basic.c | 70 +++++++++-- tests/benchmark.c | 21 ++-- tests/fips186-dsa.c | 11 +- tests/fipsdrv.c | 341 ++++++++++++++++++++++++++++++++++++++++++++++++++- tests/keygen.c | 60 +++++++-- tests/pubkey.c | 72 +++++++++-- 22 files changed, 1068 insertions(+), 175 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From jussi.kivilinna at iki.fi Sun Mar 20 13:54:47 2016 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sun, 20 Mar 2016 14:54:47 +0200 Subject: version 1.7 In-Reply-To: <87vb4kgn02.fsf@wheatstone.g10code.de> References: <20160128170750.23462.38269.stgit@localhost6.localdomain6> <87io2cn41i.fsf@vigenere.g10code.de> <6bakoc-207.ln1@argenau.bebt.de> <87twlgb9uv.fsf@vigenere.g10code.de> <20160212131505.GA1242@argenau.bebt.de> <87vb4kgn02.fsf@wheatstone.g10code.de> Message-ID: <56EE9D97.3090303@iki.fi> On 18.03.2016 11:21, Werner Koch wrote: > On Fri, 12 Feb 2016 14:15, ametzler at bebt.de said: > >> Out of the yet tried builds only one failed, PPC64: > >> selftest for CFB failed - see syslog for details >> pass 0, algo 4, mode 1, gcry_cipher_setkey failed: Selftest failed > >> This is also present in 1.6 where we work around it with >> http://sources.debian.net/src/libgcrypt20/1.6.5-2/debian/patches/20_fedora_libgcrypt-1.6.3-aliasing.patch/ > > which adds > > __attribute__ ((optimize("no-strict-aliasing"))) > > to the inline functions of bufhelp.h. > > > @jussi: I recall that you fixed some alignment problems - might that > problem be related? > Problem here was wrong assumption that unaligned memory accesses can be done on PPC64. This is now solved by disabling unaligned accesses on PowerPC: http://git.gnupg.org/cgi-bin/gitweb.cgi?p=libgcrypt.git;a=commit;h=1da793d089b65ac8c1ead65dacb6b8699f5b6e69 The earlier alignment problems, if I remember right, were clang undefined behaviour sanitizer warnings and fixed with: http://git.gnupg.org/cgi-bin/gitweb.cgi?p=libgcrypt.git;a=commit;h=92fa5f16d69707e302c0f85b2e5e80af8dc037f1 -Jussi > > Shalom-Salam, > > Werner > > From cvs at cvs.gnupg.org Sun Mar 20 14:29:40 2016 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Sun, 20 Mar 2016 14:29:40 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-354-g583919d Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via 583919d70763671ed9feeaa14e1f66379aff88cc (commit) from 897ccd21b7221982806b5c024518f4e989152f14 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 583919d70763671ed9feeaa14e1f66379aff88cc Author: Jussi Kivilinna Date: Sun Mar 20 15:21:40 2016 +0200 Fix ARM NEON support detection on ARMv6 target * configure.ac (gcry_cv_gcc_inline_asm_neon): Use '.arm' directive instead of '.thumb'. -- Fix allows building ARM NEON assembly implementations when compiler target is ARMv6. This enables NEON implementations on ARMv7+NEON CPUs running on ARMv6 OS (for example, Raspbian on Raspberry Pi 2/3). Signed-off-by: Jussi Kivilinna diff --git a/configure.ac b/configure.ac index 8ed8d26..6a2d61b 100644 --- a/configure.ac +++ b/configure.ac @@ -1487,7 +1487,7 @@ AC_CACHE_CHECK([whether GCC inline assembler supports NEON instructions], AC_COMPILE_IFELSE([AC_LANG_SOURCE( [[__asm__( ".syntax unified\n\t" - ".thumb\n\t" + ".arm\n\t" ".fpu neon\n\t" "vld1.64 {%q0-%q1}, [%r0]!;\n\t" "vrev64.8 %q0, %q3;\n\t" ----------------------------------------------------------------------- Summary of changes: configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From peter at lekensteyn.nl Tue Mar 22 11:08:44 2016 From: peter at lekensteyn.nl (Peter Wu) Date: Tue, 22 Mar 2016 11:08:44 +0100 Subject: (Bug) Buffer overrun in gcry_cipher_gettag Message-ID: <20160322100844.GB24506@al> Hi, While working on a Lua binding to libgcrypt[1], I found that some implementations of the gcry_cipher_gettag routine do not properly validate their tag length. Originally found in GCM, it seems that OCB and Poly1305 are also affected. Their code look like this: _gcry_cipher_ocb_get_tag (gcry_cipher_hd_t c, unsigned char *outtag, size_t outtagsize) { if (c->u_mode.ocb.taglen > outtagsize) return GPG_ERR_BUFFER_TOO_SHORT; ... memcpy (outtag, c->u_mode.ocb.tag, c->u_mode.ocb.taglen); ... } That is, a lower bound is checked, but the upper bound is not. Result: memcpy (or memcmp) outside their buffers. Unaffected modes are: - CCM: returns GCRY_ERR_INV_LENGTH - CMAC: returns GCRY_ERR_INV_ARG -- Kind regards, Peter Wu https://lekensteyn.nl [1]: https://github.com/Lekensteyn/luagcrypt From wk at gnupg.org Tue Mar 22 14:16:06 2016 From: wk at gnupg.org (Werner Koch) Date: Tue, 22 Mar 2016 14:16:06 +0100 Subject: (Bug) Buffer overrun in gcry_cipher_gettag In-Reply-To: <20160322100844.GB24506@al> (Peter Wu's message of "Tue, 22 Mar 2016 11:08:44 +0100") References: <20160322100844.GB24506@al> Message-ID: <87lh5a1wmh.fsf@wheatstone.g10code.de> On Tue, 22 Mar 2016 11:08, peter at lekensteyn.nl said: > implementations of the gcry_cipher_gettag routine do not properly > validate their tag length. Please explain. > _gcry_cipher_ocb_get_tag (gcry_cipher_hd_t c, > unsigned char *outtag, size_t outtagsize) > { > if (c->u_mode.ocb.taglen > outtagsize) > return GPG_ERR_BUFFER_TOO_SHORT; > ... > > memcpy (outtag, c->u_mode.ocb.tag, c->u_mode.ocb.taglen); The coment above that function states: /* Copy the already computed tag to OUTTAG. OUTTAGSIZE is the allocated size of OUTTAG; the function returns an error if that is too short to hold the tag. */ This I can't see why there would be a buffer overrun: OUTTAG has been allocated by the caller with a size of OUTTAGSIZE. We check that the tag we want to copy to OUTBUF is less or equal than the buffer allocated for OUTTAG. And then we do the memcpy. Where do you see the problem or what did I miss? Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From cvs at cvs.gnupg.org Tue Mar 22 17:56:08 2016 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Tue, 22 Mar 2016 17:56:08 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-356-gd328095 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via d328095dd4de83b839d9d8c4bdbeec0956971016 (commit) from 5f9b3c2e220ca6d0eaff32324a973ef67933a844 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit d328095dd4de83b839d9d8c4bdbeec0956971016 Author: Werner Koch Date: Tue Mar 22 17:49:50 2016 +0100 tests: Add options --fips to keygen for manual tests. (main): Add option --fips. * tests/keygen.c (check_rsa_keys): Create an 2048 bit key with e=65539 because that is valid in FIPS mode. Check that key generation fails for too short keys in FIPS mode. (check_ecc_keys): Check that key generation fails for Ed25519 keys in FIPS mode. -- This option allows to test the FIPS mode manually for key generation. We should eventually expand all tests to allow testing in FIPS mode in non FIPS enabled boxes. Signed-off-by: Werner Koch diff --git a/tests/keygen.c b/tests/keygen.c index 4bcea20..ebb708b 100644 --- a/tests/keygen.c +++ b/tests/keygen.c @@ -234,23 +234,20 @@ check_rsa_keys (void) } gcry_sexp_release (key); - if (verbose) - show ("creating 1024 bit RSA key with e=65539\n"); + show ("creating 2048 bit RSA key with e=65539\n"); rc = gcry_sexp_new (&keyparm, "(genkey\n" " (rsa\n" - " (nbits 4:1024)\n" + " (nbits 4:2048)\n" " (rsa-use-e 5:65539)\n" " ))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); gcry_sexp_release (keyparm); - if (rc && !in_fips_mode) + if (rc) fail ("error generating RSA key: %s\n", gpg_strerror (rc)); - else if (!rc && in_fips_mode) - fail ("generating RSA key must not work!"); if (!rc) check_generated_rsa_key (key, 65539); @@ -274,6 +271,10 @@ check_rsa_keys (void) else if (!rc && in_fips_mode) fail ("generating 512 bit RSA key must not work!"); + if (verbose && rc && in_fips_mode) + show ("... correctly rejected key creation in FIPS mode (%s)\n", + gpg_strerror (rc)); + if (!rc) check_generated_rsa_key (key, 257); gcry_sexp_release (key); @@ -295,6 +296,11 @@ check_rsa_keys (void) else if (!rc && in_fips_mode) fail ("generating 512 bit RSA key must not work!"); + if (verbose && rc && in_fips_mode) + show ("... correctly rejected key creation in FIPS mode (%s)\n", + gpg_strerror (rc)); + + if (!rc) check_generated_rsa_key (key, 0); /* We don't expect a constant exponent. */ gcry_sexp_release (key); @@ -517,14 +523,23 @@ check_ecc_keys (void) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); gcry_sexp_release (keyparm); - if (rc) + if (rc && !in_fips_mode) die ("error generating ECC key using curve Ed25519 for ECDSA: %s\n", gpg_strerror (rc)); + else if (!rc && in_fips_mode) + fail ("generating Ed25519 key must not work!"); - if (verbose > 1) - show_sexp ("ECC key:\n", key); + if (verbose && rc && in_fips_mode) + show ("... correctly rejected key creation in FIPS mode (%s)\n", + gpg_strerror (rc)); - check_generated_ecc_key (key); + if (!rc) + { + if (verbose > 1) + show_sexp ("ECC key:\n", key); + + check_generated_ecc_key (key); + } gcry_sexp_release (key); if (verbose) @@ -535,10 +550,16 @@ check_ecc_keys (void) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); gcry_sexp_release (keyparm); - if (rc) + if (rc && !in_fips_mode) die ("error generating ECC key using curve Ed25519 for ECDSA" " (nocomp): %s\n", gpg_strerror (rc)); + else if (!rc && in_fips_mode) + fail ("generating Ed25519 key must not work in FIPS mode!"); + + if (verbose && rc && in_fips_mode) + show ("... correctly rejected key creation in FIPS mode (%s)\n", + gpg_strerror (rc)); if (verbose) show ("creating ECC key using curve NIST P-384 for ECDSA\n"); @@ -589,13 +610,23 @@ check_ecc_keys (void) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); gcry_sexp_release (keyparm); - if (rc) + if (rc && !in_fips_mode) die ("error generating ECC key using curve Ed25519 for ECDSA" " (transient-key): %s\n", gpg_strerror (rc)); - if (verbose > 1) - show_sexp ("ECC key:\n", key); - check_generated_ecc_key (key); + else if (!rc && in_fips_mode) + fail ("generating Ed25519 key must not work in FIPS mode!"); + + if (verbose && rc && in_fips_mode) + show ("... correctly rejected key creation in FIPS mode (%s)\n", + gpg_strerror (rc)); + + if (!rc) + { + if (verbose > 1) + show_sexp ("ECC key:\n", key); + check_generated_ecc_key (key); + } gcry_sexp_release (key); if (verbose) @@ -608,13 +639,23 @@ check_ecc_keys (void) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); gcry_sexp_release (keyparm); - if (rc) + if (rc && !in_fips_mode) die ("error generating ECC key using curve Ed25519 for ECDSA" " (transient-key no-keytest): %s\n", gpg_strerror (rc)); - if (verbose > 1) - show_sexp ("ECC key:\n", key); - check_generated_ecc_key (key); + else if (!rc && in_fips_mode) + fail ("generating Ed25519 key must not work in FIPS mode!"); + + if (verbose && rc && in_fips_mode) + show ("... correctly rejected key creation in FIPS mode (%s)\n", + gpg_strerror (rc)); + + if (!rc) + { + if (verbose > 1) + show_sexp ("ECC key:\n", key); + check_generated_ecc_key (key); + } gcry_sexp_release (key); } @@ -682,6 +723,7 @@ usage (int mode) "Options:\n" " --verbose be verbose\n" " --debug flyswatter\n" + " --fips run in FIPS mode\n" " --progress print progress indicators\n", mode? stderr : stdout); if (mode) @@ -692,6 +734,7 @@ int main (int argc, char **argv) { int last_argc = -1; + int opt_fips = 0; int with_progress = 0; if (argc) @@ -721,6 +764,11 @@ main (int argc, char **argv) debug++; argc--; argv++; } + else if (!strcmp (*argv, "--fips")) + { + argc--; argv++; + opt_fips = 1; + } else if (!strcmp (*argv, "--progress")) { argc--; argv++; @@ -732,9 +780,16 @@ main (int argc, char **argv) break; } + gcry_control (GCRYCTL_SET_VERBOSITY, (int)verbose); + if (opt_fips) + gcry_control (GCRYCTL_FORCE_FIPS_MODE, 0); + if (!gcry_check_version (GCRYPT_VERSION)) die ("version mismatch\n"); - gcry_control (GCRYCTL_DISABLE_SECMEM, 0); + + if (!opt_fips) + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); if (debug) gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0); @@ -746,6 +801,9 @@ main (int argc, char **argv) if ( gcry_fips_mode_active () ) in_fips_mode = 1; + if (opt_fips && !in_fips_mode) + die ("failed to switch into FIPS mode\n"); + if (!argc) { check_rsa_keys (); ----------------------------------------------------------------------- Summary of changes: tests/keygen.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 78 insertions(+), 20 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From peter at lekensteyn.nl Tue Mar 22 23:27:26 2016 From: peter at lekensteyn.nl (Peter Wu) Date: Tue, 22 Mar 2016 23:27:26 +0100 Subject: (Bug) Buffer overrun in gcry_cipher_gettag In-Reply-To: <87lh5a1wmh.fsf@wheatstone.g10code.de> References: <20160322100844.GB24506@al> <87lh5a1wmh.fsf@wheatstone.g10code.de> Message-ID: <20160322222726.GA1232@al> On Tue, Mar 22, 2016 at 02:16:06PM +0100, Werner Koch wrote: > On Tue, 22 Mar 2016 11:08, peter at lekensteyn.nl said: > > > implementations of the gcry_cipher_gettag routine do not properly > > validate their tag length. > > Please explain. > > > _gcry_cipher_ocb_get_tag (gcry_cipher_hd_t c, > > unsigned char *outtag, size_t outtagsize) > > { > > if (c->u_mode.ocb.taglen > outtagsize) > > return GPG_ERR_BUFFER_TOO_SHORT; > > ... > > > > memcpy (outtag, c->u_mode.ocb.tag, c->u_mode.ocb.taglen); > > The coment above that function states: > > /* Copy the already computed tag to OUTTAG. OUTTAGSIZE is the > allocated size of OUTTAG; the function returns an error if that is > too short to hold the tag. */ > > This I can't see why there would be a buffer overrun: OUTTAG has been > allocated by the caller with a size of OUTTAGSIZE. We check that the > tag we want to copy to OUTBUF is less or equal than the buffer allocated > for OUTTAG. And then we do the memcpy. Where do you see the problem or > what did I miss? Ah, my bad. OCB happens to be unaffected, I included it because the code is smaller than the GCM case. I originally triggered it with AES-GCM. Please find minimal reproducers in the attached crash.c file. On the current stable (1.6.5) it crashes. On master, the GCM implementation also crashes when setiv/gettag(/authenticate?) is called before setkey is called. Last time I forgot to ask, is there a way to query the valid size for the tag length? (This can then be used to allocate a buffer for the tag without having to know what cipher or mode is in use.) -- Kind regards, Peter Wu https://lekensteyn.nl From peter at lekensteyn.nl Wed Mar 23 03:25:12 2016 From: peter at lekensteyn.nl (Peter Wu) Date: Wed, 23 Mar 2016 03:25:12 +0100 Subject: (Bug) Buffer overrun in gcry_cipher_gettag In-Reply-To: <20160322235908.GQ19540@yoink.cs.uwaterloo.ca> References: <20160322100844.GB24506@al> <87lh5a1wmh.fsf@wheatstone.g10code.de> <20160322222726.GA1232@al> <20160322235908.GQ19540@yoink.cs.uwaterloo.ca> Message-ID: <20160323022512.GA29017@al> On Tue, Mar 22, 2016 at 07:59:08PM -0400, Ian Goldberg wrote: > On Tue, Mar 22, 2016 at 11:27:26PM +0100, Peter Wu wrote: > > Ah, my bad. OCB happens to be unaffected, I included it because the code > > is smaller than the GCM case. I originally triggered it with AES-GCM. > > Please find minimal reproducers in the attached crash.c file. > > You didn't attach anything? Oops, now I do. It also found that the meaning of the tag length is not fixed. For OCB the tag length can be 64, 96 or 128 bits (based on RFC 7253) so the libgcrypt API allows you to specify the maximum buffer size. Current implemented constraints: * CCM: taglen == authlen * cmac (as used by MAC-CMAC): 1 <= taglen <= block_size * GCM: 16 <= taglen (bug!) * OCB: ocb.taglen <= taglen (copy at most ocb.taglen) * Poly1305: 16 <= taglen (bug!) Anything outside this range results in one of the following errors: * GPG_ERR_BUFFER_TOO_SHORT (GCM, OCB, Poly1305) * GPG_ERR_INV_ARG (CCM, CMAC) * GPG_ERR_INV_LENGTH (CCM) I have some patches for the gettag crashes, but maybe it would also be nice to be consistent here and treat the input size solely as a hint for the input buffer size, and return failure if it is too small (instead of too large)? Of course the documentation has to be updated for this. -- Kind regards, Peter Wu https://lekensteyn.nl -------------- next part -------------- A non-text attachment was scrubbed... Name: crash.c Type: text/x-c Size: 1395 bytes Desc: not available URL: From peter at lekensteyn.nl Wed Mar 23 03:45:19 2016 From: peter at lekensteyn.nl (Peter Wu) Date: Wed, 23 Mar 2016 03:45:19 +0100 Subject: [PATCH 0/2] Fixes for gcry_cipher_gettag crashes Message-ID: <1458701121-6794-1-git-send-email-peter@lekensteyn.nl> Hi, As reported earlier[1], some modes can result in a buffer overrun when improperly used. These patches avoid relying on the user-supplied input. Poly1305 was introduced this cycle (1.7.0), but GCM was introduced in 1.6.0. Maybe a backport is appropriate? One crash is not fixed, that is the crash when setkey is not invoked before using the GCM ciphers (introduced in the 1.7.0 cycle). Either these functions should check that the key is present, or they should initialize the ghash table earlier. Affected functions: _gcry_cipher_gcm_encrypt _gcry_cipher_gcm_decrypt _gcry_cipher_gcm_authenticate _gcry_cipher_gcm_initiv (via _gcry_cipher_gcm_setiv) _gcry_cipher_gcm_tag (via _gcry_cipher_gcm_get_tag, _gcry_cipher_gcm_check_tag) Kind regards, Peter [1]: https://lists.gnupg.org/pipermail/gcrypt-devel/2016-March/003753.html Peter Wu (2): Fix buffer overrun in gettag for GCM Fix buffer overrun in gettag for Poly1305 cipher/cipher-gcm.c | 4 ++-- cipher/cipher-poly1305.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) -- 2.7.4 From peter at lekensteyn.nl Wed Mar 23 03:45:20 2016 From: peter at lekensteyn.nl (Peter Wu) Date: Wed, 23 Mar 2016 03:45:20 +0100 Subject: [PATCH 1/2] Fix buffer overrun in gettag for GCM In-Reply-To: <1458701121-6794-1-git-send-email-peter@lekensteyn.nl> References: <1458701121-6794-1-git-send-email-peter@lekensteyn.nl> Message-ID: <1458701121-6794-2-git-send-email-peter@lekensteyn.nl> * cipher/cipher-gcm.c: copy a fixed length instead of the user-supplied number. -- The outbuflen is used to check the minimum size, the real tag is always of fixed length. Signed-off-by: Peter Wu --- cipher/cipher-gcm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c index d390ef8..cb81ea9 100644 --- a/cipher/cipher-gcm.c +++ b/cipher/cipher-gcm.c @@ -803,12 +803,12 @@ _gcry_cipher_gcm_tag (gcry_cipher_hd_t c, if (!check) { - memcpy (outbuf, c->u_mode.gcm.u_tag.tag, outbuflen); + memcpy (outbuf, c->u_mode.gcm.u_tag.tag, GCRY_GCM_BLOCK_LEN); return GPG_ERR_NO_ERROR; } else { - return buf_eq_const(outbuf, c->u_mode.gcm.u_tag.tag, outbuflen) ? + return buf_eq_const(outbuf, c->u_mode.gcm.u_tag.tag, GCRY_GCM_BLOCK_LEN) ? GPG_ERR_NO_ERROR : GPG_ERR_CHECKSUM; } -- 2.7.4 From peter at lekensteyn.nl Wed Mar 23 03:45:21 2016 From: peter at lekensteyn.nl (Peter Wu) Date: Wed, 23 Mar 2016 03:45:21 +0100 Subject: [PATCH 2/2] Fix buffer overrun in gettag for Poly1305 In-Reply-To: <1458701121-6794-1-git-send-email-peter@lekensteyn.nl> References: <1458701121-6794-1-git-send-email-peter@lekensteyn.nl> Message-ID: <1458701121-6794-3-git-send-email-peter@lekensteyn.nl> * cipher/cipher-poly1305.c: copy a fixed length instead of the user-supplied number. -- The outbuflen is used to check the minimum size, the real tag is always of fixed length. Signed-off-by: Peter Wu --- cipher/cipher-poly1305.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cipher/cipher-poly1305.c b/cipher/cipher-poly1305.c index 965a7b6..fb81774 100644 --- a/cipher/cipher-poly1305.c +++ b/cipher/cipher-poly1305.c @@ -215,7 +215,7 @@ _gcry_cipher_poly1305_tag (gcry_cipher_hd_t c, { gcry_err_code_t err; - if (outbuflen < GCRY_GCM_BLOCK_LEN) + if (outbuflen < POLY1305_TAGLEN) return GPG_ERR_BUFFER_TOO_SHORT; if (c->u_mode.poly1305.bytecount_over_limits) return GPG_ERR_INV_LENGTH; @@ -244,10 +244,10 @@ _gcry_cipher_poly1305_tag (gcry_cipher_hd_t c, } if (check) - return buf_eq_const(outbuf, c->u_iv.iv, outbuflen) ? + return buf_eq_const(outbuf, c->u_iv.iv, POLY1305_TAGLEN) ? GPG_ERR_NO_ERROR : GPG_ERR_CHECKSUM; - memcpy (outbuf, c->u_iv.iv, outbuflen); + memcpy (outbuf, c->u_iv.iv, POLY1305_TAGLEN); return GPG_ERR_NO_ERROR; } -- 2.7.4 From cvs at cvs.gnupg.org Wed Mar 23 12:51:59 2016 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Wed, 23 Mar 2016 12:51:59 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-360-g7c9c82f Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via 7c9c82feecf94a455c66d9c38576f36c9c4b484c (commit) via 6821e1bd94969106a70e3de17b86f6e6181f4e59 (commit) via 15785bc9fb1787554bf371945ecb191830c15bfd (commit) via d3d7bdf8215275b3b20690dfde3f43dbe25b6f85 (commit) from d328095dd4de83b839d9d8c4bdbeec0956971016 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 7c9c82feecf94a455c66d9c38576f36c9c4b484c Author: Werner Koch Date: Wed Mar 23 12:47:30 2016 +0100 cipher: Check length of supplied tag in _gcry_cipher_poly1305_check_tag. * cipher/cipher-poly1305.c (_gcry_cipher_poly1305_tag): Check that the provided tag length matches the actual tag length. -- Signed-off-by: Werner Koch diff --git a/cipher/cipher-poly1305.c b/cipher/cipher-poly1305.c index fb81774..a2a74e8 100644 --- a/cipher/cipher-poly1305.c +++ b/cipher/cipher-poly1305.c @@ -243,12 +243,20 @@ _gcry_cipher_poly1305_tag (gcry_cipher_hd_t c, c->marks.tag = 1; } - if (check) - return buf_eq_const(outbuf, c->u_iv.iv, POLY1305_TAGLEN) ? - GPG_ERR_NO_ERROR : GPG_ERR_CHECKSUM; + if (!check) + { + memcpy (outbuf, c->u_iv.iv, POLY1305_TAGLEN); + } + else + { + /* OUTBUFLEN gives the length of the user supplied tag in OUTBUF + * and thus we need to compare its length first. */ + if (outbuflen != POLY1305_TAGLEN + || !buf_eq_const (outbuf, c->u_iv.iv, POLY1305_TAGLEN)) + return GPG_ERR_CHECKSUM; + } - memcpy (outbuf, c->u_iv.iv, POLY1305_TAGLEN); - return GPG_ERR_NO_ERROR; + return 0; } commit 6821e1bd94969106a70e3de17b86f6e6181f4e59 Author: Peter Wu Date: Wed Mar 23 03:45:21 2016 +0100 Fix buffer overrun in gettag for Poly1305 * cipher/cipher-poly1305.c: copy a fixed length instead of the user-supplied number. -- The outbuflen is used to check the minimum size, the real tag is always of fixed length. Signed-off-by: Peter Wu diff --git a/cipher/cipher-poly1305.c b/cipher/cipher-poly1305.c index 965a7b6..fb81774 100644 --- a/cipher/cipher-poly1305.c +++ b/cipher/cipher-poly1305.c @@ -215,7 +215,7 @@ _gcry_cipher_poly1305_tag (gcry_cipher_hd_t c, { gcry_err_code_t err; - if (outbuflen < GCRY_GCM_BLOCK_LEN) + if (outbuflen < POLY1305_TAGLEN) return GPG_ERR_BUFFER_TOO_SHORT; if (c->u_mode.poly1305.bytecount_over_limits) return GPG_ERR_INV_LENGTH; @@ -244,10 +244,10 @@ _gcry_cipher_poly1305_tag (gcry_cipher_hd_t c, } if (check) - return buf_eq_const(outbuf, c->u_iv.iv, outbuflen) ? + return buf_eq_const(outbuf, c->u_iv.iv, POLY1305_TAGLEN) ? GPG_ERR_NO_ERROR : GPG_ERR_CHECKSUM; - memcpy (outbuf, c->u_iv.iv, outbuflen); + memcpy (outbuf, c->u_iv.iv, POLY1305_TAGLEN); return GPG_ERR_NO_ERROR; } commit 15785bc9fb1787554bf371945ecb191830c15bfd Author: Werner Koch Date: Wed Mar 23 11:07:52 2016 +0100 cipher: Check length of supplied tag in _gcry_cipher_gcm_check_tag. * cipher/cipher-gcm.c (_gcry_cipher_gcm_tag): Check that the provided tag length matches the actual tag length. Avoid gratuitous return statements. -- Signed-off-by: Werner Koch diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c index cb81ea9..5e9dec4 100644 --- a/cipher/cipher-gcm.c +++ b/cipher/cipher-gcm.c @@ -803,13 +803,18 @@ _gcry_cipher_gcm_tag (gcry_cipher_hd_t c, if (!check) { + /* NB: We already checked that OUTBUF is large enough to hold + the result. */ memcpy (outbuf, c->u_mode.gcm.u_tag.tag, GCRY_GCM_BLOCK_LEN); - return GPG_ERR_NO_ERROR; } else { - return buf_eq_const(outbuf, c->u_mode.gcm.u_tag.tag, GCRY_GCM_BLOCK_LEN) ? - GPG_ERR_NO_ERROR : GPG_ERR_CHECKSUM; + /* OUTBUFLEN gives the length of the user supplied tag in OUTBUF + * and thus we need to compare its length first. */ + if (outbuflen != GCRY_GCM_BLOCK_LEN + || !buf_eq_const (outbuf, c->u_mode.gcm.u_tag.tag, + GCRY_GCM_BLOCK_LEN)) + return GPG_ERR_CHECKSUM; } return 0; commit d3d7bdf8215275b3b20690dfde3f43dbe25b6f85 Author: Peter Wu Date: Wed Mar 23 03:45:20 2016 +0100 Fix buffer overrun in gettag for GCM * cipher/cipher-gcm.c: copy a fixed length instead of the user-supplied number. -- The outbuflen is used to check the minimum size, the real tag is always of fixed length. Signed-off-by: Peter Wu Actually this is not a buffer overrun because we copy not more than has been allocated for OUTBUF. However a too long OUTBUFLEN accesses data outside of the source buffer. -wk diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c index d390ef8..cb81ea9 100644 --- a/cipher/cipher-gcm.c +++ b/cipher/cipher-gcm.c @@ -803,12 +803,12 @@ _gcry_cipher_gcm_tag (gcry_cipher_hd_t c, if (!check) { - memcpy (outbuf, c->u_mode.gcm.u_tag.tag, outbuflen); + memcpy (outbuf, c->u_mode.gcm.u_tag.tag, GCRY_GCM_BLOCK_LEN); return GPG_ERR_NO_ERROR; } else { - return buf_eq_const(outbuf, c->u_mode.gcm.u_tag.tag, outbuflen) ? + return buf_eq_const(outbuf, c->u_mode.gcm.u_tag.tag, GCRY_GCM_BLOCK_LEN) ? GPG_ERR_NO_ERROR : GPG_ERR_CHECKSUM; } ----------------------------------------------------------------------- Summary of changes: cipher/cipher-gcm.c | 13 +++++++++---- cipher/cipher-poly1305.c | 20 ++++++++++++++------ 2 files changed, 23 insertions(+), 10 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From wk at gnupg.org Wed Mar 23 12:52:36 2016 From: wk at gnupg.org (Werner Koch) Date: Wed, 23 Mar 2016 12:52:36 +0100 Subject: [PATCH 0/2] Fixes for gcry_cipher_gettag crashes In-Reply-To: <1458701121-6794-1-git-send-email-peter@lekensteyn.nl> (Peter Wu's message of "Wed, 23 Mar 2016 03:45:19 +0100") References: <1458701121-6794-1-git-send-email-peter@lekensteyn.nl> Message-ID: <87wpotxvgb.fsf@wheatstone.g10code.de> On Wed, 23 Mar 2016 03:45, peter at lekensteyn.nl said: > Poly1305 was introduced this cycle (1.7.0), but GCM was introduced in 1.6.0. > Maybe a backport is appropriate? Definitely. I'll do that soon. > Peter Wu (2): > Fix buffer overrun in gettag for GCM > Fix buffer overrun in gettag for Poly1305 I applied them but also added this additional fix: --8<---------------cut here---------------start------------->8--- cipher: Check length of supplied tag in _gcry_cipher_gcm_check_tag. * cipher/cipher-gcm.c (_gcry_cipher_gcm_tag): Check that the provided tag length matches the actual tag length. Avoid gratuitous return statements. -- Signed-off-by: Werner Koch Modified cipher/cipher-gcm.c diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c index cb81ea9..5e9dec4 100644 --- a/cipher/cipher-gcm.c +++ b/cipher/cipher-gcm.c @@ -803,13 +803,18 @@ _gcry_cipher_gcm_tag (gcry_cipher_hd_t c, if (!check) { + /* NB: We already checked that OUTBUF is large enough to hold + the result. */ memcpy (outbuf, c->u_mode.gcm.u_tag.tag, GCRY_GCM_BLOCK_LEN); - return GPG_ERR_NO_ERROR; } else { - return buf_eq_const(outbuf, c->u_mode.gcm.u_tag.tag, GCRY_GCM_BLOCK_LEN) ? - GPG_ERR_NO_ERROR : GPG_ERR_CHECKSUM; + /* OUTBUFLEN gives the length of the user supplied tag in OUTBUF + * and thus we need to compare its length first. */ + if (outbuflen != GCRY_GCM_BLOCK_LEN + || !buf_eq_const (outbuf, c->u_mode.gcm.u_tag.tag, + GCRY_GCM_BLOCK_LEN)) + return GPG_ERR_CHECKSUM; } --8<---------------cut here---------------end--------------->8--- The same goes for poly1305. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From cvs at cvs.gnupg.org Wed Mar 23 14:16:56 2016 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Wed, 23 Mar 2016 14:16:56 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-361-ge709d86 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via e709d86fe596a4bcf235799468947c13ae657d78 (commit) from 7c9c82feecf94a455c66d9c38576f36c9c4b484c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit e709d86fe596a4bcf235799468947c13ae657d78 Author: Werner Koch Date: Wed Mar 23 14:13:18 2016 +0100 cipher: Avoid NULL-segv in GCM mode if a key has not been set. * cipher/cipher-gcm.c (_gcry_cipher_gcm_encrypt): Check that GHASH_FN has been initialized. (_gcry_cipher_gcm_decrypt): Ditto. (_gcry_cipher_gcm_authenticate): Ditto. (_gcry_cipher_gcm_initiv): Ditto. (_gcry_cipher_gcm_tag): Ditto. -- Avoid a crash if certain functions are used before setkey. Reported-by: Peter Wu One crash is not fixed, that is the crash when setkey is not invoked before using the GCM ciphers (introduced in the 1.7.0 cycle). Either these functions should check that the key is present, or they should initialize the ghash table earlier. Affected functions: _gcry_cipher_gcm_encrypt _gcry_cipher_gcm_decrypt _gcry_cipher_gcm_authenticate _gcry_cipher_gcm_initiv (via _gcry_cipher_gcm_setiv) _gcry_cipher_gcm_tag (via _gcry_cipher_gcm_get_tag, _gcry_cipher_gcm_check_tag) Regression-due-to: 4a0795af021305f9240f23626a3796157db46bd7 Signed-off-by: Werner Koch diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c index 5e9dec4..712641e 100644 --- a/cipher/cipher-gcm.c +++ b/cipher/cipher-gcm.c @@ -535,7 +535,9 @@ _gcry_cipher_gcm_encrypt (gcry_cipher_hd_t c, return GPG_ERR_BUFFER_TOO_SHORT; if (c->u_mode.gcm.datalen_over_limits) return GPG_ERR_INV_LENGTH; - if (c->marks.tag || c->u_mode.gcm.ghash_data_finalized) + if (c->marks.tag + || c->u_mode.gcm.ghash_data_finalized + || !c->u_mode.gcm.ghash_fn) return GPG_ERR_INV_STATE; if (!c->marks.iv) @@ -581,7 +583,9 @@ _gcry_cipher_gcm_decrypt (gcry_cipher_hd_t c, return GPG_ERR_BUFFER_TOO_SHORT; if (c->u_mode.gcm.datalen_over_limits) return GPG_ERR_INV_LENGTH; - if (c->marks.tag || c->u_mode.gcm.ghash_data_finalized) + if (c->marks.tag + || c->u_mode.gcm.ghash_data_finalized + || !c->u_mode.gcm.ghash_fn) return GPG_ERR_INV_STATE; if (!c->marks.iv) @@ -617,8 +621,10 @@ _gcry_cipher_gcm_authenticate (gcry_cipher_hd_t c, return GPG_ERR_CIPHER_ALGO; if (c->u_mode.gcm.datalen_over_limits) return GPG_ERR_INV_LENGTH; - if (c->marks.tag || c->u_mode.gcm.ghash_aad_finalized || - c->u_mode.gcm.ghash_data_finalized) + if (c->marks.tag + || c->u_mode.gcm.ghash_aad_finalized + || c->u_mode.gcm.ghash_data_finalized + || !c->u_mode.gcm.ghash_fn) return GPG_ERR_INV_STATE; if (!c->marks.iv) @@ -666,6 +672,9 @@ _gcry_cipher_gcm_initiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen) u32 iv_bytes[2] = {0, 0}; u32 bitlengths[2][2]; + if (!c->u_mode.gcm.ghash_fn) + return GPG_ERR_INV_STATE; + memset(c->u_ctr.ctr, 0, GCRY_GCM_BLOCK_LEN); gcm_bytecounter_add(iv_bytes, ivlen); @@ -773,6 +782,9 @@ _gcry_cipher_gcm_tag (gcry_cipher_hd_t c, { u32 bitlengths[2][2]; + if (!c->u_mode.gcm.ghash_fn) + return GPG_ERR_INV_STATE; + /* aad length */ bitlengths[0][1] = be_bswap32(c->u_mode.gcm.aadlen[0] << 3); bitlengths[0][0] = be_bswap32((c->u_mode.gcm.aadlen[0] >> 29) | ----------------------------------------------------------------------- Summary of changes: cipher/cipher-gcm.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From wk at gnupg.org Wed Mar 23 14:18:14 2016 From: wk at gnupg.org (Werner Koch) Date: Wed, 23 Mar 2016 14:18:14 +0100 Subject: [PATCH 0/2] Fixes for gcry_cipher_gettag crashes In-Reply-To: <1458701121-6794-1-git-send-email-peter@lekensteyn.nl> (Peter Wu's message of "Wed, 23 Mar 2016 03:45:19 +0100") References: <1458701121-6794-1-git-send-email-peter@lekensteyn.nl> Message-ID: <87lh59xrhl.fsf@wheatstone.g10code.de> On Wed, 23 Mar 2016 03:45, peter at lekensteyn.nl said: > One crash is not fixed, that is the crash when setkey is not invoked before > using the GCM ciphers (introduced in the 1.7.0 cycle). Either these functions > should check that the key is present, or they should initialize the Thanks for reporting. Fixed with commit e709d86. This was a regression due to 4a0795af021305f9240f23626a3796157db46bd7 and needs to backport to 1.6. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From cvs at cvs.gnupg.org Wed Mar 23 15:26:52 2016 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Wed, 23 Mar 2016 15:26:52 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-362-gfea5971 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via fea5971488e049f902d7912df22a945bc755ad6d (commit) from e709d86fe596a4bcf235799468947c13ae657d78 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit fea5971488e049f902d7912df22a945bc755ad6d Author: Werner Koch Date: Wed Mar 23 15:24:40 2016 +0100 Add new control GCRYCTL_GET_TAGLEN for use with gcry_cipher_info. * src/gcrypt.h.in (GCRYCTL_GET_TAGLEN): New. * cipher/cipher.c (_gcry_cipher_info): Add GCRYCTL_GET_TAGLEN feature. * tests/basic.c (_check_gcm_cipher): Check that new feature. (_check_poly1305_cipher): Ditto. (check_ccm_cipher): Ditto. (do_check_ocb_cipher): Ditto. (check_ctr_cipher): Add negative test for new feature. -- Signed-off-by: Werner Koch diff --git a/NEWS b/NEWS index 0064bbe..9cb5e36 100644 --- a/NEWS +++ b/NEWS @@ -69,6 +69,7 @@ Noteworthy changes in version 1.7.0 (unreleased) GCRY_CIPHER_MODE_POLY1305 NEW. GCRY_CIPHER_MODE_OCB NEW. GCRYCTL_SET_TAGLEN NEW. + GCRYCTL_GET_TAGLEN NEW. gcry_cipher_final NEW macro. GCRY_PK_EDDSA NEW constant. diff --git a/cipher/cipher.c b/cipher/cipher.c index 3a8597f..bdcbfbd 100644 --- a/cipher/cipher.c +++ b/cipher/cipher.c @@ -1361,24 +1361,55 @@ _gcry_cipher_ctl (gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen) /* Return information about the cipher handle H. CMD is the kind of - information requested. BUFFER and NBYTES are reserved for now. - - There are no values for CMD yet defined. - - The function always returns GPG_ERR_INV_OP. - + * information requested. + * + * CMD may be one of: + * + * GCRYCTL_GET_TAGLEN: + * Return the length of the tag for an AE algorithm mode. An + * error is returned for modes which do not support a tag. + * BUFFER must be given as NULL. On success the result is stored + * at NBYTES. The taglen is returned in bytes. + * + * The function returns 0 on success or an error code. */ gcry_err_code_t _gcry_cipher_info (gcry_cipher_hd_t h, int cmd, void *buffer, size_t *nbytes) { gcry_err_code_t rc = 0; - (void)h; - (void)buffer; - (void)nbytes; - switch (cmd) { + case GCRYCTL_GET_TAGLEN: + if (!h || buffer || !nbytes) + rc = GPG_ERR_INV_ARG; + else + { + switch (h->mode) + { + case GCRY_CIPHER_MODE_OCB: + *nbytes = h->u_mode.ocb.taglen; + break; + + case GCRY_CIPHER_MODE_CCM: + *nbytes = h->u_mode.ccm.authlen; + break; + + case GCRY_CIPHER_MODE_GCM: + *nbytes = GCRY_GCM_BLOCK_LEN; + break; + + case GCRY_CIPHER_MODE_POLY1305: + *nbytes = POLY1305_TAGLEN; + break; + + default: + rc = GPG_ERR_INV_CIPHER_MODE; + break; + } + } + break; + default: rc = GPG_ERR_INV_OP; } diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index 3265a70..8451627 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -1900,12 +1900,24 @@ handle @var{h}. Please see the comments in the source code (@code{src/global.c}) for details. @end deftypefun - at deftypefun gcry_error_t gcry_cipher_info (gcry_cipher_hd_t @var{h}, int @var{what}, void *@var{buffer}, size_t *@var{nbytes}) + at deftypefun gcry_error_t gcry_cipher_info (gcry_cipher_hd_t @var{h}, @ + int @var{what}, void *@var{buffer}, size_t *@var{nbytes}) @code{gcry_cipher_info} is used to retrieve various information about a cipher context or the cipher module in general. -Currently no information is available. + at c begin constants for gcry_cipher_info + at table @code + + at item GCRYCTL_GET_TAGLEN: +Return the length of the tag for an AE algorithm mode. An error is +returned for modes which do not support a tag. @var{buffer} must be +given as NULL. On success the result is stored @var{nbytes}. The +taglen is returned in bytes. + + at end table + at c end constants for gcry_cipher_info + @end deftypefun @node General cipher functions diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index 797da2e..c269621 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -332,7 +332,8 @@ enum gcry_ctl_cmds GCRYCTL_REACTIVATE_FIPS_FLAG = 72, GCRYCTL_SET_SBOX = 73, GCRYCTL_DRBG_REINIT = 74, - GCRYCTL_SET_TAGLEN = 75 + GCRYCTL_SET_TAGLEN = 75, + GCRYCTL_GET_TAGLEN = 76 }; /* Perform various operations defined by CMD. */ @@ -986,7 +987,7 @@ enum gcry_cipher_flags gcry_error_t gcry_cipher_open (gcry_cipher_hd_t *handle, int algo, int mode, unsigned int flags); -/* Close the cioher handle H and release all resource. */ +/* Close the cipher handle H and release all resource. */ void gcry_cipher_close (gcry_cipher_hd_t h); /* Perform various operations on the cipher object H. */ diff --git a/tests/basic.c b/tests/basic.c index c633ae9..36a83d0 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -690,6 +690,7 @@ check_ctr_cipher (void) unsigned char out[MAX_DATA_LEN]; int i, j, keylen, blklen; gcry_error_t err = 0; + size_t taglen2; if (verbose) fprintf (stderr, " Starting CTR cipher checks.\n"); @@ -753,6 +754,17 @@ check_ctr_cipher (void) return; } + + err = gcry_cipher_info (hde, GCRYCTL_GET_TAGLEN, NULL, &taglen2); + if (gpg_err_code (err) != GPG_ERR_INV_CIPHER_MODE) + { + fail ("aes-ctr, gcryctl_get_taglen failed to fail (tv %d): %s\n", + i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + if (verbose) fprintf (stderr, " checking CTR mode for %s [%i]\n", gcry_cipher_algo_name (tv[i].algo), @@ -1418,7 +1430,7 @@ _check_gcm_cipher (unsigned int step) unsigned char tag[GCRY_GCM_BLOCK_LEN]; int i, keylen; gcry_error_t err = 0; - size_t pos, poslen; + size_t pos, poslen, taglen2; int byteNum; if (verbose) @@ -1478,6 +1490,25 @@ _check_gcm_cipher (unsigned int step) return; } + err = gcry_cipher_info (hde, GCRYCTL_GET_TAGLEN, NULL, &taglen2); + if (err) + { + fail ("cipher-gcm, gcryctl_get_taglen failed (tv %d): %s\n", + i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + if (taglen2 != GCRY_GCM_BLOCK_LEN) + { + fail ("cipher-gcm, gcryctl_get_taglen returned bad length" + " (tv %d): got=%zu want=%d\n", + i, taglen2, GCRY_GCM_BLOCK_LEN); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + for (pos = 0; pos < tv[i].aadlen; pos += step) { poslen = (pos + step < tv[i].aadlen) ? step : tv[i].aadlen - pos; @@ -1772,7 +1803,7 @@ _check_poly1305_cipher (unsigned int step) unsigned char tag[16]; int i, keylen; gcry_error_t err = 0; - size_t pos, poslen; + size_t pos, poslen, taglen2; int byteNum; if (verbose) @@ -1824,6 +1855,25 @@ _check_poly1305_cipher (unsigned int step) return; } + err = gcry_cipher_info (hde, GCRYCTL_GET_TAGLEN, NULL, &taglen2); + if (err) + { + fail ("cipher-poly1305, gcryctl_get_taglen failed (tv %d): %s\n", + i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + if (taglen2 != 16) + { + fail ("cipher-poly1305, gcryctl_get_taglen returned bad length" + " (tv %d): got=%zu want=%d\n", + i, taglen2, 16); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + for (pos = 0; pos < tv[i].aadlen; pos += step) { poslen = (pos + step < tv[i].aadlen) ? step : tv[i].aadlen - pos; @@ -2446,7 +2496,7 @@ check_ccm_cipher (void) unsigned char out[MAX_DATA_LEN]; u64 ctl_params[3]; int split, aadsplit; - size_t j, i, keylen, blklen, authlen; + size_t j, i, keylen, blklen, authlen, taglen2; gcry_error_t err = 0; if (verbose) @@ -2539,6 +2589,25 @@ check_ccm_cipher (void) return; } + err = gcry_cipher_info (hde, GCRYCTL_GET_TAGLEN, NULL, &taglen2); + if (err) + { + fail ("cipher-ccm, gcryctl_get_taglen failed (tv %d): %s\n", + i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + if (taglen2 != authlen) + { + fail ("cipher-ccm, gcryctl_get_taglen returned bad length" + " (tv %d): got=%zu want=%zu\n", + i, taglen2, authlen); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + aadsplit = split > tv[i].aadlen ? 0 : split; err = gcry_cipher_authenticate (hde, tv[i].aad, @@ -2973,6 +3042,7 @@ do_check_ocb_cipher (int inplace) char *key, *nonce, *aad, *ciph, *plain; size_t keylen, noncelen, aadlen, ciphlen, plainlen; int taglen; + size_t taglen2; if (verbose) fprintf (stderr, " checking OCB mode for %s [%i] (tv %d)\n", @@ -3030,6 +3100,25 @@ do_check_ocb_cipher (int inplace) return; } + err = gcry_cipher_info (hde, GCRYCTL_GET_TAGLEN, NULL, &taglen2); + if (err) + { + fail ("cipher-ocb, gcryctl_get_taglen failed (tv %d): %s\n", + tidx, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + if (taglen2 != tv[tidx].taglen) + { + fail ("cipher-ocb, gcryctl_get_taglen returned bad length (tv %d): " + "got=%zu want=%d\n", + tidx, taglen2, tv[tidx].taglen); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + err = gcry_cipher_setkey (hde, key, keylen); if (!err) err = gcry_cipher_setkey (hdd, key, keylen); ----------------------------------------------------------------------- Summary of changes: NEWS | 1 + cipher/cipher.c | 51 +++++++++++++++++++++++++------ doc/gcrypt.texi | 16 ++++++++-- src/gcrypt.h.in | 5 +-- tests/basic.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 151 insertions(+), 17 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From wk at gnupg.org Wed Mar 23 15:31:28 2016 From: wk at gnupg.org (Werner Koch) Date: Wed, 23 Mar 2016 15:31:28 +0100 Subject: (Bug) Buffer overrun in gcry_cipher_gettag In-Reply-To: <20160322222726.GA1232@al> (Peter Wu's message of "Tue, 22 Mar 2016 23:27:26 +0100") References: <20160322100844.GB24506@al> <87lh5a1wmh.fsf@wheatstone.g10code.de> <20160322222726.GA1232@al> Message-ID: <87egb1xo3j.fsf@wheatstone.g10code.de> On Tue, 22 Mar 2016 23:27, peter at lekensteyn.nl said: > Last time I forgot to ask, is there a way to query the valid size for > the tag length? (This can then be used to allocate a buffer for the tag There is one _now_. Commit fea5971. Thanks for the suggestion. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From peter at lekensteyn.nl Wed Mar 23 18:21:53 2016 From: peter at lekensteyn.nl (Peter Wu) Date: Wed, 23 Mar 2016 18:21:53 +0100 Subject: [PATCH] Fix memleaks in (self)tests. Message-ID: <1458753713-31165-1-git-send-email-peter@lekensteyn.nl> * cipher/dsa.c: release memory for MPI and sexp structures. * cipher/ecc.c: release memory for sexp structure. * tests/keygen.c: Likewise. -- These leaks broke the mpitests, basic and keygen tests when running under AddressSanitizer. Signed-off-by: Peter Wu --- cipher/dsa.c | 7 +++++++ cipher/ecc.c | 1 + tests/keygen.c | 3 +++ 3 files changed, 11 insertions(+) diff --git a/cipher/dsa.c b/cipher/dsa.c index 909a8ca..40fdcfe 100644 --- a/cipher/dsa.c +++ b/cipher/dsa.c @@ -1254,6 +1254,7 @@ selftest_sign (gcry_sexp_t pkey, gcry_sexp_t skey) calculated_r = _gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); if (!calculated_r) goto leave; + sexp_release (l2); l2 = _gcry_sexp_find_token (l1, "s", 0); if (!l2) @@ -1289,6 +1290,12 @@ selftest_sign (gcry_sexp_t pkey, gcry_sexp_t skey) leave: + _gcry_mpi_release (calculated_s); + _gcry_mpi_release (calculated_r); + _gcry_mpi_release (s); + _gcry_mpi_release (r); + sexp_release (l2); + sexp_release (l1); sexp_release (sig); sexp_release (data_bad); sexp_release (data); diff --git a/cipher/ecc.c b/cipher/ecc.c index 5b03530..f233f78 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -2045,6 +2045,7 @@ selftest_sign (gcry_sexp_t pkey, gcry_sexp_t skey) calculated_r = _gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); if (!calculated_r) goto leave; + sexp_release (l2); l2 = _gcry_sexp_find_token (l1, "s", 0); if (!l2) diff --git a/tests/keygen.c b/tests/keygen.c index ebb708b..a6795bb 100644 --- a/tests/keygen.c +++ b/tests/keygen.c @@ -219,6 +219,8 @@ check_rsa_keys (void) " ))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gpg_strerror (rc)); + gcry_sexp_release (key); + rc = gcry_pk_genkey (&key, keyparm); gcry_sexp_release (keyparm); if (rc && !in_fips_mode) @@ -560,6 +562,7 @@ check_ecc_keys (void) if (verbose && rc && in_fips_mode) show ("... correctly rejected key creation in FIPS mode (%s)\n", gpg_strerror (rc)); + gcry_sexp_release (key); if (verbose) show ("creating ECC key using curve NIST P-384 for ECDSA\n"); -- 2.7.4 From peter at lekensteyn.nl Thu Mar 24 00:29:36 2016 From: peter at lekensteyn.nl (Peter Wu) Date: Thu, 24 Mar 2016 00:29:36 +0100 Subject: [PATCH] Avoid undefined behavior for hashes using XOF Message-ID: <1458775776-15785-1-git-send-email-peter@lekensteyn.nl> cipher/md.c: skip memcpy for hashes without a fixed length. -- Caught by UndefinedBehaviorSanitizer wjile running tests/benchmarks. While the functions could simply shortcircuit and return early, let's perform the hash calculations anyway such that the benchmarks can be run. Copying zero bytes is valid according to the documentation of gcry_md_hash_buffer{,s} as gcry_md_get_algo_dlen() returns 0. Signed-off-by: Peter Wu --- Given the variable length output of XOFs like SHAKE128 and SHAKE256, I doubt that these convenience functions are useful. Let's prevent the undefined behavior at least. --- cipher/md.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cipher/md.c b/cipher/md.c index 0414dcb..5982b8f 100644 --- a/cipher/md.c +++ b/cipher/md.c @@ -972,7 +972,8 @@ _gcry_md_hash_buffer (int algo, void *digest, algo, gpg_strerror (gcry_error(err))); md_write (h, (byte *) buffer, length); md_final (h); - memcpy (digest, md_read (h, algo), md_digest_length (algo)); + if (md_digest_length (algo)) + memcpy (digest, md_read (h, algo), md_digest_length (algo)); md_close (h); } } @@ -1046,7 +1047,8 @@ _gcry_md_hash_buffers (int algo, unsigned int flags, void *digest, for (;iovcnt; iov++, iovcnt--) md_write (h, (const char*)iov[0].data + iov[0].off, iov[0].len); md_final (h); - memcpy (digest, md_read (h, algo), md_digest_length (algo)); + if (md_digest_length (algo)) + memcpy (digest, md_read (h, algo), md_digest_length (algo)); md_close (h); } -- 2.7.4 From peter at lekensteyn.nl Thu Mar 24 11:06:23 2016 From: peter at lekensteyn.nl (Peter Wu) Date: Thu, 24 Mar 2016 11:06:23 +0100 Subject: [PATCH] Mark constant MPIs as non-leaked Message-ID: <1458813983-17324-1-git-send-email-peter@lekensteyn.nl> * mpi/mpiutil.c: Mark "constant" MPIs as explicitly leaked. -- Requires libgpg-error 1.22 (unreleased) for the macros, but since it is a minor debugging aid, do not bump the minimum required version. Signed-off-by: Peter Wu --- Hi, Thanks Werner for the quick the libgpg-error feedback (merged). Minor observation about the libgpg-error NEWS file, it should say "Interface changes relative to the 1.21 release" instead of "1.20". After this and two other (proposed) patches ("Fix memleaks in (self)tests." and "Avoid undefined behavior for hashes using XOF"), the only UBSan report (for make check) that remains to be fixed is https://bugs.gnupg.org/gnupg/issue2292. Kind regards, Peter --- mpi/mpiutil.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mpi/mpiutil.c b/mpi/mpiutil.c index 99402b8..6dee0b9 100644 --- a/mpi/mpiutil.c +++ b/mpi/mpiutil.c @@ -211,7 +211,12 @@ _gcry_mpi_free( gcry_mpi_t a ) if (!a ) return; if ((a->flags & 32)) + { +#if GPGRT_VERSION_NUMBER >= 0x011600 /* 1.22 */ + gpgrt_annotate_leaked_object(a); +#endif return; /* Never release a constant. */ + } if ((a->flags & 4)) xfree( a->d ); else -- 2.7.4 From wk at gnupg.org Thu Mar 24 11:25:04 2016 From: wk at gnupg.org (Werner Koch) Date: Thu, 24 Mar 2016 11:25:04 +0100 Subject: [PATCH] Avoid undefined behavior for hashes using XOF In-Reply-To: <1458775776-15785-1-git-send-email-peter@lekensteyn.nl> (Peter Wu's message of "Thu, 24 Mar 2016 00:29:36 +0100") References: <1458775776-15785-1-git-send-email-peter@lekensteyn.nl> Message-ID: <87twjwtbpb.fsf@wheatstone.g10code.de> On Thu, 24 Mar 2016 00:29, peter at lekensteyn.nl said: > While the functions could simply shortcircuit and return early, let's > perform the hash calculations anyway such that the benchmarks can be > run. Copying zero bytes is valid according to the documentation of > gcry_md_hash_buffer{,s} as gcry_md_get_algo_dlen() returns 0. Your code is now: if (md_digest_length (algo)) memcpy (digest, md_read (h, algo), md_digest_length (algo)); By adding the condition you avoid calling md_read which would return NULL in the case of SHAKE128. So the UB seems to be that memcpy (foo, NULL, 0) is not defined - impractical but obviously another gcc/clang annoyance. I would suggest not to test for md_digest_length but to const void *tmp = md_read (h, algo); if (tmp) memcpy (digest, tmp, md_digest_length (algo)); which uses the real cause for the condition. _gcry_md_hash_buffers should however return an error and not silently ignore it. Even if that means to adjust the tests ;-) Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Thu Mar 24 12:52:23 2016 From: wk at gnupg.org (Werner Koch) Date: Thu, 24 Mar 2016 12:52:23 +0100 Subject: [PATCH] Mark constant MPIs as non-leaked In-Reply-To: <1458813983-17324-1-git-send-email-peter@lekensteyn.nl> (Peter Wu's message of "Thu, 24 Mar 2016 11:06:23 +0100") References: <1458813983-17324-1-git-send-email-peter@lekensteyn.nl> Message-ID: <87io0ct7ns.fsf@wheatstone.g10code.de> On Thu, 24 Mar 2016 11:06, peter at lekensteyn.nl said: > * mpi/mpiutil.c: Mark "constant" MPIs as explicitly leaked. Thanks. > Thanks Werner for the quick the libgpg-error feedback (merged). Minor > observation about the libgpg-error NEWS file, it should say "Interface changes > relative to the 1.21 release" instead of "1.20". I fix those things for the release. >> After this and two other (proposed) patches ("Fix memleaks in (self)tests." and > "Avoid undefined behavior for hashes using XOF"), the only UBSan report (for > make check) that remains to be fixed is > https://bugs.gnupg.org/gnupg/issue2292 I'll look at them toon. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From peter at lekensteyn.nl Thu Mar 24 13:01:54 2016 From: peter at lekensteyn.nl (Peter Wu) Date: Thu, 24 Mar 2016 13:01:54 +0100 Subject: [PATCH] Avoid undefined behavior for hashes using XOF In-Reply-To: <87twjwtbpb.fsf@wheatstone.g10code.de> References: <1458775776-15785-1-git-send-email-peter@lekensteyn.nl> <87twjwtbpb.fsf@wheatstone.g10code.de> Message-ID: <20160324120154.GA17055@al> On Thu, Mar 24, 2016 at 11:25:04AM +0100, Werner Koch wrote: > On Thu, 24 Mar 2016 00:29, peter at lekensteyn.nl said: > > > While the functions could simply shortcircuit and return early, let's > > perform the hash calculations anyway such that the benchmarks can be > > run. Copying zero bytes is valid according to the documentation of > > gcry_md_hash_buffer{,s} as gcry_md_get_algo_dlen() returns 0. > > Your code is now: > > if (md_digest_length (algo)) > memcpy (digest, md_read (h, algo), md_digest_length (algo)); > > By adding the condition you avoid calling md_read which would return > NULL in the case of SHAKE128. So the UB seems to be that memcpy (foo, > NULL, 0) is not defined - impractical but obviously another gcc/clang > annoyance. > > I would suggest not to test for md_digest_length but to > > const void *tmp = md_read (h, algo); > if (tmp) > memcpy (digest, tmp, md_digest_length (algo)); > > which uses the real cause for the condition. The UB warning comes from the md_read() function returning NULL, but that only happens because SHAKE128 has no read function for outputting a fixed hash length. I think that md_digest_length() is still more suitable here, the message is not "avoid memcpy on a NULL source", but "avoid a memcpy if there is nothing to copy". The former might hide hypothetical errors where the length is non-zero, but md_read returns NULL for some reason. > _gcry_md_hash_buffers should however return an error and not silently > ignore it. Even if that means to adjust the tests ;-) Failing with an error indeed seems a better hint for the user, I will fix that for the next patch. The benchmark is not quite accurate anyway for XOFs, what about skipping tests for such functions? -- Kind regards, Peter Wu https://lekensteyn.nl From peter at lekensteyn.nl Thu Mar 24 13:38:06 2016 From: peter at lekensteyn.nl (Peter Wu) Date: Thu, 24 Mar 2016 13:38:06 +0100 Subject: [PATCH v2] Disallow XOF algorithms for gcry_md_hash_buffers In-Reply-To: <20160324120154.GA17055@al> References: <20160324120154.GA17055@al> Message-ID: <1458823086-25226-1-git-send-email-peter@lekensteyn.nl> * cipher/md.c (_gcry_md_hash_buffer): Skip calculation for XOFs. (_gcry_md_hash_buffers): Fail when XOFs are selected. * doc/gcrypt.texi: Explicitly document above behavior for XOFs. * tests/benchmark.c: Skip benchmarking hash functions without a fixed output length. -- Caught by UndefinedBehaviorSanitizer while running tests/benchmarks where gcry_md_hash_buffer(GCRY_MD_SHAKE128) would result in memcpy(digest, NULL, 0). Signed-off-by: Peter Wu --- v2: just shortcircuit in gcry_md_hash_buffer for XOFs and reject the algo in gcry_md_hash_buffers. Adjust documentation and tests accordingly. tests/benchmarks md SHAKE128 now shows "0ms" for the last column, but at least the UB warning is gone. --- cipher/md.c | 5 +++++ doc/gcrypt.texi | 4 +++- tests/benchmark.c | 2 ++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/cipher/md.c b/cipher/md.c index 0414dcb..d1d0812 100644 --- a/cipher/md.c +++ b/cipher/md.c @@ -948,6 +948,8 @@ _gcry_md_hash_buffer (int algo, void *digest, _gcry_sha1_hash_buffer (digest, buffer, length); else if (algo == GCRY_MD_RMD160 && !fips_mode () ) _gcry_rmd160_hash_buffer (digest, buffer, length); + else if (md_digest_length (algo) == 0) + ; /* Nothing to do for hashes without a fixed output length. */ else { /* For the others we do not have a fast function, so we use the @@ -1007,6 +1009,9 @@ _gcry_md_hash_buffers (int algo, unsigned int flags, void *digest, if (hmac && iovcnt < 1) return GPG_ERR_INV_ARG; + if (md_digest_length (algo) == 0) + return GPG_ERR_INV_ARG; + if (algo == GCRY_MD_SHA1 && !hmac) _gcry_sha1_hash_buffers (digest, iov, iovcnt); else diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index 3265a70..9481be9 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -3378,6 +3378,7 @@ described by @var{iov} and @var{iovcnt}. @var{digest} must be allocated by the caller, large enough to hold the message digest yielded by the the specified algorithm @var{algo}. This required size may be obtained by using the function @code{gcry_md_get_algo_dlen}. +This function cannot be used for extendable-output functions. @var{iov} is an array of buffer descriptions with @var{iovcnt} items. The caller should zero out the structures in this array and for each @@ -3402,7 +3403,8 @@ immediately returns the message digest of the @var{length} bytes at @var{buffer}. @var{digest} must be allocated by the caller, large enough to hold the message digest yielded by the the specified algorithm @var{algo}. This required size may be obtained by using the function - at code{gcry_md_get_algo_dlen}. + at code{gcry_md_get_algo_dlen}. This function has no effect for +extendable-output functions. Note that in contrast to @code{gcry_md_hash_buffers} this function will abort the process if an unavailable algorithm is used. diff --git a/tests/benchmark.c b/tests/benchmark.c index 53b83b1..5f94cc8 100644 --- a/tests/benchmark.c +++ b/tests/benchmark.c @@ -499,6 +499,8 @@ md_bench ( const char *algoname ) for (i=1; i < 400; i++) if (in_fips_mode && i == GCRY_MD_MD5) ; /* Don't use MD5 in fips mode. */ + else if (gcry_md_get_algo_dlen (i) == 0) + ; /* Skip hash functions without a fixed output length. */ else if ( !gcry_md_test_algo (i) ) md_bench (gcry_md_algo_name (i)); return; -- 2.7.4 From peter at lekensteyn.nl Thu Mar 24 14:04:27 2016 From: peter at lekensteyn.nl (Peter Wu) Date: Thu, 24 Mar 2016 14:04:27 +0100 Subject: [PATCH v2] Mark constant MPIs as non-leaked In-Reply-To: <1458813983-17324-1-git-send-email-peter@lekensteyn.nl> References: <1458813983-17324-1-git-send-email-peter@lekensteyn.nl> Message-ID: <1458824667-2305-1-git-send-email-peter@lekensteyn.nl> * mpi/mpiutil.c: Mark "constant" MPIs as explicitly leaked. -- Requires libgpg-error 1.22 (unreleased) for the macros, but since it is a minor debugging aid, do not bump the minimum required version. Signed-off-by: Peter Wu --- v2: mark as non-leaked when the const flag is set, not just on the free path. This avoids a warning on constants from _gcry_mpi_init. --- mpi/mpiutil.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/mpi/mpiutil.c b/mpi/mpiutil.c index 99402b8..142c74e 100644 --- a/mpi/mpiutil.c +++ b/mpi/mpiutil.c @@ -61,7 +61,7 @@ _gcry_mpi_init (void) default: log_bug ("invalid mpi_const selector %d\n", idx); } constants[idx] = mpi_alloc_set_ui (value); - constants[idx]->flags = (16|32); + _gcry_mpi_set_flag(constants[idx], GCRYMPI_FLAG_CONST); } return 0; @@ -665,7 +665,12 @@ _gcry_mpi_set_flag (gcry_mpi_t a, enum gcry_mpi_flag flag) switch (flag) { case GCRYMPI_FLAG_SECURE: mpi_set_secure(a); break; - case GCRYMPI_FLAG_CONST: a->flags |= (16|32); break; + case GCRYMPI_FLAG_CONST: + a->flags |= (16|32); +#if GPGRT_VERSION_NUMBER >= 0x011600 /* 1.22 */ + gpgrt_annotate_leaked_object(a); +#endif + break; case GCRYMPI_FLAG_IMMUTABLE: a->flags |= 16; break; case GCRYMPI_FLAG_USER1: -- 2.7.4 From wk at gnupg.org Thu Mar 24 15:34:17 2016 From: wk at gnupg.org (Werner Koch) Date: Thu, 24 Mar 2016 15:34:17 +0100 Subject: [PATCH] Avoid undefined behavior for hashes using XOF In-Reply-To: <20160324120154.GA17055@al> (Peter Wu's message of "Thu, 24 Mar 2016 13:01:54 +0100") References: <1458775776-15785-1-git-send-email-peter@lekensteyn.nl> <87twjwtbpb.fsf@wheatstone.g10code.de> <20160324120154.GA17055@al> Message-ID: <874mbwt05y.fsf@wheatstone.g10code.de> On Thu, 24 Mar 2016 13:01, peter at lekensteyn.nl said: > I think that md_digest_length() is still more suitable here, the message > is not "avoid memcpy on a NULL source", but "avoid a memcpy if there is > nothing to copy". The former might hide hypothetical errors where the The memcpy specs in C99 say [#2] The memcpy function copies n characters from the object pointed to by s2 into the object pointed to by s1. If copying takes place between objects that overlap, the behavior is undefined. Thus it doesn't mention a NULL pointer. However, a NULL pointer might be assumed to trigger the overlapped case and than it would be UB. > length is non-zero, but md_read returns NULL for some reason. Not for some reason but because, as you mentioned, SHAKE128 does not have a read function. Other hashes may not have one either and thus I think that checking for the NULL case is more robust that checking for the algo's length. At worst a wrong definition of a hash (or CRC) could give a length but no read function. > Failing with an error indeed seems a better hint for the user, I will > fix that for the next patch. The benchmark is not quite accurate anyway Right, gcry_md_hash_buffers used to be simple function to return a SHA-1 hash and that was always defined. However, I latter changed that to allow all algos but I could not add an error return because existing callers do not check it. That was fixed with hash_buffers. You may also just die if md_read() return NULL. This is what gcry_md_hash_buffers does for inknown algorithms. > for XOFs, what about skipping tests for such functions? Yes. But print "skipped". Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From jussi.kivilinna at iki.fi Thu Mar 24 16:36:44 2016 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Thu, 24 Mar 2016 17:36:44 +0200 Subject: (Bug) Buffer overrun in gcry_cipher_gettag In-Reply-To: <20160323022512.GA29017@al> References: <20160322100844.GB24506@al> <87lh5a1wmh.fsf@wheatstone.g10code.de> <20160322222726.GA1232@al> <20160322235908.GQ19540@yoink.cs.uwaterloo.ca> <20160323022512.GA29017@al> Message-ID: <56F4098C.4000606@iki.fi> On 23.03.2016 04:25, Peter Wu wrote: > On Tue, Mar 22, 2016 at 07:59:08PM -0400, Ian Goldberg wrote: >> On Tue, Mar 22, 2016 at 11:27:26PM +0100, Peter Wu wrote: >>> Ah, my bad. OCB happens to be unaffected, I included it because the code >>> is smaller than the GCM case. I originally triggered it with AES-GCM. >>> Please find minimal reproducers in the attached crash.c file. >> >> You didn't attach anything? > > Oops, now I do. > > > It also found that the meaning of the tag length is not fixed. > For OCB the tag length can be 64, 96 or 128 bits (based on RFC 7253) so > the libgcrypt API allows you to specify the maximum buffer size. > > Current implemented constraints: > * CCM: taglen == authlen > * cmac (as used by MAC-CMAC): 1 <= taglen <= block_size > * GCM: 16 <= taglen (bug!) > * OCB: ocb.taglen <= taglen (copy at most ocb.taglen) > * Poly1305: 16 <= taglen (bug!) Looks like that the tag length check for GCM should be: if (outbuflen > GCRY_GCM_BLOCK_LEN) return GPG_ERR_INV_LENGTH; else if (outbuflen == 0) return GPG_ERR_INV_ARG; instead of current, which is just wrong: if (outbuflen < GCRY_GCM_BLOCK_LEN) return GPG_ERR_BUFFER_TOO_SHORT; That function should allow tag length that are less than maximum tag length as GCM spec (NIST Special Publication 800-38D) tag may be truncated by application. For Poly1305, tag size is fixed to 128-bits (in RFC 7539), so enforcing that should be ok. -Jussi > > Anything outside this range results in one of the following errors: > * GPG_ERR_BUFFER_TOO_SHORT (GCM, OCB, Poly1305) > * GPG_ERR_INV_ARG (CCM, CMAC) > * GPG_ERR_INV_LENGTH (CCM) > > I have some patches for the gettag crashes, but maybe it would also be > nice to be consistent here and treat the input size solely as a hint for > the input buffer size, and return failure if it is too small (instead of > too large)? Of course the documentation has to be updated for this. > > > > _______________________________________________ > Gcrypt-devel mailing list > Gcrypt-devel at gnupg.org > http://lists.gnupg.org/mailman/listinfo/gcrypt-devel > From cvs at cvs.gnupg.org Thu Mar 24 17:04:08 2016 From: cvs at cvs.gnupg.org (by Peter Wu) Date: Thu, 24 Mar 2016 17:04:08 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-364-g4a064e2 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via 4a064e2a06fe737f344d1dfd8a45cc4c2abbe4c9 (commit) via 470a30db241a2d567739ef2adb2a2ee64992d8b4 (commit) from fea5971488e049f902d7912df22a945bc755ad6d (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 4a064e2a06fe737f344d1dfd8a45cc4c2abbe4c9 Author: Peter Wu Date: Wed Mar 23 18:21:53 2016 +0100 cipher: Fix memleaks in (self)tests. * cipher/dsa.c: Release memory for MPI and sexp structures. * cipher/ecc.c: Release memory for sexp structure. * tests/keygen.c: Likewise. -- These leaks broke the mpitests, basic and keygen tests when running under AddressSanitizer. Signed-off-by: Peter Wu Minor formatting changes by -wk. diff --git a/cipher/dsa.c b/cipher/dsa.c index 909a8ca..22d8d78 100644 --- a/cipher/dsa.c +++ b/cipher/dsa.c @@ -1255,6 +1255,7 @@ selftest_sign (gcry_sexp_t pkey, gcry_sexp_t skey) if (!calculated_r) goto leave; + sexp_release (l2); l2 = _gcry_sexp_find_token (l1, "s", 0); if (!l2) goto leave; @@ -1289,6 +1290,12 @@ selftest_sign (gcry_sexp_t pkey, gcry_sexp_t skey) leave: + _gcry_mpi_release (calculated_s); + _gcry_mpi_release (calculated_r); + _gcry_mpi_release (s); + _gcry_mpi_release (r); + sexp_release (l2); + sexp_release (l1); sexp_release (sig); sexp_release (data_bad); sexp_release (data); diff --git a/cipher/ecc.c b/cipher/ecc.c index 5b03530..8dbf5bd 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -2046,6 +2046,7 @@ selftest_sign (gcry_sexp_t pkey, gcry_sexp_t skey) if (!calculated_r) goto leave; + sexp_release (l2); l2 = _gcry_sexp_find_token (l1, "s", 0); if (!l2) goto leave; diff --git a/tests/keygen.c b/tests/keygen.c index ebb708b..c4520e9 100644 --- a/tests/keygen.c +++ b/tests/keygen.c @@ -219,6 +219,8 @@ check_rsa_keys (void) " ))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gpg_strerror (rc)); + + gcry_sexp_release (key); rc = gcry_pk_genkey (&key, keyparm); gcry_sexp_release (keyparm); if (rc && !in_fips_mode) @@ -560,6 +562,7 @@ check_ecc_keys (void) if (verbose && rc && in_fips_mode) show ("... correctly rejected key creation in FIPS mode (%s)\n", gpg_strerror (rc)); + gcry_sexp_release (key); if (verbose) show ("creating ECC key using curve NIST P-384 for ECDSA\n"); commit 470a30db241a2d567739ef2adb2a2ee64992d8b4 Author: Peter Wu Date: Thu Mar 24 11:06:23 2016 +0100 Mark constant MPIs as non-leaked * mpi/mpiutil.c: Mark "constant" MPIs as explicitly leaked. -- Requires libgpg-error 1.22 (unreleased) for the macros, but since it is a minor debugging aid, do not bump the minimum required version. Signed-off-by: Peter Wu diff --git a/mpi/mpiutil.c b/mpi/mpiutil.c index 99402b8..6dee0b9 100644 --- a/mpi/mpiutil.c +++ b/mpi/mpiutil.c @@ -211,7 +211,12 @@ _gcry_mpi_free( gcry_mpi_t a ) if (!a ) return; if ((a->flags & 32)) + { +#if GPGRT_VERSION_NUMBER >= 0x011600 /* 1.22 */ + gpgrt_annotate_leaked_object(a); +#endif return; /* Never release a constant. */ + } if ((a->flags & 4)) xfree( a->d ); else ----------------------------------------------------------------------- Summary of changes: cipher/dsa.c | 7 +++++++ cipher/ecc.c | 1 + mpi/mpiutil.c | 5 +++++ tests/keygen.c | 3 +++ 4 files changed, 16 insertions(+) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From wk at gnupg.org Thu Mar 24 17:04:38 2016 From: wk at gnupg.org (Werner Koch) Date: Thu, 24 Mar 2016 17:04:38 +0100 Subject: [PATCH] Fix memleaks in (self)tests. In-Reply-To: <1458753713-31165-1-git-send-email-peter@lekensteyn.nl> (Peter Wu's message of "Wed, 23 Mar 2016 18:21:53 +0100") References: <1458753713-31165-1-git-send-email-peter@lekensteyn.nl> Message-ID: <87oaa3svzd.fsf@wheatstone.g10code.de> On Wed, 23 Mar 2016 18:21, peter at lekensteyn.nl said: > These leaks broke the mpitests, basic and keygen tests when running > under AddressSanitizer. Thanks. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From jussi.kivilinna at iki.fi Thu Mar 24 17:22:57 2016 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Thu, 24 Mar 2016 18:22:57 +0200 Subject: [PATCH] cipher: GCM: check that length of supplied tag is one of valid lengths Message-ID: <20160324162257.14670.71953.stgit@localhost6.localdomain6> * cipher/cipher-gcm.c (is_tag_length_valid): New. (_gcry_cipher_gcm_tag): Check that 'outbuflen' has valid tag length. * tests/basic.c (_check_gcm_cipher): Add test-vectors with different valid tag lengths and negative test vectors with invalid lengths. -- NIST SP 800-38D limits tag lengths to following: 128, 120, 112, 104, 96, 64 and 32. Signed-off-by: Jussi Kivilinna --- 0 files changed diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c index 712641e..ea099ef 100644 --- a/cipher/cipher-gcm.c +++ b/cipher/cipher-gcm.c @@ -769,12 +769,32 @@ _gcry_cipher_gcm_geniv (gcry_cipher_hd_t c, #endif +static int +is_tag_length_valid(size_t taglen) +{ + switch (taglen) + { + /* Allowed tag lengths from NIST SP 800-38D. */ + case 128 / 8: + case 120 / 8: + case 112 / 8: + case 104 / 8: + case 96 / 8: + case 64 / 8: + case 32 / 8: + return 1; + + default: + return 0; + } +} + static gcry_err_code_t _gcry_cipher_gcm_tag (gcry_cipher_hd_t c, byte * outbuf, size_t outbuflen, int check) { - if (outbuflen < GCRY_GCM_BLOCK_LEN) - return GPG_ERR_BUFFER_TOO_SHORT; + if (!is_tag_length_valid(outbuflen)) + return GPG_ERR_INV_LENGTH; if (c->u_mode.gcm.datalen_over_limits) return GPG_ERR_INV_LENGTH; @@ -815,17 +835,11 @@ _gcry_cipher_gcm_tag (gcry_cipher_hd_t c, if (!check) { - /* NB: We already checked that OUTBUF is large enough to hold - the result. */ - memcpy (outbuf, c->u_mode.gcm.u_tag.tag, GCRY_GCM_BLOCK_LEN); + memcpy (outbuf, c->u_mode.gcm.u_tag.tag, outbuflen); } else { - /* OUTBUFLEN gives the length of the user supplied tag in OUTBUF - * and thus we need to compare its length first. */ - if (outbuflen != GCRY_GCM_BLOCK_LEN - || !buf_eq_const (outbuf, c->u_mode.gcm.u_tag.tag, - GCRY_GCM_BLOCK_LEN)) + if (!buf_eq_const (outbuf, c->u_mode.gcm.u_tag.tag, outbuflen)) return GPG_ERR_CHECKSUM; } diff --git a/tests/basic.c b/tests/basic.c index 36a83d0..39957ad 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -1304,6 +1304,8 @@ _check_gcm_cipher (unsigned int step) int inlen; char out[MAX_DATA_LEN]; char tag[MAX_DATA_LEN]; + int taglen; + int should_fail; } tv[] = { /* http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf */ @@ -1319,6 +1321,78 @@ _check_gcm_cipher (unsigned int step) "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, "", 0, + "", + 0, + "", + "\x58\xe2\xfc\xce\xfa\x7e\x30\x61\x36\x7f\x1d\x57\xa4\xe7\x45", + 15 }, + { GCRY_CIPHER_AES, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "", 0, + "", + 0, + "", + "\x58\xe2\xfc\xce\xfa\x7e\x30\x61\x36\x7f\x1d\x57\xa4\xe7", + 14 }, + { GCRY_CIPHER_AES, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "", 0, + "", + 0, + "", + "\x58\xe2\xfc\xce\xfa\x7e\x30\x61\x36\x7f\x1d\x57\xa4", + 13 }, + { GCRY_CIPHER_AES, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "", 0, + "", + 0, + "", + "\x58\xe2\xfc\xce\xfa\x7e\x30\x61\x36\x7f\x1d\x57", + 12 }, + { GCRY_CIPHER_AES, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "", 0, + "", + 0, + "", + "\x58\xe2\xfc\xce\xfa\x7e\x30\x61\x36\x7f\x1d", + 11, 1 }, + { GCRY_CIPHER_AES, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "", 0, + "", + 0, + "", + "\x58\xe2\xfc\xce\xfa\x7e\x30\x61", + 8 }, + { GCRY_CIPHER_AES, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "", 0, + "", + 0, + "", + "\x58\xe2\xfc\xce", + 4 }, + { GCRY_CIPHER_AES, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "", 0, + "", + 0, + "", + "\x58", + 1, 1 }, + { GCRY_CIPHER_AES, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "", 0, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16, "\x03\x88\xda\xce\x60\xb6\xa3\x92\xf3\x28\xc2\xb9\x71\xb2\xfe\x78", @@ -1570,9 +1644,14 @@ _check_gcm_cipher (unsigned int step) if (memcmp (tv[i].plaintext, out, tv[i].inlen)) fail ("aes-gcm, decrypt mismatch entry %d (step %d)\n", i, step); - err = gcry_cipher_gettag (hde, out, GCRY_GCM_BLOCK_LEN); + taglen2 = tv[i].taglen ? tv[i].taglen : GCRY_GCM_BLOCK_LEN; + + err = gcry_cipher_gettag (hde, out, taglen2); if (err) { + if (tv[i].should_fail) + goto next_tv; + fail ("aes-gcm, gcry_cipher_gettag(%d) failed: %s\n", i, gpg_strerror (err)); gcry_cipher_close (hde); @@ -1580,11 +1659,10 @@ _check_gcm_cipher (unsigned int step) return; } - if (memcmp (tv[i].tag, out, GCRY_GCM_BLOCK_LEN)) + if (memcmp (tv[i].tag, out, taglen2)) fail ("aes-gcm, encrypt tag mismatch entry %d\n", i); - - err = gcry_cipher_checktag (hdd, out, GCRY_GCM_BLOCK_LEN); + err = gcry_cipher_checktag (hdd, out, taglen2); if (err) { fail ("aes-gcm, gcry_cipher_checktag(%d) failed: %s\n", @@ -1660,17 +1738,22 @@ _check_gcm_cipher (unsigned int step) if (memcmp (tv[i].out, out, tv[i].inlen)) fail ("aes-gcm, encrypt mismatch entry %d, (byte-buf)\n", i); - err = gcry_cipher_gettag (hde, tag, GCRY_GCM_BLOCK_LEN); + taglen2 = tv[i].taglen ? tv[i].taglen : GCRY_GCM_BLOCK_LEN; + + err = gcry_cipher_gettag (hde, tag, taglen2); if (err) { - fail ("aes-gcm, gcry_cipher_gettag(%d) (byte-buf) failed: %s\n", - i, gpg_strerror (err)); + if (tv[i].should_fail) + goto next_tv; + + fail ("aes-gcm, gcry_cipher_gettag(%d, %d) (byte-buf) failed: %s\n", + i, taglen2, gpg_strerror (err)); gcry_cipher_close (hde); gcry_cipher_close (hdd); return; } - if (memcmp (tv[i].tag, tag, GCRY_GCM_BLOCK_LEN)) + if (memcmp (tv[i].tag, tag, taglen2)) fail ("aes-gcm, encrypt tag mismatch entry %d, (byte-buf)\n", i); for (byteNum = 0; byteNum < tv[i].inlen; ++byteNum) @@ -1689,7 +1772,7 @@ _check_gcm_cipher (unsigned int step) if (memcmp (tv[i].plaintext, out, tv[i].inlen)) fail ("aes-gcm, decrypt mismatch entry %d\n", i); - err = gcry_cipher_checktag (hdd, tag, GCRY_GCM_BLOCK_LEN); + err = gcry_cipher_checktag (hdd, tag, taglen2); if (err) { fail ("aes-gcm, gcry_cipher_checktag(%d) (byte-buf) failed: %s\n", @@ -1699,6 +1782,15 @@ _check_gcm_cipher (unsigned int step) return; } + if (tv[i].should_fail) + { + fail ("aes-gcm, negative test succeeded %d\n", i); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + +next_tv: gcry_cipher_close (hde); gcry_cipher_close (hdd); } From jussi.kivilinna at iki.fi Thu Mar 24 17:54:06 2016 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Thu, 24 Mar 2016 18:54:06 +0200 Subject: [PATCH 1/3] Add Aarch64 assembly implementation of AES Message-ID: <20160324165406.18609.20695.stgit@localhost6.localdomain6> * cipher/Makefile.am: Add 'rijndael-aarch64.S'. * cipher/rijndael-aarch64.S: New. * cipher/rijndael-internal.h: Enable USE_ARM_ASM if __AARCH64EL__ and HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS defined. * configure.ac (gcry_cv_gcc_aarch64_platform_as_ok): New check. [host=aarch64]: Add 'rijndael-aarch64.lo'. -- Patch adds ARMv8/Aarch64 implementation of AES. Benchmark on Cortex-A53 (1536 Mhz): Before: AES | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 19.37 ns/B 49.22 MiB/s 29.76 c/B ECB dec | 19.85 ns/B 48.03 MiB/s 30.50 c/B CBC enc | 16.84 ns/B 56.62 MiB/s 25.87 c/B CBC dec | 16.81 ns/B 56.74 MiB/s 25.82 c/B CFB enc | 16.80 ns/B 56.75 MiB/s 25.81 c/B CFB dec | 16.81 ns/B 56.75 MiB/s 25.81 c/B OFB enc | 20.02 ns/B 47.64 MiB/s 30.75 c/B OFB dec | 20.02 ns/B 47.64 MiB/s 30.75 c/B CTR enc | 17.06 ns/B 55.91 MiB/s 26.20 c/B CTR dec | 17.06 ns/B 55.92 MiB/s 26.20 c/B CCM enc | 33.94 ns/B 28.10 MiB/s 52.13 c/B CCM dec | 33.94 ns/B 28.10 MiB/s 52.14 c/B CCM auth | 16.97 ns/B 56.18 MiB/s 26.07 c/B GCM enc | 28.70 ns/B 33.23 MiB/s 44.09 c/B GCM dec | 28.70 ns/B 33.23 MiB/s 44.09 c/B GCM auth | 11.66 ns/B 81.81 MiB/s 17.90 c/B OCB enc | 17.66 ns/B 53.99 MiB/s 27.13 c/B OCB dec | 17.61 ns/B 54.16 MiB/s 27.05 c/B OCB auth | 17.44 ns/B 54.69 MiB/s 26.78 c/B = AES192 | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 21.82 ns/B 43.71 MiB/s 33.51 c/B ECB dec | 22.55 ns/B 42.30 MiB/s 34.63 c/B CBC enc | 19.33 ns/B 49.33 MiB/s 29.70 c/B CBC dec | 19.50 ns/B 48.91 MiB/s 29.95 c/B CFB enc | 19.29 ns/B 49.44 MiB/s 29.63 c/B CFB dec | 19.28 ns/B 49.46 MiB/s 29.61 c/B OFB enc | 22.49 ns/B 42.40 MiB/s 34.55 c/B OFB dec | 22.50 ns/B 42.38 MiB/s 34.56 c/B CTR enc | 19.53 ns/B 48.83 MiB/s 30.00 c/B CTR dec | 19.54 ns/B 48.80 MiB/s 30.02 c/B CCM enc | 38.91 ns/B 24.51 MiB/s 59.77 c/B CCM dec | 38.90 ns/B 24.51 MiB/s 59.76 c/B CCM auth | 19.45 ns/B 49.02 MiB/s 29.88 c/B GCM enc | 31.13 ns/B 30.63 MiB/s 47.82 c/B GCM dec | 31.14 ns/B 30.63 MiB/s 47.82 c/B GCM auth | 11.66 ns/B 81.80 MiB/s 17.91 c/B OCB enc | 20.15 ns/B 47.33 MiB/s 30.95 c/B OCB dec | 20.30 ns/B 46.98 MiB/s 31.18 c/B OCB auth | 19.92 ns/B 47.88 MiB/s 30.59 c/B = AES256 | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 24.33 ns/B 39.19 MiB/s 37.38 c/B ECB dec | 25.23 ns/B 37.80 MiB/s 38.76 c/B CBC enc | 21.82 ns/B 43.71 MiB/s 33.51 c/B CBC dec | 22.18 ns/B 42.99 MiB/s 34.07 c/B CFB enc | 21.77 ns/B 43.80 MiB/s 33.44 c/B CFB dec | 21.77 ns/B 43.81 MiB/s 33.44 c/B OFB enc | 24.99 ns/B 38.16 MiB/s 38.39 c/B OFB dec | 24.99 ns/B 38.17 MiB/s 38.38 c/B CTR enc | 22.02 ns/B 43.32 MiB/s 33.82 c/B CTR dec | 22.02 ns/B 43.31 MiB/s 33.82 c/B CCM enc | 43.86 ns/B 21.74 MiB/s 67.38 c/B CCM dec | 43.87 ns/B 21.74 MiB/s 67.39 c/B CCM auth | 21.94 ns/B 43.48 MiB/s 33.69 c/B GCM enc | 33.66 ns/B 28.33 MiB/s 51.71 c/B GCM dec | 33.66 ns/B 28.33 MiB/s 51.70 c/B GCM auth | 11.69 ns/B 81.59 MiB/s 17.95 c/B OCB enc | 22.90 ns/B 41.65 MiB/s 35.17 c/B OCB dec | 23.25 ns/B 41.02 MiB/s 35.71 c/B OCB auth | 22.69 ns/B 42.03 MiB/s 34.85 c/B = After (~1.2x faster): AES | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 16.40 ns/B 58.16 MiB/s 25.19 c/B ECB dec | 17.01 ns/B 56.07 MiB/s 26.13 c/B CBC enc | 13.99 ns/B 68.15 MiB/s 21.49 c/B CBC dec | 14.04 ns/B 67.94 MiB/s 21.56 c/B CFB enc | 13.96 ns/B 68.32 MiB/s 21.44 c/B CFB dec | 13.95 ns/B 68.34 MiB/s 21.43 c/B OFB enc | 17.14 ns/B 55.65 MiB/s 26.32 c/B OFB dec | 17.13 ns/B 55.67 MiB/s 26.31 c/B CTR enc | 14.17 ns/B 67.31 MiB/s 21.76 c/B CTR dec | 14.17 ns/B 67.29 MiB/s 21.77 c/B CCM enc | 28.16 ns/B 33.86 MiB/s 43.26 c/B CCM dec | 28.16 ns/B 33.87 MiB/s 43.26 c/B CCM auth | 14.08 ns/B 67.71 MiB/s 21.63 c/B GCM enc | 25.82 ns/B 36.94 MiB/s 39.66 c/B GCM dec | 25.82 ns/B 36.94 MiB/s 39.65 c/B GCM auth | 11.67 ns/B 81.74 MiB/s 17.92 c/B OCB enc | 14.78 ns/B 64.55 MiB/s 22.69 c/B OCB dec | 14.80 ns/B 64.43 MiB/s 22.74 c/B OCB auth | 14.59 ns/B 65.36 MiB/s 22.41 c/B = AES192 | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 19.05 ns/B 50.07 MiB/s 29.25 c/B ECB dec | 19.62 ns/B 48.62 MiB/s 30.13 c/B CBC enc | 16.56 ns/B 57.59 MiB/s 25.44 c/B CBC dec | 16.69 ns/B 57.14 MiB/s 25.64 c/B CFB enc | 16.52 ns/B 57.71 MiB/s 25.38 c/B CFB dec | 16.52 ns/B 57.73 MiB/s 25.37 c/B OFB enc | 19.70 ns/B 48.41 MiB/s 30.26 c/B OFB dec | 19.69 ns/B 48.43 MiB/s 30.24 c/B CTR enc | 16.73 ns/B 57.00 MiB/s 25.70 c/B CTR dec | 16.73 ns/B 57.01 MiB/s 25.70 c/B CCM enc | 33.29 ns/B 28.65 MiB/s 51.13 c/B CCM dec | 33.29 ns/B 28.65 MiB/s 51.13 c/B CCM auth | 16.65 ns/B 57.29 MiB/s 25.57 c/B GCM enc | 28.39 ns/B 33.60 MiB/s 43.60 c/B GCM dec | 28.39 ns/B 33.59 MiB/s 43.60 c/B GCM auth | 11.64 ns/B 81.92 MiB/s 17.88 c/B OCB enc | 17.33 ns/B 55.03 MiB/s 26.62 c/B OCB dec | 17.40 ns/B 54.82 MiB/s 26.72 c/B OCB auth | 17.16 ns/B 55.59 MiB/s 26.35 c/B = AES256 | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 21.56 ns/B 44.23 MiB/s 33.12 c/B ECB dec | 22.09 ns/B 43.17 MiB/s 33.93 c/B CBC enc | 19.09 ns/B 49.97 MiB/s 29.31 c/B CBC dec | 19.13 ns/B 49.86 MiB/s 29.38 c/B CFB enc | 19.04 ns/B 50.09 MiB/s 29.24 c/B CFB dec | 19.04 ns/B 50.08 MiB/s 29.25 c/B OFB enc | 22.22 ns/B 42.93 MiB/s 34.13 c/B OFB dec | 22.22 ns/B 42.92 MiB/s 34.13 c/B CTR enc | 19.25 ns/B 49.53 MiB/s 29.57 c/B CTR dec | 19.25 ns/B 49.55 MiB/s 29.57 c/B CCM enc | 38.33 ns/B 24.88 MiB/s 58.88 c/B CCM dec | 38.34 ns/B 24.88 MiB/s 58.88 c/B CCM auth | 19.17 ns/B 49.76 MiB/s 29.44 c/B GCM enc | 30.91 ns/B 30.86 MiB/s 47.47 c/B GCM dec | 30.91 ns/B 30.85 MiB/s 47.48 c/B GCM auth | 11.71 ns/B 81.47 MiB/s 17.98 c/B OCB enc | 19.85 ns/B 48.04 MiB/s 30.49 c/B OCB dec | 19.89 ns/B 47.95 MiB/s 30.55 c/B OCB auth | 19.67 ns/B 48.48 MiB/s 30.22 c/B = Signed-off-by: Jussi Kivilinna --- 0 files changed diff --git a/cipher/Makefile.am b/cipher/Makefile.am index ab71fa7..56da706 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -80,6 +80,7 @@ md5.c \ poly1305-sse2-amd64.S poly1305-avx2-amd64.S poly1305-armv7-neon.S \ rijndael.c rijndael-internal.h rijndael-tables.h rijndael-aesni.c \ rijndael-padlock.c rijndael-amd64.S rijndael-arm.S rijndael-ssse3-amd64.c \ + rijndael-aarch64.S \ rmd160.c \ rsa.c \ salsa20.c salsa20-amd64.S salsa20-armv7-neon.S \ diff --git a/cipher/rijndael-aarch64.S b/cipher/rijndael-aarch64.S new file mode 100644 index 0000000..2f91a1d --- /dev/null +++ b/cipher/rijndael-aarch64.S @@ -0,0 +1,510 @@ +/* rijndael-aarch64.S - ARMv8/Aarch64 assembly implementation of AES cipher + * + * Copyright (C) 2016 Jussi Kivilinna + * + * 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 + +#if defined(__AARCH64EL__) +#ifdef HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS + +.text + +/* register macros */ +#define CTX x0 +#define RDST x1 +#define RSRC x2 +#define NROUNDS w3 +#define RTAB x4 +#define RMASK w5 + +#define RA w8 +#define RB w9 +#define RC w10 +#define RD w11 + +#define RNA w12 +#define RNB w13 +#define RNC w14 +#define RND w15 + +#define RT0 w6 +#define RT1 w7 +#define RT2 w16 +#define xRT0 x6 +#define xRT1 x7 +#define xRT2 x16 + +#define xw8 x8 +#define xw9 x9 +#define xw10 x10 +#define xw11 x11 + +#define xw12 x12 +#define xw13 x13 +#define xw14 x14 +#define xw15 x15 + +/*********************************************************************** + * ARMv8/Aarch64 assembly implementation of the AES cipher + ***********************************************************************/ +#define preload_first_key(round, ra) \ + ldr ra, [CTX, #(((round) * 16) + 0 * 4)]; + +#define dummy(round, ra) /* nothing */ + +#define addroundkey(ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key) \ + ldp rna, rnb, [CTX]; \ + ldp rnc, rnd, [CTX, #8]; \ + eor ra, ra, rna; \ + eor rb, rb, rnb; \ + eor rc, rc, rnc; \ + preload_key(1, rna); \ + eor rd, rd, rnd; + +#define do_encround(next_r, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key) \ + ldr rnb, [CTX, #(((next_r) * 16) + 1 * 4)]; \ + \ + and RT0, RMASK, ra, lsl#2; \ + ldr rnc, [CTX, #(((next_r) * 16) + 2 * 4)]; \ + and RT1, RMASK, ra, lsr#(8 - 2); \ + ldr rnd, [CTX, #(((next_r) * 16) + 3 * 4)]; \ + and RT2, RMASK, ra, lsr#(16 - 2); \ + ldr RT0, [RTAB, xRT0]; \ + and ra, RMASK, ra, lsr#(24 - 2); \ + \ + ldr RT1, [RTAB, xRT1]; \ + eor rna, rna, RT0; \ + ldr RT2, [RTAB, xRT2]; \ + and RT0, RMASK, rd, lsl#2; \ + ldr ra, [RTAB, x##ra]; \ + \ + eor rnd, rnd, RT1, ror #24; \ + and RT1, RMASK, rd, lsr#(8 - 2); \ + eor rnc, rnc, RT2, ror #16; \ + and RT2, RMASK, rd, lsr#(16 - 2); \ + eor rnb, rnb, ra, ror #8; \ + ldr RT0, [RTAB, xRT0]; \ + and rd, RMASK, rd, lsr#(24 - 2); \ + \ + ldr RT1, [RTAB, xRT1]; \ + eor rnd, rnd, RT0; \ + ldr RT2, [RTAB, xRT2]; \ + and RT0, RMASK, rc, lsl#2; \ + ldr rd, [RTAB, x##rd]; \ + \ + eor rnc, rnc, RT1, ror #24; \ + and RT1, RMASK, rc, lsr#(8 - 2); \ + eor rnb, rnb, RT2, ror #16; \ + and RT2, RMASK, rc, lsr#(16 - 2); \ + eor rna, rna, rd, ror #8; \ + ldr RT0, [RTAB, xRT0]; \ + and rc, RMASK, rc, lsr#(24 - 2); \ + \ + ldr RT1, [RTAB, xRT1]; \ + eor rnc, rnc, RT0; \ + ldr RT2, [RTAB, xRT2]; \ + and RT0, RMASK, rb, lsl#2; \ + ldr rc, [RTAB, x##rc]; \ + \ + eor rnb, rnb, RT1, ror #24; \ + and RT1, RMASK, rb, lsr#(8 - 2); \ + eor rna, rna, RT2, ror #16; \ + and RT2, RMASK, rb, lsr#(16 - 2); \ + eor rnd, rnd, rc, ror #8; \ + ldr RT0, [RTAB, xRT0]; \ + and rb, RMASK, rb, lsr#(24 - 2); \ + \ + ldr RT1, [RTAB, xRT1]; \ + eor rnb, rnb, RT0; \ + ldr RT2, [RTAB, xRT2]; \ + eor rna, rna, RT1, ror #24; \ + ldr rb, [RTAB, x##rb]; \ + \ + eor rnd, rnd, RT2, ror #16; \ + preload_key((next_r) + 1, ra); \ + eor rnc, rnc, rb, ror #8; + +#define do_lastencround(ra, rb, rc, rd, rna, rnb, rnc, rnd) \ + and RT0, RMASK, ra, lsl#2; \ + and RT1, RMASK, ra, lsr#(8 - 2); \ + and RT2, RMASK, ra, lsr#(16 - 2); \ + ldrb rna, [RTAB, xRT0]; \ + and ra, RMASK, ra, lsr#(24 - 2); \ + ldrb rnd, [RTAB, xRT1]; \ + and RT0, RMASK, rd, lsl#2; \ + ldrb rnc, [RTAB, xRT2]; \ + ror rnd, rnd, #24; \ + ldrb rnb, [RTAB, x##ra]; \ + and RT1, RMASK, rd, lsr#(8 - 2); \ + ror rnc, rnc, #16; \ + and RT2, RMASK, rd, lsr#(16 - 2); \ + ror rnb, rnb, #8; \ + ldrb RT0, [RTAB, xRT0]; \ + and rd, RMASK, rd, lsr#(24 - 2); \ + ldrb RT1, [RTAB, xRT1]; \ + \ + orr rnd, rnd, RT0; \ + ldrb RT2, [RTAB, xRT2]; \ + and RT0, RMASK, rc, lsl#2; \ + ldrb rd, [RTAB, x##rd]; \ + orr rnc, rnc, RT1, ror #24; \ + and RT1, RMASK, rc, lsr#(8 - 2); \ + orr rnb, rnb, RT2, ror #16; \ + and RT2, RMASK, rc, lsr#(16 - 2); \ + orr rna, rna, rd, ror #8; \ + ldrb RT0, [RTAB, xRT0]; \ + and rc, RMASK, rc, lsr#(24 - 2); \ + ldrb RT1, [RTAB, xRT1]; \ + \ + orr rnc, rnc, RT0; \ + ldrb RT2, [RTAB, xRT2]; \ + and RT0, RMASK, rb, lsl#2; \ + ldrb rc, [RTAB, x##rc]; \ + orr rnb, rnb, RT1, ror #24; \ + and RT1, RMASK, rb, lsr#(8 - 2); \ + orr rna, rna, RT2, ror #16; \ + ldrb RT0, [RTAB, xRT0]; \ + and RT2, RMASK, rb, lsr#(16 - 2); \ + ldrb RT1, [RTAB, xRT1]; \ + orr rnd, rnd, rc, ror #8; \ + ldrb RT2, [RTAB, xRT2]; \ + and rb, RMASK, rb, lsr#(24 - 2); \ + ldrb rb, [RTAB, x##rb]; \ + \ + orr rnb, rnb, RT0; \ + orr rna, rna, RT1, ror #24; \ + orr rnd, rnd, RT2, ror #16; \ + orr rnc, rnc, rb, ror #8; + +#define firstencround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd) \ + addroundkey(ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_first_key); \ + do_encround((round) + 1, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_first_key); + +#define encround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key) \ + do_encround((round) + 1, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key); + +#define lastencround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd) \ + add CTX, CTX, #(((round) + 1) * 16); \ + add RTAB, RTAB, #1; \ + do_lastencround(ra, rb, rc, rd, rna, rnb, rnc, rnd); \ + addroundkey(rna, rnb, rnc, rnd, ra, rb, rc, rd, dummy); + +.globl _gcry_aes_arm_encrypt_block +.type _gcry_aes_arm_encrypt_block,%function; + +_gcry_aes_arm_encrypt_block: + /* input: + * %x0: keysched, CTX + * %x1: dst + * %x2: src + * %w3: number of rounds.. 10, 12 or 14 + * %x4: encryption table + */ + + /* read input block */ + + /* aligned load */ + ldp RA, RB, [RSRC]; + ldp RC, RD, [RSRC, #8]; +#ifndef __AARCH64EL__ + rev RA, RA; + rev RB, RB; + rev RC, RC; + rev RD, RD; +#endif + + mov RMASK, #(0xff<<2); + + firstencround(0, RA, RB, RC, RD, RNA, RNB, RNC, RND); + encround(1, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key); + encround(2, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key); + encround(3, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key); + encround(4, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key); + encround(5, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key); + encround(6, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key); + encround(7, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key); + + cmp NROUNDS, #12; + bge .Lenc_not_128; + + encround(8, RA, RB, RC, RD, RNA, RNB, RNC, RND, dummy); + lastencround(9, RNA, RNB, RNC, RND, RA, RB, RC, RD); + +.Lenc_done: + + /* store output block */ + + /* aligned store */ +#ifndef __AARCH64EL__ + rev RA, RA; + rev RB, RB; + rev RC, RC; + rev RD, RD; +#endif + /* write output block */ + stp RA, RB, [RDST]; + stp RC, RD, [RDST, #8]; + + mov x0, #(0); + ret; + +.ltorg +.Lenc_not_128: + beq .Lenc_192 + + encround(8, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key); + encround(9, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key); + encround(10, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key); + encround(11, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key); + encround(12, RA, RB, RC, RD, RNA, RNB, RNC, RND, dummy); + lastencround(13, RNA, RNB, RNC, RND, RA, RB, RC, RD); + + b .Lenc_done; + +.ltorg +.Lenc_192: + encround(8, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key); + encround(9, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key); + encround(10, RA, RB, RC, RD, RNA, RNB, RNC, RND, dummy); + lastencround(11, RNA, RNB, RNC, RND, RA, RB, RC, RD); + + b .Lenc_done; +.size _gcry_aes_arm_encrypt_block,.-_gcry_aes_arm_encrypt_block; + +#define addroundkey_dec(round, ra, rb, rc, rd, rna, rnb, rnc, rnd) \ + ldr rna, [CTX, #(((round) * 16) + 0 * 4)]; \ + ldr rnb, [CTX, #(((round) * 16) + 1 * 4)]; \ + eor ra, ra, rna; \ + ldr rnc, [CTX, #(((round) * 16) + 2 * 4)]; \ + eor rb, rb, rnb; \ + ldr rnd, [CTX, #(((round) * 16) + 3 * 4)]; \ + eor rc, rc, rnc; \ + preload_first_key((round) - 1, rna); \ + eor rd, rd, rnd; + +#define do_decround(next_r, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key) \ + ldr rnb, [CTX, #(((next_r) * 16) + 1 * 4)]; \ + \ + and RT0, RMASK, ra, lsl#2; \ + ldr rnc, [CTX, #(((next_r) * 16) + 2 * 4)]; \ + and RT1, RMASK, ra, lsr#(8 - 2); \ + ldr rnd, [CTX, #(((next_r) * 16) + 3 * 4)]; \ + and RT2, RMASK, ra, lsr#(16 - 2); \ + ldr RT0, [RTAB, xRT0]; \ + and ra, RMASK, ra, lsr#(24 - 2); \ + \ + ldr RT1, [RTAB, xRT1]; \ + eor rna, rna, RT0; \ + ldr RT2, [RTAB, xRT2]; \ + and RT0, RMASK, rb, lsl#2; \ + ldr ra, [RTAB, x##ra]; \ + \ + eor rnb, rnb, RT1, ror #24; \ + and RT1, RMASK, rb, lsr#(8 - 2); \ + eor rnc, rnc, RT2, ror #16; \ + and RT2, RMASK, rb, lsr#(16 - 2); \ + eor rnd, rnd, ra, ror #8; \ + ldr RT0, [RTAB, xRT0]; \ + and rb, RMASK, rb, lsr#(24 - 2); \ + \ + ldr RT1, [RTAB, xRT1]; \ + eor rnb, rnb, RT0; \ + ldr RT2, [RTAB, xRT2]; \ + and RT0, RMASK, rc, lsl#2; \ + ldr rb, [RTAB, x##rb]; \ + \ + eor rnc, rnc, RT1, ror #24; \ + and RT1, RMASK, rc, lsr#(8 - 2); \ + eor rnd, rnd, RT2, ror #16; \ + and RT2, RMASK, rc, lsr#(16 - 2); \ + eor rna, rna, rb, ror #8; \ + ldr RT0, [RTAB, xRT0]; \ + and rc, RMASK, rc, lsr#(24 - 2); \ + \ + ldr RT1, [RTAB, xRT1]; \ + eor rnc, rnc, RT0; \ + ldr RT2, [RTAB, xRT2]; \ + and RT0, RMASK, rd, lsl#2; \ + ldr rc, [RTAB, x##rc]; \ + \ + eor rnd, rnd, RT1, ror #24; \ + and RT1, RMASK, rd, lsr#(8 - 2); \ + eor rna, rna, RT2, ror #16; \ + and RT2, RMASK, rd, lsr#(16 - 2); \ + eor rnb, rnb, rc, ror #8; \ + ldr RT0, [RTAB, xRT0]; \ + and rd, RMASK, rd, lsr#(24 - 2); \ + \ + ldr RT1, [RTAB, xRT1]; \ + eor rnd, rnd, RT0; \ + ldr RT2, [RTAB, xRT2]; \ + eor rna, rna, RT1, ror #24; \ + ldr rd, [RTAB, x##rd]; \ + \ + eor rnb, rnb, RT2, ror #16; \ + preload_key((next_r) - 1, ra); \ + eor rnc, rnc, rd, ror #8; + +#define do_lastdecround(ra, rb, rc, rd, rna, rnb, rnc, rnd) \ + and RT0, RMASK, ra; \ + and RT1, RMASK, ra, lsr#8; \ + and RT2, RMASK, ra, lsr#16; \ + ldrb rna, [RTAB, xRT0]; \ + lsr ra, ra, #24; \ + ldrb rnb, [RTAB, xRT1]; \ + and RT0, RMASK, rb; \ + ldrb rnc, [RTAB, xRT2]; \ + ror rnb, rnb, #24; \ + ldrb rnd, [RTAB, x##ra]; \ + and RT1, RMASK, rb, lsr#8; \ + ror rnc, rnc, #16; \ + and RT2, RMASK, rb, lsr#16; \ + ror rnd, rnd, #8; \ + ldrb RT0, [RTAB, xRT0]; \ + lsr rb, rb, #24; \ + ldrb RT1, [RTAB, xRT1]; \ + \ + orr rnb, rnb, RT0; \ + ldrb RT2, [RTAB, xRT2]; \ + and RT0, RMASK, rc; \ + ldrb rb, [RTAB, x##rb]; \ + orr rnc, rnc, RT1, ror #24; \ + and RT1, RMASK, rc, lsr#8; \ + orr rnd, rnd, RT2, ror #16; \ + and RT2, RMASK, rc, lsr#16; \ + orr rna, rna, rb, ror #8; \ + ldrb RT0, [RTAB, xRT0]; \ + lsr rc, rc, #24; \ + ldrb RT1, [RTAB, xRT1]; \ + \ + orr rnc, rnc, RT0; \ + ldrb RT2, [RTAB, xRT2]; \ + and RT0, RMASK, rd; \ + ldrb rc, [RTAB, x##rc]; \ + orr rnd, rnd, RT1, ror #24; \ + and RT1, RMASK, rd, lsr#8; \ + orr rna, rna, RT2, ror #16; \ + ldrb RT0, [RTAB, xRT0]; \ + and RT2, RMASK, rd, lsr#16; \ + ldrb RT1, [RTAB, xRT1]; \ + orr rnb, rnb, rc, ror #8; \ + ldrb RT2, [RTAB, xRT2]; \ + lsr rd, rd, #24; \ + ldrb rd, [RTAB, x##rd]; \ + \ + orr rnd, rnd, RT0; \ + orr rna, rna, RT1, ror #24; \ + orr rnb, rnb, RT2, ror #16; \ + orr rnc, rnc, rd, ror #8; + +#define firstdecround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd) \ + addroundkey_dec(((round) + 1), ra, rb, rc, rd, rna, rnb, rnc, rnd); \ + do_decround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_first_key); + +#define decround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key) \ + do_decround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key); + +#define set_last_round_rmask(_, __) \ + mov RMASK, #0xff; + +#define lastdecround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd) \ + add RTAB, RTAB, #(4 * 256); \ + do_lastdecround(ra, rb, rc, rd, rna, rnb, rnc, rnd); \ + addroundkey(rna, rnb, rnc, rnd, ra, rb, rc, rd, dummy); + +.globl _gcry_aes_arm_decrypt_block +.type _gcry_aes_arm_decrypt_block,%function; + +_gcry_aes_arm_decrypt_block: + /* input: + * %x0: keysched, CTX + * %x1: dst + * %x2: src + * %w3: number of rounds.. 10, 12 or 14 + * %x4: decryption table + */ + + /* read input block */ + + /* aligned load */ + ldp RA, RB, [RSRC]; + ldp RC, RD, [RSRC, #8]; +#ifndef __AARCH64EL__ + rev RA, RA; + rev RB, RB; + rev RC, RC; + rev RD, RD; +#endif + + mov RMASK, #(0xff << 2); + + cmp NROUNDS, #12; + bge .Ldec_256; + + firstdecround(9, RA, RB, RC, RD, RNA, RNB, RNC, RND); +.Ldec_tail: + decround(8, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key); + decround(7, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key); + decround(6, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key); + decround(5, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key); + decround(4, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key); + decround(3, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key); + decround(2, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key); + decround(1, RA, RB, RC, RD, RNA, RNB, RNC, RND, set_last_round_rmask); + lastdecround(0, RNA, RNB, RNC, RND, RA, RB, RC, RD); + + /* store output block */ + + /* aligned store */ +#ifndef __AARCH64EL__ + rev RA, RA; + rev RB, RB; + rev RC, RC; + rev RD, RD; +#endif + /* write output block */ + stp RA, RB, [RDST]; + stp RC, RD, [RDST, #8]; + + mov x0, #(0); + ret; + +.ltorg +.Ldec_256: + beq .Ldec_192; + + firstdecround(13, RA, RB, RC, RD, RNA, RNB, RNC, RND); + decround(12, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key); + decround(11, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key); + decround(10, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key); + decround(9, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key); + + b .Ldec_tail; + +.ltorg +.Ldec_192: + firstdecround(11, RA, RB, RC, RD, RNA, RNB, RNC, RND); + decround(10, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key); + decround(9, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key); + + b .Ldec_tail; +.size _gcry_aes_arm_decrypt_block,.-_gcry_aes_arm_decrypt_block; + +#endif /*HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS*/ +#endif /*__AARCH64EL__ */ diff --git a/cipher/rijndael-arm.S b/cipher/rijndael-arm.S index 694369d..bf3fc36 100644 --- a/cipher/rijndael-arm.S +++ b/cipher/rijndael-arm.S @@ -581,5 +581,5 @@ _gcry_aes_arm_decrypt_block: b .Ldec_tail; .size _gcry_aes_arm_encrypt_block,.-_gcry_aes_arm_encrypt_block; -#endif /*HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS*/ +#endif /*HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS*/ #endif /*__ARMEL__ */ diff --git a/cipher/rijndael-internal.h b/cipher/rijndael-internal.h index 6641728..5cc85d8 100644 --- a/cipher/rijndael-internal.h +++ b/cipher/rijndael-internal.h @@ -58,6 +58,11 @@ # define USE_ARM_ASM 1 # endif #endif +#if defined(__AARCH64EL__) +# ifdef HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS +# define USE_ARM_ASM 1 +# endif +#endif /* USE_PADLOCK indicates whether to compile the padlock specific code. */ diff --git a/configure.ac b/configure.ac index 6a2d61b..485478f 100644 --- a/configure.ac +++ b/configure.ac @@ -1058,6 +1058,32 @@ fi # +# Check whether GCC assembler supports features needed for our ARMv8/Aarch64 +# implementations. This needs to be done before setting up the +# assembler stuff. +# +AC_CACHE_CHECK([whether GCC assembler is compatible for ARMv8/Aarch64 assembly implementations], + [gcry_cv_gcc_aarch64_platform_as_ok], + [gcry_cv_gcc_aarch64_platform_as_ok=no + AC_COMPILE_IFELSE([AC_LANG_SOURCE( + [[__asm__( + "asmfunc:\n\t" + "eor x0, x0, x30, ror #12;\n\t" + "add x0, x0, x30, asr #12;\n\t" + "eor v0.16b, v0.16b, v31.16b;\n\t" + + /* Test if '.type' and '.size' are supported. */ + ".size asmfunc,.-asmfunc;\n\t" + ".type asmfunc, at function;\n\t" + );]])], + [gcry_cv_gcc_aarch64_platform_as_ok=yes])]) +if test "$gcry_cv_gcc_aarch64_platform_as_ok" = "yes" ; then + AC_DEFINE(HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS,1, + [Defined if underlying assembler is compatible with ARMv8/Aarch64 assembly implementations]) +fi + + +# # Check whether underscores in symbols are required. This needs to be # done before setting up the assembler stuff. # @@ -1838,6 +1864,10 @@ if test "$found" = "1" ; then # Build with the assembly implementation GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-arm.lo" ;; + aarch64-*-*) + # Build with the assembly implementation + GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-aarch64.lo" + ;; esac case "$mpi_cpu_arch" in From jussi.kivilinna at iki.fi Thu Mar 24 17:54:16 2016 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Thu, 24 Mar 2016 18:54:16 +0200 Subject: [PATCH 3/3] Add Aarch64 implementation of Twofish In-Reply-To: <20160324165406.18609.20695.stgit@localhost6.localdomain6> References: <20160324165406.18609.20695.stgit@localhost6.localdomain6> Message-ID: <20160324165416.18609.66354.stgit@localhost6.localdomain6> * cipher/Makefile.am: Add 'twofish-aarch64.S'. * cipher/twofish-aarch64.S: New. * cipher/twofish.c: Enable USE_ARM_ASM if __AARCH64EL__ and HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS defined. * configure.ac [host=aarch64]: Add 'twofish-aarch64.lo'. -- Patch adds ARMv8/Aarch64 implementation of Twofish. Benchmark on Cortex-A53 (1536 Mhz): Before: TWOFISH128 | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 20.62 ns/B 46.25 MiB/s 31.67 c/B ECB dec | 19.77 ns/B 48.24 MiB/s 30.37 c/B CBC enc | 21.48 ns/B 44.40 MiB/s 32.99 c/B CBC dec | 19.65 ns/B 48.53 MiB/s 30.18 c/B CFB enc | 21.40 ns/B 44.57 MiB/s 32.87 c/B CFB dec | 20.54 ns/B 46.42 MiB/s 31.56 c/B OFB enc | 21.29 ns/B 44.80 MiB/s 32.70 c/B OFB dec | 21.28 ns/B 44.82 MiB/s 32.69 c/B CTR enc | 20.68 ns/B 46.12 MiB/s 31.76 c/B CTR dec | 20.68 ns/B 46.12 MiB/s 31.76 c/B CCM enc | 41.47 ns/B 22.99 MiB/s 63.71 c/B CCM dec | 41.47 ns/B 23.00 MiB/s 63.70 c/B CCM auth | 20.84 ns/B 45.77 MiB/s 32.01 c/B GCM enc | 32.33 ns/B 29.50 MiB/s 49.66 c/B GCM dec | 32.33 ns/B 29.50 MiB/s 49.66 c/B GCM auth | 11.69 ns/B 81.55 MiB/s 17.96 c/B OCB enc | 22.17 ns/B 43.02 MiB/s 34.05 c/B OCB dec | 21.27 ns/B 44.84 MiB/s 32.67 c/B OCB auth | 21.73 ns/B 43.88 MiB/s 33.38 c/B = After (~1.3x faster): TWOFISH128 | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 14.98 ns/B 63.67 MiB/s 23.01 c/B ECB dec | 13.72 ns/B 69.53 MiB/s 21.07 c/B CBC enc | 15.71 ns/B 60.69 MiB/s 24.14 c/B CBC dec | 13.75 ns/B 69.34 MiB/s 21.13 c/B CFB enc | 15.62 ns/B 61.04 MiB/s 24.00 c/B CFB dec | 14.98 ns/B 63.67 MiB/s 23.01 c/B OFB enc | 15.71 ns/B 60.70 MiB/s 24.13 c/B OFB dec | 15.69 ns/B 60.77 MiB/s 24.11 c/B CTR enc | 15.14 ns/B 62.97 MiB/s 23.26 c/B CTR dec | 15.14 ns/B 62.98 MiB/s 23.26 c/B CCM enc | 30.40 ns/B 31.37 MiB/s 46.70 c/B CCM dec | 30.39 ns/B 31.38 MiB/s 46.68 c/B CCM auth | 15.30 ns/B 62.34 MiB/s 23.50 c/B GCM enc | 26.79 ns/B 35.60 MiB/s 41.15 c/B GCM dec | 26.80 ns/B 35.59 MiB/s 41.16 c/B GCM auth | 11.65 ns/B 81.85 MiB/s 17.90 c/B OCB enc | 16.61 ns/B 57.41 MiB/s 25.52 c/B OCB dec | 15.28 ns/B 62.43 MiB/s 23.46 c/B OCB auth | 16.16 ns/B 59.00 MiB/s 24.83 c/B = Signed-off-by: Jussi Kivilinna --- 0 files changed diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 46125db..82c79d8 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -96,7 +96,7 @@ keccak.c keccak_permute_32.h keccak_permute_64.h keccak-armv7-neon.S \ stribog.c \ tiger.c \ whirlpool.c whirlpool-sse2-amd64.S \ -twofish.c twofish-amd64.S twofish-arm.S \ +twofish.c twofish-amd64.S twofish-arm.S twofish-aarch64.S \ rfc2268.c \ camellia.c camellia.h camellia-glue.c camellia-aesni-avx-amd64.S \ camellia-aesni-avx2-amd64.S camellia-arm.S camellia-aarch64.S diff --git a/cipher/twofish-aarch64.S b/cipher/twofish-aarch64.S new file mode 100644 index 0000000..13ea15b --- /dev/null +++ b/cipher/twofish-aarch64.S @@ -0,0 +1,317 @@ +/* twofish-aarch64.S - ARMv8/Aarch64 assembly implementation of Twofish cipher + * + * Copyright (C) 2016 Jussi Kivilinna + * + * 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 + +#if defined(__AARCH64EL__) +#ifdef HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS + +.text + +/* structure of TWOFISH_context: */ +#define s0 0 +#define s1 ((s0) + 4 * 256) +#define s2 ((s1) + 4 * 256) +#define s3 ((s2) + 4 * 256) +#define w ((s3) + 4 * 256) +#define k ((w) + 4 * 8) + +/* register macros */ +#define CTX x0 +#define RDST x1 +#define RSRC x2 +#define CTXs0 CTX +#define CTXs1 x3 +#define CTXs2 x4 +#define CTXs3 x5 +#define CTXw x17 + +#define RA w6 +#define RB w7 +#define RC w8 +#define RD w9 + +#define RX w10 +#define RY w11 + +#define xRX x10 +#define xRY x11 + +#define RMASK w12 + +#define RT0 w13 +#define RT1 w14 +#define RT2 w15 +#define RT3 w16 + +#define xRT0 x13 +#define xRT1 x14 +#define xRT2 x15 +#define xRT3 x16 + +/* helper macros */ +#ifndef __AARCH64EL__ + /* bswap on big-endian */ + #define host_to_le(reg) \ + rev reg, reg; + #define le_to_host(reg) \ + rev reg, reg; +#else + /* nop on little-endian */ + #define host_to_le(reg) /*_*/ + #define le_to_host(reg) /*_*/ +#endif + +#define ldr_input_aligned_le(rin, a, b, c, d) \ + ldr a, [rin, #0]; \ + ldr b, [rin, #4]; \ + le_to_host(a); \ + ldr c, [rin, #8]; \ + le_to_host(b); \ + ldr d, [rin, #12]; \ + le_to_host(c); \ + le_to_host(d); + +#define str_output_aligned_le(rout, a, b, c, d) \ + le_to_host(a); \ + le_to_host(b); \ + str a, [rout, #0]; \ + le_to_host(c); \ + str b, [rout, #4]; \ + le_to_host(d); \ + str c, [rout, #8]; \ + str d, [rout, #12]; + +/* unaligned word reads/writes allowed */ +#define ldr_input_le(rin, ra, rb, rc, rd, rtmp) \ + ldr_input_aligned_le(rin, ra, rb, rc, rd) + +#define str_output_le(rout, ra, rb, rc, rd, rtmp0, rtmp1) \ + str_output_aligned_le(rout, ra, rb, rc, rd) + +/********************************************************************** + 1-way twofish + **********************************************************************/ +#define encrypt_round(a, b, rc, rd, n, ror_a, adj_a) \ + and RT0, RMASK, b, lsr#(8 - 2); \ + and RY, RMASK, b, lsr#(16 - 2); \ + and RT1, RMASK, b, lsr#(24 - 2); \ + ldr RY, [CTXs3, xRY]; \ + and RT2, RMASK, b, lsl#(2); \ + ldr RT0, [CTXs2, xRT0]; \ + and RT3, RMASK, a, lsr#(16 - 2 + (adj_a)); \ + ldr RT1, [CTXs0, xRT1]; \ + and RX, RMASK, a, lsr#(8 - 2 + (adj_a)); \ + ldr RT2, [CTXs1, xRT2]; \ + ldr RX, [CTXs1, xRX]; \ + ror_a(a); \ + \ + eor RY, RY, RT0; \ + ldr RT3, [CTXs2, xRT3]; \ + and RT0, RMASK, a, lsl#(2); \ + eor RY, RY, RT1; \ + and RT1, RMASK, a, lsr#(24 - 2); \ + eor RY, RY, RT2; \ + ldr RT0, [CTXs0, xRT0]; \ + eor RX, RX, RT3; \ + ldr RT1, [CTXs3, xRT1]; \ + eor RX, RX, RT0; \ + \ + ldr RT3, [CTXs3, #(k - s3 + 8 * (n) + 4)]; \ + eor RX, RX, RT1; \ + ldr RT2, [CTXs3, #(k - s3 + 8 * (n))]; \ + \ + add RT0, RX, RY, lsl #1; \ + add RX, RX, RY; \ + add RT0, RT0, RT3; \ + add RX, RX, RT2; \ + eor rd, RT0, rd, ror #31; \ + eor rc, rc, RX; + +#define dummy(x) /*_*/ + +#define ror1(r) \ + ror r, r, #1; + +#define decrypt_round(a, b, rc, rd, n, ror_b, adj_b) \ + and RT3, RMASK, b, lsl#(2 - (adj_b)); \ + and RT1, RMASK, b, lsr#(8 - 2 + (adj_b)); \ + ror_b(b); \ + and RT2, RMASK, a, lsl#(2); \ + and RT0, RMASK, a, lsr#(8 - 2); \ + \ + ldr RY, [CTXs1, xRT3]; \ + ldr RX, [CTXs0, xRT2]; \ + and RT3, RMASK, b, lsr#(16 - 2); \ + ldr RT1, [CTXs2, xRT1]; \ + and RT2, RMASK, a, lsr#(16 - 2); \ + ldr RT0, [CTXs1, xRT0]; \ + \ + ldr RT3, [CTXs3, xRT3]; \ + eor RY, RY, RT1; \ + \ + and RT1, RMASK, b, lsr#(24 - 2); \ + eor RX, RX, RT0; \ + ldr RT2, [CTXs2, xRT2]; \ + and RT0, RMASK, a, lsr#(24 - 2); \ + \ + ldr RT1, [CTXs0, xRT1]; \ + \ + eor RY, RY, RT3; \ + ldr RT0, [CTXs3, xRT0]; \ + eor RX, RX, RT2; \ + eor RY, RY, RT1; \ + \ + ldr RT1, [CTXs3, #(k - s3 + 8 * (n) + 4)]; \ + eor RX, RX, RT0; \ + ldr RT2, [CTXs3, #(k - s3 + 8 * (n))]; \ + \ + add RT0, RX, RY, lsl #1; \ + add RX, RX, RY; \ + add RT0, RT0, RT1; \ + add RX, RX, RT2; \ + eor rd, rd, RT0; \ + eor rc, RX, rc, ror #31; + +#define first_encrypt_cycle(nc) \ + encrypt_round(RA, RB, RC, RD, (nc) * 2, dummy, 0); \ + encrypt_round(RC, RD, RA, RB, (nc) * 2 + 1, ror1, 1); + +#define encrypt_cycle(nc) \ + encrypt_round(RA, RB, RC, RD, (nc) * 2, ror1, 1); \ + encrypt_round(RC, RD, RA, RB, (nc) * 2 + 1, ror1, 1); + +#define last_encrypt_cycle(nc) \ + encrypt_round(RA, RB, RC, RD, (nc) * 2, ror1, 1); \ + encrypt_round(RC, RD, RA, RB, (nc) * 2 + 1, ror1, 1); \ + ror1(RA); + +#define first_decrypt_cycle(nc) \ + decrypt_round(RC, RD, RA, RB, (nc) * 2 + 1, dummy, 0); \ + decrypt_round(RA, RB, RC, RD, (nc) * 2, ror1, 1); + +#define decrypt_cycle(nc) \ + decrypt_round(RC, RD, RA, RB, (nc) * 2 + 1, ror1, 1); \ + decrypt_round(RA, RB, RC, RD, (nc) * 2, ror1, 1); + +#define last_decrypt_cycle(nc) \ + decrypt_round(RC, RD, RA, RB, (nc) * 2 + 1, ror1, 1); \ + decrypt_round(RA, RB, RC, RD, (nc) * 2, ror1, 1); \ + ror1(RD); + +.globl _gcry_twofish_arm_encrypt_block +.type _gcry_twofish_arm_encrypt_block,%function; + +_gcry_twofish_arm_encrypt_block: + /* input: + * x0: ctx + * x1: dst + * x2: src + */ + + add CTXw, CTX, #(w); + + ldr_input_le(RSRC, RA, RB, RC, RD, RT0); + + /* Input whitening */ + ldp RT0, RT1, [CTXw, #(0*8)]; + ldp RT2, RT3, [CTXw, #(1*8)]; + add CTXs3, CTX, #(s3); + add CTXs2, CTX, #(s2); + add CTXs1, CTX, #(s1); + mov RMASK, #(0xff << 2); + eor RA, RA, RT0; + eor RB, RB, RT1; + eor RC, RC, RT2; + eor RD, RD, RT3; + + first_encrypt_cycle(0); + encrypt_cycle(1); + encrypt_cycle(2); + encrypt_cycle(3); + encrypt_cycle(4); + encrypt_cycle(5); + encrypt_cycle(6); + last_encrypt_cycle(7); + + /* Output whitening */ + ldp RT0, RT1, [CTXw, #(2*8)]; + ldp RT2, RT3, [CTXw, #(3*8)]; + eor RC, RC, RT0; + eor RD, RD, RT1; + eor RA, RA, RT2; + eor RB, RB, RT3; + + str_output_le(RDST, RC, RD, RA, RB, RT0, RT1); + + ret; +.ltorg +.size _gcry_twofish_arm_encrypt_block,.-_gcry_twofish_arm_encrypt_block; + +.globl _gcry_twofish_arm_decrypt_block +.type _gcry_twofish_arm_decrypt_block,%function; + +_gcry_twofish_arm_decrypt_block: + /* input: + * %r0: ctx + * %r1: dst + * %r2: src + */ + + add CTXw, CTX, #(w); + + ldr_input_le(RSRC, RC, RD, RA, RB, RT0); + + /* Input whitening */ + ldp RT0, RT1, [CTXw, #(2*8)]; + ldp RT2, RT3, [CTXw, #(3*8)]; + add CTXs3, CTX, #(s3); + add CTXs2, CTX, #(s2); + add CTXs1, CTX, #(s1); + mov RMASK, #(0xff << 2); + eor RC, RC, RT0; + eor RD, RD, RT1; + eor RA, RA, RT2; + eor RB, RB, RT3; + + first_decrypt_cycle(7); + decrypt_cycle(6); + decrypt_cycle(5); + decrypt_cycle(4); + decrypt_cycle(3); + decrypt_cycle(2); + decrypt_cycle(1); + last_decrypt_cycle(0); + + /* Output whitening */ + ldp RT0, RT1, [CTXw, #(0*8)]; + ldp RT2, RT3, [CTXw, #(1*8)]; + eor RA, RA, RT0; + eor RB, RB, RT1; + eor RC, RC, RT2; + eor RD, RD, RT3; + + str_output_le(RDST, RA, RB, RC, RD, RT0, RT1); + + ret; +.size _gcry_twofish_arm_decrypt_block,.-_gcry_twofish_arm_decrypt_block; + +#endif /*HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS*/ +#endif /*__AARCH64EL__*/ diff --git a/cipher/twofish.c b/cipher/twofish.c index f6ecd67..7a4d26a 100644 --- a/cipher/twofish.c +++ b/cipher/twofish.c @@ -66,6 +66,11 @@ # define USE_ARM_ASM 1 # endif #endif +# if defined(__AARCH64EL__) +# ifdef HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS +# define USE_ARM_ASM 1 +# endif +# endif /* Prototype for the self-test function. */ diff --git a/configure.ac b/configure.ac index 34791fa..076a92b 100644 --- a/configure.ac +++ b/configure.ac @@ -1895,6 +1895,10 @@ if test "$found" = "1" ; then # Build with the assembly implementation GCRYPT_CIPHERS="$GCRYPT_CIPHERS twofish-arm.lo" ;; + aarch64-*-*) + # Build with the assembly implementation + GCRYPT_CIPHERS="$GCRYPT_CIPHERS twofish-aarch64.lo" + ;; esac fi From jussi.kivilinna at iki.fi Thu Mar 24 17:54:11 2016 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Thu, 24 Mar 2016 18:54:11 +0200 Subject: [PATCH 2/3] Add Aarch64 assembly implementation of Camellia In-Reply-To: <20160324165406.18609.20695.stgit@localhost6.localdomain6> References: <20160324165406.18609.20695.stgit@localhost6.localdomain6> Message-ID: <20160324165411.18609.18424.stgit@localhost6.localdomain6> * cipher/Makefile.am: Add 'camellia-aarch64.S'. * cipher/camellia-aarch64.S: New. * cipher/camellia-glue.c [USE_ARM_ASM][__aarch64__]: Set stack burn size to zero. * cipher/camellia.h: Enable USE_ARM_ASM if __AARCH64EL__ and HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS defined. * configure.ac [host=aarch64]: Add 'rijndael-aarch64.lo'. -- Patch adds ARMv8/Aarch64 implementation of Camellia. Benchmark on Cortex-A53 (1536 Mhz): Before: CAMELLIA128 | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 29.83 ns/B 31.97 MiB/s 45.81 c/B ECB dec | 29.83 ns/B 31.97 MiB/s 45.81 c/B CBC enc | 30.64 ns/B 31.13 MiB/s 47.06 c/B CBC dec | 29.79 ns/B 32.01 MiB/s 45.76 c/B CFB enc | 30.56 ns/B 31.21 MiB/s 46.94 c/B CFB dec | 29.79 ns/B 32.01 MiB/s 45.76 c/B OFB enc | 30.62 ns/B 31.15 MiB/s 47.03 c/B OFB dec | 30.62 ns/B 31.15 MiB/s 47.03 c/B CTR enc | 29.95 ns/B 31.84 MiB/s 46.01 c/B CTR dec | 29.95 ns/B 31.84 MiB/s 46.00 c/B CCM enc | 60.07 ns/B 15.88 MiB/s 92.26 c/B CCM dec | 60.06 ns/B 15.88 MiB/s 92.25 c/B CCM auth | 30.20 ns/B 31.58 MiB/s 46.39 c/B GCM enc | 41.61 ns/B 22.92 MiB/s 63.92 c/B GCM dec | 41.60 ns/B 22.92 MiB/s 63.90 c/B GCM auth | 11.70 ns/B 81.54 MiB/s 17.97 c/B OCB enc | 31.60 ns/B 30.18 MiB/s 48.53 c/B OCB dec | 31.64 ns/B 30.14 MiB/s 48.61 c/B OCB auth | 31.06 ns/B 30.70 MiB/s 47.71 c/B = CAMELLIA256 | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 39.32 ns/B 24.25 MiB/s 60.40 c/B ECB dec | 39.33 ns/B 24.25 MiB/s 60.41 c/B CBC enc | 40.10 ns/B 23.78 MiB/s 61.59 c/B CBC dec | 39.06 ns/B 24.41 MiB/s 60.00 c/B CFB enc | 40.02 ns/B 23.83 MiB/s 61.47 c/B CFB dec | 39.11 ns/B 24.39 MiB/s 60.07 c/B OFB enc | 39.95 ns/B 23.87 MiB/s 61.37 c/B OFB dec | 39.95 ns/B 23.87 MiB/s 61.37 c/B CTR enc | 39.27 ns/B 24.28 MiB/s 60.32 c/B CTR dec | 39.28 ns/B 24.28 MiB/s 60.33 c/B CCM enc | 78.75 ns/B 12.11 MiB/s 121.0 c/B CCM dec | 78.75 ns/B 12.11 MiB/s 121.0 c/B CCM auth | 39.55 ns/B 24.11 MiB/s 60.74 c/B GCM enc | 50.93 ns/B 18.73 MiB/s 78.23 c/B GCM dec | 50.93 ns/B 18.73 MiB/s 78.23 c/B GCM auth | 11.66 ns/B 81.76 MiB/s 17.92 c/B OCB enc | 40.89 ns/B 23.32 MiB/s 62.81 c/B OCB dec | 40.86 ns/B 23.34 MiB/s 62.76 c/B OCB auth | 40.38 ns/B 23.62 MiB/s 62.03 c/B = After (~1.7x faster): CAMELLIA128 | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 16.68 ns/B 57.17 MiB/s 25.62 c/B ECB dec | 16.69 ns/B 57.14 MiB/s 25.64 c/B CBC enc | 17.46 ns/B 54.63 MiB/s 26.81 c/B CBC dec | 16.60 ns/B 57.46 MiB/s 25.50 c/B CFB enc | 17.38 ns/B 54.88 MiB/s 26.69 c/B CFB dec | 16.61 ns/B 57.41 MiB/s 25.52 c/B OFB enc | 17.34 ns/B 55.00 MiB/s 26.63 c/B OFB dec | 17.34 ns/B 54.99 MiB/s 26.64 c/B CTR enc | 16.77 ns/B 56.88 MiB/s 25.75 c/B CTR dec | 16.77 ns/B 56.86 MiB/s 25.76 c/B CCM enc | 33.65 ns/B 28.34 MiB/s 51.69 c/B CCM dec | 33.66 ns/B 28.34 MiB/s 51.69 c/B CCM auth | 16.97 ns/B 56.18 MiB/s 26.07 c/B GCM enc | 28.43 ns/B 33.54 MiB/s 43.67 c/B GCM dec | 28.43 ns/B 33.55 MiB/s 43.66 c/B GCM auth | 11.64 ns/B 81.96 MiB/s 17.87 c/B OCB enc | 18.23 ns/B 52.32 MiB/s 28.00 c/B OCB dec | 18.19 ns/B 52.43 MiB/s 27.94 c/B OCB auth | 17.81 ns/B 53.55 MiB/s 27.35 c/B = CAMELLIA256 | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 21.82 ns/B 43.71 MiB/s 33.51 c/B ECB dec | 21.89 ns/B 43.57 MiB/s 33.62 c/B CBC enc | 22.58 ns/B 42.23 MiB/s 34.69 c/B CBC dec | 21.72 ns/B 43.91 MiB/s 33.36 c/B CFB enc | 22.50 ns/B 42.39 MiB/s 34.56 c/B CFB dec | 21.73 ns/B 43.89 MiB/s 33.37 c/B OFB enc | 22.46 ns/B 42.45 MiB/s 34.50 c/B OFB dec | 22.46 ns/B 42.45 MiB/s 34.50 c/B CTR enc | 21.87 ns/B 43.60 MiB/s 33.60 c/B CTR dec | 21.87 ns/B 43.60 MiB/s 33.60 c/B CCM enc | 43.91 ns/B 21.72 MiB/s 67.44 c/B CCM dec | 43.91 ns/B 21.72 MiB/s 67.45 c/B CCM auth | 22.10 ns/B 43.15 MiB/s 33.95 c/B GCM enc | 33.55 ns/B 28.43 MiB/s 51.53 c/B GCM dec | 33.55 ns/B 28.42 MiB/s 51.53 c/B GCM auth | 11.71 ns/B 81.47 MiB/s 17.98 c/B OCB enc | 23.33 ns/B 40.87 MiB/s 35.84 c/B OCB dec | 23.35 ns/B 40.85 MiB/s 35.86 c/B OCB auth | 22.94 ns/B 41.58 MiB/s 35.23 c/B = Signed-off-by: Jussi Kivilinna --- 0 files changed diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 56da706..46125db 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -99,7 +99,7 @@ whirlpool.c whirlpool-sse2-amd64.S \ twofish.c twofish-amd64.S twofish-arm.S \ rfc2268.c \ camellia.c camellia.h camellia-glue.c camellia-aesni-avx-amd64.S \ - camellia-aesni-avx2-amd64.S camellia-arm.S + camellia-aesni-avx2-amd64.S camellia-arm.S camellia-aarch64.S gost28147.lo: gost-sb.h gost-sb.h: gost-s-box diff --git a/cipher/camellia-aarch64.S b/cipher/camellia-aarch64.S new file mode 100644 index 0000000..6fd937e --- /dev/null +++ b/cipher/camellia-aarch64.S @@ -0,0 +1,557 @@ +/* camellia-aarch64.S - ARMv8/Aarch64 assembly implementation of Camellia + * cipher + * + * Copyright (C) 2016 Jussi Kivilinna + * + * 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 + +#if defined(__AARCH64EL__) +#ifdef HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS + +.text + +/* struct camellia_ctx: */ +#define key_table 0 + +/* register macros */ +#define CTX x0 +#define RDST x1 +#define RSRC x2 +#define RKEYBITS x3 + +#define RTAB1 x4 +#define RTAB2 x5 +#define RTAB3 x6 +#define RTAB4 x7 +#define RMASK w8 + +#define IL w9 +#define IR w10 + +#define xIL x9 +#define xIR x10 + +#define XL w11 +#define XR w12 +#define YL w13 +#define YR w14 + +#define RT0 w15 +#define RT1 w16 +#define RT2 w17 +#define RT3 w18 + +#define xRT0 x15 +#define xRT1 x16 +#define xRT2 x17 +#define xRT3 x18 + +#ifdef __AARCH64EL__ + #define host_to_be(reg, rtmp) \ + rev reg, reg; + #define be_to_host(reg, rtmp) \ + rev reg, reg; +#else + /* nop on big-endian */ + #define host_to_be(reg, rtmp) /*_*/ + #define be_to_host(reg, rtmp) /*_*/ +#endif + +#define ldr_input_aligned_be(rin, a, b, c, d, rtmp) \ + ldr a, [rin, #0]; \ + ldr b, [rin, #4]; \ + be_to_host(a, rtmp); \ + ldr c, [rin, #8]; \ + be_to_host(b, rtmp); \ + ldr d, [rin, #12]; \ + be_to_host(c, rtmp); \ + be_to_host(d, rtmp); + +#define str_output_aligned_be(rout, a, b, c, d, rtmp) \ + be_to_host(a, rtmp); \ + be_to_host(b, rtmp); \ + str a, [rout, #0]; \ + be_to_host(c, rtmp); \ + str b, [rout, #4]; \ + be_to_host(d, rtmp); \ + str c, [rout, #8]; \ + str d, [rout, #12]; + +/* unaligned word reads/writes allowed */ +#define ldr_input_be(rin, ra, rb, rc, rd, rtmp) \ + ldr_input_aligned_be(rin, ra, rb, rc, rd, rtmp) + +#define str_output_be(rout, ra, rb, rc, rd, rtmp0, rtmp1) \ + str_output_aligned_be(rout, ra, rb, rc, rd, rtmp0) + +/********************************************************************** + 1-way camellia + **********************************************************************/ +#define roundsm(xl, xr, kl, kr, yl, yr) \ + ldr RT2, [CTX, #(key_table + ((kl) * 4))]; \ + and IR, RMASK, xr, lsl#(4); /*sp1110*/ \ + ldr RT3, [CTX, #(key_table + ((kr) * 4))]; \ + and IL, RMASK, xl, lsr#(24 - 4); /*sp1110*/ \ + and RT0, RMASK, xr, lsr#(16 - 4); /*sp3033*/ \ + ldr IR, [RTAB1, xIR]; \ + and RT1, RMASK, xl, lsr#(8 - 4); /*sp3033*/ \ + eor yl, yl, RT2; \ + ldr IL, [RTAB1, xIL]; \ + eor yr, yr, RT3; \ + \ + ldr RT0, [RTAB3, xRT0]; \ + ldr RT1, [RTAB3, xRT1]; \ + \ + and RT2, RMASK, xr, lsr#(24 - 4); /*sp0222*/ \ + and RT3, RMASK, xl, lsr#(16 - 4); /*sp0222*/ \ + \ + eor IR, IR, RT0; \ + eor IL, IL, RT1; \ + \ + ldr RT2, [RTAB2, xRT2]; \ + and RT0, RMASK, xr, lsr#(8 - 4); /*sp4404*/ \ + ldr RT3, [RTAB2, xRT3]; \ + and RT1, RMASK, xl, lsl#(4); /*sp4404*/ \ + \ + ldr RT0, [RTAB4, xRT0]; \ + ldr RT1, [RTAB4, xRT1]; \ + \ + eor IR, IR, RT2; \ + eor IL, IL, RT3; \ + eor IR, IR, RT0; \ + eor IL, IL, RT1; \ + \ + eor IR, IR, IL; \ + eor yr, yr, IL, ror#8; \ + eor yl, yl, IR; \ + eor yr, yr, IR; + +#define enc_rounds(n) \ + roundsm(XL, XR, ((n) + 2) * 2 + 0, ((n) + 2) * 2 + 1, YL, YR); \ + roundsm(YL, YR, ((n) + 3) * 2 + 0, ((n) + 3) * 2 + 1, XL, XR); \ + roundsm(XL, XR, ((n) + 4) * 2 + 0, ((n) + 4) * 2 + 1, YL, YR); \ + roundsm(YL, YR, ((n) + 5) * 2 + 0, ((n) + 5) * 2 + 1, XL, XR); \ + roundsm(XL, XR, ((n) + 6) * 2 + 0, ((n) + 6) * 2 + 1, YL, YR); \ + roundsm(YL, YR, ((n) + 7) * 2 + 0, ((n) + 7) * 2 + 1, XL, XR); + +#define dec_rounds(n) \ + roundsm(XL, XR, ((n) + 7) * 2 + 0, ((n) + 7) * 2 + 1, YL, YR); \ + roundsm(YL, YR, ((n) + 6) * 2 + 0, ((n) + 6) * 2 + 1, XL, XR); \ + roundsm(XL, XR, ((n) + 5) * 2 + 0, ((n) + 5) * 2 + 1, YL, YR); \ + roundsm(YL, YR, ((n) + 4) * 2 + 0, ((n) + 4) * 2 + 1, XL, XR); \ + roundsm(XL, XR, ((n) + 3) * 2 + 0, ((n) + 3) * 2 + 1, YL, YR); \ + roundsm(YL, YR, ((n) + 2) * 2 + 0, ((n) + 2) * 2 + 1, XL, XR); + +/* perform FL and FL?? */ +#define fls(ll, lr, rl, rr, kll, klr, krl, krr) \ + ldr RT0, [CTX, #(key_table + ((kll) * 4))]; \ + ldr RT2, [CTX, #(key_table + ((krr) * 4))]; \ + and RT0, RT0, ll; \ + ldr RT3, [CTX, #(key_table + ((krl) * 4))]; \ + orr RT2, RT2, rr; \ + ldr RT1, [CTX, #(key_table + ((klr) * 4))]; \ + eor rl, rl, RT2; \ + eor lr, lr, RT0, ror#31; \ + and RT3, RT3, rl; \ + orr RT1, RT1, lr; \ + eor ll, ll, RT1; \ + eor rr, rr, RT3, ror#31; + +#define enc_fls(n) \ + fls(XL, XR, YL, YR, \ + (n) * 2 + 0, (n) * 2 + 1, \ + (n) * 2 + 2, (n) * 2 + 3); + +#define dec_fls(n) \ + fls(XL, XR, YL, YR, \ + (n) * 2 + 2, (n) * 2 + 3, \ + (n) * 2 + 0, (n) * 2 + 1); + +#define inpack(n) \ + ldr_input_be(RSRC, XL, XR, YL, YR, RT0); \ + ldr RT0, [CTX, #(key_table + ((n) * 8) + 0)]; \ + ldr RT1, [CTX, #(key_table + ((n) * 8) + 4)]; \ + eor XL, XL, RT0; \ + eor XR, XR, RT1; + +#define outunpack(n) \ + ldr RT0, [CTX, #(key_table + ((n) * 8) + 0)]; \ + ldr RT1, [CTX, #(key_table + ((n) * 8) + 4)]; \ + eor YL, YL, RT0; \ + eor YR, YR, RT1; \ + str_output_be(RDST, YL, YR, XL, XR, RT0, RT1); + +.globl _gcry_camellia_arm_encrypt_block +.type _gcry_camellia_arm_encrypt_block, at function; + +_gcry_camellia_arm_encrypt_block: + /* input: + * x0: keytable + * x1: dst + * x2: src + * x3: keybitlen + */ + + adr RTAB1, _gcry_camellia_arm_tables; + mov RMASK, #(0xff<<4); /* byte mask */ + add RTAB2, RTAB1, #(1 * 4); + add RTAB3, RTAB1, #(2 * 4); + add RTAB4, RTAB1, #(3 * 4); + + inpack(0); + + enc_rounds(0); + enc_fls(8); + enc_rounds(8); + enc_fls(16); + enc_rounds(16); + + cmp RKEYBITS, #(16 * 8); + bne .Lenc_256; + + outunpack(24); + + ret; +.ltorg + +.Lenc_256: + enc_fls(24); + enc_rounds(24); + + outunpack(32); + + ret; +.ltorg +.size _gcry_camellia_arm_encrypt_block,.-_gcry_camellia_arm_encrypt_block; + +.globl _gcry_camellia_arm_decrypt_block +.type _gcry_camellia_arm_decrypt_block, at function; + +_gcry_camellia_arm_decrypt_block: + /* input: + * x0: keytable + * x1: dst + * x2: src + * x3: keybitlen + */ + + adr RTAB1, _gcry_camellia_arm_tables; + mov RMASK, #(0xff<<4); /* byte mask */ + add RTAB2, RTAB1, #(1 * 4); + add RTAB3, RTAB1, #(2 * 4); + add RTAB4, RTAB1, #(3 * 4); + + cmp RKEYBITS, #(16 * 8); + bne .Ldec_256; + + inpack(24); + +.Ldec_128: + dec_rounds(16); + dec_fls(16); + dec_rounds(8); + dec_fls(8); + dec_rounds(0); + + outunpack(0); + + ret; +.ltorg + +.Ldec_256: + inpack(32); + dec_rounds(24); + dec_fls(24); + + b .Ldec_128; +.ltorg +.size _gcry_camellia_arm_decrypt_block,.-_gcry_camellia_arm_decrypt_block; + +/* Encryption/Decryption tables */ +.globl _gcry_camellia_arm_tables +.type _gcry_camellia_arm_tables, at object; +.balign 32 +_gcry_camellia_arm_tables: +.Lcamellia_sp1110: +.long 0x70707000 +.Lcamellia_sp0222: + .long 0x00e0e0e0 +.Lcamellia_sp3033: + .long 0x38003838 +.Lcamellia_sp4404: + .long 0x70700070 +.long 0x82828200, 0x00050505, 0x41004141, 0x2c2c002c +.long 0x2c2c2c00, 0x00585858, 0x16001616, 0xb3b300b3 +.long 0xececec00, 0x00d9d9d9, 0x76007676, 0xc0c000c0 +.long 0xb3b3b300, 0x00676767, 0xd900d9d9, 0xe4e400e4 +.long 0x27272700, 0x004e4e4e, 0x93009393, 0x57570057 +.long 0xc0c0c000, 0x00818181, 0x60006060, 0xeaea00ea +.long 0xe5e5e500, 0x00cbcbcb, 0xf200f2f2, 0xaeae00ae +.long 0xe4e4e400, 0x00c9c9c9, 0x72007272, 0x23230023 +.long 0x85858500, 0x000b0b0b, 0xc200c2c2, 0x6b6b006b +.long 0x57575700, 0x00aeaeae, 0xab00abab, 0x45450045 +.long 0x35353500, 0x006a6a6a, 0x9a009a9a, 0xa5a500a5 +.long 0xeaeaea00, 0x00d5d5d5, 0x75007575, 0xeded00ed +.long 0x0c0c0c00, 0x00181818, 0x06000606, 0x4f4f004f +.long 0xaeaeae00, 0x005d5d5d, 0x57005757, 0x1d1d001d +.long 0x41414100, 0x00828282, 0xa000a0a0, 0x92920092 +.long 0x23232300, 0x00464646, 0x91009191, 0x86860086 +.long 0xefefef00, 0x00dfdfdf, 0xf700f7f7, 0xafaf00af +.long 0x6b6b6b00, 0x00d6d6d6, 0xb500b5b5, 0x7c7c007c +.long 0x93939300, 0x00272727, 0xc900c9c9, 0x1f1f001f +.long 0x45454500, 0x008a8a8a, 0xa200a2a2, 0x3e3e003e +.long 0x19191900, 0x00323232, 0x8c008c8c, 0xdcdc00dc +.long 0xa5a5a500, 0x004b4b4b, 0xd200d2d2, 0x5e5e005e +.long 0x21212100, 0x00424242, 0x90009090, 0x0b0b000b +.long 0xededed00, 0x00dbdbdb, 0xf600f6f6, 0xa6a600a6 +.long 0x0e0e0e00, 0x001c1c1c, 0x07000707, 0x39390039 +.long 0x4f4f4f00, 0x009e9e9e, 0xa700a7a7, 0xd5d500d5 +.long 0x4e4e4e00, 0x009c9c9c, 0x27002727, 0x5d5d005d +.long 0x1d1d1d00, 0x003a3a3a, 0x8e008e8e, 0xd9d900d9 +.long 0x65656500, 0x00cacaca, 0xb200b2b2, 0x5a5a005a +.long 0x92929200, 0x00252525, 0x49004949, 0x51510051 +.long 0xbdbdbd00, 0x007b7b7b, 0xde00dede, 0x6c6c006c +.long 0x86868600, 0x000d0d0d, 0x43004343, 0x8b8b008b +.long 0xb8b8b800, 0x00717171, 0x5c005c5c, 0x9a9a009a +.long 0xafafaf00, 0x005f5f5f, 0xd700d7d7, 0xfbfb00fb +.long 0x8f8f8f00, 0x001f1f1f, 0xc700c7c7, 0xb0b000b0 +.long 0x7c7c7c00, 0x00f8f8f8, 0x3e003e3e, 0x74740074 +.long 0xebebeb00, 0x00d7d7d7, 0xf500f5f5, 0x2b2b002b +.long 0x1f1f1f00, 0x003e3e3e, 0x8f008f8f, 0xf0f000f0 +.long 0xcecece00, 0x009d9d9d, 0x67006767, 0x84840084 +.long 0x3e3e3e00, 0x007c7c7c, 0x1f001f1f, 0xdfdf00df +.long 0x30303000, 0x00606060, 0x18001818, 0xcbcb00cb +.long 0xdcdcdc00, 0x00b9b9b9, 0x6e006e6e, 0x34340034 +.long 0x5f5f5f00, 0x00bebebe, 0xaf00afaf, 0x76760076 +.long 0x5e5e5e00, 0x00bcbcbc, 0x2f002f2f, 0x6d6d006d +.long 0xc5c5c500, 0x008b8b8b, 0xe200e2e2, 0xa9a900a9 +.long 0x0b0b0b00, 0x00161616, 0x85008585, 0xd1d100d1 +.long 0x1a1a1a00, 0x00343434, 0x0d000d0d, 0x04040004 +.long 0xa6a6a600, 0x004d4d4d, 0x53005353, 0x14140014 +.long 0xe1e1e100, 0x00c3c3c3, 0xf000f0f0, 0x3a3a003a +.long 0x39393900, 0x00727272, 0x9c009c9c, 0xdede00de +.long 0xcacaca00, 0x00959595, 0x65006565, 0x11110011 +.long 0xd5d5d500, 0x00ababab, 0xea00eaea, 0x32320032 +.long 0x47474700, 0x008e8e8e, 0xa300a3a3, 0x9c9c009c +.long 0x5d5d5d00, 0x00bababa, 0xae00aeae, 0x53530053 +.long 0x3d3d3d00, 0x007a7a7a, 0x9e009e9e, 0xf2f200f2 +.long 0xd9d9d900, 0x00b3b3b3, 0xec00ecec, 0xfefe00fe +.long 0x01010100, 0x00020202, 0x80008080, 0xcfcf00cf +.long 0x5a5a5a00, 0x00b4b4b4, 0x2d002d2d, 0xc3c300c3 +.long 0xd6d6d600, 0x00adadad, 0x6b006b6b, 0x7a7a007a +.long 0x51515100, 0x00a2a2a2, 0xa800a8a8, 0x24240024 +.long 0x56565600, 0x00acacac, 0x2b002b2b, 0xe8e800e8 +.long 0x6c6c6c00, 0x00d8d8d8, 0x36003636, 0x60600060 +.long 0x4d4d4d00, 0x009a9a9a, 0xa600a6a6, 0x69690069 +.long 0x8b8b8b00, 0x00171717, 0xc500c5c5, 0xaaaa00aa +.long 0x0d0d0d00, 0x001a1a1a, 0x86008686, 0xa0a000a0 +.long 0x9a9a9a00, 0x00353535, 0x4d004d4d, 0xa1a100a1 +.long 0x66666600, 0x00cccccc, 0x33003333, 0x62620062 +.long 0xfbfbfb00, 0x00f7f7f7, 0xfd00fdfd, 0x54540054 +.long 0xcccccc00, 0x00999999, 0x66006666, 0x1e1e001e +.long 0xb0b0b000, 0x00616161, 0x58005858, 0xe0e000e0 +.long 0x2d2d2d00, 0x005a5a5a, 0x96009696, 0x64640064 +.long 0x74747400, 0x00e8e8e8, 0x3a003a3a, 0x10100010 +.long 0x12121200, 0x00242424, 0x09000909, 0x00000000 +.long 0x2b2b2b00, 0x00565656, 0x95009595, 0xa3a300a3 +.long 0x20202000, 0x00404040, 0x10001010, 0x75750075 +.long 0xf0f0f000, 0x00e1e1e1, 0x78007878, 0x8a8a008a +.long 0xb1b1b100, 0x00636363, 0xd800d8d8, 0xe6e600e6 +.long 0x84848400, 0x00090909, 0x42004242, 0x09090009 +.long 0x99999900, 0x00333333, 0xcc00cccc, 0xdddd00dd +.long 0xdfdfdf00, 0x00bfbfbf, 0xef00efef, 0x87870087 +.long 0x4c4c4c00, 0x00989898, 0x26002626, 0x83830083 +.long 0xcbcbcb00, 0x00979797, 0xe500e5e5, 0xcdcd00cd +.long 0xc2c2c200, 0x00858585, 0x61006161, 0x90900090 +.long 0x34343400, 0x00686868, 0x1a001a1a, 0x73730073 +.long 0x7e7e7e00, 0x00fcfcfc, 0x3f003f3f, 0xf6f600f6 +.long 0x76767600, 0x00ececec, 0x3b003b3b, 0x9d9d009d +.long 0x05050500, 0x000a0a0a, 0x82008282, 0xbfbf00bf +.long 0x6d6d6d00, 0x00dadada, 0xb600b6b6, 0x52520052 +.long 0xb7b7b700, 0x006f6f6f, 0xdb00dbdb, 0xd8d800d8 +.long 0xa9a9a900, 0x00535353, 0xd400d4d4, 0xc8c800c8 +.long 0x31313100, 0x00626262, 0x98009898, 0xc6c600c6 +.long 0xd1d1d100, 0x00a3a3a3, 0xe800e8e8, 0x81810081 +.long 0x17171700, 0x002e2e2e, 0x8b008b8b, 0x6f6f006f +.long 0x04040400, 0x00080808, 0x02000202, 0x13130013 +.long 0xd7d7d700, 0x00afafaf, 0xeb00ebeb, 0x63630063 +.long 0x14141400, 0x00282828, 0x0a000a0a, 0xe9e900e9 +.long 0x58585800, 0x00b0b0b0, 0x2c002c2c, 0xa7a700a7 +.long 0x3a3a3a00, 0x00747474, 0x1d001d1d, 0x9f9f009f +.long 0x61616100, 0x00c2c2c2, 0xb000b0b0, 0xbcbc00bc +.long 0xdedede00, 0x00bdbdbd, 0x6f006f6f, 0x29290029 +.long 0x1b1b1b00, 0x00363636, 0x8d008d8d, 0xf9f900f9 +.long 0x11111100, 0x00222222, 0x88008888, 0x2f2f002f +.long 0x1c1c1c00, 0x00383838, 0x0e000e0e, 0xb4b400b4 +.long 0x32323200, 0x00646464, 0x19001919, 0x78780078 +.long 0x0f0f0f00, 0x001e1e1e, 0x87008787, 0x06060006 +.long 0x9c9c9c00, 0x00393939, 0x4e004e4e, 0xe7e700e7 +.long 0x16161600, 0x002c2c2c, 0x0b000b0b, 0x71710071 +.long 0x53535300, 0x00a6a6a6, 0xa900a9a9, 0xd4d400d4 +.long 0x18181800, 0x00303030, 0x0c000c0c, 0xabab00ab +.long 0xf2f2f200, 0x00e5e5e5, 0x79007979, 0x88880088 +.long 0x22222200, 0x00444444, 0x11001111, 0x8d8d008d +.long 0xfefefe00, 0x00fdfdfd, 0x7f007f7f, 0x72720072 +.long 0x44444400, 0x00888888, 0x22002222, 0xb9b900b9 +.long 0xcfcfcf00, 0x009f9f9f, 0xe700e7e7, 0xf8f800f8 +.long 0xb2b2b200, 0x00656565, 0x59005959, 0xacac00ac +.long 0xc3c3c300, 0x00878787, 0xe100e1e1, 0x36360036 +.long 0xb5b5b500, 0x006b6b6b, 0xda00dada, 0x2a2a002a +.long 0x7a7a7a00, 0x00f4f4f4, 0x3d003d3d, 0x3c3c003c +.long 0x91919100, 0x00232323, 0xc800c8c8, 0xf1f100f1 +.long 0x24242400, 0x00484848, 0x12001212, 0x40400040 +.long 0x08080800, 0x00101010, 0x04000404, 0xd3d300d3 +.long 0xe8e8e800, 0x00d1d1d1, 0x74007474, 0xbbbb00bb +.long 0xa8a8a800, 0x00515151, 0x54005454, 0x43430043 +.long 0x60606000, 0x00c0c0c0, 0x30003030, 0x15150015 +.long 0xfcfcfc00, 0x00f9f9f9, 0x7e007e7e, 0xadad00ad +.long 0x69696900, 0x00d2d2d2, 0xb400b4b4, 0x77770077 +.long 0x50505000, 0x00a0a0a0, 0x28002828, 0x80800080 +.long 0xaaaaaa00, 0x00555555, 0x55005555, 0x82820082 +.long 0xd0d0d000, 0x00a1a1a1, 0x68006868, 0xecec00ec +.long 0xa0a0a000, 0x00414141, 0x50005050, 0x27270027 +.long 0x7d7d7d00, 0x00fafafa, 0xbe00bebe, 0xe5e500e5 +.long 0xa1a1a100, 0x00434343, 0xd000d0d0, 0x85850085 +.long 0x89898900, 0x00131313, 0xc400c4c4, 0x35350035 +.long 0x62626200, 0x00c4c4c4, 0x31003131, 0x0c0c000c +.long 0x97979700, 0x002f2f2f, 0xcb00cbcb, 0x41410041 +.long 0x54545400, 0x00a8a8a8, 0x2a002a2a, 0xefef00ef +.long 0x5b5b5b00, 0x00b6b6b6, 0xad00adad, 0x93930093 +.long 0x1e1e1e00, 0x003c3c3c, 0x0f000f0f, 0x19190019 +.long 0x95959500, 0x002b2b2b, 0xca00caca, 0x21210021 +.long 0xe0e0e000, 0x00c1c1c1, 0x70007070, 0x0e0e000e +.long 0xffffff00, 0x00ffffff, 0xff00ffff, 0x4e4e004e +.long 0x64646400, 0x00c8c8c8, 0x32003232, 0x65650065 +.long 0xd2d2d200, 0x00a5a5a5, 0x69006969, 0xbdbd00bd +.long 0x10101000, 0x00202020, 0x08000808, 0xb8b800b8 +.long 0xc4c4c400, 0x00898989, 0x62006262, 0x8f8f008f +.long 0x00000000, 0x00000000, 0x00000000, 0xebeb00eb +.long 0x48484800, 0x00909090, 0x24002424, 0xcece00ce +.long 0xa3a3a300, 0x00474747, 0xd100d1d1, 0x30300030 +.long 0xf7f7f700, 0x00efefef, 0xfb00fbfb, 0x5f5f005f +.long 0x75757500, 0x00eaeaea, 0xba00baba, 0xc5c500c5 +.long 0xdbdbdb00, 0x00b7b7b7, 0xed00eded, 0x1a1a001a +.long 0x8a8a8a00, 0x00151515, 0x45004545, 0xe1e100e1 +.long 0x03030300, 0x00060606, 0x81008181, 0xcaca00ca +.long 0xe6e6e600, 0x00cdcdcd, 0x73007373, 0x47470047 +.long 0xdadada00, 0x00b5b5b5, 0x6d006d6d, 0x3d3d003d +.long 0x09090900, 0x00121212, 0x84008484, 0x01010001 +.long 0x3f3f3f00, 0x007e7e7e, 0x9f009f9f, 0xd6d600d6 +.long 0xdddddd00, 0x00bbbbbb, 0xee00eeee, 0x56560056 +.long 0x94949400, 0x00292929, 0x4a004a4a, 0x4d4d004d +.long 0x87878700, 0x000f0f0f, 0xc300c3c3, 0x0d0d000d +.long 0x5c5c5c00, 0x00b8b8b8, 0x2e002e2e, 0x66660066 +.long 0x83838300, 0x00070707, 0xc100c1c1, 0xcccc00cc +.long 0x02020200, 0x00040404, 0x01000101, 0x2d2d002d +.long 0xcdcdcd00, 0x009b9b9b, 0xe600e6e6, 0x12120012 +.long 0x4a4a4a00, 0x00949494, 0x25002525, 0x20200020 +.long 0x90909000, 0x00212121, 0x48004848, 0xb1b100b1 +.long 0x33333300, 0x00666666, 0x99009999, 0x99990099 +.long 0x73737300, 0x00e6e6e6, 0xb900b9b9, 0x4c4c004c +.long 0x67676700, 0x00cecece, 0xb300b3b3, 0xc2c200c2 +.long 0xf6f6f600, 0x00ededed, 0x7b007b7b, 0x7e7e007e +.long 0xf3f3f300, 0x00e7e7e7, 0xf900f9f9, 0x05050005 +.long 0x9d9d9d00, 0x003b3b3b, 0xce00cece, 0xb7b700b7 +.long 0x7f7f7f00, 0x00fefefe, 0xbf00bfbf, 0x31310031 +.long 0xbfbfbf00, 0x007f7f7f, 0xdf00dfdf, 0x17170017 +.long 0xe2e2e200, 0x00c5c5c5, 0x71007171, 0xd7d700d7 +.long 0x52525200, 0x00a4a4a4, 0x29002929, 0x58580058 +.long 0x9b9b9b00, 0x00373737, 0xcd00cdcd, 0x61610061 +.long 0xd8d8d800, 0x00b1b1b1, 0x6c006c6c, 0x1b1b001b +.long 0x26262600, 0x004c4c4c, 0x13001313, 0x1c1c001c +.long 0xc8c8c800, 0x00919191, 0x64006464, 0x0f0f000f +.long 0x37373700, 0x006e6e6e, 0x9b009b9b, 0x16160016 +.long 0xc6c6c600, 0x008d8d8d, 0x63006363, 0x18180018 +.long 0x3b3b3b00, 0x00767676, 0x9d009d9d, 0x22220022 +.long 0x81818100, 0x00030303, 0xc000c0c0, 0x44440044 +.long 0x96969600, 0x002d2d2d, 0x4b004b4b, 0xb2b200b2 +.long 0x6f6f6f00, 0x00dedede, 0xb700b7b7, 0xb5b500b5 +.long 0x4b4b4b00, 0x00969696, 0xa500a5a5, 0x91910091 +.long 0x13131300, 0x00262626, 0x89008989, 0x08080008 +.long 0xbebebe00, 0x007d7d7d, 0x5f005f5f, 0xa8a800a8 +.long 0x63636300, 0x00c6c6c6, 0xb100b1b1, 0xfcfc00fc +.long 0x2e2e2e00, 0x005c5c5c, 0x17001717, 0x50500050 +.long 0xe9e9e900, 0x00d3d3d3, 0xf400f4f4, 0xd0d000d0 +.long 0x79797900, 0x00f2f2f2, 0xbc00bcbc, 0x7d7d007d +.long 0xa7a7a700, 0x004f4f4f, 0xd300d3d3, 0x89890089 +.long 0x8c8c8c00, 0x00191919, 0x46004646, 0x97970097 +.long 0x9f9f9f00, 0x003f3f3f, 0xcf00cfcf, 0x5b5b005b +.long 0x6e6e6e00, 0x00dcdcdc, 0x37003737, 0x95950095 +.long 0xbcbcbc00, 0x00797979, 0x5e005e5e, 0xffff00ff +.long 0x8e8e8e00, 0x001d1d1d, 0x47004747, 0xd2d200d2 +.long 0x29292900, 0x00525252, 0x94009494, 0xc4c400c4 +.long 0xf5f5f500, 0x00ebebeb, 0xfa00fafa, 0x48480048 +.long 0xf9f9f900, 0x00f3f3f3, 0xfc00fcfc, 0xf7f700f7 +.long 0xb6b6b600, 0x006d6d6d, 0x5b005b5b, 0xdbdb00db +.long 0x2f2f2f00, 0x005e5e5e, 0x97009797, 0x03030003 +.long 0xfdfdfd00, 0x00fbfbfb, 0xfe00fefe, 0xdada00da +.long 0xb4b4b400, 0x00696969, 0x5a005a5a, 0x3f3f003f +.long 0x59595900, 0x00b2b2b2, 0xac00acac, 0x94940094 +.long 0x78787800, 0x00f0f0f0, 0x3c003c3c, 0x5c5c005c +.long 0x98989800, 0x00313131, 0x4c004c4c, 0x02020002 +.long 0x06060600, 0x000c0c0c, 0x03000303, 0x4a4a004a +.long 0x6a6a6a00, 0x00d4d4d4, 0x35003535, 0x33330033 +.long 0xe7e7e700, 0x00cfcfcf, 0xf300f3f3, 0x67670067 +.long 0x46464600, 0x008c8c8c, 0x23002323, 0xf3f300f3 +.long 0x71717100, 0x00e2e2e2, 0xb800b8b8, 0x7f7f007f +.long 0xbababa00, 0x00757575, 0x5d005d5d, 0xe2e200e2 +.long 0xd4d4d400, 0x00a9a9a9, 0x6a006a6a, 0x9b9b009b +.long 0x25252500, 0x004a4a4a, 0x92009292, 0x26260026 +.long 0xababab00, 0x00575757, 0xd500d5d5, 0x37370037 +.long 0x42424200, 0x00848484, 0x21002121, 0x3b3b003b +.long 0x88888800, 0x00111111, 0x44004444, 0x96960096 +.long 0xa2a2a200, 0x00454545, 0x51005151, 0x4b4b004b +.long 0x8d8d8d00, 0x001b1b1b, 0xc600c6c6, 0xbebe00be +.long 0xfafafa00, 0x00f5f5f5, 0x7d007d7d, 0x2e2e002e +.long 0x72727200, 0x00e4e4e4, 0x39003939, 0x79790079 +.long 0x07070700, 0x000e0e0e, 0x83008383, 0x8c8c008c +.long 0xb9b9b900, 0x00737373, 0xdc00dcdc, 0x6e6e006e +.long 0x55555500, 0x00aaaaaa, 0xaa00aaaa, 0x8e8e008e +.long 0xf8f8f800, 0x00f1f1f1, 0x7c007c7c, 0xf5f500f5 +.long 0xeeeeee00, 0x00dddddd, 0x77007777, 0xb6b600b6 +.long 0xacacac00, 0x00595959, 0x56005656, 0xfdfd00fd +.long 0x0a0a0a00, 0x00141414, 0x05000505, 0x59590059 +.long 0x36363600, 0x006c6c6c, 0x1b001b1b, 0x98980098 +.long 0x49494900, 0x00929292, 0xa400a4a4, 0x6a6a006a +.long 0x2a2a2a00, 0x00545454, 0x15001515, 0x46460046 +.long 0x68686800, 0x00d0d0d0, 0x34003434, 0xbaba00ba +.long 0x3c3c3c00, 0x00787878, 0x1e001e1e, 0x25250025 +.long 0x38383800, 0x00707070, 0x1c001c1c, 0x42420042 +.long 0xf1f1f100, 0x00e3e3e3, 0xf800f8f8, 0xa2a200a2 +.long 0xa4a4a400, 0x00494949, 0x52005252, 0xfafa00fa +.long 0x40404000, 0x00808080, 0x20002020, 0x07070007 +.long 0x28282800, 0x00505050, 0x14001414, 0x55550055 +.long 0xd3d3d300, 0x00a7a7a7, 0xe900e9e9, 0xeeee00ee +.long 0x7b7b7b00, 0x00f6f6f6, 0xbd00bdbd, 0x0a0a000a +.long 0xbbbbbb00, 0x00777777, 0xdd00dddd, 0x49490049 +.long 0xc9c9c900, 0x00939393, 0xe400e4e4, 0x68680068 +.long 0x43434300, 0x00868686, 0xa100a1a1, 0x38380038 +.long 0xc1c1c100, 0x00838383, 0xe000e0e0, 0xa4a400a4 +.long 0x15151500, 0x002a2a2a, 0x8a008a8a, 0x28280028 +.long 0xe3e3e300, 0x00c7c7c7, 0xf100f1f1, 0x7b7b007b +.long 0xadadad00, 0x005b5b5b, 0xd600d6d6, 0xc9c900c9 +.long 0xf4f4f400, 0x00e9e9e9, 0x7a007a7a, 0xc1c100c1 +.long 0x77777700, 0x00eeeeee, 0xbb00bbbb, 0xe3e300e3 +.long 0xc7c7c700, 0x008f8f8f, 0xe300e3e3, 0xf4f400f4 +.long 0x80808000, 0x00010101, 0x40004040, 0xc7c700c7 +.long 0x9e9e9e00, 0x003d3d3d, 0x4f004f4f, 0x9e9e009e +.size _gcry_camellia_arm_tables,.-_gcry_camellia_arm_tables; + +#endif /*HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS*/ +#endif /*__AARCH64EL__*/ diff --git a/cipher/camellia-glue.c b/cipher/camellia-glue.c index dfddb4a..1be35c9 100644 --- a/cipher/camellia-glue.c +++ b/cipher/camellia-glue.c @@ -285,12 +285,19 @@ static void Camellia_DecryptBlock(const int keyBitLength, keyBitLength); } +#ifdef __aarch64__ +# define CAMELLIA_encrypt_stack_burn_size (0) +# define CAMELLIA_decrypt_stack_burn_size (0) +#else +# define CAMELLIA_encrypt_stack_burn_size (15*4) +# define CAMELLIA_decrypt_stack_burn_size (15*4) +#endif + static unsigned int camellia_encrypt(void *c, byte *outbuf, const byte *inbuf) { CAMELLIA_context *ctx = c; Camellia_EncryptBlock(ctx->keybitlength,inbuf,ctx->keytable,outbuf); -#define CAMELLIA_encrypt_stack_burn_size (15*4) return /*burn_stack*/ (CAMELLIA_encrypt_stack_burn_size); } @@ -299,7 +306,6 @@ camellia_decrypt(void *c, byte *outbuf, const byte *inbuf) { CAMELLIA_context *ctx=c; Camellia_DecryptBlock(ctx->keybitlength,inbuf,ctx->keytable,outbuf); -#define CAMELLIA_decrypt_stack_burn_size (15*4) return /*burn_stack*/ (CAMELLIA_decrypt_stack_burn_size); } diff --git a/cipher/camellia.h b/cipher/camellia.h index d0e3c18..d7a1e6f 100644 --- a/cipher/camellia.h +++ b/cipher/camellia.h @@ -37,6 +37,11 @@ # define USE_ARM_ASM 1 # endif # endif +# if defined(__AARCH64EL__) +# ifdef HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS +# define USE_ARM_ASM 1 +# endif +# endif #endif #ifdef CAMELLIA_EXT_SYM_PREFIX #define CAMELLIA_PREFIX1(x,y) x ## y @@ -80,7 +85,7 @@ void Camellia_DecryptBlock(const int keyBitLength, const unsigned char *cipherText, const KEY_TABLE_TYPE keyTable, unsigned char *plaintext); -#endif /*!USE_ARMV6_ASM*/ +#endif /*!USE_ARM_ASM*/ #ifdef __cplusplus diff --git a/configure.ac b/configure.ac index 485478f..34791fa 100644 --- a/configure.ac +++ b/configure.ac @@ -1943,6 +1943,10 @@ if test "$found" = "1" ; then # Build with the assembly implementation GCRYPT_CIPHERS="$GCRYPT_CIPHERS camellia-arm.lo" ;; + aarch64-*-*) + # Build with the assembly implementation + GCRYPT_CIPHERS="$GCRYPT_CIPHERS camellia-aarch64.lo" + ;; esac if test x"$avxsupport" = xyes ; then From ian at cypherpunks.ca Thu Mar 24 18:16:17 2016 From: ian at cypherpunks.ca (Ian Goldberg) Date: Thu, 24 Mar 2016 13:16:17 -0400 Subject: [PATCH] Avoid undefined behavior for hashes using XOF In-Reply-To: <874mbwt05y.fsf@wheatstone.g10code.de> References: <1458775776-15785-1-git-send-email-peter@lekensteyn.nl> <87twjwtbpb.fsf@wheatstone.g10code.de> <20160324120154.GA17055@al> <874mbwt05y.fsf@wheatstone.g10code.de> Message-ID: <20160324171617.GS4943@thunk.cs.uwaterloo.ca> On Thu, Mar 24, 2016 at 03:34:17PM +0100, Werner Koch wrote: > On Thu, 24 Mar 2016 13:01, peter at lekensteyn.nl said: > > > I think that md_digest_length() is still more suitable here, the message > > is not "avoid memcpy on a NULL source", but "avoid a memcpy if there is > > nothing to copy". The former might hide hypothetical errors where the > > The memcpy specs in C99 say > > [#2] The memcpy function copies n characters from the object > pointed to by s2 into the object pointed to by s1. If > copying takes place between objects that overlap, the > behavior is undefined. > > Thus it doesn't mention a NULL pointer. However, a NULL pointer might > be assumed to trigger the overlapped case and than it would be UB. The triggering clause in the spec is actually a couple of paragraphs earlier, in 7.21.1[2]: Where an argument declared as size_t n specifies the length of the array for a function, n can have the value zero on a call to that function. Unless explicitly stated otherwise in the description of a particular function in this subclause, pointer arguments on such a call shall still have valid values, as described in 7.1.4. That is, NULL (an "invalid value", according to 7.1.4) cannot be passed to memcopy, memmove, etc., *even if* the number of bytes to be copied is 0. This has always seemed ridiculous to me, but there it is. - Ian From andrew.stevenson at sociomantic.com Thu Mar 24 18:21:35 2016 From: andrew.stevenson at sociomantic.com (Andrew Stevenson) Date: Thu, 24 Mar 2016 18:21:35 +0100 Subject: 3des-cfb failing to decrypt Message-ID: <56F4221F.4080605@sociomantic.com> Hi, I am trying to use libgcrypt to decrypt some data encoded using 3des-cfb. Unfortunately I only ever manage to decrypt the first character. I'm guessing its user error on my behalf though I've been through the documentation several times and can't see what I'm doing wrong. I have some example code posted here: https://gist.github.com/andrew-stevenson-sociomantic/7b28d0bd9f8f34bcef00 It has hard coded key, iv, cipher text and plain text. It then tries to decrypt the cipher text with OpenSSL/libcrypto, libmcrypt and libgcrypt, asserting after each that the decrypted test matches the plaintext. The libcrypto and libmcrypt methods work OK but decrypt_3des_gcrypt doesn't so the assert on line 148 fails. Can someone see what I'm doing wrong? Thanks, Andrew From andrew.stevenson at sociomantic.com Thu Mar 24 18:15:30 2016 From: andrew.stevenson at sociomantic.com (Andrew Stevenson) Date: Thu, 24 Mar 2016 18:15:30 +0100 Subject: 3des-cfb failing to decrypt Message-ID: <56F420B2.2020702@sociomantic.com> Hi, I am trying to use libgcrypt to decrypt some data encoded using 3des-cfb. Unfortunately I only ever manage to decrypt the first character. I'm guessing its user error on my behalf though I've been through the documentation several times and can't see what I'm doing wrong. I have some example code posted here: https://gist.github.com/andrew-stevenson-sociomantic/7b28d0bd9f8f34bcef00 It has hard coded key, iv, cipher text and plain text. It then tries to decrypt the cipher text with OpenSSL/libcrypto, libmcrypt and libgcrypt, asserting after each that the decrypted test matches the plaintext. The libcrypto and libmcrypt methods work OK but decrypt_3des_gcrypt doesn't so the assert on line 148 fails. Can someone see what I'm doing wrong? Thanks, Andrew From peter at lekensteyn.nl Fri Mar 25 00:31:10 2016 From: peter at lekensteyn.nl (Peter Wu) Date: Fri, 25 Mar 2016 00:31:10 +0100 Subject: [PATCH] Avoid undefined behavior for hashes using XOF In-Reply-To: <874mbwt05y.fsf@wheatstone.g10code.de> References: <1458775776-15785-1-git-send-email-peter@lekensteyn.nl> <87twjwtbpb.fsf@wheatstone.g10code.de> <20160324120154.GA17055@al> <874mbwt05y.fsf@wheatstone.g10code.de> Message-ID: <20160324233110.GD17055@al> On Thu, Mar 24, 2016 at 03:34:17PM +0100, Werner Koch wrote: > On Thu, 24 Mar 2016 13:01, peter at lekensteyn.nl said: > > > I think that md_digest_length() is still more suitable here, the message > > is not "avoid memcpy on a NULL source", but "avoid a memcpy if there is > > nothing to copy". The former might hide hypothetical errors where the > > The memcpy specs in C99 say > > [#2] The memcpy function copies n characters from the object > pointed to by s2 into the object pointed to by s1. If > copying takes place between objects that overlap, the > behavior is undefined. > > Thus it doesn't mention a NULL pointer. However, a NULL pointer might > be assumed to trigger the overlapped case and than it would be UB. Right, the point I was trying to make is that while we have to avoid the NULL as second parameter (since it is UB), there are different conditions to do so. The above should not be a problem anymore in V2 of this patch as the function just shortcircuits. Please have a look at https://lists.gnupg.org/pipermail/gcrypt-devel/2016-March/003770.html > You may also just die if md_read() return NULL. This is what > gcry_md_hash_buffers does for inknown algorithms. The function was defined to "abort on unavailable algorithms" (presumably cases where gcry_md_test_algo fails), not sure if it is a good idea to extend the cases where it can crash a program. (It is unfortunate that no error code can be returned, that makes the API hard to use (unreliable) in language bindings where the parameters can be supplied by the user). > > for XOFs, what about skipping tests for such functions? > > Yes. But print "skipped". In v2 (see above) I just omit the test from the generic list of algorithms (like it skips MD5 in FIPS mode without messages). Only if you explicitly give it (normally not done) it would try to execute it (and print garbage). Is this simple approach sufficient? -- Kind regards, Peter Wu https://lekensteyn.nl From jussi.kivilinna at iki.fi Fri Mar 25 10:49:24 2016 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Fri, 25 Mar 2016 11:49:24 +0200 Subject: [PATCH v2] cipher: GCM: check that length of supplied tag is one of valid lengths Message-ID: <20160325094924.14199.5223.stgit@localhost6.localdomain6> * cipher/cipher-gcm.c (is_tag_length_valid): New. (_gcry_cipher_gcm_tag): Check that 'outbuflen' has valid tag length. * tests/basic.c (_check_gcm_cipher): Add test-vectors with different valid tag lengths and negative test vectors with invalid lengths. -- NIST SP 800-38D allows following tag lengths: 128, 120, 112, 104, 96, 64 and 32 bits. [v2: allow larger buffer when outputting tag. 128-bit tag is written to target buffer in this case] Signed-off-by: Jussi Kivilinna --- 0 files changed diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c index 712641e..6e0959a 100644 --- a/cipher/cipher-gcm.c +++ b/cipher/cipher-gcm.c @@ -769,12 +769,32 @@ _gcry_cipher_gcm_geniv (gcry_cipher_hd_t c, #endif +static int +is_tag_length_valid(size_t taglen) +{ + switch (taglen) + { + /* Allowed tag lengths from NIST SP 800-38D. */ + case 128 / 8: /* GCRY_GCM_BLOCK_LEN */ + case 120 / 8: + case 112 / 8: + case 104 / 8: + case 96 / 8: + case 64 / 8: + case 32 / 8: + return 1; + + default: + return 0; + } +} + static gcry_err_code_t _gcry_cipher_gcm_tag (gcry_cipher_hd_t c, byte * outbuf, size_t outbuflen, int check) { - if (outbuflen < GCRY_GCM_BLOCK_LEN) - return GPG_ERR_BUFFER_TOO_SHORT; + if (!(is_tag_length_valid (outbuflen) || outbuflen >= GCRY_GCM_BLOCK_LEN)) + return GPG_ERR_INV_LENGTH; if (c->u_mode.gcm.datalen_over_limits) return GPG_ERR_INV_LENGTH; @@ -815,17 +835,19 @@ _gcry_cipher_gcm_tag (gcry_cipher_hd_t c, if (!check) { + if (outbuflen > GCRY_GCM_BLOCK_LEN) + outbuflen = GCRY_GCM_BLOCK_LEN; + /* NB: We already checked that OUTBUF is large enough to hold - the result. */ - memcpy (outbuf, c->u_mode.gcm.u_tag.tag, GCRY_GCM_BLOCK_LEN); + * the result or has valid truncated length. */ + memcpy (outbuf, c->u_mode.gcm.u_tag.tag, outbuflen); } else { /* OUTBUFLEN gives the length of the user supplied tag in OUTBUF * and thus we need to compare its length first. */ - if (outbuflen != GCRY_GCM_BLOCK_LEN - || !buf_eq_const (outbuf, c->u_mode.gcm.u_tag.tag, - GCRY_GCM_BLOCK_LEN)) + if (!is_tag_length_valid (outbuflen) + || !buf_eq_const (outbuf, c->u_mode.gcm.u_tag.tag, outbuflen)) return GPG_ERR_CHECKSUM; } diff --git a/tests/basic.c b/tests/basic.c index 36a83d0..25d31ee 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -1304,6 +1304,8 @@ _check_gcm_cipher (unsigned int step) int inlen; char out[MAX_DATA_LEN]; char tag[MAX_DATA_LEN]; + int taglen; + int should_fail; } tv[] = { /* http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf */ @@ -1319,6 +1321,78 @@ _check_gcm_cipher (unsigned int step) "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, "", 0, + "", + 0, + "", + "\x58\xe2\xfc\xce\xfa\x7e\x30\x61\x36\x7f\x1d\x57\xa4\xe7\x45", + 15 }, + { GCRY_CIPHER_AES, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "", 0, + "", + 0, + "", + "\x58\xe2\xfc\xce\xfa\x7e\x30\x61\x36\x7f\x1d\x57\xa4\xe7", + 14 }, + { GCRY_CIPHER_AES, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "", 0, + "", + 0, + "", + "\x58\xe2\xfc\xce\xfa\x7e\x30\x61\x36\x7f\x1d\x57\xa4", + 13 }, + { GCRY_CIPHER_AES, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "", 0, + "", + 0, + "", + "\x58\xe2\xfc\xce\xfa\x7e\x30\x61\x36\x7f\x1d\x57", + 12 }, + { GCRY_CIPHER_AES, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "", 0, + "", + 0, + "", + "\x58\xe2\xfc\xce\xfa\x7e\x30\x61\x36\x7f\x1d", + 11, 1 }, + { GCRY_CIPHER_AES, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "", 0, + "", + 0, + "", + "\x58\xe2\xfc\xce\xfa\x7e\x30\x61", + 8 }, + { GCRY_CIPHER_AES, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "", 0, + "", + 0, + "", + "\x58\xe2\xfc\xce", + 4 }, + { GCRY_CIPHER_AES, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "", 0, + "", + 0, + "", + "\x58", + 1, 1 }, + { GCRY_CIPHER_AES, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "", 0, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16, "\x03\x88\xda\xce\x60\xb6\xa3\x92\xf3\x28\xc2\xb9\x71\xb2\xfe\x78", @@ -1570,9 +1644,14 @@ _check_gcm_cipher (unsigned int step) if (memcmp (tv[i].plaintext, out, tv[i].inlen)) fail ("aes-gcm, decrypt mismatch entry %d (step %d)\n", i, step); - err = gcry_cipher_gettag (hde, out, GCRY_GCM_BLOCK_LEN); + taglen2 = tv[i].taglen ? tv[i].taglen : GCRY_GCM_BLOCK_LEN; + + err = gcry_cipher_gettag (hde, out, taglen2); if (err) { + if (tv[i].should_fail) + goto next_tv; + fail ("aes-gcm, gcry_cipher_gettag(%d) failed: %s\n", i, gpg_strerror (err)); gcry_cipher_close (hde); @@ -1580,11 +1659,10 @@ _check_gcm_cipher (unsigned int step) return; } - if (memcmp (tv[i].tag, out, GCRY_GCM_BLOCK_LEN)) + if (memcmp (tv[i].tag, out, taglen2)) fail ("aes-gcm, encrypt tag mismatch entry %d\n", i); - - err = gcry_cipher_checktag (hdd, out, GCRY_GCM_BLOCK_LEN); + err = gcry_cipher_checktag (hdd, out, taglen2); if (err) { fail ("aes-gcm, gcry_cipher_checktag(%d) failed: %s\n", @@ -1660,17 +1738,25 @@ _check_gcm_cipher (unsigned int step) if (memcmp (tv[i].out, out, tv[i].inlen)) fail ("aes-gcm, encrypt mismatch entry %d, (byte-buf)\n", i); - err = gcry_cipher_gettag (hde, tag, GCRY_GCM_BLOCK_LEN); + /* Test output to larger than 16-byte buffer. */ + taglen2 = tv[i].taglen ? tv[i].taglen : GCRY_GCM_BLOCK_LEN + 1; + + err = gcry_cipher_gettag (hde, tag, taglen2); if (err) { - fail ("aes-gcm, gcry_cipher_gettag(%d) (byte-buf) failed: %s\n", - i, gpg_strerror (err)); + if (tv[i].should_fail) + goto next_tv; + + fail ("aes-gcm, gcry_cipher_gettag(%d, %d) (byte-buf) failed: %s\n", + i, taglen2, gpg_strerror (err)); gcry_cipher_close (hde); gcry_cipher_close (hdd); return; } - if (memcmp (tv[i].tag, tag, GCRY_GCM_BLOCK_LEN)) + taglen2 = tv[i].taglen ? tv[i].taglen : GCRY_GCM_BLOCK_LEN; + + if (memcmp (tv[i].tag, tag, taglen2)) fail ("aes-gcm, encrypt tag mismatch entry %d, (byte-buf)\n", i); for (byteNum = 0; byteNum < tv[i].inlen; ++byteNum) @@ -1689,7 +1775,7 @@ _check_gcm_cipher (unsigned int step) if (memcmp (tv[i].plaintext, out, tv[i].inlen)) fail ("aes-gcm, decrypt mismatch entry %d\n", i); - err = gcry_cipher_checktag (hdd, tag, GCRY_GCM_BLOCK_LEN); + err = gcry_cipher_checktag (hdd, tag, taglen2); if (err) { fail ("aes-gcm, gcry_cipher_checktag(%d) (byte-buf) failed: %s\n", @@ -1699,6 +1785,34 @@ _check_gcm_cipher (unsigned int step) return; } + err = gcry_cipher_checktag (hdd, tag, 1); + if (!err) + { + fail ("aes-gcm, gcry_cipher_checktag(%d) did not fail for invalid " + " tag length of '%d'\n", i, 1); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + err = gcry_cipher_checktag (hdd, tag, 17); + if (!err) + { + fail ("aes-gcm, gcry_cipher_checktag(%d) did not fail for invalid " + " tag length of '%d'\n", i, 17); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + if (tv[i].should_fail) + { + fail ("aes-gcm, negative test succeeded %d\n", i); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + +next_tv: gcry_cipher_close (hde); gcry_cipher_close (hdd); } From wk at gnupg.org Fri Mar 25 12:24:48 2016 From: wk at gnupg.org (Werner Koch) Date: Fri, 25 Mar 2016 12:24:48 +0100 Subject: [admin] Mail problems yesterday Message-ID: <87mvpmre9r.fsf@wheatstone.g10code.de> Hi! There was a small problem with the mailing list server yesterday [1]. In case your MTA is sending or receiving via an IPv6 address you may have missed some mails or posted mails may have get lost. If they don't show up today, please resent your mail or check the mail archives. Sorry for that. Salam-Shalom, Werner [1] I added a v6 address for gnutls.org to the server but forgot to explicitly set the v6 address to be used by Exim. Thus mails were wrongly sent from the gnutls.org v6 address which does not match lists.gnupg.org. -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 180 bytes Desc: not available URL: From jussi.kivilinna at iki.fi Fri Mar 25 12:28:45 2016 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Fri, 25 Mar 2016 13:28:45 +0200 Subject: 3des-cfb failing to decrypt In-Reply-To: <56F420B2.2020702@sociomantic.com> References: <56F420B2.2020702@sociomantic.com> Message-ID: <56F520ED.50007@iki.fi> Hello, In your example, you are using OpenSSL/libcrypto and mcrypt with CFB-8bit mode. Libgcrypt CFB-mode works as CFB-64 for 64-bit blockciphers and as CFB-128 for 128-bit. -Jussi On 24.03.2016 19:15, Andrew Stevenson wrote: > Hi, > > I am trying to use libgcrypt to decrypt some data encoded using 3des-cfb. Unfortunately I only ever manage to decrypt the first character. I'm guessing its user error on my behalf though I've been through the documentation several times and can't see what I'm doing wrong. > > I have some example code posted here: https://gist.github.com/andrew-stevenson-sociomantic/7b28d0bd9f8f34bcef00 > > It has hard coded key, iv, cipher text and plain text. It then tries to decrypt the cipher text with OpenSSL/libcrypto, libmcrypt and libgcrypt, asserting after each that the decrypted test matches the plaintext. The libcrypto and libmcrypt methods work OK but decrypt_3des_gcrypt doesn't so the assert on line 148 fails. > > Can someone see what I'm doing wrong? > > Thanks, > > Andrew > > > _______________________________________________ > Gcrypt-devel mailing list > Gcrypt-devel at gnupg.org > http://lists.gnupg.org/mailman/listinfo/gcrypt-devel > From cvs at cvs.gnupg.org Sun Mar 27 10:18:30 2016 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Sun, 27 Mar 2016 10:18:30 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-365-gf2260e3 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via f2260e3a2e962ac80124ef938e54041bbea08561 (commit) from 4a064e2a06fe737f344d1dfd8a45cc4c2abbe4c9 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit f2260e3a2e962ac80124ef938e54041bbea08561 Author: Jussi Kivilinna Date: Sun Mar 27 11:17:39 2016 +0300 cipher: GCM: check that length of supplied tag is one of valid lengths * cipher/cipher-gcm.c (is_tag_length_valid): New. (_gcry_cipher_gcm_tag): Check that 'outbuflen' has valid tag length. * tests/basic.c (_check_gcm_cipher): Add test-vectors with different valid tag lengths and negative test vectors with invalid lengths. -- NIST SP 800-38D allows following tag lengths: 128, 120, 112, 104, 96, 64 and 32 bits. [v2: allow larger buffer when outputting tag. 128-bit tag is written to target buffer in this case] Signed-off-by: Jussi Kivilinna diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c index 712641e..6e0959a 100644 --- a/cipher/cipher-gcm.c +++ b/cipher/cipher-gcm.c @@ -769,12 +769,32 @@ _gcry_cipher_gcm_geniv (gcry_cipher_hd_t c, #endif +static int +is_tag_length_valid(size_t taglen) +{ + switch (taglen) + { + /* Allowed tag lengths from NIST SP 800-38D. */ + case 128 / 8: /* GCRY_GCM_BLOCK_LEN */ + case 120 / 8: + case 112 / 8: + case 104 / 8: + case 96 / 8: + case 64 / 8: + case 32 / 8: + return 1; + + default: + return 0; + } +} + static gcry_err_code_t _gcry_cipher_gcm_tag (gcry_cipher_hd_t c, byte * outbuf, size_t outbuflen, int check) { - if (outbuflen < GCRY_GCM_BLOCK_LEN) - return GPG_ERR_BUFFER_TOO_SHORT; + if (!(is_tag_length_valid (outbuflen) || outbuflen >= GCRY_GCM_BLOCK_LEN)) + return GPG_ERR_INV_LENGTH; if (c->u_mode.gcm.datalen_over_limits) return GPG_ERR_INV_LENGTH; @@ -815,17 +835,19 @@ _gcry_cipher_gcm_tag (gcry_cipher_hd_t c, if (!check) { + if (outbuflen > GCRY_GCM_BLOCK_LEN) + outbuflen = GCRY_GCM_BLOCK_LEN; + /* NB: We already checked that OUTBUF is large enough to hold - the result. */ - memcpy (outbuf, c->u_mode.gcm.u_tag.tag, GCRY_GCM_BLOCK_LEN); + * the result or has valid truncated length. */ + memcpy (outbuf, c->u_mode.gcm.u_tag.tag, outbuflen); } else { /* OUTBUFLEN gives the length of the user supplied tag in OUTBUF * and thus we need to compare its length first. */ - if (outbuflen != GCRY_GCM_BLOCK_LEN - || !buf_eq_const (outbuf, c->u_mode.gcm.u_tag.tag, - GCRY_GCM_BLOCK_LEN)) + if (!is_tag_length_valid (outbuflen) + || !buf_eq_const (outbuf, c->u_mode.gcm.u_tag.tag, outbuflen)) return GPG_ERR_CHECKSUM; } diff --git a/tests/basic.c b/tests/basic.c index 36a83d0..25d31ee 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -1304,6 +1304,8 @@ _check_gcm_cipher (unsigned int step) int inlen; char out[MAX_DATA_LEN]; char tag[MAX_DATA_LEN]; + int taglen; + int should_fail; } tv[] = { /* http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf */ @@ -1319,6 +1321,78 @@ _check_gcm_cipher (unsigned int step) "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, "", 0, + "", + 0, + "", + "\x58\xe2\xfc\xce\xfa\x7e\x30\x61\x36\x7f\x1d\x57\xa4\xe7\x45", + 15 }, + { GCRY_CIPHER_AES, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "", 0, + "", + 0, + "", + "\x58\xe2\xfc\xce\xfa\x7e\x30\x61\x36\x7f\x1d\x57\xa4\xe7", + 14 }, + { GCRY_CIPHER_AES, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "", 0, + "", + 0, + "", + "\x58\xe2\xfc\xce\xfa\x7e\x30\x61\x36\x7f\x1d\x57\xa4", + 13 }, + { GCRY_CIPHER_AES, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "", 0, + "", + 0, + "", + "\x58\xe2\xfc\xce\xfa\x7e\x30\x61\x36\x7f\x1d\x57", + 12 }, + { GCRY_CIPHER_AES, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "", 0, + "", + 0, + "", + "\x58\xe2\xfc\xce\xfa\x7e\x30\x61\x36\x7f\x1d", + 11, 1 }, + { GCRY_CIPHER_AES, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "", 0, + "", + 0, + "", + "\x58\xe2\xfc\xce\xfa\x7e\x30\x61", + 8 }, + { GCRY_CIPHER_AES, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "", 0, + "", + 0, + "", + "\x58\xe2\xfc\xce", + 4 }, + { GCRY_CIPHER_AES, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "", 0, + "", + 0, + "", + "\x58", + 1, 1 }, + { GCRY_CIPHER_AES, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "", 0, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16, "\x03\x88\xda\xce\x60\xb6\xa3\x92\xf3\x28\xc2\xb9\x71\xb2\xfe\x78", @@ -1570,9 +1644,14 @@ _check_gcm_cipher (unsigned int step) if (memcmp (tv[i].plaintext, out, tv[i].inlen)) fail ("aes-gcm, decrypt mismatch entry %d (step %d)\n", i, step); - err = gcry_cipher_gettag (hde, out, GCRY_GCM_BLOCK_LEN); + taglen2 = tv[i].taglen ? tv[i].taglen : GCRY_GCM_BLOCK_LEN; + + err = gcry_cipher_gettag (hde, out, taglen2); if (err) { + if (tv[i].should_fail) + goto next_tv; + fail ("aes-gcm, gcry_cipher_gettag(%d) failed: %s\n", i, gpg_strerror (err)); gcry_cipher_close (hde); @@ -1580,11 +1659,10 @@ _check_gcm_cipher (unsigned int step) return; } - if (memcmp (tv[i].tag, out, GCRY_GCM_BLOCK_LEN)) + if (memcmp (tv[i].tag, out, taglen2)) fail ("aes-gcm, encrypt tag mismatch entry %d\n", i); - - err = gcry_cipher_checktag (hdd, out, GCRY_GCM_BLOCK_LEN); + err = gcry_cipher_checktag (hdd, out, taglen2); if (err) { fail ("aes-gcm, gcry_cipher_checktag(%d) failed: %s\n", @@ -1660,17 +1738,25 @@ _check_gcm_cipher (unsigned int step) if (memcmp (tv[i].out, out, tv[i].inlen)) fail ("aes-gcm, encrypt mismatch entry %d, (byte-buf)\n", i); - err = gcry_cipher_gettag (hde, tag, GCRY_GCM_BLOCK_LEN); + /* Test output to larger than 16-byte buffer. */ + taglen2 = tv[i].taglen ? tv[i].taglen : GCRY_GCM_BLOCK_LEN + 1; + + err = gcry_cipher_gettag (hde, tag, taglen2); if (err) { - fail ("aes-gcm, gcry_cipher_gettag(%d) (byte-buf) failed: %s\n", - i, gpg_strerror (err)); + if (tv[i].should_fail) + goto next_tv; + + fail ("aes-gcm, gcry_cipher_gettag(%d, %d) (byte-buf) failed: %s\n", + i, taglen2, gpg_strerror (err)); gcry_cipher_close (hde); gcry_cipher_close (hdd); return; } - if (memcmp (tv[i].tag, tag, GCRY_GCM_BLOCK_LEN)) + taglen2 = tv[i].taglen ? tv[i].taglen : GCRY_GCM_BLOCK_LEN; + + if (memcmp (tv[i].tag, tag, taglen2)) fail ("aes-gcm, encrypt tag mismatch entry %d, (byte-buf)\n", i); for (byteNum = 0; byteNum < tv[i].inlen; ++byteNum) @@ -1689,7 +1775,7 @@ _check_gcm_cipher (unsigned int step) if (memcmp (tv[i].plaintext, out, tv[i].inlen)) fail ("aes-gcm, decrypt mismatch entry %d\n", i); - err = gcry_cipher_checktag (hdd, tag, GCRY_GCM_BLOCK_LEN); + err = gcry_cipher_checktag (hdd, tag, taglen2); if (err) { fail ("aes-gcm, gcry_cipher_checktag(%d) (byte-buf) failed: %s\n", @@ -1699,6 +1785,34 @@ _check_gcm_cipher (unsigned int step) return; } + err = gcry_cipher_checktag (hdd, tag, 1); + if (!err) + { + fail ("aes-gcm, gcry_cipher_checktag(%d) did not fail for invalid " + " tag length of '%d'\n", i, 1); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + err = gcry_cipher_checktag (hdd, tag, 17); + if (!err) + { + fail ("aes-gcm, gcry_cipher_checktag(%d) did not fail for invalid " + " tag length of '%d'\n", i, 17); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + if (tv[i].should_fail) + { + fail ("aes-gcm, negative test succeeded %d\n", i); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + +next_tv: gcry_cipher_close (hde); gcry_cipher_close (hdd); } ----------------------------------------------------------------------- Summary of changes: cipher/cipher-gcm.c | 36 +++++++++++--- tests/basic.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 152 insertions(+), 16 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From ametzler at bebt.de Sun Mar 27 15:36:47 2016 From: ametzler at bebt.de (Andreas Metzler) Date: Sun, 27 Mar 2016 15:36:47 +0200 Subject: Crash in bench-slope Message-ID: <20160327133647.GA1824@argenau.bebt.de> Hello, bench-slope occasionally crashes (amd64), backtrace (for GIT master) attached. I only see this with fortify, I am buildig with: CFLAGS=-g -O2 -fstack-protector-strong -Wformat -Werror=format-security CPPFLAGS=-Wdate-time -D_FORTIFY_SOURCE=2 CXXFLAGS=-g -O2 -fstack-protector-strong -Wformat -Werror=format-security FCFLAGS=-g -O2 -fstack-protector-strong FFLAGS=-g -O2 -fstack-protector-strong GCJFLAGS=-g -O2 -fstack-protector-strong LDFLAGS=-Wl,-z,relro OBJCFLAGS=-g -O2 -fstack-protector-strong -Wformat -Werror=format-security OBJCXXFLAGS=-g -O2 -fstack-protector-strong -Wformat -Werror=format-security cu Andreas -- `What a good friend you are to him, Dr. Maturin. His other friends are so grateful to you.' `I sew his ears on from time to time, sure' -------------- next part -------------- (sid)ametzler at argenau:/tmp/GCR/libgcrypt.git$ env GCRYPT_IN_REGRESSION_TEST=1 gdb build*/tests/bench-slope GNU gdb (Debian 7.10-1+b1) 7.10 Copyright (C) 2015 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: . Find the GDB manual and other documentation resources online at: . For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from build-tree/tests/bench-slope...done. (gdb) run Starting program: /tmp/GCR/libgcrypt.git/build-tree/tests/bench-slope Note: bench-slope running in quick regression test mode. Hash: | nanosecs/byte mebibytes/sec cycles/byte MD5 | 1.47 ns/B 648.4 MiB/s - c/B SHA1 | 1.04 ns/B 916.7 MiB/s - c/B RIPEMD160 | 2.33 ns/B 408.7 MiB/s - c/B TIGER192 | 1.54 ns/B 619.1 MiB/s - c/B SHA256 | 2.46 ns/B 387.9 MiB/s - c/B SHA384 | 1.68 ns/B 566.0 MiB/s - c/B SHA512 | 1.63 ns/B 583.6 MiB/s - c/B SHA224 | 2.35 ns/B 405.9 MiB/s - c/B MD4 | 0.829 ns/B 1150.0 MiB/s - c/B CRC32 | 0.041 ns/B 23370.2 MiB/s - c/B CRC32RFC1510 | 0.041 ns/B 23523.1 MiB/s - c/B CRC24RFC2440 | 0.072 ns/B 13263.1 MiB/s - c/B WHIRLPOOL | 3.87 ns/B 246.3 MiB/s - c/B TIGER | 1.51 ns/B 631.5 MiB/s - c/B TIGER2 | 1.51 ns/B 632.3 MiB/s - c/B GOSTR3411_94 | 19.42 ns/B 49.11 MiB/s - c/B STRIBOG256 | 7.25 ns/B 131.5 MiB/s - c/B STRIBOG512 | 7.53 ns/B 126.6 MiB/s - c/B GOSTR3411_CP | 19.74 ns/B 48.32 MiB/s - c/B SHA3-224 | 2.43 ns/B 392.9 MiB/s - c/B SHA3-256 | 2.66 ns/B 358.2 MiB/s - c/B SHA3-384 | 3.05 ns/B 313.2 MiB/s - c/B SHA3-512 | 4.46 ns/B 214.0 MiB/s - c/B SHAKE128 | 2.10 ns/B 454.4 MiB/s - c/B SHAKE256 | 2.39 ns/B 399.4 MiB/s - c/B = MAC: | nanosecs/byte mebibytes/sec cycles/byte HMAC_SHA256 | 2.35 ns/B 405.6 MiB/s - c/B HMAC_SHA224 | 2.31 ns/B 413.1 MiB/s - c/B HMAC_SHA512 | 1.64 ns/B 579.8 MiB/s - c/B HMAC_SHA384 | 1.56 ns/B 612.9 MiB/s - c/B HMAC_SHA1 | 1.04 ns/B 913.7 MiB/s - c/B HMAC_MD5 | 1.48 ns/B 645.0 MiB/s - c/B HMAC_MD4 | 0.831 ns/B 1147.4 MiB/s - c/B HMAC_RIPEMD160 | 2.29 ns/B 417.0 MiB/s - c/B HMAC_TIGER | 1.51 ns/B 632.5 MiB/s - c/B HMAC_WHIRLPOOL | 3.96 ns/B 241.0 MiB/s - c/B HMAC_GOSTR3411_94 | 19.75 ns/B 48.29 MiB/s - c/B HMAC_STRIBOG256 | 7.57 ns/B 125.9 MiB/s - c/B HMAC_STRIBOG512 | 7.40 ns/B 128.9 MiB/s - c/B HMAC_SHA3_224 | 2.15 ns/B 442.9 MiB/s - c/B HMAC_SHA3_256 | 2.55 ns/B 374.7 MiB/s - c/B HMAC_SHA3_384 | 3.12 ns/B 305.7 MiB/s - c/B HMAC_SHA3_512 | 4.56 ns/B 209.0 MiB/s - c/B CMAC_AES | 0.771 ns/B 1237.0 MiB/s - c/B CMAC_3DES | 24.84 ns/B 38.40 MiB/s - c/B CMAC_CAMELLIA | 5.54 ns/B 172.2 MiB/s - c/B CMAC_CAST5 | 8.28 ns/B 115.2 MiB/s - c/B CMAC_BLOWFISH | 7.47 ns/B 127.6 MiB/s - c/B CMAC_TWOFISH | 4.65 ns/B 205.1 MiB/s - c/B CMAC_SERPENT | 10.54 ns/B 90.46 MiB/s - c/B CMAC_SEED | 11.60 ns/B 82.21 MiB/s - c/B CMAC_RFC2268 | 15.29 ns/B 62.38 MiB/s - c/B CMAC_IDEA | 10.66 ns/B 89.46 MiB/s - c/B CMAC_GOST28147 | 16.32 ns/B 58.45 MiB/s - c/B GMAC_AES | 0.163 ns/B 5866.3 MiB/s - c/B GMAC_CAMELLIA | 0.228 ns/B 4179.1 MiB/s - c/B GMAC_TWOFISH | 0.161 ns/B 5912.6 MiB/s - c/B GMAC_SERPENT | 0.162 ns/B 5900.4 MiB/s - c/B GMAC_SEED | 0.162 ns/B 5893.7 MiB/s - c/B POLY1305 | 0.189 ns/B 5039.0 MiB/s - c/B POLY1305_AES | 0.190 ns/B 5014.5 MiB/s - c/B POLY1305_CAMELLIA | 0.077 ns/B 12356.4 MiB/s - c/B POLY1305_TWOFISH | 0.277 ns/B 3445.1 MiB/s - c/B POLY1305_SERPENT | 0.275 ns/B 3473.8 MiB/s - c/B POLY1305_SEED | 0.189 ns/B 5049.0 MiB/s - c/B = Cipher: IDEA | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 9.27 ns/B 102.9 MiB/s - c/B ECB dec | 9.08 ns/B 105.1 MiB/s - c/B CBC enc | 9.97 ns/B 95.70 MiB/s - c/B CBC dec | 9.17 ns/B 104.0 MiB/s - c/B CFB enc | 9.89 ns/B 96.44 MiB/s - c/B CFB dec | 9.40 ns/B 101.4 MiB/s - c/B OFB enc | 9.78 ns/B 97.51 MiB/s - c/B OFB dec | 9.95 ns/B 95.88 MiB/s - c/B CTR enc | 10.00 ns/B 95.41 MiB/s - c/B CTR dec | 9.75 ns/B 97.81 MiB/s - c/B = 3DES | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 23.16 ns/B 41.18 MiB/s - c/B ECB dec | 23.50 ns/B 40.58 MiB/s - c/B CBC enc | 24.43 ns/B 39.03 MiB/s - c/B CBC dec | 11.29 ns/B 84.45 MiB/s - c/B CFB enc | 24.36 ns/B 39.15 MiB/s - c/B CFB dec | 11.58 ns/B 82.35 MiB/s - c/B OFB enc | 24.02 ns/B 39.70 MiB/s - c/B OFB dec | 23.89 ns/B 39.92 MiB/s - c/B CTR enc | 11.61 ns/B 82.16 MiB/s - c/B CTR dec | 11.35 ns/B 84.03 MiB/s - c/B = CAST5 | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 6.57 ns/B 145.2 MiB/s - c/B ECB dec | 6.75 ns/B 141.4 MiB/s - c/B CBC enc | 8.09 ns/B 117.9 MiB/s - c/B CBC dec | 2.69 ns/B 354.9 MiB/s - c/B CFB enc | 8.04 ns/B 118.6 MiB/s - c/B CFB dec | 2.67 ns/B 357.6 MiB/s - c/B OFB enc | 8.02 ns/B 118.9 MiB/s - c/B OFB dec | 7.91 ns/B 120.6 MiB/s - c/B CTR enc | 2.72 ns/B 351.2 MiB/s - c/B CTR dec | 2.75 ns/B 346.7 MiB/s - c/B = BLOWFISH | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 5.36 ns/B 178.0 MiB/s - c/B ECB dec | 5.35 ns/B 178.4 MiB/s - c/B CBC enc | 7.30 ns/B 130.6 MiB/s - c/B CBC dec | 2.06 ns/B 462.0 MiB/s - c/B CFB enc | 7.37 ns/B 129.4 MiB/s - c/B CFB dec | 2.23 ns/B 428.3 MiB/s - c/B OFB enc | 7.28 ns/B 131.0 MiB/s - c/B OFB dec | 7.06 ns/B 135.2 MiB/s - c/B CTR enc | 2.07 ns/B 460.5 MiB/s - c/B CTR dec | 2.14 ns/B 446.2 MiB/s - c/B = AES | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 0.250 ns/B 3815.2 MiB/s - c/B ECB dec | 0.263 ns/B 3630.0 MiB/s - c/B CBC enc | 0.720 ns/B 1325.1 MiB/s - c/B CBC dec | 0.156 ns/B 6094.2 MiB/s - c/B CFB enc | 0.761 ns/B 1252.7 MiB/s - c/B CFB dec | 0.136 ns/B 7034.6 MiB/s - c/B OFB enc | 0.797 ns/B 1196.3 MiB/s - c/B OFB dec | 0.761 ns/B 1252.6 MiB/s - c/B CTR enc | 0.150 ns/B 6338.8 MiB/s - c/B CTR dec | 0.150 ns/B 6373.7 MiB/s - c/B CCM enc | 0.920 ns/B 1036.5 MiB/s - c/B CCM dec | 0.927 ns/B 1028.6 MiB/s - c/B CCM auth | 0.628 ns/B 1518.5 MiB/s - c/B GCM enc | 0.286 ns/B 3330.3 MiB/s - c/B GCM dec | 0.301 ns/B 3167.7 MiB/s - c/B GCM auth | 0.092 ns/B 10355.1 MiB/s - c/B OCB enc | 0.096 ns/B 9937.0 MiB/s - c/B OCB dec | 0.137 ns/B 6953.5 MiB/s - c/B OCB auth | 0.108 ns/B 8813.2 MiB/s - c/B = AES192 | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 0.284 ns/B 3358.3 MiB/s - c/B ECB dec | 0.331 ns/B 2878.6 MiB/s - c/B CBC enc | 0.831 ns/B 1147.0 MiB/s - c/B CBC dec | 0.176 ns/B 5433.7 MiB/s - c/B CFB enc | 0.893 ns/B 1068.5 MiB/s - c/B CFB dec | 0.182 ns/B 5251.5 MiB/s - c/B OFB enc | 0.861 ns/B 1107.4 MiB/s - c/B OFB dec | 0.882 ns/B 1080.7 MiB/s - c/B CTR enc | 0.172 ns/B 5537.8 MiB/s - c/B CTR dec | 0.191 ns/B 5004.8 MiB/s - c/B CCM enc | 0.976 ns/B 977.2 MiB/s - c/B CCM dec | 0.944 ns/B 1009.9 MiB/s - c/B CCM auth | 0.718 ns/B 1329.1 MiB/s - c/B GCM enc | 0.295 ns/B 3227.7 MiB/s - c/B GCM dec | 0.289 ns/B 3304.9 MiB/s - c/B GCM auth | 0.093 ns/B 10244.9 MiB/s - c/B OCB enc | 0.215 ns/B 4431.3 MiB/s - c/B OCB dec | 0.134 ns/B 7117.4 MiB/s - c/B OCB auth | 0.184 ns/B 5185.5 MiB/s - c/B = AES256 | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 0.398 ns/B 2393.7 MiB/s - c/B ECB dec | 0.391 ns/B 2437.4 MiB/s - c/B CBC enc | 0.977 ns/B 976.3 MiB/s - c/B CBC dec | 0.212 ns/B 4493.9 MiB/s - c/B CFB enc | 0.955 ns/B 998.3 MiB/s - c/B CFB dec | 0.216 ns/B 4406.0 MiB/s - c/B OFB enc | 1.02 ns/B 936.5 MiB/s - c/B OFB dec | 1.05 ns/B 910.1 MiB/s - c/B CTR enc | 0.231 ns/B 4126.3 MiB/s - c/B CTR dec | 0.209 ns/B 4552.8 MiB/s - c/B CCM enc | 1.61 ns/B 592.1 MiB/s - c/B CCM dec | 1.09 ns/B 871.3 MiB/s - c/B CCM auth | 0.877 ns/B 1087.9 MiB/s - c/B GCM enc | 0.312 ns/B 3056.0 MiB/s - c/B GCM dec | 0.339 ns/B 2810.7 MiB/s - c/B GCM auth | 0.152 ns/B 6294.5 MiB/s - c/B OCB enc | 0.156 ns/B 6129.8 MiB/s - c/B OCB dec | 0.155 ns/B 6162.3 MiB/s - c/B OCB auth | 0.202 ns/B 4717.9 MiB/s - c/B = TWOFISH | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 4.27 ns/B 223.3 MiB/s - c/B ECB dec | 4.12 ns/B 231.7 MiB/s - c/B CBC enc | 4.69 ns/B 203.4 MiB/s - c/B CBC dec | 2.66 ns/B 358.4 MiB/s - c/B CFB enc | 4.64 ns/B 205.6 MiB/s - c/B CFB dec | 2.69 ns/B 354.4 MiB/s - c/B OFB enc | 4.15 ns/B 230.0 MiB/s - c/B OFB dec | 4.27 ns/B 223.5 MiB/s - c/B CTR enc | 2.69 ns/B 354.6 MiB/s - c/B CTR dec | 2.68 ns/B 356.3 MiB/s - c/B CCM enc | 7.11 ns/B 134.1 MiB/s - c/B CCM dec | 7.06 ns/B 135.1 MiB/s - c/B CCM auth | 4.38 ns/B 217.9 MiB/s - c/B GCM enc | 2.84 ns/B 336.3 MiB/s - c/B GCM dec | 2.83 ns/B 337.6 MiB/s - c/B GCM auth | 0.095 ns/B 10019.6 MiB/s - c/B OCB enc | 2.72 ns/B 350.3 MiB/s - c/B OCB dec | 2.65 ns/B 359.5 MiB/s - c/B OCB auth | 2.48 ns/B 384.3 MiB/s - c/B = ARCFOUR | nanosecs/byte mebibytes/sec cycles/byte STREAM enc | 1.43 ns/B 664.9 MiB/s - c/B STREAM dec | 1.39 ns/B 684.2 MiB/s - c/B = DES | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 10.16 ns/B 93.91 MiB/s - c/B ECB dec | 10.05 ns/B 94.93 MiB/s - c/B CBC enc | 11.18 ns/B 85.27 MiB/s - c/B CBC dec | 10.17 ns/B 93.80 MiB/s - c/B CFB enc | 11.07 ns/B 86.17 MiB/s - c/B CFB dec | 10.11 ns/B 94.30 MiB/s - c/B OFB enc | 10.86 ns/B 87.78 MiB/s - c/B OFB dec | 11.11 ns/B 85.82 MiB/s - c/B CTR enc | 11.37 ns/B 83.87 MiB/s - c/B CTR dec | 11.10 ns/B 85.94 MiB/s - c/B = TWOFISH128 | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 4.12 ns/B 231.5 MiB/s - c/B ECB dec | 3.89 ns/B 244.9 MiB/s - c/B CBC enc | 4.68 ns/B 203.7 MiB/s - c/B CBC dec | 2.71 ns/B 352.0 MiB/s - c/B CFB enc | 4.73 ns/B 201.5 MiB/s - c/B CFB dec | 2.79 ns/B 341.8 MiB/s - c/B OFB enc | 4.28 ns/B 222.8 MiB/s - c/B OFB dec | 4.12 ns/B 231.3 MiB/s - c/B CTR enc | 2.74 ns/B 347.7 MiB/s - c/B CTR dec | 2.77 ns/B 344.6 MiB/s - c/B CCM enc | 7.16 ns/B 133.1 MiB/s - c/B CCM dec | 7.18 ns/B 132.9 MiB/s - c/B CCM auth | 4.45 ns/B 214.3 MiB/s - c/B GCM enc | 2.94 ns/B 324.8 MiB/s - c/B GCM dec | 2.80 ns/B 340.2 MiB/s - c/B GCM auth | 0.110 ns/B 8662.1 MiB/s - c/B OCB enc | 2.92 ns/B 326.8 MiB/s - c/B OCB dec | 2.79 ns/B 341.9 MiB/s - c/B OCB auth | 2.91 ns/B 327.2 MiB/s - c/B = SERPENT128 | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 10.18 ns/B 93.66 MiB/s - c/B ECB dec | 9.04 ns/B 105.5 MiB/s - c/B CBC enc | 10.31 ns/B 92.49 MiB/s - c/B CBC dec | 1.14 ns/B 836.6 MiB/s - c/B CFB enc | 10.30 ns/B 92.62 MiB/s - c/B CFB dec | 1.13 ns/B 846.8 MiB/s - c/B OFB enc | 9.84 ns/B 96.92 MiB/s - c/B OFB dec | 9.89 ns/B 96.42 MiB/s - c/B CTR enc | 1.21 ns/B 788.7 MiB/s - c/B CTR dec | 0.993 ns/B 959.9 MiB/s - c/B CCM enc | 11.61 ns/B 82.15 MiB/s - c/B CCM dec | 11.62 ns/B 82.04 MiB/s - c/B CCM auth | 10.28 ns/B 92.76 MiB/s - c/B GCM enc | 1.25 ns/B 762.2 MiB/s - c/B GCM dec | 1.29 ns/B 738.8 MiB/s - c/B GCM auth | 0.044 ns/B 21493.8 MiB/s - c/B OCB enc | 0.978 ns/B 974.6 MiB/s - c/B OCB dec | 0.990 ns/B 963.2 MiB/s - c/B OCB auth | 0.879 ns/B 1085.4 MiB/s - c/B = SERPENT192 | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 9.96 ns/B 95.79 MiB/s - c/B ECB dec | 8.94 ns/B 106.6 MiB/s - c/B CBC enc | 10.20 ns/B 93.51 MiB/s - c/B CBC dec | 1.15 ns/B 831.3 MiB/s - c/B CFB enc | 10.58 ns/B 90.15 MiB/s - c/B CFB dec | 1.21 ns/B 789.3 MiB/s - c/B OFB enc | 10.38 ns/B 91.88 MiB/s - c/B OFB dec | 9.89 ns/B 96.39 MiB/s - c/B CTR enc | 1.17 ns/B 817.8 MiB/s - c/B CTR dec | 1.16 ns/B 820.4 MiB/s - c/B CCM enc | 11.14 ns/B 85.62 MiB/s - c/B CCM dec | 11.60 ns/B 82.19 MiB/s - c/B CCM auth | 10.25 ns/B 93.07 MiB/s - c/B GCM enc | 1.37 ns/B 697.4 MiB/s - c/B GCM dec | 1.14 ns/B 834.1 MiB/s - c/B GCM auth | 0.169 ns/B 5649.2 MiB/s - c/B OCB enc | 1.13 ns/B 843.2 MiB/s - c/B OCB dec | 1.10 ns/B 865.5 MiB/s - c/B OCB auth | 1.09 ns/B 877.0 MiB/s - c/B = SERPENT256 | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 9.85 ns/B 96.87 MiB/s - c/B ECB dec | 9.12 ns/B 104.5 MiB/s - c/B CBC enc | 10.48 ns/B 91.02 MiB/s - c/B CBC dec | 1.15 ns/B 826.3 MiB/s - c/B CFB enc | 10.24 ns/B 93.17 MiB/s - c/B CFB dec | 1.25 ns/B 764.1 MiB/s - c/B OFB enc | 9.72 ns/B 98.14 MiB/s - c/B OFB dec | 10.16 ns/B 93.90 MiB/s - c/B CTR enc | 1.19 ns/B 801.3 MiB/s - c/B CTR dec | 1.07 ns/B 887.4 MiB/s - c/B CCM enc | 11.46 ns/B 83.19 MiB/s - c/B CCM dec | 11.67 ns/B 81.70 MiB/s - c/B CCM auth | 10.12 ns/B 94.20 MiB/s - c/B GCM enc | 1.27 ns/B 749.0 MiB/s - c/B GCM dec | 1.37 ns/B 694.2 MiB/s - c/B GCM auth | Program received signal SIGABRT, Aborted. 0x00007ffff7548478 in __GI_raise (sig=sig at entry=6) at ../sysdeps/unix/sysv/linux/raise.c:55 55 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory. (gdb) set pagination 0 (gdb) bt full #0 0x00007ffff7548478 in __GI_raise (sig=sig at entry=6) at ../sysdeps/unix/sysv/linux/raise.c:55 resultvar = 0 pid = 2258 selftid = 2258 #1 0x00007ffff75498fa in __GI_abort () at abort.c:89 save_stage = 2 act = {__sigaction_handler = {sa_handler = 0x7772203030306666, sa_sigaction = 0x7772203030306666}, sa_mask = {__val = {3472328296226648109, 3475143045726351408, 2314885530819502128, 2314885530818453536, 2314885530818453536, 8391150724257423392, 7378697234196161377, 3919933115663279718, 7378634724483280944, 7378697629483820646, 8223625903103619126, 3472328295963457581, 4192904167887482928, 2314885531086893104, 2314885530818453536, 8528445641706184736}}, sa_flags = 1668512115, sa_restorer = 0x61} sigs = {__val = {32, 0 }} #2 0x00007ffff7586ffa in __libc_message (do_abort=do_abort at entry=2, fmt=fmt at entry=0x7ffff767cd11 "*** %s ***: %s terminated\n") at ../sysdeps/posix/libc_fatal.c:175 ap = fd = 3 on_2 = list = nlist = cp = written = #3 0x00007ffff760e347 in __GI___fortify_fail (msg=msg at entry=0x7ffff767cca8 "buffer overflow detected") at fortify_fail.c:31 No locals. #4 0x00007ffff760c510 in __GI___chk_fail () at chk_fail.c:28 No locals. #5 0x00007ffff760b6fd in __strcat_chk (dest=dest at entry=0x7fffffffe410 "-531842.093 MiB/-", src=src at entry=0x404cd5 " MiB/s", destlen=, destlen at entry=16) at strcat_chk.c:37 s1 = s2 = c = #6 0x0000000000402a4c in strncat (__len=15, __src=0x404cd5 " MiB/s", __dest=0x7fffffffe410 "-531842.093 MiB/-") at /usr/include/x86_64-linux-gnu/bits/string3.h:156 No locals. #7 bench_print_result_std (nsecs_per_byte=) at ../../tests/bench-slope.c:539 mbytes_per_sec = nsecpbyte_buf = "-0.002 ns/B\000A\000\000" mbpsec_buf = "-531842.093 MiB/" cycles_per_byte = cpbyte_buf = "-\000@\000\000\000\000\000`e`\000\000\000\000" #8 bench_print_result (nsecs_per_byte=) at ../../tests/bench-slope.c:551 No locals. #9 0x0000000000403d8d in cipher_bench_one (pmode=, algo=306) at ../../tests/bench-slope.c:1232 mode = {mode = 9, name = 0x404ef8 "GCM auth", ops = 0x606700 , algo = 306} obj = {ops = 0x606700 , num_measure_repetitions = 2, min_bufsize = 16, max_bufsize = 4112, step_size = 64, priv = 0x6071c0} result = blklen = #10 _cipher_bench (algo=algo at entry=306) at ../../tests/bench-slope.c:1247 algoname = i = #11 0x00000000004042b6 in cipher_bench (argv=, argc=0) at ../../tests/bench-slope.c:1273 i = 306 #12 0x0000000000401d2c in main (argc=0, argv=0x7fffffffe620) at ../../tests/bench-slope.c:1911 last_argc = debug = 0 (gdb) x/16i $pc => 0x7ffff7548478 <__GI_raise+56>: cmp $0xfffffffffffff000,%rax 0x7ffff754847e <__GI_raise+62>: ja 0x7ffff75484a0 <__GI_raise+96> 0x7ffff7548480 <__GI_raise+64>: repz retq 0x7ffff7548482 <__GI_raise+66>: nopw 0x0(%rax,%rax,1) 0x7ffff7548488 <__GI_raise+72>: test %ecx,%ecx 0x7ffff754848a <__GI_raise+74>: jg 0x7ffff754846b <__GI_raise+43> 0x7ffff754848c <__GI_raise+76>: mov %ecx,%edx 0x7ffff754848e <__GI_raise+78>: neg %edx 0x7ffff7548490 <__GI_raise+80>: and $0x7fffffff,%ecx 0x7ffff7548496 <__GI_raise+86>: cmove %esi,%edx 0x7ffff7548499 <__GI_raise+89>: mov %edx,%ecx 0x7ffff754849b <__GI_raise+91>: jmp 0x7ffff754846b <__GI_raise+43> 0x7ffff754849d <__GI_raise+93>: nopl (%rax) 0x7ffff75484a0 <__GI_raise+96>: mov 0x36a9c9(%rip),%rdx # 0x7ffff78b2e70 0x7ffff75484a7 <__GI_raise+103>: neg %eax 0x7ffff75484a9 <__GI_raise+105>: mov %eax,%fs:(%rdx) (gdb) thread apply all backtrace Thread 1 (process 2258): #0 0x00007ffff7548478 in __GI_raise (sig=sig at entry=6) at ../sysdeps/unix/sysv/linux/raise.c:55 #1 0x00007ffff75498fa in __GI_abort () at abort.c:89 #2 0x00007ffff7586ffa in __libc_message (do_abort=do_abort at entry=2, fmt=fmt at entry=0x7ffff767cd11 "*** %s ***: %s terminated\n") at ../sysdeps/posix/libc_fatal.c:175 #3 0x00007ffff760e347 in __GI___fortify_fail (msg=msg at entry=0x7ffff767cca8 "buffer overflow detected") at fortify_fail.c:31 #4 0x00007ffff760c510 in __GI___chk_fail () at chk_fail.c:28 #5 0x00007ffff760b6fd in __strcat_chk (dest=dest at entry=0x7fffffffe410 "-531842.093 MiB/-", src=src at entry=0x404cd5 " MiB/s", destlen=, destlen at entry=16) at strcat_chk.c:37 #6 0x0000000000402a4c in strncat (__len=15, __src=0x404cd5 " MiB/s", __dest=0x7fffffffe410 "-531842.093 MiB/-") at /usr/include/x86_64-linux-gnu/bits/string3.h:156 #7 bench_print_result_std (nsecs_per_byte=) at ../../tests/bench-slope.c:539 #8 bench_print_result (nsecs_per_byte=) at ../../tests/bench-slope.c:551 #9 0x0000000000403d8d in cipher_bench_one (pmode=, algo=306) at ../../tests/bench-slope.c:1232 #10 _cipher_bench (algo=algo at entry=306) at ../../tests/bench-slope.c:1247 #11 0x00000000004042b6 in cipher_bench (argv=, argc=0) at ../../tests/bench-slope.c:1273 #12 0x0000000000401d2c in main (argc=0, argv=0x7fffffffe620) at ../../tests/bench-slope.c:1911 (gdb) quit A debugging session is active. Inferior 1 [process 2258] will be killed. Quit anyway? (y or n) y From andrew.stevenson at sociomantic.com Tue Mar 29 10:47:29 2016 From: andrew.stevenson at sociomantic.com (Andrew Stevenson) Date: Tue, 29 Mar 2016 10:47:29 +0200 Subject: 3des-cfb failing to decrypt In-Reply-To: <56F520ED.50007@iki.fi> References: <56F420B2.2020702@sociomantic.com> <56F520ED.50007@iki.fi> Message-ID: <56FA4121.5020601@sociomantic.com> On 25.03.2016 12:28, Jussi Kivilinna wrote: > Hello, > > In your example, you are using OpenSSL/libcrypto and mcrypt with CFB-8bit mode. > > Libgcrypt CFB-mode works as CFB-64 for 64-bit blockciphers and as CFB-128 for > 128-bit. Ah - that makes sense. Does gcrypt support 8 bit mode? I don't see anything in the docs... Thanks, Andrew From cvs at cvs.gnupg.org Tue Mar 29 11:32:20 2016 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Tue, 29 Mar 2016 11:32:20 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-366-ge2cbd22 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via e2cbd22e03a68fbecc930052330df0c2096d2788 (commit) from f2260e3a2e962ac80124ef938e54041bbea08561 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit e2cbd22e03a68fbecc930052330df0c2096d2788 Author: Werner Koch Date: Tue Mar 29 11:31:55 2016 +0200 doc: Update for gcry_cipher_gettag and gcry_cipher_checktag. -- Also re-indent one label. Signed-off-by: Werner Koch diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index 8451627..5433ae8 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -1794,15 +1794,23 @@ authenticated data (AAD) for AEAD cipher modes. @end deftypefun - at deftypefun gcry_error_t gcry_cipher_gettag (gcry_cipher_hd_t @var{h}, void *@var{tag}, size_t @var{taglen}) + at deftypefun {gcry_error_t} gcry_cipher_gettag @ + (@w{gcry_cipher_hd_t @var{h}}, @ + @w{void *@var{tag}}, @w{size_t @var{taglen}}) This function is used to read the authentication tag after encryption. The function finalizes and outputs the authentication tag to the buffer @var{tag} of length @var{taglen} bytes. +Depending on the used mode certain restrictions for @var{taglen} are +enforced: For GCM @var{taglen} must be at least 16 or one of the +allowed truncated lengths (4, 8, 12, 13, 14, or 15). + @end deftypefun - at deftypefun gcry_error_t gcry_cipher_checktag (gcry_cipher_hd_t @var{h}, const void *@var{tag}, size_t @var{taglen}) + at deftypefun {gcry_error_t} gcry_cipher_checktag @ + (@w{gcry_cipher_hd_t @var{h}}, @ + @w{const void *@var{tag}}, @w{size_t @var{taglen}}) Check the authentication tag after decryption. The authentication tag is passed as the buffer @var{tag} of length @var{taglen} bytes @@ -1811,6 +1819,10 @@ decryption. Error code @code{GPG_ERR_CHECKSUM} is returned if the authentication tag in the buffer @var{tag} does not match the authentication tag calculated during decryption. +Depending on the used mode certain restrictions for @var{taglen} are +enforced: For GCM @var{taglen} must either be 16 or one of the allowed +truncated lengths (4, 8, 12, 13, 14, or 15). + @end deftypefun The actual encryption and decryption is done by using one of the diff --git a/tests/basic.c b/tests/basic.c index 25d31ee..1a7d3cb 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -1812,7 +1812,7 @@ _check_gcm_cipher (unsigned int step) return; } -next_tv: + next_tv: gcry_cipher_close (hde); gcry_cipher_close (hdd); } ----------------------------------------------------------------------- Summary of changes: doc/gcrypt.texi | 16 ++++++++++++++-- tests/basic.c | 2 +- 2 files changed, 15 insertions(+), 3 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From cvs at cvs.gnupg.org Tue Mar 29 12:07:04 2016 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Tue, 29 Mar 2016 12:07:04 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-367-g48ee918 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via 48ee918400762281bec5b6fc218a9f0d119aac7c (commit) from e2cbd22e03a68fbecc930052330df0c2096d2788 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 48ee918400762281bec5b6fc218a9f0d119aac7c Author: Werner Koch Date: Tue Mar 29 12:06:25 2016 +0200 tests: Fix buffer overflow in bench-slope. * tests/bench-slope.c (bench_print_result_std): Remove wrong use of strncat. -- Reported-by: Andreas Metzler Signed-off-by: Werner Koch diff --git a/tests/bench-slope.c b/tests/bench-slope.c index 8938f18..d97494c 100644 --- a/tests/bench-slope.c +++ b/tests/bench-slope.c @@ -520,8 +520,6 @@ bench_print_result_std (double nsecs_per_byte) char mbpsec_buf[16]; char cpbyte_buf[16]; - strcpy (cpbyte_buf, "-"); - double_to_str (nsecpbyte_buf, sizeof (nsecpbyte_buf), nsecs_per_byte); /* If user didn't provide CPU speed, we cannot show cycles/byte results. */ @@ -530,16 +528,15 @@ bench_print_result_std (double nsecs_per_byte) cycles_per_byte = nsecs_per_byte * cpu_ghz; double_to_str (cpbyte_buf, sizeof (cpbyte_buf), cycles_per_byte); } + else + strcpy (cpbyte_buf, "-"); mbytes_per_sec = (1000.0 * 1000.0 * 1000.0) / (nsecs_per_byte * 1024 * 1024); double_to_str (mbpsec_buf, sizeof (mbpsec_buf), mbytes_per_sec); - strncat (nsecpbyte_buf, " ns/B", sizeof (nsecpbyte_buf) - 1); - strncat (mbpsec_buf, " MiB/s", sizeof (mbpsec_buf) - 1); - strncat (cpbyte_buf, " c/B", sizeof (cpbyte_buf) - 1); - - printf ("%14s %15s %13s\n", nsecpbyte_buf, mbpsec_buf, cpbyte_buf); + printf ("%9s ns/B %9s MiB/s %9s c/B\n", + nsecpbyte_buf, mbpsec_buf, cpbyte_buf); } static void ----------------------------------------------------------------------- Summary of changes: tests/bench-slope.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From wk at gnupg.org Tue Mar 29 12:09:01 2016 From: wk at gnupg.org (Werner Koch) Date: Tue, 29 Mar 2016 12:09:01 +0200 Subject: Crash in bench-slope In-Reply-To: <20160327133647.GA1824@argenau.bebt.de> (Andreas Metzler's message of "Sun, 27 Mar 2016 15:36:47 +0200") References: <20160327133647.GA1824@argenau.bebt.de> Message-ID: <87r3etmw8y.fsf@wheatstone.g10code.de> On Sun, 27 Mar 2016 15:36, ametzler at bebt.de said: > bench-slope occasionally crashes (amd64), backtrace (for GIT master) > attached. strncat was not used correctly. A long number would overflow a static buffer when adding the measurement module. commit 48ee918 should fix this. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Tue Mar 29 12:34:02 2016 From: wk at gnupg.org (Werner Koch) Date: Tue, 29 Mar 2016 12:34:02 +0200 Subject: 3des-cfb failing to decrypt In-Reply-To: <56FA4121.5020601@sociomantic.com> (Andrew Stevenson's message of "Tue, 29 Mar 2016 10:47:29 +0200") References: <56F420B2.2020702@sociomantic.com> <56F520ED.50007@iki.fi> <56FA4121.5020601@sociomantic.com> Message-ID: <87egatmv39.fsf@wheatstone.g10code.de> On Tue, 29 Mar 2016 10:47, andrew.stevenson at sociomantic.com said: > Ah - that makes sense. Does gcrypt support 8 bit mode? I don't see No. Why is actually using anything but a mode macthing the block size? Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From andrew.stevenson at sociomantic.com Tue Mar 29 12:36:24 2016 From: andrew.stevenson at sociomantic.com (Andrew Stevenson) Date: Tue, 29 Mar 2016 12:36:24 +0200 Subject: 3des-cfb failing to decrypt In-Reply-To: <87egatmv39.fsf@wheatstone.g10code.de> References: <56F420B2.2020702@sociomantic.com> <56F520ED.50007@iki.fi> <56FA4121.5020601@sociomantic.com> <87egatmv39.fsf@wheatstone.g10code.de> Message-ID: <56FA5AA8.10403@sociomantic.com> On 29.03.2016 12:34, Werner Koch wrote: > On Tue, 29 Mar 2016 10:47, andrew.stevenson at sociomantic.com said: > >> Ah - that makes sense. Does gcrypt support 8 bit mode? I don't see > No. Why is actually using anything but a mode macthing the block size? No idea - I didn't encrypt the data (well not the real data I need to decrypt) - I just get sent it and need to make sense of it. Thanks! Andrew -- Andrew Stevenson Software Developer sociomantic labs GmbH Paul-Linkce-Ufer 39/40 10999 BERLIN DEUTSCHLAND http://www.sociomantic.com Fon: +49 (0)30 5015 4701 Fax: +49 (0)30 3087 4619 Skype: andrew.stevenson.sociomantic Twitter: http://www.twitter.com/sociomantic Facebook: http://bit.ly/labsfacebook ----------------------------------------------------------- sociomantic labs GmbH, Location: Berlin Commercial Register - AG Charlottenburg: HRB 121302 B VAT No. - USt-ID: DE 266262100 Managing Directors: Thomas Nicolai, Thomas Brandhoff From jussi.kivilinna at iki.fi Tue Mar 29 14:32:54 2016 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 29 Mar 2016 15:32:54 +0300 Subject: 3des-cfb failing to decrypt In-Reply-To: <87egatmv39.fsf@wheatstone.g10code.de> References: <56F420B2.2020702@sociomantic.com> <56F520ED.50007@iki.fi> <56FA4121.5020601@sociomantic.com> <87egatmv39.fsf@wheatstone.g10code.de> Message-ID: <56FA75F6.6000203@iki.fi> On 2016-03-29 13:34, Werner Koch wrote: > On Tue, 29 Mar 2016 10:47, andrew.stevenson at sociomantic.com said: > >> Ah - that makes sense. Does gcrypt support 8 bit mode? I don't see > > No. Why is actually using anything but a mode macthing the block size? > FIPS-81 defines k-bit CFB mode for DES where k is any number from 1 to 64. Maybe this had something to do with systems with different bits per byte (6/7/8/?). -Jussi > > Salam-Shalom, > > Werner > From ametzler at bebt.de Thu Mar 31 19:46:15 2016 From: ametzler at bebt.de (Andreas Metzler) Date: Thu, 31 Mar 2016 19:46:15 +0200 Subject: Crash in bench-slope References: <20160327133647.GA1824@argenau.bebt.de> <87r3etmw8y.fsf@wheatstone.g10code.de> Message-ID: <5c40tc-cn1.ln1@argenau.bebt.de> Werner Koch wrote: [...] > strncat was not used correctly. A long number would overflow a static > buffer when adding the measurement module. > commit 48ee918 should fix this. Thanks. FYI 48ee918 built successfully on all Debian release archs and most of the ports (powerpcspe and sh4, did not fail, they just did not try yet.) cu Andreas https://buildd.debian.org/status/package.php?p=libgcrypt20&suite=experimental -- `What a good friend you are to him, Dr. Maturin. His other friends are so grateful to you.' `I sew his ears on from time to time, sure' From cvs at cvs.gnupg.org Thu Mar 31 20:33:34 2016 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Thu, 31 Mar 2016 20:33:34 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-370-gfcce0cb Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via fcce0cb6e8af70b134c6ecc3f56afa07a7d31f27 (commit) via a9cbe2d1f6a517a831517da8bc1d29e3e0b2c0c0 (commit) via 142a479a484cb4e84d0561be9b05b44dac9e6fe2 (commit) from 48ee918400762281bec5b6fc218a9f0d119aac7c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit fcce0cb6e8af70b134c6ecc3f56afa07a7d31f27 Author: Werner Koch Date: Thu Mar 31 20:16:10 2016 +0200 cipher: Remove specialized rmd160 functions. * cipher/rmd160.c: Replace rmd.h by hash-common.h. (RMD160_CONTEXT): Move from rmd.h to here. (_gcry_rmd160_init): Remove. (_gcry_rmd160_mixblock): Remove. (_gcry_rmd160_hash_buffer): Use rmd160_init directly. * cipher/md.c: Remove rmd.h which was not actually used. * cipher/rmd.h: Remove. * cipher/Makefile.am (libcipher_la_SOURCES): Remove rmd.h. * configure.ac (USE_RMD160): Allow to build without RMD160. -- Those functions are not anymore required because random-csprng.c now uses SHA-1. Signed-off-by: Werner Koch diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 85248a2..f60338a 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -57,7 +57,7 @@ bufhelp.h \ primegen.c \ hash-common.c hash-common.h \ dsa-common.c rsa-common.c \ -sha1.h rmd.h +sha1.h EXTRA_libcipher_la_SOURCES = \ arcfour.c arcfour-amd64.S \ diff --git a/cipher/md.c b/cipher/md.c index 5b4f0c1..d0ef00f 100644 --- a/cipher/md.c +++ b/cipher/md.c @@ -28,8 +28,6 @@ #include "g10lib.h" #include "cipher.h" -#include "rmd.h" - /* This is the list of the digest implementations included in libgcrypt. */ diff --git a/cipher/rmd.h b/cipher/rmd.h deleted file mode 100644 index a56ee49..0000000 --- a/cipher/rmd.h +++ /dev/null @@ -1,35 +0,0 @@ -/* rmd.h - RIPE-MD hash functions - * Copyright (C) 1998, 2001, 2002 Free Software Foundation, Inc. - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ -#ifndef G10_RMD_H -#define G10_RMD_H - -#include "hash-common.h" - -/* We need this here because random.c must have direct access. */ -typedef struct -{ - gcry_md_block_ctx_t bctx; - u32 h0,h1,h2,h3,h4; -} RMD160_CONTEXT; - -void _gcry_rmd160_init ( void *context ); -void _gcry_rmd160_mixblock ( RMD160_CONTEXT *hd, void *blockof64byte ); - -#endif /*G10_RMD_H*/ diff --git a/cipher/rmd160.c b/cipher/rmd160.c index cf7531e..0a019b9 100644 --- a/cipher/rmd160.c +++ b/cipher/rmd160.c @@ -24,7 +24,7 @@ #include #include "g10lib.h" -#include "rmd.h" +#include "hash-common.h" #include "cipher.h" /* Only used for the rmd160_hash_buffer() prototype. */ #include "bithelp.h" @@ -140,6 +140,13 @@ * 1 million times "a" 52783243c1697bdbe16d37f97f68f08325dc1528 */ +typedef struct +{ + gcry_md_block_ctx_t bctx; + u32 h0,h1,h2,h3,h4; +} RMD160_CONTEXT; + + static unsigned int transform ( void *ctx, const unsigned char *data, size_t nblks ); @@ -164,13 +171,6 @@ rmd160_init (void *context, unsigned int flags) } -void -_gcry_rmd160_init (void *context) -{ - rmd160_init (context, 0); -} - - /**************** * Transform the message X which consists of 16 32-bit-words */ @@ -399,32 +399,9 @@ transform ( void *c, const unsigned char *data, size_t nblks ) } -/**************** - * Apply the rmd160 transform function on the buffer which must have - * a length 64 bytes. Do not use this function together with the - * other functions, use rmd160_init to initialize internal variables. - * Buffer must be 32-bit aligned. - * Returns: 20 bytes in buffer with the mixed contents of buffer. +/* + * The routine terminates the computation */ -void -_gcry_rmd160_mixblock ( RMD160_CONTEXT *hd, void *blockof64byte ) -{ - u32 *p = blockof64byte; - - transform ( hd, blockof64byte, 1 ); -#define X(a) do { p[a] = hd->h##a; } while(0) - X(0); - X(1); - X(2); - X(3); - X(4); -#undef X -} - - -/* The routine terminates the computation - */ - static void rmd160_final( void *context ) { @@ -503,7 +480,7 @@ _gcry_rmd160_hash_buffer (void *outbuf, const void *buffer, size_t length ) { RMD160_CONTEXT hd; - _gcry_rmd160_init ( &hd ); + rmd160_init (&hd, 0); _gcry_md_block_write ( &hd, buffer, length ); rmd160_final ( &hd ); memcpy ( outbuf, hd.bctx.buf, 20 ); diff --git a/configure.ac b/configure.ac index 6a2d61b..716c6ec 100644 --- a/configure.ac +++ b/configure.ac @@ -2066,6 +2066,12 @@ if test "$found" = "1" ; then AC_DEFINE(USE_MD5, 1, [Defined if this module should be included]) fi +LIST_MEMBER(rmd160, $enabled_digests) +if test "$found" = "1" ; then + GCRYPT_DIGESTS="$GCRYPT_DIGESTS rmd160.lo" + AC_DEFINE(USE_RMD160, 1, [Defined if this module should be included]) +fi + LIST_MEMBER(sha256, $enabled_digests) if test "$found" = "1" ; then GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha256.lo" @@ -2142,9 +2148,9 @@ if test "$found" = "1" ; then esac fi -# rmd160 and sha1 should be included always. -GCRYPT_DIGESTS="$GCRYPT_DIGESTS rmd160.lo sha1.lo" -AC_DEFINE(USE_RMD160, 1, [Defined if this module should be included]) +# SHA-1 needs to be included always for example because it is used by +# random-csprng.c. +GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha1.lo" AC_DEFINE(USE_SHA1, 1, [Defined if this module should be included]) case "${host}" in commit a9cbe2d1f6a517a831517da8bc1d29e3e0b2c0c0 Author: Werner Koch Date: Thu Mar 31 19:33:43 2016 +0200 random: Replace RMD160 by SHA-1 for mixing the CSPRNG pool. * cipher/sha1.c (_gcry_sha1_mixblock_init): New. (_gcry_sha1_mixblock): New. * random/random-csprng.c: Include sha1.h instead of rmd.h. (mix_pool): Use SHA-1 instead of RIPE-MD-160 for mixing. Signed-off-by: Werner Koch diff --git a/cipher/sha1.c b/cipher/sha1.c index 19e75b2..d15c2a2 100644 --- a/cipher/sha1.c +++ b/cipher/sha1.c @@ -130,6 +130,17 @@ sha1_init (void *context, unsigned int flags) (void)features; } +/* + * Initialize the context HD. This is used to prepare the use of + * _gcry_sha1_mixblock. WARNING: This is a special purpose function + * for exclusive use by random-csprng.c. + */ +void +_gcry_sha1_mixblock_init (SHA1_CONTEXT *hd) +{ + sha1_init (hd, 0); +} + /* Round function macros. */ #define K1 0x5A827999L @@ -354,6 +365,33 @@ transform (void *ctx, const unsigned char *data, size_t nblks) } +/* + * Apply the SHA-1 transform function on the buffer BLOCKOF64BYTE + * which must have a length 64 bytes. BLOCKOF64BYTE must be 32-bit + * aligned. Updates the 20 bytes in BLOCKOF64BYTE with its mixed + * content. Returns the number of bytes which should be burned on the + * stack. You need to use _gcry_sha1_mixblock_init to initialize the + * context. + * WARNING: This is a special purpose function for exclusive use by + * random-csprng.c. + */ +unsigned int +_gcry_sha1_mixblock (SHA1_CONTEXT *hd, void *blockof64byte) +{ + u32 *p = blockof64byte; + unsigned int nburn; + + nburn = transform (hd, blockof64byte, 1); + p[0] = hd->h0; + p[1] = hd->h1; + p[2] = hd->h2; + p[3] = hd->h3; + p[4] = hd->h4; + + return nburn; +} + + /* The routine final terminates the computation and * returns the digest. * The handle is prepared for a new cycle, but adding bytes to the diff --git a/cipher/sha1.h b/cipher/sha1.h index c023e15..6b87631 100644 --- a/cipher/sha1.h +++ b/cipher/sha1.h @@ -33,4 +33,7 @@ typedef struct } SHA1_CONTEXT; +void _gcry_sha1_mixblock_init (SHA1_CONTEXT *hd); +unsigned int _gcry_sha1_mixblock (SHA1_CONTEXT *hd, void *blockof64byte); + #endif /*GCRY_SHA1_H*/ diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index 5433ae8..437dddb 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -5685,7 +5685,7 @@ Practically Strong Random Numbers". at footnote{Also described in chapter 6 of his book "Cryptographic Security Architecture", New York, 2004, ISBN 0-387-95387-6.} -A pool of 600 bytes is used and mixed using the core RIPE-MD160 hash +A pool of 600 bytes is used and mixed using the core SHA-1 hash transform function. Several extra features are used to make the robust against a wide variety of attacks and to protect against failures of subsystems. The state of the generator may be saved to a diff --git a/random/random-csprng.c b/random/random-csprng.c index e7b751a..a0bfc78 100644 --- a/random/random-csprng.c +++ b/random/random-csprng.c @@ -56,10 +56,10 @@ #include #endif #include "g10lib.h" -#include "../cipher/rmd.h" #include "random.h" #include "rand-internal.h" -#include "cipher.h" /* Required for the rmd160_hash_buffer() prototype. */ +#include "cipher.h" /* _gcry_sha1_hash_buffer */ +#include "../cipher/sha1.h" /* _gcry_sha1_mixblock */ #ifndef RAND_MAX /* For SunOS. */ #define RAND_MAX 32767 @@ -83,7 +83,7 @@ /* Contstants pertaining to the hash pool. */ #define BLOCKLEN 64 /* Hash this amount of bytes... */ -#define DIGESTLEN 20 /* ... into a digest of this length (rmd160). */ +#define DIGESTLEN 20 /* ... into a digest of this length (sha-1). */ /* POOLBLOCKS is the number of digests which make up the pool. */ #define POOLBLOCKS 30 /* POOLSIZE must be a multiple of the digest length to make the AND @@ -593,20 +593,21 @@ mix_pool(unsigned char *pool) unsigned char *hashbuf = pool + POOLSIZE; unsigned char *p, *pend; int i, n; - RMD160_CONTEXT md; + SHA1_CONTEXT md; + unsigned int nburn; #if DIGESTLEN != 20 -#error must have a digest length of 20 for ripe-md-160 +#error must have a digest length of 20 for SHA-1 #endif gcry_assert (pool_is_locked); - _gcry_rmd160_init( &md ); + _gcry_sha1_mixblock_init (&md); /* Loop over the pool. */ pend = pool + POOLSIZE; memcpy(hashbuf, pend - DIGESTLEN, DIGESTLEN ); memcpy(hashbuf+DIGESTLEN, pool, BLOCKLEN-DIGESTLEN); - _gcry_rmd160_mixblock( &md, hashbuf); + nburn = _gcry_sha1_mixblock (&md, hashbuf); memcpy(pool, hashbuf, 20 ); if (failsafe_digest_valid && pool == rndpool) @@ -635,21 +636,21 @@ mix_pool(unsigned char *pool) } } - _gcry_rmd160_mixblock ( &md, hashbuf); + _gcry_sha1_mixblock (&md, hashbuf); memcpy(p, hashbuf, 20 ); } - /* Our hash implementation does only leave small parts (64 bytes) - of the pool on the stack, so it is okay not to require secure - memory here. Before we use this pool, it will be copied to the - help buffer anyway. */ - if ( pool == rndpool) - { - _gcry_rmd160_hash_buffer (failsafe_digest, pool, POOLSIZE); - failsafe_digest_valid = 1; - } - - _gcry_burn_stack (384); /* for the rmd160_mixblock(), rmd160_hash_buffer */ + /* Our hash implementation does only leave small parts (64 bytes) + of the pool on the stack, so it is okay not to require secure + memory here. Before we use this pool, it will be copied to the + help buffer anyway. */ + if ( pool == rndpool) + { + _gcry_sha1_hash_buffer (failsafe_digest, pool, POOLSIZE); + failsafe_digest_valid = 1; + } + + _gcry_burn_stack (nburn); } commit 142a479a484cb4e84d0561be9b05b44dac9e6fe2 Author: Werner Koch Date: Thu Mar 31 19:16:15 2016 +0200 cipher: Move sha1 context definition to a separate file. * cipher/sha1.c: Replace hash-common.h by sha1.h. (SHA1_CONTEXT): Move to ... * cipher/sha1.h: new. Always include all flags. * cipher/Makefile.am (libcipher_la_SOURCES): Add sha1.h. -- Signed-off-by: Werner Koch diff --git a/cipher/Makefile.am b/cipher/Makefile.am index ab71fa7..85248a2 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -57,7 +57,7 @@ bufhelp.h \ primegen.c \ hash-common.c hash-common.h \ dsa-common.c rsa-common.c \ -rmd.h +sha1.h rmd.h EXTRA_libcipher_la_SOURCES = \ arcfour.c arcfour-amd64.S \ diff --git a/cipher/sha1.c b/cipher/sha1.c index 0de8412..19e75b2 100644 --- a/cipher/sha1.c +++ b/cipher/sha1.c @@ -40,7 +40,7 @@ #include "bithelp.h" #include "bufhelp.h" #include "cipher.h" -#include "hash-common.h" +#include "sha1.h" /* USE_SSSE3 indicates whether to compile with Intel SSSE3 code. */ @@ -88,23 +88,6 @@ /* # define U32_ALIGNED_P(p) (!(((uintptr_t)p) % sizeof (u32))) */ /* #endif */ -typedef struct -{ - gcry_md_block_ctx_t bctx; - u32 h0,h1,h2,h3,h4; -#ifdef USE_SSSE3 - unsigned int use_ssse3:1; -#endif -#ifdef USE_AVX - unsigned int use_avx:1; -#endif -#ifdef USE_BMI2 - unsigned int use_bmi2:1; -#endif -#ifdef USE_NEON - unsigned int use_neon:1; -#endif -} SHA1_CONTEXT; static unsigned int transform (void *c, const unsigned char *data, size_t nblks); diff --git a/cipher/sha1.h b/cipher/sha1.h new file mode 100644 index 0000000..c023e15 --- /dev/null +++ b/cipher/sha1.h @@ -0,0 +1,36 @@ +/* sha1.h - SHA-1 context definition + * Copyright (C) 1998, 2001, 2002, 2003, 2008 Free Software Foundation, Inc. + * + * 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 . + */ +#ifndef GCRY_SHA1_H +#define GCRY_SHA1_H + +#include "hash-common.h" + +/* We need this here for direct use by random-csprng.c. */ +typedef struct +{ + gcry_md_block_ctx_t bctx; + u32 h0,h1,h2,h3,h4; + unsigned int use_ssse3:1; + unsigned int use_avx:1; + unsigned int use_bmi2:1; + unsigned int use_neon:1; +} SHA1_CONTEXT; + + +#endif /*GCRY_SHA1_H*/ ----------------------------------------------------------------------- Summary of changes: cipher/Makefile.am | 2 +- cipher/md.c | 2 -- cipher/rmd160.c | 45 ++++++++++---------------------------- cipher/sha1.c | 57 +++++++++++++++++++++++++++++++++--------------- cipher/{rmd.h => sha1.h} | 28 ++++++++++++++---------- configure.ac | 12 +++++++--- doc/gcrypt.texi | 2 +- random/random-csprng.c | 39 +++++++++++++++++---------------- 8 files changed, 97 insertions(+), 90 deletions(-) rename cipher/{rmd.h => sha1.h} (54%) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From wk at gnupg.org Thu Mar 31 20:45:24 2016 From: wk at gnupg.org (Werner Koch) Date: Thu, 31 Mar 2016 20:45:24 +0200 Subject: Crash in bench-slope In-Reply-To: <5c40tc-cn1.ln1@argenau.bebt.de> (Andreas Metzler's message of "Thu, 31 Mar 2016 19:46:15 +0200") References: <20160327133647.GA1824@argenau.bebt.de> <87r3etmw8y.fsf@wheatstone.g10code.de> <5c40tc-cn1.ln1@argenau.bebt.de> Message-ID: <87a8leh4fv.fsf@wheatstone.g10code.de> On Thu, 31 Mar 2016 19:46, ametzler at bebt.de said: > Thanks. FYI 48ee918 built successfully on all Debian release archs and > most of the ports (powerpcspe and sh4, did not fail, they just did not Thanks for testing. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Thu Mar 31 20:53:49 2016 From: wk at gnupg.org (Werner Koch) Date: Thu, 31 Mar 2016 20:53:49 +0200 Subject: SHA-1 now used for mixing the entropy pool (was: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-370-gfcce0cb) In-Reply-To: (by Werner Koch's message of "Thu, 31 Mar 2016 20:33:34 +0200") References: Message-ID: <8760w2h41u.fsf@wheatstone.g10code.de> Hi! For historical reasons the RNG used RIPE-MD-160 for mixing its pool. This is not a widely used hash algorithm but Libgcrypt requires to be built with it due to the RNG. I have just replaced the mixing function by SHA-1. Due to the hardware support and the optimized implementation we have for SHA-1, this change might also speed up the pool mixing - whether this is really a performance advantage is questionable, though. BTW, the design of the RNG requires a mixing function with an output of 20 bytes. Thus we can't replace it with SHA-256 without changing a couple of other things. Anyway, there is no cryptographic need for a stronger algorithm in this use case. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz.