From cvs at cvs.gnupg.org Tue Feb 2 06:07:00 2016 From: cvs at cvs.gnupg.org (by NIIBE Yutaka) Date: Tue, 02 Feb 2016 06:07:00 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-308-ga2f9afc 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 a2f9afcd7fcdafd5951498b07f34957f9766dce9 (commit) from 57b60bb1718b4f2c2500bb447ebd1d4562a5aa9b (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 a2f9afcd7fcdafd5951498b07f34957f9766dce9 Author: NIIBE Yutaka Date: Tue Feb 2 13:58:48 2016 +0900 ecc: Fix ECDH of Curve25519. * cipher/ecc-misc.c (_gcry_ecc_mont_decodepoint): Fix calc of NBITS and prefix detection. * cipher/ecc.c (ecc_generate): Use NBITS instead of CTX->NBITS. (ecc_encrypt_raw): Use NBITS from curve instead of from P. Fix rawmpilen calculation. (ecc_decrypt_raw): Likewise. Add debug output. -- This fixes the commit dd3d06e7. NBITS is defined 256 in ecc-curves.c, thus, ecc_get_nbits returns 256. But CTX->NBITS has 255 for Montgomery curve. diff --git a/cipher/ecc-misc.c b/cipher/ecc-misc.c index 67e3b3d..33af6f7 100644 --- a/cipher/ecc-misc.c +++ b/cipher/ecc-misc.c @@ -322,7 +322,9 @@ _gcry_ecc_mont_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx, mpi_point_t result) } else { - a = rawmpi = _gcry_mpi_get_buffer (pk, ctx->nbits/8, &rawmpilen, NULL); + unsigned int nbytes = (ctx->nbits+7)/8; + + a = rawmpi = _gcry_mpi_get_buffer (pk, nbytes, &rawmpilen, NULL); if (!a) return gpg_err_code_from_syserror (); /* @@ -339,16 +341,17 @@ _gcry_ecc_mont_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx, mpi_point_t result) * So, we need to check if it's really the prefix or not. * Only when it's the prefix, we remove it. */ - if (ctx->nbits/8 == rawmpilen - 1) - rawmpi++; - else if (rawmpilen < ctx->nbits/8) + if (rawmpilen > nbytes) + {/* Prefix 0x40 or 0x00 */ + rawmpi++; + rawmpilen = nbytes; + } + else if (rawmpilen < nbytes) {/* * It is possible for data created by older implementation * to have shorter length when it was parsed as MPI. */ - unsigned int new_rawmpilen = ctx->nbits/8; - - rawmpi = xtrymalloc (new_rawmpilen); + rawmpi = xtrymalloc (nbytes); if (!rawmpi) { gpg_err_code_t err = gpg_err_code_from_syserror (); @@ -356,8 +359,8 @@ _gcry_ecc_mont_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx, mpi_point_t result) return err; } - memset (rawmpi, 0, new_rawmpilen - rawmpilen); - memcpy (rawmpi + new_rawmpilen - rawmpilen, a, rawmpilen); + memset (rawmpi, 0, nbytes - rawmpilen); + memcpy (rawmpi + nbytes - rawmpilen, a, rawmpilen); } } diff --git a/cipher/ecc.c b/cipher/ecc.c index 105650e..7d6ad94 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -606,8 +606,8 @@ ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey) &encpk, &encpklen); else { - encpk = _gcry_mpi_get_buffer_extra (Qx, ctx->nbits/8, -1, - &encpklen, NULL); + encpk = _gcry_mpi_get_buffer_extra (Qx, nbits/8, + -1, &encpklen, NULL); if (encpk == NULL) rc = gpg_err_code_from_syserror (); else @@ -1231,6 +1231,7 @@ ecc_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms) static gcry_err_code_t ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms) { + unsigned int nbits; gcry_err_code_t rc; struct pk_encoding_ctx ctx; gcry_sexp_t l1 = NULL; @@ -1246,7 +1247,7 @@ ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms) memset (&pk, 0, sizeof pk); _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_ENCRYPT, - ecc_get_nbits (keyparms)); + (nbits = ecc_get_nbits (keyparms))); /* Look for flags. */ l1 = sexp_find_token (keyparms, "flags", 0); @@ -1371,13 +1372,13 @@ ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms) mpi_s = _gcry_ecc_ec2os (x, y, pk.E.p); else { - rawmpi = _gcry_mpi_get_buffer_extra (x, ec->nbits/8, -1, - &rawmpilen, NULL); + rawmpi = _gcry_mpi_get_buffer_extra (x, nbits/8, -1, &rawmpilen, NULL); if (!rawmpi) rc = gpg_err_code_from_syserror (); else { rawmpi[0] = 0x40; + rawmpilen++; mpi_s = mpi_new (0); mpi_set_opaque (mpi_s, rawmpi, rawmpilen*8); } @@ -1392,13 +1393,13 @@ ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms) mpi_e = _gcry_ecc_ec2os (x, y, pk.E.p); else { - rawmpi = _gcry_mpi_get_buffer_extra (x, ec->nbits/8, -1, - &rawmpilen, NULL); + rawmpi = _gcry_mpi_get_buffer_extra (x, nbits/8, -1, &rawmpilen, NULL); if (!rawmpi) rc = gpg_err_code_from_syserror (); else { rawmpi[0] = 0x40; + rawmpilen++; mpi_e = mpi_new (0); mpi_set_opaque (mpi_e, rawmpi, rawmpilen*8); } @@ -1447,6 +1448,7 @@ ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms) static gcry_err_code_t ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms) { + unsigned int nbits; gpg_err_code_t rc; struct pk_encoding_ctx ctx; gcry_sexp_t l1 = NULL; @@ -1465,7 +1467,7 @@ ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms) point_init (&R); _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_DECRYPT, - ecc_get_nbits (keyparms)); + (nbits = ecc_get_nbits (keyparms))); /* Look for flags. */ l1 = sexp_find_token (keyparms, "flags", 0); @@ -1565,6 +1567,9 @@ ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms) if (rc) goto leave; + if (DBG_CIPHER) + log_printpnt ("ecc_decrypt kG", &kG, NULL); + /* R = dkG */ _gcry_mpi_ec_mul_point (&R, sk.d, &kG, ec); @@ -1588,7 +1593,7 @@ ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms) unsigned char *rawmpi; unsigned int rawmpilen; - rawmpi = _gcry_mpi_get_buffer_extra (x, ec->nbits/8, -1, + rawmpi = _gcry_mpi_get_buffer_extra (x, nbits/8, -1, &rawmpilen, NULL); if (!rawmpi) { @@ -1598,6 +1603,7 @@ ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms) else { rawmpi[0] = 0x40; + rawmpilen++; r = mpi_new (0); mpi_set_opaque (r, rawmpi, rawmpilen*8); } ----------------------------------------------------------------------- Summary of changes: cipher/ecc-misc.c | 21 ++++++++++++--------- cipher/ecc.c | 24 +++++++++++++++--------- 2 files changed, 27 insertions(+), 18 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 Feb 2 09:33:22 2016 From: cvs at cvs.gnupg.org (by NIIBE Yutaka) Date: Tue, 02 Feb 2016 09:33:22 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-309-g48ba5a5 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 48ba5a50066611ecacea850ced13f5cb66097a81 (commit) from a2f9afcd7fcdafd5951498b07f34957f9766dce9 (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 48ba5a50066611ecacea850ced13f5cb66097a81 Author: NIIBE Yutaka Date: Tue Feb 2 17:24:10 2016 +0900 ecc: more fix of Curve25519. * cipher/ecc-misc.c (gcry_ecc_mont_decodepoint): Fix removing of prefix. Clear the MSB, according to RFC7748. -- This change fixes two things. * Handle the case the prefix 0x40 comes at the end when scanned as standard MPI. * Implement MSB handling. In the page 7 of RFC7748, it says about decoding u-coordinate: When receiving such an array, implementations of X25519 (but not X448) MUST mask the most significant bit in the final byte. Signed-off-by: NIIBE Yutaka diff --git a/cipher/ecc-misc.c b/cipher/ecc-misc.c index 33af6f7..e0dfec3 100644 --- a/cipher/ecc-misc.c +++ b/cipher/ecc-misc.c @@ -342,10 +342,8 @@ _gcry_ecc_mont_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx, mpi_point_t result) * Only when it's the prefix, we remove it. */ if (rawmpilen > nbytes) - {/* Prefix 0x40 or 0x00 */ - rawmpi++; - rawmpilen = nbytes; - } + /* Prefix 0x40 or 0x00, which comes at the end (reverse) */ + rawmpilen = nbytes; else if (rawmpilen < nbytes) {/* * It is possible for data created by older implementation @@ -364,6 +362,7 @@ _gcry_ecc_mont_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx, mpi_point_t result) } } + rawmpi[0] &= (1 << (ctx->nbits % 8)) - 1; _gcry_mpi_set_buffer (result->x, rawmpi, rawmpilen, 0); xfree (a); mpi_set_ui (result->z, 1); ----------------------------------------------------------------------- Summary of changes: cipher/ecc-misc.c | 7 +++---- 1 file changed, 3 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 gniibe at fsij.org Tue Feb 2 09:48:38 2016 From: gniibe at fsij.org (NIIBE Yutaka) Date: Tue, 2 Feb 2016 17:48:38 +0900 Subject: [PATCH] Update NEWS In-Reply-To: <87io2cn41i.fsf@vigenere.g10code.de> References: <20160128170750.23462.38269.stgit@localhost6.localdomain6> <87io2cn41i.fsf@vigenere.g10code.de> Message-ID: <56B06D66.30609@fsij.org> On 01/29/2016 06:11 PM, Werner Koch wrote: > I would like to get libgcrypt 1.7 out soon. The following topics need > to be addressed before a release: > > - Addition of a new DRNG to replace or the X9.31 RNG we use for in FIPS > mode. Quite some time ago Stephan Mueller posted an implementation > which can be used for this. > > - Add a test to check our Curve25519 implementation against the test > vectors from RFC-7748 (Elliptic Curves for Security). I'm going to add a test. We have a small API issue, here. In RFC-7748, the function X25519 is defined as it cares input scalar MSB and LSBs. In libgcrypt, _gcry_mpi_ec_mul_point does not handle those bit-handling. For ecc_encrypt_raw, it is up to users (for example, GnuPG) to make sure those bits correctness. For ecc_decrypt_raw, private key scalar is guaranteed to be correct by ecc_generate. I think that it is OK to implement this bit-handling within the test program. > - Check that all constant-time improvements gniibe posted are applied. We have a patch to libgcrypt-1.6, which can be also applied to master. It's waiting coordination. > - Check whether there are important things left in the bug tracker. I will check, too. -- From cvs at cvs.gnupg.org Tue Feb 2 13:17:25 2016 From: cvs at cvs.gnupg.org (by NIIBE Yutaka) Date: Tue, 02 Feb 2016 13:17:25 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-310-g6cb6df9 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 6cb6df9dddac6ad246002b83c2ce0aaa0ecf30e5 (commit) from 48ba5a50066611ecacea850ced13f5cb66097a81 (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 6cb6df9dddac6ad246002b83c2ce0aaa0ecf30e5 Author: NIIBE Yutaka Date: Tue Feb 2 20:58:04 2016 +0900 ecc: Fix Curve25519 for data by older implementation. * cipher/ecc-misc.c (gcry_ecc_mont_decodepoint): Fix code path for short length data. -- Signed-off-by: NIIBE Yutaka diff --git a/cipher/ecc-misc.c b/cipher/ecc-misc.c index e0dfec3..8f7b8c4 100644 --- a/cipher/ecc-misc.c +++ b/cipher/ecc-misc.c @@ -292,7 +292,6 @@ _gcry_ecc_compute_public (mpi_point_t Q, mpi_ec_t ec, gpg_err_code_t _gcry_ecc_mont_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx, mpi_point_t result) { - unsigned char *a; unsigned char *rawmpi; unsigned int rawmpilen; @@ -312,8 +311,8 @@ _gcry_ecc_mont_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx, mpi_point_t result) buf++; } - a = rawmpi = xtrymalloc (rawmpilen? rawmpilen:1); - if (!a) + rawmpi = xtrymalloc (rawmpilen? rawmpilen:1); + if (!rawmpi) return gpg_err_code_from_syserror (); p = rawmpi + rawmpilen; @@ -324,8 +323,8 @@ _gcry_ecc_mont_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx, mpi_point_t result) { unsigned int nbytes = (ctx->nbits+7)/8; - a = rawmpi = _gcry_mpi_get_buffer (pk, nbytes, &rawmpilen, NULL); - if (!a) + rawmpi = _gcry_mpi_get_buffer (pk, nbytes, &rawmpilen, NULL); + if (!rawmpi) return gpg_err_code_from_syserror (); /* * It is not reliable to assume that 0x40 means the prefix. @@ -341,30 +340,29 @@ _gcry_ecc_mont_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx, mpi_point_t result) * So, we need to check if it's really the prefix or not. * Only when it's the prefix, we remove it. */ - if (rawmpilen > nbytes) - /* Prefix 0x40 or 0x00, which comes at the end (reverse) */ - rawmpilen = nbytes; - else if (rawmpilen < nbytes) + if (pk->nlimbs * BYTES_PER_MPI_LIMB < nbytes) {/* * It is possible for data created by older implementation * to have shorter length when it was parsed as MPI. */ - rawmpi = xtrymalloc (nbytes); - if (!rawmpi) - { - gpg_err_code_t err = gpg_err_code_from_syserror (); - xfree (a); - return err; - } - - memset (rawmpi, 0, nbytes - rawmpilen); - memcpy (rawmpi + nbytes - rawmpilen, a, rawmpilen); + unsigned int len = pk->nlimbs * BYTES_PER_MPI_LIMB; + + memmove (rawmpi + nbytes - len, rawmpi, len); + memset (rawmpi, 0, nbytes - len); } + + /* + * When we have the prefix (0x40 or 0x00), it comes at the end, + * since it is taken by _gcry_mpi_get_buffer with little endian. + * Just setting RAWMPILEN to NBYTES is enough in this case. + * Othewise, RAWMPILEN is NBYTES already. + */ + rawmpilen = nbytes; } rawmpi[0] &= (1 << (ctx->nbits % 8)) - 1; _gcry_mpi_set_buffer (result->x, rawmpi, rawmpilen, 0); - xfree (a); + xfree (rawmpi); mpi_set_ui (result->z, 1); return 0; ----------------------------------------------------------------------- Summary of changes: cipher/ecc-misc.c | 38 ++++++++++++++++++-------------------- 1 file changed, 18 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 cvs at cvs.gnupg.org Wed Feb 3 04:28:16 2016 From: cvs at cvs.gnupg.org (by NIIBE Yutaka) Date: Wed, 03 Feb 2016 04:28:16 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-311-gb8b3361 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 b8b3361504950689ef1e779fb3357cecf8a9f739 (commit) from 6cb6df9dddac6ad246002b83c2ce0aaa0ecf30e5 (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 b8b3361504950689ef1e779fb3357cecf8a9f739 Author: NIIBE Yutaka Date: Wed Feb 3 12:24:46 2016 +0900 tests: Add a test for Curve25519. * tests/Makefile.am (tests_bin): Add t-cv25519. * tests/t-cv25519.c: New. -- Signed-off-by: NIIBE Yutaka diff --git a/tests/Makefile.am b/tests/Makefile.am index a5c10dd..d462f30 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -22,7 +22,7 @@ tests_bin = \ version mpitests t-sexp t-convert \ t-mpi-bit t-mpi-point curves t-lock \ prime basic keygen pubkey hmac hashtest t-kdf keygrip \ - fips186-dsa aeswrap pkcs1v2 random dsa-rfc6979 t-ed25519 + fips186-dsa aeswrap pkcs1v2 random dsa-rfc6979 t-ed25519 t-cv25519 tests_bin_last = benchmark bench-slope diff --git a/tests/t-cv25519.c b/tests/t-cv25519.c new file mode 100644 index 0000000..69aa005 --- /dev/null +++ b/tests/t-cv25519.c @@ -0,0 +1,568 @@ +/* t-cv25519.c - Check the cv25519 crypto + * Copyright (C) 2016 g10 Code GmbH + * + * 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 . + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include + +#include "../src/gcrypt-int.h" + +#include "stopwatch.h" + +#define PGM "t-cv25519" +#define N_TESTS 6 + +#define my_isascii(c) (!((c) & 0x80)) +#define digitp(p) (*(p) >= '0' && *(p) <= '9') +#define hexdigitp(a) (digitp (a) \ + || (*(a) >= 'A' && *(a) <= 'F') \ + || (*(a) >= 'a' && *(a) <= 'f')) +#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \ + *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10)) +#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1)) +#define xmalloc(a) gcry_xmalloc ((a)) +#define xcalloc(a,b) gcry_xcalloc ((a),(b)) +#define xstrdup(a) gcry_xstrdup ((a)) +#define xfree(a) gcry_free ((a)) +#define pass() do { ; } while (0) + +static int verbose; +static int debug; +static int error_count; + +static void +print_mpi (const char *text, gcry_mpi_t a) +{ + gcry_error_t err; + char *buf; + void *bufaddr = &buf; + + err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a); + if (err) + fprintf (stderr, "%s: [error printing number: %s]\n", + text, gpg_strerror (err)); + else + { + fprintf (stderr, "%s: %s\n", text, buf); + gcry_free (buf); + } +} + +static void +die (const char *format, ...) +{ + va_list arg_ptr ; + + fflush (stdout); + fprintf (stderr, "%s: ", PGM); + va_start( arg_ptr, format ) ; + vfprintf (stderr, format, arg_ptr ); + va_end(arg_ptr); + if (*format && format[strlen(format)-1] != '\n') + putc ('\n', stderr); + exit (1); +} + +static void +fail (const char *format, ...) +{ + va_list arg_ptr; + + fflush (stdout); + fprintf (stderr, "%s: ", PGM); + /* if (wherestr) */ + /* fprintf (stderr, "%s: ", wherestr); */ + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); + if (*format && format[strlen(format)-1] != '\n') + putc ('\n', stderr); + error_count++; + if (error_count >= 50) + die ("stopped after 50 errors."); +} + +static void +show (const char *format, ...) +{ + va_list arg_ptr; + + if (!verbose) + return; + fprintf (stderr, "%s: ", PGM); + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + if (*format && format[strlen(format)-1] != '\n') + putc ('\n', stderr); + va_end (arg_ptr); +} + + +static void +show_note (const char *format, ...) +{ + va_list arg_ptr; + + if (!verbose && getenv ("srcdir")) + fputs (" ", stderr); /* To align above "PASS: ". */ + else + fprintf (stderr, "%s: ", PGM); + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + if (*format && format[strlen(format)-1] != '\n') + putc ('\n', stderr); + va_end (arg_ptr); +} + + +/* Convert STRING consisting of hex characters into its binary + representation and return it as an allocated buffer. The valid + length of the buffer is returned at R_LENGTH. The string is + delimited by end of string. The function returns NULL on + error. */ +static void * +hex2buffer (const char *string, size_t *r_length) +{ + const char *s; + unsigned char *buffer; + size_t length; + + buffer = xmalloc (strlen(string)/2+1); + length = 0; + for (s=string; *s; s +=2 ) + { + if (!hexdigitp (s) || !hexdigitp (s+1)) + return NULL; /* Invalid hex digits. */ + ((unsigned char*)buffer)[length++] = xtoi_2 (s); + } + *r_length = length; + return buffer; +} + +static void +reverse_buffer (unsigned char *buffer, unsigned int length) +{ + unsigned int tmp, i; + + for (i=0; i < length/2; i++) + { + tmp = buffer[i]; + buffer[i] = buffer[length-1-i]; + buffer[length-1-i] = tmp; + } +} + + +/* + * Test X25519 functionality through higher layer crypto routines. + * + * Input: K (as hex string), U (as hex string), R (as hex string) + * + * where R is expected result of X25519 (K, U). + * + * It calls gcry_pk_decrypt with Curve25519 private key and let + * it compute X25519. + */ +static void +test_cv (int testno, const char *k_str, const char *u_str, + const char *result_str) +{ + gpg_error_t err; + void *buffer = NULL; + size_t buflen; + unsigned char *p; + gcry_sexp_t s_sk = NULL; + gcry_sexp_t s_data = NULL; + gcry_sexp_t s_result = NULL; + gcry_sexp_t s_tmp = NULL; + unsigned char *res = NULL; + size_t res_len; + + if (verbose > 1) + show ("Running test %d\n", testno); + + if (!(buffer = hex2buffer (k_str, &buflen)) || buflen != 32) + { + fail ("error building s-exp for test %d, %s: %s", + testno, "k", "invalid hex string"); + goto leave; + } + + /* + * Do what decodeScalar25519 does. + */ + p = (unsigned char *)buffer; + p[0] &= 248; + p[31] &= 127; + p[31] |= 64; + reverse_buffer (buffer, buflen); + + if ((err = gcry_sexp_build (&s_sk, NULL, + "(private-key" + " (ecc" + " (curve \"Curve25519\")" + " (flags djb-tweak)" + " (d %b)))", (int)buflen, buffer))) + { + fail ("error building s-exp for test %d, %s: %s", + testno, "sk", gpg_strerror (err)); + goto leave; + } + + xfree (buffer); + if (!(buffer = hex2buffer (u_str, &buflen))) + { + fail ("error building s-exp for test %d, %s: %s", + testno, "u", "invalid hex string"); + goto leave; + } + + /* + * The procedure of decodeUCoordinate will be done internally + * by _gcry_ecc_mont_decodepoint. So, we just put the little-endian + * binary to build S-exp. + * + * We could add the prefix 0x40, but libgcrypt also supports + * format with no prefix. So, it is OK not to put the prefix. + */ + if ((err = gcry_sexp_build (&s_data, NULL, + "(enc-val" + " (ecdh" + " (e %b)))", (int)buflen, buffer))) + { + fail ("error building s-exp for test %d, %s: %s", + testno, "data", gpg_strerror (err)); + goto leave; + } + + xfree (buffer); + buffer = NULL; + + if ((err = gcry_pk_decrypt (&s_result, s_data, s_sk))) + fail ("gcry_pk_decrypt failed for test %d: %s", testno, + gpg_strerror (err)); + + s_tmp = gcry_sexp_find_token (s_result, "value", 0); + if (!s_tmp || !(res = gcry_sexp_nth_buffer (s_tmp, 1, &res_len))) + fail ("gcry_pk_decrypt failed for test %d: %s", testno, "missing value"); + else + { + char *r, *r0; + int i; + + /* To skip the prefix 0x40, for-loop start with i=1 */ + r0 = r = xmalloc (2*(res_len)+1); + if (!r0) + { + fail ("memory allocation", testno); + goto leave; + } + + for (i=1; i < res_len; i++, r += 2) + snprintf (r, 3, "%02x", res[i]); + if (strcmp (result_str, r0)) + { + fail ("gcry_pk_decrypt failed for test %d: %s", + testno, "wrong value returned"); + show (" expected: '%s'", result_str); + show (" got: '%s'", r0); + } + xfree (r0); + } + + leave: + xfree (res); + gcry_sexp_release (s_tmp); + gcry_sexp_release (s_result); + gcry_sexp_release (s_data); + gcry_sexp_release (s_sk); + xfree (buffer); +} + +/* + * Test iterative X25519 computation through lower layer MPI routines. + * + * Input: K (as hex string), ITER, R (as hex string) + * + * where R is expected result of iterating X25519 by ITER times. + * + */ +static void +test_it (int testno, const char *k_str, int iter, const char *result_str) +{ + gcry_ctx_t ctx; + gpg_error_t err; + void *buffer = NULL; + size_t buflen; + gcry_mpi_t mpi_k = NULL; + gcry_mpi_t mpi_x = NULL; + gcry_mpi_point_t P = NULL; + gcry_mpi_point_t Q; + int i; + gcry_mpi_t mpi_kk = NULL; + + if (verbose > 1) + show ("Running test %d: iteration=%d\n", testno, iter); + + gcry_mpi_ec_new (&ctx, NULL, "Curve25519"); + Q = gcry_mpi_point_new (0); + + if (!(buffer = hex2buffer (k_str, &buflen)) || buflen != 32) + { + fail ("error scanning MPI for test %d, %s: %s", + testno, "k", "invalid hex string"); + goto leave; + } + reverse_buffer (buffer, buflen); + if ((err = gcry_mpi_scan (&mpi_x, GCRYMPI_FMT_USG, buffer, buflen, NULL))) + { + fail ("error scanning MPI for test %d, %s: %s", + testno, "x", gpg_strerror (err)); + goto leave; + } + + xfree (buffer); + buffer = NULL; + + P = gcry_mpi_point_set (NULL, mpi_x, NULL, GCRYMPI_CONST_ONE); + + mpi_k = gcry_mpi_copy (mpi_x); + if (debug) + print_mpi ("k", mpi_k); + + for (i = 0; i < iter; i++) + { + /* + * Another variant of decodeScalar25519 thing. + */ + mpi_kk = gcry_mpi_set (mpi_kk, mpi_k); + gcry_mpi_set_bit (mpi_kk, 254); + gcry_mpi_clear_bit (mpi_kk, 255); + gcry_mpi_clear_bit (mpi_kk, 0); + gcry_mpi_clear_bit (mpi_kk, 1); + gcry_mpi_clear_bit (mpi_kk, 2); + + gcry_mpi_ec_mul (Q, mpi_kk, P, ctx); + + P = gcry_mpi_point_set (P, mpi_k, NULL, GCRYMPI_CONST_ONE); + gcry_mpi_ec_get_affine (mpi_k, NULL, Q, ctx); + + if (debug) + print_mpi ("k", mpi_k); + } + + { + unsigned char res[32]; + char *r, *r0; + + gcry_mpi_print (GCRYMPI_FMT_USG, res, 32, NULL, mpi_k); + reverse_buffer (res, 32); + + r0 = r = xmalloc (65); + if (!r0) + { + fail ("memory allocation", testno); + goto leave; + } + + for (i=0; i < 32; i++, r += 2) + snprintf (r, 3, "%02x", res[i]); + + if (strcmp (result_str, r0)) + { + fail ("curv25519 failed for test %d: %s", + testno, "wrong value returned"); + show (" expected: '%s'", result_str); + show (" got: '%s'", r0); + } + xfree (r0); + } + + leave: + gcry_mpi_release (mpi_kk); + gcry_mpi_release (mpi_k); + gcry_mpi_point_release (P); + gcry_mpi_release (mpi_x); + xfree (buffer); + gcry_mpi_point_release (Q); + gcry_ctx_release (ctx); +} + +/* + * X-coordinate of generator of the Curve25519. + */ +#define G_X "0900000000000000000000000000000000000000000000000000000000000000" + +/* + * Test Diffie-Hellman in RFC-7748. + * + * Note that it's not like the ECDH of OpenPGP, where we use + * ephemeral public key. + */ +static void +test_dh (int testno, const char *a_priv_str, const char *a_pub_str, + const char *b_priv_str, const char *b_pub_str, + const char *result_str) +{ + /* Test A for private key corresponds to public key. */ + test_cv (testno, a_priv_str, G_X, a_pub_str); + /* Test B for private key corresponds to public key. */ + test_cv (testno, b_priv_str, G_X, b_pub_str); + /* Test DH with A's private key and B's public key. */ + test_cv (testno, a_priv_str, b_pub_str, result_str); + /* Test DH with B's private key and A's public key. */ + test_cv (testno, b_priv_str, a_pub_str, result_str); +} + + +static void +check_cv25519 (void) +{ + int ntests; + + show ("Checking Curve25519.\n"); + + ntests = 0; + + /* + * Values are cited from RFC-7748: 5.2. Test Vectors. + * Following two tests are for the first type test. + */ + test_cv (1, + "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", + "e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c", + "c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552"); + ntests++; + test_cv (2, + "4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d", + "e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493", + "95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957"); + ntests++; + + /* + * Additional test. Value is from second type test. + */ + test_cv (3, + G_X, + G_X, + "422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079"); + ntests++; + + /* + * Following two tests are for the second type test, + * with one iteration and 1,000 iterations. (1,000,000 iterations + * takes too long.) + */ + test_it (4, + G_X, + 1, + "422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079"); + ntests++; + + test_it (5, + G_X, + 1000, + "684cf59ba83309552800ef566f2f4d3c1c3887c49360e3875f2eb94d99532c51"); + ntests++; + + /* + * Last test is from: 6. Diffie-Hellman, 6.1. Curve25519 + */ + test_dh (6, + /* Alice's private key, a */ + "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a", + /* Alice's public key, X25519(a, 9) */ + "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a", + /* Bob's private key, b */ + "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb", + /* Bob's public key, X25519(b, 9) */ + "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f", + /* Their shared secret, K */ + "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742"); + ntests++; + + if (ntests != N_TESTS) + fail ("did %d tests but expected %d", ntests, N_TESTS); + else if ((ntests % 256)) + show_note ("%d tests done\n", ntests); +} + + +int +main (int argc, char **argv) +{ + int last_argc = -1; + + if (argc) + { argc--; argv++; } + + while (argc && last_argc != argc ) + { + last_argc = argc; + if (!strcmp (*argv, "--")) + { + argc--; argv++; + break; + } + else if (!strcmp (*argv, "--help")) + { + fputs ("usage: " PGM " [options]\n" + "Options:\n" + " --verbose print timings etc.\n" + " --debug flyswatter\n", + stdout); + exit (0); + } + else if (!strcmp (*argv, "--verbose")) + { + verbose++; + argc--; argv++; + } + else if (!strcmp (*argv, "--debug")) + { + verbose += 2; + debug++; + argc--; argv++; + } + else if (!strncmp (*argv, "--", 2)) + die ("unknown option '%s'", *argv); + } + + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); + if (!gcry_check_version (GCRYPT_VERSION)) + die ("version mismatch\n"); + if (debug) + gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0); + gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); + + start_timer (); + check_cv25519 (); + stop_timer (); + + show ("All tests completed in %s. Errors: %d\n", + elapsed_time (1), error_count); + return !!error_count; +} ----------------------------------------------------------------------- Summary of changes: tests/Makefile.am | 2 +- tests/t-cv25519.c | 568 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 569 insertions(+), 1 deletion(-) create mode 100644 tests/t-cv25519.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 ametzler at bebt.de Sun Feb 7 18:09:28 2016 From: ametzler at bebt.de (Andreas Metzler) Date: Sun, 7 Feb 2016 18:09:28 +0100 Subject: version 1.7 (was: [PATCH] Update NEWS) References: <20160128170750.23462.38269.stgit@localhost6.localdomain6> <87io2cn41i.fsf@vigenere.g10code.de> Message-ID: <6bakoc-207.ln1@argenau.bebt.de> Werner Koch wrote: [...] > I would like to get libgcrypt 1.7 out soon. The following topics need > to be addressed before a release: [...] Would it make sense to upload GIT head to Debian/experimental to get some autobuilder exposure? 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' From cvs at cvs.gnupg.org Mon Feb 8 19:16:52 2016 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Mon, 08 Feb 2016 19:16:52 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-312-g8353884 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 8353884bc65c820d5bcacaf1ac23cdee72091a09 (commit) from b8b3361504950689ef1e779fb3357cecf8a9f739 (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 8353884bc65c820d5bcacaf1ac23cdee72091a09 Author: Jussi Kivilinna Date: Mon Feb 8 20:13:38 2016 +0200 Add ARM assembly implementation of SHA-512 * cipher/Makefile.am: Add 'sha512-arm.S'. * cipher/sha512-arm.S: New. * cipher/sha512.c (USE_ARM_ASM): New. (_gcry_sha512_transform_arm): New. (transform) [USE_ARM_ASM]: Use ARM assembly implementation instead of generic. * configure.ac: Add 'sha512-arm.lo'. -- Benchmark on Cortex-A8 (armv6, 1008 Mhz): Before: | nanosecs/byte mebibytes/sec cycles/byte SHA512 | 112.0 ns/B 8.52 MiB/s 112.9 c/B After (3.3x faster): | nanosecs/byte mebibytes/sec cycles/byte SHA512 | 34.01 ns/B 28.04 MiB/s 34.28 c/B Signed-off-by: Jussi Kivilinna diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 88c8fbf..65d7afb 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -89,7 +89,7 @@ sha1.c sha1-ssse3-amd64.S sha1-avx-amd64.S sha1-avx-bmi2-amd64.S \ sha1-armv7-neon.S \ sha256.c sha256-ssse3-amd64.S sha256-avx-amd64.S sha256-avx2-bmi2-amd64.S \ sha512.c sha512-ssse3-amd64.S sha512-avx-amd64.S sha512-avx2-bmi2-amd64.S \ - sha512-armv7-neon.S \ + sha512-armv7-neon.S sha512-arm.S \ keccak.c keccak_permute_32.h keccak_permute_64.h keccak-armv7-neon.S \ stribog.c \ tiger.c \ diff --git a/cipher/sha512-arm.S b/cipher/sha512-arm.S new file mode 100644 index 0000000..28f156e --- /dev/null +++ b/cipher/sha512-arm.S @@ -0,0 +1,465 @@ +/* sha512-arm.S - ARM assembly implementation of SHA-512 transform + * + * 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(__ARMEL__) +#ifdef HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS + +.text + +.syntax unified +.arm + +/* structure of SHA512_CONTEXT */ +#define hd_a 0 +#define hd_b ((hd_a) + 8) +#define hd_c ((hd_b) + 8) +#define hd_d ((hd_c) + 8) +#define hd_e ((hd_d) + 8) +#define hd_f ((hd_e) + 8) +#define hd_g ((hd_f) + 8) +#define hd_h ((hd_g) + 8) + +/* register macros */ +#define RK %r2 + +#define RElo %r0 +#define REhi %r1 + +#define RT1lo %r3 +#define RT1hi %r4 +#define RT2lo %r5 +#define RT2hi %r6 +#define RWlo %r7 +#define RWhi %r8 +#define RT3lo %r9 +#define RT3hi %r10 +#define RT4lo %r11 +#define RT4hi %ip + +#define RRND %lr + +/* variable offsets in stack */ +#define ctx (0) +#define data ((ctx) + 4) +#define nblks ((data) + 4) +#define _a ((nblks) + 4) +#define _b ((_a) + 8) +#define _c ((_b) + 8) +#define _d ((_c) + 8) +#define _e ((_d) + 8) +#define _f ((_e) + 8) +#define _g ((_f) + 8) +#define _h ((_g) + 8) + +#define w(i) ((_h) + 8 + ((i) % 16) * 8) + +#define STACK_MAX (w(15) + 8) + +/* helper macros */ +#define ldr_unaligned_be(rout, rsrc, offs, rtmp) \ + ldrb rout, [rsrc, #((offs) + 3)]; \ + ldrb rtmp, [rsrc, #((offs) + 2)]; \ + orr rout, rout, rtmp, lsl #8; \ + ldrb rtmp, [rsrc, #((offs) + 1)]; \ + orr rout, rout, rtmp, lsl #16; \ + ldrb rtmp, [rsrc, #((offs) + 0)]; \ + orr rout, rout, rtmp, lsl #24; + +#ifdef __ARMEL__ + /* bswap on little-endian */ +#ifdef HAVE_ARM_ARCH_V6 + #define be_to_host(reg, rtmp) \ + rev reg, reg; +#else + #define be_to_host(reg, rtmp) \ + eor rtmp, reg, reg, ror #16; \ + mov rtmp, rtmp, lsr #8; \ + bic rtmp, rtmp, #65280; \ + eor reg, rtmp, reg, ror #8; +#endif +#else + /* nop on big-endian */ + #define be_to_host(reg, rtmp) /*_*/ +#endif + +#define host_to_host(x, y) /*_*/ + +#define read_u64_aligned_4(rin, offs, lo0, hi0, lo1, hi1, lo2, hi2, lo3, hi3, convert, rtmp) \ + ldr lo0, [rin, #((offs) + 0 * 8 + 4)]; \ + ldr hi0, [rin, #((offs) + 0 * 8 + 0)]; \ + ldr lo1, [rin, #((offs) + 1 * 8 + 4)]; \ + ldr hi1, [rin, #((offs) + 1 * 8 + 0)]; \ + ldr lo2, [rin, #((offs) + 2 * 8 + 4)]; \ + convert(lo0, rtmp); \ + ldr hi2, [rin, #((offs) + 2 * 8 + 0)]; \ + convert(hi0, rtmp); \ + ldr lo3, [rin, #((offs) + 3 * 8 + 4)]; \ + convert(lo1, rtmp); \ + ldr hi3, [rin, #((offs) + 3 * 8 + 0)]; \ + convert(hi1, rtmp); \ + convert(lo2, rtmp); \ + convert(hi2, rtmp); \ + convert(lo3, rtmp); \ + convert(hi3, rtmp); + +#define read_be64_aligned_4(rin, offs, lo0, hi0, lo1, hi1, lo2, hi2, lo3, hi3, rtmp0) \ + read_u64_aligned_4(rin, offs, lo0, hi0, lo1, hi1, lo2, hi2, lo3, hi3, be_to_host, rtmp0) + +/* need to handle unaligned reads by byte reads */ +#define read_be64_unaligned_4(rin, offs, lo0, hi0, lo1, hi1, lo2, hi2, lo3, hi3, rtmp0) \ + ldr_unaligned_be(lo0, rin, (offs) + 0 * 8 + 4, rtmp0); \ + ldr_unaligned_be(hi0, rin, (offs) + 0 * 8 + 0, rtmp0); \ + ldr_unaligned_be(lo1, rin, (offs) + 1 * 8 + 4, rtmp0); \ + ldr_unaligned_be(hi1, rin, (offs) + 1 * 8 + 0, rtmp0); \ + ldr_unaligned_be(lo2, rin, (offs) + 2 * 8 + 4, rtmp0); \ + ldr_unaligned_be(hi2, rin, (offs) + 2 * 8 + 0, rtmp0); \ + ldr_unaligned_be(lo3, rin, (offs) + 3 * 8 + 4, rtmp0); \ + ldr_unaligned_be(hi3, rin, (offs) + 3 * 8 + 0, rtmp0); + +/*********************************************************************** + * ARM assembly implementation of sha512 transform + ***********************************************************************/ + +/* Round function */ + +#define R(_a,_b,_c,_d,_e,_f,_g,_h,W,wi) \ + /* Message expansion, t1 = _h + w[i] */ \ + W(_a,_h,wi); \ + \ + /* w = Sum1(_e) */ \ + mov RWlo, RElo, lsr#14; \ + ldm RK!, {RT2lo-RT2hi}; \ + mov RWhi, REhi, lsr#14; \ + eor RWlo, RWlo, RElo, lsr#18; \ + eor RWhi, RWhi, REhi, lsr#18; \ + ldr RT3lo, [%sp, #(_f)]; \ + adds RT1lo, RT2lo; /* t1 += K */ \ + ldr RT3hi, [%sp, #(_f) + 4]; \ + adc RT1hi, RT2hi; \ + ldr RT4lo, [%sp, #(_g)]; \ + eor RWlo, RWlo, RElo, lsl#23; \ + ldr RT4hi, [%sp, #(_g) + 4]; \ + eor RWhi, RWhi, REhi, lsl#23; \ + eor RWlo, RWlo, REhi, lsl#18; \ + eor RWhi, RWhi, RElo, lsl#18; \ + eor RWlo, RWlo, REhi, lsl#14; \ + eor RWhi, RWhi, RElo, lsl#14; \ + eor RWlo, RWlo, REhi, lsr#9; \ + eor RWhi, RWhi, RElo, lsr#9; \ + \ + /* Cho(_e,_f,_g) => (_e & _f) ^ (~_e & _g) */ \ + adds RT1lo, RWlo; /* t1 += Sum1(_e) */ \ + and RT3lo, RT3lo, RElo; \ + adc RT1hi, RWhi; \ + and RT3hi, RT3hi, REhi; \ + bic RT4lo, RT4lo, RElo; \ + bic RT4hi, RT4hi, REhi; \ + eor RT3lo, RT3lo, RT4lo; \ + eor RT3hi, RT3hi, RT4hi; \ + \ + /* Load D */ \ + /* t1 += Cho(_e,_f,_g) */ \ + ldr RElo, [%sp, #(_d)]; \ + adds RT1lo, RT3lo; \ + ldr REhi, [%sp, #(_d) + 4]; \ + adc RT1hi, RT3hi; \ + \ + /* Load A */ \ + ldr RT3lo, [%sp, #(_a)]; \ + \ + /* _d += t1 */ \ + adds RElo, RT1lo; \ + ldr RT3hi, [%sp, #(_a) + 4]; \ + adc REhi, RT1hi; \ + \ + /* Store D */ \ + str RElo, [%sp, #(_d)]; \ + \ + /* t2 = Sum0(_a) */ \ + mov RT2lo, RT3lo, lsr#28; \ + str REhi, [%sp, #(_d) + 4]; \ + mov RT2hi, RT3hi, lsr#28; \ + ldr RWlo, [%sp, #(_b)]; \ + eor RT2lo, RT2lo, RT3lo, lsl#30; \ + ldr RWhi, [%sp, #(_b) + 4]; \ + eor RT2hi, RT2hi, RT3hi, lsl#30; \ + eor RT2lo, RT2lo, RT3lo, lsl#25; \ + eor RT2hi, RT2hi, RT3hi, lsl#25; \ + eor RT2lo, RT2lo, RT3hi, lsl#4; \ + eor RT2hi, RT2hi, RT3lo, lsl#4; \ + eor RT2lo, RT2lo, RT3hi, lsr#2; \ + eor RT2hi, RT2hi, RT3lo, lsr#2; \ + eor RT2lo, RT2lo, RT3hi, lsr#7; \ + eor RT2hi, RT2hi, RT3lo, lsr#7; \ + \ + /* t2 += t1 */ \ + adds RT2lo, RT1lo; \ + ldr RT1lo, [%sp, #(_c)]; \ + adc RT2hi, RT1hi; \ + \ + /* Maj(_a,_b,_c) => ((_a & _b) ^ (_c & (_a ^ _b))) */ \ + ldr RT1hi, [%sp, #(_c) + 4]; \ + and RT4lo, RWlo, RT3lo; \ + and RT4hi, RWhi, RT3hi; \ + eor RWlo, RWlo, RT3lo; \ + eor RWhi, RWhi, RT3hi; \ + and RWlo, RWlo, RT1lo; \ + and RWhi, RWhi, RT1hi; \ + eor RWlo, RWlo, RT4lo; \ + eor RWhi, RWhi, RT4hi; \ + +/* Message expansion */ + +#define W_0_63(_a,_h,i) \ + ldr RT3lo, [%sp, #(w(i-2))]; \ + adds RT2lo, RWlo; /* _h = t2 + Maj(_a,_b,_c) */ \ + ldr RT3hi, [%sp, #(w(i-2)) + 4]; \ + adc RT2hi, RWhi; \ + /* nw = S1(w[i-2]) */ \ + ldr RT1lo, [%sp, #(_h)]; /* Load H */ \ + mov RWlo, RT3lo, lsr#19; \ + str RT2lo, [%sp, #(_a)]; \ + eor RWlo, RWlo, RT3lo, lsl#3; \ + ldr RT1hi, [%sp, #(_h) + 4]; \ + mov RWhi, RT3hi, lsr#19; \ + ldr RT2lo, [%sp, #(w(i-7))]; \ + eor RWhi, RWhi, RT3hi, lsl#3; \ + str RT2hi, [%sp, #(_a) + 4]; \ + eor RWlo, RWlo, RT3lo, lsr#6; \ + ldr RT2hi, [%sp, #(w(i-7)) + 4]; \ + eor RWhi, RWhi, RT3hi, lsr#6; \ + eor RWlo, RWlo, RT3hi, lsl#13; \ + eor RWhi, RWhi, RT3lo, lsl#13; \ + eor RWlo, RWlo, RT3hi, lsr#29; \ + eor RWhi, RWhi, RT3lo, lsr#29; \ + ldr RT3lo, [%sp, #(w(i-15))]; \ + eor RWlo, RWlo, RT3hi, lsl#26; \ + ldr RT3hi, [%sp, #(w(i-15)) + 4]; \ + \ + adds RT2lo, RWlo; /* nw += w[i-7] */ \ + ldr RWlo, [%sp, #(w(i-16))]; \ + adc RT2hi, RWhi; \ + mov RT4lo, RT3lo, lsr#1; /* S0(w[i-15]) */ \ + ldr RWhi, [%sp, #(w(i-16)) + 4]; \ + mov RT4hi, RT3hi, lsr#1; \ + adds RT2lo, RWlo; /* nw += w[i-16] */ \ + eor RT4lo, RT4lo, RT3lo, lsr#8; \ + eor RT4hi, RT4hi, RT3hi, lsr#8; \ + eor RT4lo, RT4lo, RT3lo, lsr#7; \ + eor RT4hi, RT4hi, RT3hi, lsr#7; \ + eor RT4lo, RT4lo, RT3hi, lsl#31; \ + eor RT4hi, RT4hi, RT3lo, lsl#31; \ + eor RT4lo, RT4lo, RT3hi, lsl#24; \ + eor RT4hi, RT4hi, RT3lo, lsl#24; \ + eor RT4lo, RT4lo, RT3hi, lsl#25; \ + adc RT2hi, RWhi; \ + \ + /* nw += S0(w[i-15]) */ \ + adds RT2lo, RT4lo; \ + adc RT2hi, RT4hi; \ + \ + /* w[0] = nw */ \ + str RT2lo, [%sp, #(w(i))]; \ + adds RT1lo, RWlo; \ + str RT2hi, [%sp, #(w(i)) + 4]; \ + adc RT1hi, RWhi; + +#define W_64_79(_a,_h,i) \ + adds RT2lo, RWlo; /* _h = t2 + Maj(_a,_b,_c) */ \ + ldr RWlo, [%sp, #(w(i-16))]; \ + adc RT2hi, RWhi; \ + ldr RWhi, [%sp, #(w(i-16)) + 4]; \ + ldr RT1lo, [%sp, #(_h)]; /* Load H */ \ + ldr RT1hi, [%sp, #(_h) + 4]; \ + str RT2lo, [%sp, #(_a)]; \ + str RT2hi, [%sp, #(_a) + 4]; \ + adds RT1lo, RWlo; \ + adc RT1hi, RWhi; + +.align 3 +.globl _gcry_sha512_transform_arm +.type _gcry_sha512_transform_arm,%function; + +_gcry_sha512_transform_arm: + /* Input: + * %r0: SHA512_CONTEXT + * %r1: data + * %r2: u64 k[] constants + * %r3: nblks + */ + push {%r4-%r11, %ip, %lr}; + sub %sp, %sp, #STACK_MAX; + movs RWlo, %r3; + str %r0, [%sp, #(ctx)]; + + beq .Ldone; + +.Loop_blocks: + str RWlo, [%sp, #nblks]; + + /* Load context to stack */ + add RWhi, %sp, #(_a); + ldm %r0!, {RT1lo,RT1hi,RT2lo,RT2hi,RT3lo,RT3hi,RT4lo,RT4hi} + stm RWhi!, {RT1lo,RT1hi,RT2lo,RT2hi,RT3lo,RT3hi,RT4lo,RT4hi} + ldm %r0, {RT1lo,RT1hi,RT2lo,RT2hi,RT3lo,RT3hi,RT4lo,RT4hi} + stm RWhi, {RT1lo,RT1hi,RT2lo,RT2hi,RT3lo,RT3hi,RT4lo,RT4hi} + + /* Load input to w[16] */ +#ifndef __ARM_FEATURE_UNALIGNED + /* test if data is unaligned */ + tst %r1, #3; + beq 1f; + + /* unaligned load */ + add RWhi, %sp, #(w(0)); + read_be64_unaligned_4(%r1, 0 * 8, RT1lo, RT1hi, RT2lo, RT2hi, RT3lo, RT3hi, RT4lo, RT4hi, RWlo); + stm RWhi!, {RT1lo,RT1hi,RT2lo,RT2hi,RT3lo,RT3hi,RT4lo,RT4hi} + + read_be64_unaligned_4(%r1, 4 * 8, RT1lo, RT1hi, RT2lo, RT2hi, RT3lo, RT3hi, RT4lo, RT4hi, RWlo); + stm RWhi!, {RT1lo,RT1hi,RT2lo,RT2hi,RT3lo,RT3hi,RT4lo,RT4hi} + + read_be64_unaligned_4(%r1, 8 * 8, RT1lo, RT1hi, RT2lo, RT2hi, RT3lo, RT3hi, RT4lo, RT4hi, RWlo); + stm RWhi!, {RT1lo,RT1hi,RT2lo,RT2hi,RT3lo,RT3hi,RT4lo,RT4hi} + + read_be64_unaligned_4(%r1, 12 * 8, RT1lo, RT1hi, RT2lo, RT2hi, RT3lo, RT3hi, RT4lo, RT4hi, RWlo); + b 2f; +#endif +1: + /* aligned load */ + add RWhi, %sp, #(w(0)); + read_be64_aligned_4(%r1, 0 * 8, RT1lo, RT1hi, RT2lo, RT2hi, RT3lo, RT3hi, RT4lo, RT4hi, RWlo); + stm RWhi!, {RT1lo,RT1hi,RT2lo,RT2hi,RT3lo,RT3hi,RT4lo,RT4hi} + + read_be64_aligned_4(%r1, 4 * 8, RT1lo, RT1hi, RT2lo, RT2hi, RT3lo, RT3hi, RT4lo, RT4hi, RWlo); + stm RWhi!, {RT1lo,RT1hi,RT2lo,RT2hi,RT3lo,RT3hi,RT4lo,RT4hi} + + read_be64_aligned_4(%r1, 8 * 8, RT1lo, RT1hi, RT2lo, RT2hi, RT3lo, RT3hi, RT4lo, RT4hi, RWlo); + stm RWhi!, {RT1lo,RT1hi,RT2lo,RT2hi,RT3lo,RT3hi,RT4lo,RT4hi} + + read_be64_aligned_4(%r1, 12 * 8, RT1lo, RT1hi, RT2lo, RT2hi, RT3lo, RT3hi, RT4lo, RT4hi, RWlo); +2: + add %r1, #(16 * 8); + stm RWhi, {RT1lo,RT1hi,RT2lo,RT2hi,RT3lo,RT3hi,RT4lo,RT4hi} + str %r1, [%sp, #(data)]; + + /* preload E & A */ + ldr RElo, [%sp, #(_e)]; + ldr REhi, [%sp, #(_e) + 4]; + mov RWlo, #0; + ldr RT2lo, [%sp, #(_a)]; + mov RRND, #(80-16); + ldr RT2hi, [%sp, #(_a) + 4]; + mov RWhi, #0; + +.Loop_rounds: + R(_a, _b, _c, _d, _e, _f, _g, _h, W_0_63, 16); + R(_h, _a, _b, _c, _d, _e, _f, _g, W_0_63, 17); + R(_g, _h, _a, _b, _c, _d, _e, _f, W_0_63, 18); + R(_f, _g, _h, _a, _b, _c, _d, _e, W_0_63, 19); + R(_e, _f, _g, _h, _a, _b, _c, _d, W_0_63, 20); + R(_d, _e, _f, _g, _h, _a, _b, _c, W_0_63, 21); + R(_c, _d, _e, _f, _g, _h, _a, _b, W_0_63, 22); + R(_b, _c, _d, _e, _f, _g, _h, _a, W_0_63, 23); + R(_a, _b, _c, _d, _e, _f, _g, _h, W_0_63, 24); + R(_h, _a, _b, _c, _d, _e, _f, _g, W_0_63, 25); + R(_g, _h, _a, _b, _c, _d, _e, _f, W_0_63, 26); + R(_f, _g, _h, _a, _b, _c, _d, _e, W_0_63, 27); + R(_e, _f, _g, _h, _a, _b, _c, _d, W_0_63, 28); + R(_d, _e, _f, _g, _h, _a, _b, _c, W_0_63, 29); + R(_c, _d, _e, _f, _g, _h, _a, _b, W_0_63, 30); + R(_b, _c, _d, _e, _f, _g, _h, _a, W_0_63, 31); + + subs RRND, #16; + bne .Loop_rounds; + + R(_a, _b, _c, _d, _e, _f, _g, _h, W_64_79, 16); + R(_h, _a, _b, _c, _d, _e, _f, _g, W_64_79, 17); + R(_g, _h, _a, _b, _c, _d, _e, _f, W_64_79, 18); + R(_f, _g, _h, _a, _b, _c, _d, _e, W_64_79, 19); + R(_e, _f, _g, _h, _a, _b, _c, _d, W_64_79, 20); + R(_d, _e, _f, _g, _h, _a, _b, _c, W_64_79, 21); + R(_c, _d, _e, _f, _g, _h, _a, _b, W_64_79, 22); + R(_b, _c, _d, _e, _f, _g, _h, _a, W_64_79, 23); + R(_a, _b, _c, _d, _e, _f, _g, _h, W_64_79, 24); + R(_h, _a, _b, _c, _d, _e, _f, _g, W_64_79, 25); + R(_g, _h, _a, _b, _c, _d, _e, _f, W_64_79, 26); + R(_f, _g, _h, _a, _b, _c, _d, _e, W_64_79, 27); + R(_e, _f, _g, _h, _a, _b, _c, _d, W_64_79, 28); + R(_d, _e, _f, _g, _h, _a, _b, _c, W_64_79, 29); + R(_c, _d, _e, _f, _g, _h, _a, _b, W_64_79, 30); + R(_b, _c, _d, _e, _f, _g, _h, _a, W_64_79, 31); + + ldr %r0, [%sp, #(ctx)]; + adds RT2lo, RWlo; /* _h = t2 + Maj(_a,_b,_c) */ + ldr %r1, [%sp, #(data)]; + adc RT2hi, RWhi; + + ldm %r0, {RT1lo,RT1hi,RWlo,RWhi,RT3lo,RT3hi,RT4lo,RT4hi} + adds RT1lo, RT2lo; + ldr RT2lo, [%sp, #(_b + 0)]; + adc RT1hi, RT2hi; + ldr RT2hi, [%sp, #(_b + 4)]; + adds RWlo, RT2lo; + ldr RT2lo, [%sp, #(_c + 0)]; + adc RWhi, RT2hi; + ldr RT2hi, [%sp, #(_c + 4)]; + adds RT3lo, RT2lo; + ldr RT2lo, [%sp, #(_d + 0)]; + adc RT3hi, RT2hi; + ldr RT2hi, [%sp, #(_d + 4)]; + adds RT4lo, RT2lo; + ldr RT2lo, [%sp, #(_e + 0)]; + adc RT4hi, RT2hi; + stm %r0!, {RT1lo,RT1hi,RWlo,RWhi,RT3lo,RT3hi,RT4lo,RT4hi} + + ldr RT2hi, [%sp, #(_e + 4)]; + ldm %r0, {RT1lo,RT1hi,RWlo,RWhi,RT3lo,RT3hi,RT4lo,RT4hi} + adds RT1lo, RT2lo; + ldr RT2lo, [%sp, #(_f + 0)]; + adc RT1hi, RT2hi; + ldr RT2hi, [%sp, #(_f + 4)]; + adds RWlo, RT2lo; + ldr RT2lo, [%sp, #(_g + 0)]; + adc RWhi, RT2hi; + ldr RT2hi, [%sp, #(_g + 4)]; + adds RT3lo, RT2lo; + ldr RT2lo, [%sp, #(_h + 0)]; + adc RT3hi, RT2hi; + ldr RT2hi, [%sp, #(_h + 4)]; + adds RT4lo, RT2lo; + adc RT4hi, RT2hi; + stm %r0, {RT1lo,RT1hi,RWlo,RWhi,RT3lo,RT3hi,RT4lo,RT4hi} + sub %r0, %r0, #(4 * 8); + ldr RWlo, [%sp, #nblks]; + + sub RK, #(80 * 8); + subs RWlo, #1; + bne .Loop_blocks; + +.Ldone: + mov %r0, #STACK_MAX; +__out: + add %sp, %sp, #STACK_MAX; + pop {%r4-%r11, %ip, %pc}; +.size _gcry_sha512_transform_arm,.-_gcry_sha512_transform_arm; + +#endif +#endif diff --git a/cipher/sha512.c b/cipher/sha512.c index 1196db9..5b25965 100644 --- a/cipher/sha512.c +++ b/cipher/sha512.c @@ -66,6 +66,13 @@ #endif /*ENABLE_NEON_SUPPORT*/ +/* USE_ARM_ASM indicates whether to enable ARM assembly code. */ +#undef USE_ARM_ASM +#if defined(__ARMEL__) && defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) +# define USE_ARM_ASM 1 +#endif + + /* USE_SSSE3 indicates whether to compile with Intel SSSE3 code. */ #undef USE_SSSE3 #if defined(__x86_64__) && defined(HAVE_GCC_INLINE_ASM_SSSE3) && \ @@ -204,36 +211,6 @@ sha384_init (void *context, unsigned int flags) } -static inline u64 -ROTR (u64 x, u64 n) -{ - return ((x >> n) | (x << (64 - n))); -} - -static inline u64 -Ch (u64 x, u64 y, u64 z) -{ - return ((x & y) ^ ( ~x & z)); -} - -static inline u64 -Maj (u64 x, u64 y, u64 z) -{ - return ((x & y) ^ (x & z) ^ (y & z)); -} - -static inline u64 -Sum0 (u64 x) -{ - return (ROTR (x, 28) ^ ROTR (x, 34) ^ ROTR (x, 39)); -} - -static inline u64 -Sum1 (u64 x) -{ - return (ROTR (x, 14) ^ ROTR (x, 18) ^ ROTR (x, 41)); -} - static const u64 k[] = { U64_C(0x428a2f98d728ae22), U64_C(0x7137449123ef65cd), @@ -278,6 +255,38 @@ static const u64 k[] = U64_C(0x5fcb6fab3ad6faec), U64_C(0x6c44198c4a475817) }; +#ifndef USE_ARM_ASM + +static inline u64 +ROTR (u64 x, u64 n) +{ + return ((x >> n) | (x << (64 - n))); +} + +static inline u64 +Ch (u64 x, u64 y, u64 z) +{ + return ((x & y) ^ ( ~x & z)); +} + +static inline u64 +Maj (u64 x, u64 y, u64 z) +{ + return ((x & y) ^ (x & z) ^ (y & z)); +} + +static inline u64 +Sum0 (u64 x) +{ + return (ROTR (x, 28) ^ ROTR (x, 34) ^ ROTR (x, 39)); +} + +static inline u64 +Sum1 (u64 x) +{ + return (ROTR (x, 14) ^ ROTR (x, 18) ^ ROTR (x, 41)); +} + /**************** * Transform the message W which consists of 16 64-bit-words */ @@ -304,7 +313,6 @@ transform_blk (SHA512_STATE *hd, const unsigned char *data) #define S0(x) (ROTR((x),1) ^ ROTR((x),8) ^ ((x)>>7)) #define S1(x) (ROTR((x),19) ^ ROTR((x),61) ^ ((x)>>6)) - for (t = 0; t < 80 - 16; ) { u64 t1, t2; @@ -545,7 +553,7 @@ transform_blk (SHA512_STATE *hd, const unsigned char *data) return /* burn_stack */ (8 + 16) * sizeof(u64) + sizeof(u32) + 3 * sizeof(void*); } - +#endif /*!USE_ARM_ASM*/ /* AMD64 assembly implementations use SystemV ABI, ABI conversion and additional * stack to store XMM6-XMM15 needed on Win64. */ @@ -568,6 +576,12 @@ void _gcry_sha512_transform_armv7_neon (SHA512_STATE *hd, const u64 k[], size_t num_blks); #endif +#ifdef USE_ARM_ASM +unsigned int _gcry_sha512_transform_arm (SHA512_STATE *hd, + const unsigned char *data, + const u64 k[], size_t num_blks); +#endif + #ifdef USE_SSSE3 unsigned int _gcry_sha512_transform_amd64_ssse3(const void *input_data, void *state, @@ -622,6 +636,9 @@ transform (void *context, const unsigned char *data, size_t nblks) } #endif +#ifdef USE_ARM_ASM + burn = _gcry_sha512_transform_arm (&ctx->state, data, k, nblks); +#else do { burn = transform_blk (&ctx->state, data) + 3 * sizeof(void*); @@ -636,6 +653,7 @@ transform (void *context, const unsigned char *data, size_t nblks) */ burn += ASM_EXTRA_STACK; #endif +#endif return burn; } diff --git a/configure.ac b/configure.ac index ed37ab5..8b50360 100644 --- a/configure.ac +++ b/configure.ac @@ -2086,6 +2086,10 @@ if test "$found" = "1" ; then GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha512-avx-amd64.lo" GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha512-avx2-bmi2-amd64.lo" ;; + arm*-*-*) + # Build with the assembly implementation + GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha512-arm.lo" + ;; esac if test x"$neonsupport" = xyes ; then ----------------------------------------------------------------------- Summary of changes: cipher/Makefile.am | 2 +- cipher/sha512-arm.S | 465 ++++++++++++++++++++++++++++++++++++++++++++++++++++ cipher/sha512.c | 82 +++++---- configure.ac | 4 + 4 files changed, 520 insertions(+), 33 deletions(-) create mode 100644 cipher/sha512-arm.S 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 Feb 9 10:26:00 2016 From: cvs at cvs.gnupg.org (by NIIBE Yutaka) Date: Tue, 09 Feb 2016 10:26:00 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-313-g23b7290 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 23b72901f8a5ba9a78485b235c7a917fbc8faae0 (commit) from 8353884bc65c820d5bcacaf1ac23cdee72091a09 (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 23b72901f8a5ba9a78485b235c7a917fbc8faae0 Author: NIIBE Yutaka Date: Wed Nov 25 08:41:41 2015 +0900 ecc: input validation on ECDH. * cipher/ecc.c (ecc_decrypt_raw): Validate the point. -- Signed-off-by: NIIBE Yutaka (forward port from LIBGCRYPT-1-6-BRANCH commit 28eb424e4427b320ec1c9c4ce56af25d495230bd) diff --git a/cipher/ecc.c b/cipher/ecc.c index 7d6ad94..b861925 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -1570,6 +1570,12 @@ ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms) if (DBG_CIPHER) log_printpnt ("ecc_decrypt kG", &kG, NULL); + if (!_gcry_mpi_ec_curve_point (&kG, ec)) + { + point_free (&kG); + return GPG_ERR_INV_DATA; + } + /* R = dkG */ _gcry_mpi_ec_mul_point (&R, sk.d, &kG, ec); ----------------------------------------------------------------------- Summary of changes: cipher/ecc.c | 6 ++++++ 1 file changed, 6 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 cvs at cvs.gnupg.org Tue Feb 9 10:58:45 2016 From: cvs at cvs.gnupg.org (by NIIBE Yutaka) Date: Tue, 09 Feb 2016 10:58:45 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-314-g4a19b19 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 4a19b195697e0b6534d28de9401ae3e9d86adb42 (commit) from 23b72901f8a5ba9a78485b235c7a917fbc8faae0 (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 4a19b195697e0b6534d28de9401ae3e9d86adb42 Author: NIIBE Yutaka Date: Tue Feb 9 18:50:47 2016 +0900 doc: about commit 23b72901f8a5ba9a78485b235c7a917fbc8faae0 -- Signed-off-by: NIIBE Yutaka Together with 88e1358962e902ff1cbec8d53ba3eee46407851a, it could be an effective contermeasure to some chosen cipher text attacks. CVE-id: CVE-2015-7511 Thanks to Daniel Genkin, Lev Pachmanov, Itamar Pipman, and Eran Tromer. http://www.cs.tau.ac.IL/~tromer/ecdh/ ----------------------------------------------------------------------- Summary of changes: 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 Wed Feb 10 09:50:39 2016 From: cvs at cvs.gnupg.org (by NIIBE Yutaka) Date: Wed, 10 Feb 2016 09:50:39 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-315-gb12dd55 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 b12dd550fd6af687ef95c584d0d8366c34965cc8 (commit) from 4a19b195697e0b6534d28de9401ae3e9d86adb42 (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 b12dd550fd6af687ef95c584d0d8366c34965cc8 Author: NIIBE Yutaka Date: Wed Feb 10 17:35:43 2016 +0900 ecc: Fix memory leaks on error. * cipher/ecc.c (ecc_decrypt_raw): Go to leave to release memory. * mpi/ec.c (_gcry_mpi_ec_curve_point): Likewise. -- Signed-off-by: NIIBE Yutaka diff --git a/cipher/ecc.c b/cipher/ecc.c index b861925..d1fe823 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -1572,8 +1572,8 @@ ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms) if (!_gcry_mpi_ec_curve_point (&kG, ec)) { - point_free (&kG); - return GPG_ERR_INV_DATA; + rc = GPG_ERR_INV_DATA; + goto leave; } /* R = dkG */ diff --git a/mpi/ec.c b/mpi/ec.c index 346e5f1..f0b8374 100644 --- a/mpi/ec.c +++ b/mpi/ec.c @@ -1478,10 +1478,12 @@ _gcry_mpi_ec_curve_point (gcry_mpi_point_t point, mpi_ec_t ctx) { case MPI_EC_WEIERSTRASS: { - gcry_mpi_t xxx = mpi_new (0); + gcry_mpi_t xxx; if (_gcry_mpi_ec_get_affine (x, y, point, ctx)) - return 0; + goto leave; + + xxx = mpi_new (0); /* y^2 == x^3 + a?x + b */ ec_pow2 (y, y, ctx); @@ -1502,7 +1504,7 @@ _gcry_mpi_ec_curve_point (gcry_mpi_point_t point, mpi_ec_t ctx) #define xx y /* With Montgomery curve, only X-coordinate is valid. */ if (_gcry_mpi_ec_get_affine (x, NULL, point, ctx)) - return 0; + goto leave; /* The equation is: b * y^2 == x^3 + a ? x^2 + x */ /* We check if right hand is quadratic residue or not by @@ -1530,7 +1532,7 @@ _gcry_mpi_ec_curve_point (gcry_mpi_point_t point, mpi_ec_t ctx) case MPI_EC_EDWARDS: { if (_gcry_mpi_ec_get_affine (x, y, point, ctx)) - return 0; + goto leave; /* a ? x^2 + y^2 - 1 - b ? x^2 ? y^2 == 0 */ ec_pow2 (x, x, ctx); @@ -1553,6 +1555,7 @@ _gcry_mpi_ec_curve_point (gcry_mpi_point_t point, mpi_ec_t ctx) break; } + leave: _gcry_mpi_release (w); _gcry_mpi_release (x); _gcry_mpi_release (y); ----------------------------------------------------------------------- Summary of changes: cipher/ecc.c | 4 ++-- mpi/ec.c | 11 +++++++---- 2 files changed, 9 insertions(+), 6 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 Feb 10 21:15:20 2016 From: wk at gnupg.org (Werner Koch) Date: Wed, 10 Feb 2016 21:15:20 +0100 Subject: version 1.7 In-Reply-To: <6bakoc-207.ln1@argenau.bebt.de> (Andreas Metzler's message of "Sun, 7 Feb 2016 18:09:28 +0100") References: <20160128170750.23462.38269.stgit@localhost6.localdomain6> <87io2cn41i.fsf@vigenere.g10code.de> <6bakoc-207.ln1@argenau.bebt.de> Message-ID: <87twlgb9uv.fsf@vigenere.g10code.de> On Sun, 7 Feb 2016 18:09, ametzler at bebt.de said: > Would it make sense to upload GIT head to Debian/experimental to get > some autobuilder exposure? That would indeed be helpful. I can also provide a tarball if you like. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From ametzler at bebt.de Thu Feb 11 11:20:38 2016 From: ametzler at bebt.de (Andreas Metzler) Date: Thu, 11 Feb 2016 11:20:38 +0100 Subject: testsuite error on git git master - t-cv25519 Message-ID: Hello, git master currently produces a testsuite error on t-cv25519: (sid)ametzler at argenau:/tmp/GCR/libgcrypt.git$ ./tests/t-cv25519 --verbose t-cv25519: Checking Curve25519. t-cv25519: gcry_pk_decrypt failed for test 2: Invalid data t-cv25519: gcry_pk_decrypt failed for test 2: missing value t-cv25519: 6 tests done t-cv25519: All tests completed in 950ms. Errors: 2 The breakage was introduced by 23b72901f8a5ba9a78485b235c7a917fbc8faae0 "ecc: input validation on ECDH." This is Debian/unstable on amd64. 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' From cvs at cvs.gnupg.org Fri Feb 12 05:51:50 2016 From: cvs at cvs.gnupg.org (by NIIBE Yutaka) Date: Fri, 12 Feb 2016 05:51:50 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-316-g7a019bc 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 7a019bc7ecdbdfdef51094e090ce95e062da9b64 (commit) from b12dd550fd6af687ef95c584d0d8366c34965cc8 (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 7a019bc7ecdbdfdef51094e090ce95e062da9b64 Author: NIIBE Yutaka Date: Fri Feb 12 13:50:02 2016 +0900 ecc: Not validate input point for Curve25519. * cipher/ecc.c (ecc_decrypt_raw): Curve25519 is an exception. -- Signed-off-by: NIIBE Yutaka diff --git a/cipher/ecc.c b/cipher/ecc.c index d1fe823..4cdbb14 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -1570,7 +1570,9 @@ ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms) if (DBG_CIPHER) log_printpnt ("ecc_decrypt kG", &kG, NULL); - if (!_gcry_mpi_ec_curve_point (&kG, ec)) + if (!(curvename && !strcmp (curvename, "Curve25519")) + /* For Curve25519, by its definition, validation should not be done. */ + && !_gcry_mpi_ec_curve_point (&kG, ec)) { rc = GPG_ERR_INV_DATA; goto leave; ----------------------------------------------------------------------- Summary of changes: cipher/ecc.c | 4 +++- 1 file changed, 3 insertions(+), 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 gniibe at fsij.org Fri Feb 12 06:21:02 2016 From: gniibe at fsij.org (NIIBE Yutaka) Date: Fri, 12 Feb 2016 14:21:02 +0900 Subject: testsuite error on git git master - t-cv25519 In-Reply-To: References: Message-ID: <56BD6BBE.8010909@fsij.org> On 02/11/2016 07:20 PM, Andreas Metzler wrote: > git master currently produces a testsuite error on t-cv25519: [...] > The breakage was introduced by > 23b72901f8a5ba9a78485b235c7a917fbc8faae0 > "ecc: input validation on ECDH." Thank you for reporting. The commit was wrong for Curve25519. I fixed it. Perhaps, the vector in RFC-7748 is intentional. Reading the RFC again: https://datatracker.ietf.org/doc/rfc7748/ It only addressed the most significant bit. In another (expired) document, there is a section for point validation: https://datatracker.ietf.org/doc/draft-ietf-tls-curve25519/ and I was confused that point validation is ok to be implemented. Well, I found an article about point validation on Curve25519. http://vnhacker.blogspot.jp/2015/09/why-not-validating-curve25519-public.html For libgcrypt implementation, it fails (segfaults) for point infinity when it tries to get X-coordinate. So, it's on safer side. -- From ametzler at bebt.de Fri Feb 12 14:25:25 2016 From: ametzler at bebt.de (Andreas Metzler) Date: Fri, 12 Feb 2016 14:25:25 +0100 Subject: [patch] LICENSES incomplete Message-ID: <20160212132525.GB1242@argenau.bebt.de> Hello, the LICENSES file seems to be incomplete. Find attached a stab at fixing this. 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 -------------- A non-text attachment was scrubbed... Name: 0001-Document-more-non-LGPL-licensed-code.patch Type: text/x-diff Size: 5920 bytes Desc: not available URL: From ametzler at bebt.de Fri Feb 12 14:15:05 2016 From: ametzler at bebt.de (Andreas Metzler) Date: Fri, 12 Feb 2016 14:15:05 +0100 Subject: version 1.7 In-Reply-To: <87twlgb9uv.fsf@vigenere.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> Message-ID: <20160212131505.GA1242@argenau.bebt.de> On 2016-02-10 Werner Koch wrote: > On Sun, 7 Feb 2016 18:09, ametzler at bebt.de said: >> Would it make sense to upload GIT head to Debian/experimental to get >> some autobuilder exposure? > That would indeed be helpful. I can also provide a tarball if you like. Hello, [x] Done This seems to have worked out quite well until now: https://buildd.debian.org/status/package.php?p=libgcrypt20&suite=experimental Out of the yet tried builds only one failed, PPC64: -------------------- PASS: prime selftest for CFB failed - see syslog for details pass 0, algo 4, mode 1, gcry_cipher_setkey failed: Selftest failed pass 0, algo 4, mode 2, gcry_cipher_setkey failed: Selftest failed pass 0, algo 4, mode 5, gcry_cipher_setkey failed: Selftest failed pass 0, algo 4, mode 3, gcry_cipher_setkey failed: Selftest failed pass 0, algo 4, mode 3, gcry_cipher_setkey failed: Selftest failed pass 0, algo 4, mode 6, gcry_cipher_setkey failed: Selftest failed FAIL: basic [...] CMAC_CAST5 20ms 20ms 30ms selftest for CFB failed - see syslog for details benchmark: error setting key for mac algorithm `CMAC_BLOWFISH': Selftest failed FAIL: benchmark selftest for CFB failed - see syslog for details bench-slope: error setting key for mac `CMAC_BLOWFISH' Note: bench-slope running in quick regression test mode. CMAC_CAST5 | 20.93 ns/B 45.57 MiB/s - c/B CMAC_BLOWFISH | FAIL: bench-slope SKIP: hashtest-256g ====================================== 3 of 25 tests failed (1 test was not run) -------------------- 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/ I had already forwarded this here in https://lists.gnupg.org/pipermail/gcrypt-devel/2015-September/003571.html 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' From cvs at cvs.gnupg.org Fri Feb 12 16:58:52 2016 From: cvs at cvs.gnupg.org (by Andreas Metzler) Date: Fri, 12 Feb 2016 16:58:52 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-317-g1c9cc46 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 1c9cc46562fd7f260f481028b5821f5ae910dc32 (commit) from 7a019bc7ecdbdfdef51094e090ce95e062da9b64 (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 1c9cc46562fd7f260f481028b5821f5ae910dc32 Author: Andreas Metzler Date: Fri Feb 12 14:19:23 2016 +0100 Document more non LGPL-licensed code. -- Add license and copyright statement for cipher/arcfour-amd64.S (public domain) and cipher/cipher-ocb.c (OCB license 1) diff --git a/LICENSES b/LICENSES index ff8b7fa..ebc18b3 100644 --- a/LICENSES +++ b/LICENSES @@ -84,3 +84,110 @@ with any binary distributions derived from the GNU C Library. ings in this Software without prior written authorization from the X Consor- tium. #+end_quote + +* Public domain + + For files: + - cipher/arcfour-amd64.S + +#+begin_quote + Author: Marc Bevand + Licence: I hereby disclaim the copyright on this code and place it + in the public domain. +#+end_quote + +* OCB license 1 + + For files: + - cipher/cipher-ocb.c + +#+begin_quote + OCB is covered by several patents but may be used freely by most + software. See http://web.cs.ucdavis.edu/~rogaway/ocb/license.htm . + In particular license 1 is suitable for Libgcrypt: See + http://web.cs.ucdavis.edu/~rogaway/ocb/license1.pdf for the full + license document; it basically says: + + License 1 ? License for Open-Source Software Implementations of OCB + (Jan 9, 2013) + + Under this license, you are authorized to make, use, and + distribute open-source software implementations of OCB. This + license terminates for you if you sue someone over their + open-source software implementation of OCB claiming that you have + a patent covering their implementation. + + + + License for Open Source Software Implementations of OCB + January 9, 2013 + + 1 Definitions + + 1.1 ?Licensor? means Phillip Rogaway. + + 1.2 ?Licensed Patents? means any patent that claims priority to United + States Patent Application No. 09/918,615 entitled ?Method and Apparatus + for Facilitating Efficient Authenticated Encryption,? and any utility, + divisional, provisional, continuation, continuations-in-part, reexamination, + reissue, or foreign counterpart patents that may issue with respect to the + aforesaid patent application. This includes, but is not limited to, United + States Patent No. 7,046,802; United States Patent No. 7,200,227; United + States Patent No. 7,949,129; United States Patent No. 8,321,675 ; and any + patent that issues out of United States Patent Application No. 13/669,114. + + 1.3 ?Use? means any practice of any invention claimed in the Licensed Patents. + + 1.4 ?Software Implementation? means any practice of any invention + claimed in the Licensed Patents that takes the form of software executing on + a user-programmable, general-purpose computer or that takes the form of a + computer-readable medium storing such software. Software Implementation does + not include, for example, application-specific integrated circuits (ASICs), + field-programmable gate arrays (FPGAs), embedded systems, or IP cores. + + 1.5 ?Open Source Software? means software whose source code is published + and made available for inspection and use by anyone because either (a) the + source code is subject to a license that permits recipients to copy, modify, + and distribute the source code without payment of fees or royalties, or + (b) the source code is in the public domain, including code released for + public use through a CC0 waiver. All licenses certified by the Open Source + Initiative at opensource.org as of January 9, 2013 and all Creative Commons + licenses identified on the creativecommons.org website as of January 9, + 2013, including the Public License Fallback of the CC0 waiver, satisfy these + requirements for the purposes of this license. + + 1.6 ?Open Source Software Implementation? means a Software + Implementation in which the software implicating the Licensed Patents is + Open Source Software. Open Source Software Implementation does not include + any Software Implementation in which the software implicating the Licensed + Patents is combined, so as to form a larger program, with software that is + not Open Source Software. + + 2 License Grant + + 2.1 License. Subject to your compliance with the term s of this license, + including the restriction set forth in Section 2.2, Licensor hereby + grants to you a perpetual, worldwide, non-exclusive, non-transferable, + non-sublicenseable, no-charge, royalty-free, irrevocable license to practice + any invention claimed in the Licensed Patents in any Open Source Software + Implementation. + + 2.2 Restriction. If you or your affiliates institute patent litigation + (including, but not limited to, a cross-claim or counterclaim in a lawsuit) + against any entity alleging that any Use authorized by this license + infringes another patent, then any rights granted to you under this license + automatically terminate as of the date such litigation is filed. + + 3 Disclaimer + YOUR USE OF THE LICENSED PATENTS IS AT YOUR OWN RISK AND UNLESS REQUIRED + BY APPLICABLE LAW, LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY + KIND CONCERNING THE LICENSED PATENTS OR ANY PRODUCT EMBODYING ANY LICENSED + PATENT, EXPRESS OR IMPLIED, STATUT ORY OR OTHERWISE, INCLUDING, WITHOUT + LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR + PURPOSE, OR NONINFRINGEMENT. IN NO EVENT WILL LICENSOR BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + ARISING FROM OR RELATED TO ANY USE OF THE LICENSED PATENTS, INCLUDING, + WITHOUT LIMITATION, DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, PUNITIVE + OR SPECIAL DAMAGES, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF + SUCH DAMAGES PRIOR TO SUCH AN OCCURRENCE. +#+end_quote ----------------------------------------------------------------------- Summary of changes: LICENSES | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 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 Fri Feb 12 16:57:05 2016 From: wk at gnupg.org (Werner Koch) Date: Fri, 12 Feb 2016 16:57:05 +0100 Subject: [patch] LICENSES incomplete In-Reply-To: <20160212132525.GB1242@argenau.bebt.de> (Andreas Metzler's message of "Fri, 12 Feb 2016 14:25:25 +0100") References: <20160212132525.GB1242@argenau.bebt.de> Message-ID: <878u2p9b1q.fsf@vigenere.g10code.de> On Fri, 12 Feb 2016 14:25, ametzler at bebt.de said: > the LICENSES file seems to be incomplete. Find attached a stab at > fixing this. Thanks. Pushed to master. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From jussi.kivilinna at iki.fi Sat Feb 13 11:10:56 2016 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sat, 13 Feb 2016 12:10:56 +0200 Subject: version 1.7 In-Reply-To: <20160212131505.GA1242@argenau.bebt.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> Message-ID: <56BF0130.7050509@iki.fi> Hello, On 12.02.2016 15:15, Andreas Metzler wrote: > On 2016-02-10 Werner Koch wrote: >> On Sun, 7 Feb 2016 18:09, ametzler at bebt.de said: >>> Would it make sense to upload GIT head to Debian/experimental to get >>> some autobuilder exposure? > >> That would indeed be helpful. I can also provide a tarball if you like. > > Hello, > > [x] Done > > This seems to have worked out quite well until now: > https://buildd.debian.org/status/package.php?p=libgcrypt20&suite=experimental > > Out of the yet tried builds only one failed, PPC64: > -------------------- > PASS: prime > selftest for CFB failed - see syslog for details > pass 0, algo 4, mode 1, gcry_cipher_setkey failed: Selftest failed > pass 0, algo 4, mode 2, gcry_cipher_setkey failed: Selftest failed > pass 0, algo 4, mode 5, gcry_cipher_setkey failed: Selftest failed > pass 0, algo 4, mode 3, gcry_cipher_setkey failed: Selftest failed > pass 0, algo 4, mode 3, gcry_cipher_setkey failed: Selftest failed > pass 0, algo 4, mode 6, gcry_cipher_setkey failed: Selftest failed > FAIL: basic > [...] > CMAC_CAST5 20ms 20ms 30ms > selftest for CFB failed - see syslog for details > benchmark: error setting key for mac algorithm `CMAC_BLOWFISH': Selftest failed > FAIL: benchmark > selftest for CFB failed - see syslog for details > bench-slope: error setting key for mac `CMAC_BLOWFISH' > Note: bench-slope running in quick regression test mode. > CMAC_CAST5 | 20.93 ns/B 45.57 MiB/s - c/B > CMAC_BLOWFISH | FAIL: bench-slope > SKIP: hashtest-256g > ====================================== > 3 of 25 tests failed > (1 test was not run) > -------------------- > > 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/ > > I had already forwarded this here in > https://lists.gnupg.org/pipermail/gcrypt-devel/2015-September/003571.html Maybe it's better to disable unaligned memory accesses on powerpc instead. Does the attached patch solve the issue? -Jussi > > cu Andreas > -------------- next part -------------- A non-text attachment was scrubbed... Name: 01-bufhelp-disable-unaligned-ppc.patch Type: text/x-patch Size: 830 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 258 bytes Desc: OpenPGP digital signature URL: From ametzler at bebt.de Sat Feb 13 13:47:07 2016 From: ametzler at bebt.de (Andreas Metzler) Date: Sat, 13 Feb 2016 13:47:07 +0100 Subject: version 1.7 In-Reply-To: <56BF0130.7050509@iki.fi> 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> <56BF0130.7050509@iki.fi> Message-ID: <20160213124707.GE1215@argenau.bebt.de> On 2016-02-13 Jussi Kivilinna wrote: > On 12.02.2016 15:15, Andreas Metzler wrote: [...] > > Out of the yet tried builds only one failed, PPC64: [...] > > I had already forwarded this here in > > https://lists.gnupg.org/pipermail/gcrypt-devel/2015-September/003571.html > Maybe it's better to disable unaligned memory accesses on powerpc instead. > Does the attached patch solve the issue? [...] yes, the build succeeded: https://buildd.debian.org/status/logs.php?pkg=libgcrypt20&arch=ppc64 https://buildd.debian.org/status/package.php?p=libgcrypt20&suite=experimental thanks, 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' From cvs at cvs.gnupg.org Sat Feb 13 19:13:34 2016 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Sat, 13 Feb 2016 19:13:34 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-318-g1da793d 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 1da793d089b65ac8c1ead65dacb6b8699f5b6e69 (commit) from 1c9cc46562fd7f260f481028b5821f5ae910dc32 (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 1da793d089b65ac8c1ead65dacb6b8699f5b6e69 Author: Jussi Kivilinna Date: Sat Feb 13 20:12:58 2016 +0200 bufhelp: disable unaligned memory accesses on powerpc * cipher/bufhelp.h (BUFHELP_FAST_UNALIGNED_ACCESS): Disable for __powerpc__ and __powerpc64__. -- Signed-off-by: Jussi Kivilinna diff --git a/cipher/bufhelp.h b/cipher/bufhelp.h index c1aa52e..aec4f1c 100644 --- a/cipher/bufhelp.h +++ b/cipher/bufhelp.h @@ -27,7 +27,6 @@ #if defined(HAVE_GCC_ATTRIBUTE_PACKED) && \ defined(HAVE_GCC_ATTRIBUTE_ALIGNED) && \ (defined(__i386__) || defined(__x86_64__) || \ - defined(__powerpc__) || defined(__powerpc64__) || \ (defined(__arm__) && defined(__ARM_FEATURE_UNALIGNED)) || \ defined(__aarch64__)) /* These architectures are able of unaligned memory accesses and can ----------------------------------------------------------------------- Summary of changes: cipher/bufhelp.h | 1 - 1 file changed, 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 dkg at fifthhorseman.net Tue Feb 16 04:27:23 2016 From: dkg at fifthhorseman.net (Daniel Kahn Gillmor) Date: Mon, 15 Feb 2016 22:27:23 -0500 Subject: building libgcrypt with --host x86_64-w64-mingw32 Message-ID: <87twl9jpwk.fsf@alice.fifthhorseman.net> Hi Gcrypt devs-- i'm exploring building gcrypt 1.6.5 using mingw32 on debian, and i find i can build it OK with i686-w64-mingw32-gcc (./configure --host i686-w64-mingw32), but not with x86_64-w64-mingw32-gcc (./configure --host x86_64-w64-mingw32). In particular: * random/rndhw.c fails to build because it selects 32-bit assembler because __x86_64__ and __LP64__ are not #define'd * linking libgcrypt-20.dll fails because the underlying assembly isn't produced, lots of errors like this one: mpi/mpi-inline.h:125: undefined reference to `_gcry_mpih_sub_n' Both of these changes are to do with assembler, i note. By way of contrast, I'm successfully able to build libgpg-error-0.dll using both toolchains, producing dlls recognized by /usr/bin/file as corresponding to these platforms: i686-w64-mingw32/bin/libgpg-error-0.dll: PE32 executable (DLL) (console) Intel 80386, for MS Windows x86_64-w64-mingw32/bin/libgpg-error-0.dll: PE32+ executable (DLL) (console) x86-64, for MS Windows Has anyone built libgcrypt for 64-bit Windows with mingw? Is this a targeted platform? If so, is there something i should try to get libgcrypt to cross-build cleanly for that target? --dkg -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 948 bytes Desc: not available URL: From jussi.kivilinna at iki.fi Tue Feb 16 09:09:39 2016 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 16 Feb 2016 10:09:39 +0200 Subject: Patch to fix libgcrypt and KeepassX issue on FreeBSD In-Reply-To: <1455579959.14668.7.camel@fbsd.es> References: <1448530649.1549.14.camel@fbsd.es> <56574E98.50707@iki.fi> <1455579959.14668.7.camel@fbsd.es> Message-ID: <56C2D943.6070505@iki.fi> Hello, On 2016-02-16 01:45, Carlos J Puga Medina wrote: > On Thu, 2015-11-26 at 20:25 +0200, Jussi Kivilinna wrote: > > Hi Jussi, > >> Hello, >> >> On 26.11.2015 11:37, Carlos J Puga Medina wrote: >>> Hi people, >>> >>> The following patch fixes a current problem on FreeBSD. Please, can >>> someone commit it for the next libgcrypt release? >>> >> >> I managed to reproduce this on Ubuntu/clang and found bug in salsa20 >> selftest code. Does attached patch fix the issue for you? > > It seems that those patches didn't solve the issue. At the moment, the > cipher-Makefile.in patch fixes it. > > See the following PR: > > https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=207042 > > Please, can you take a look? Seems as if "Ohhhh jeeee: Assertion `ctx->unused < 64' failed (salsa20.c:400:salsa20_do_encrypt_stream)" is different issue than the earlier crash. I'll look at it. -Jussi > > Best regards, >> >> -Jussi >> >>> --- cipher/Makefile.in.orig 2015-09-08 06:32:11 UTC >>> +++ cipher/Makefile.in >>> @@ -818,13 +818,19 @@ uninstall-am: >>> tags tags-am uninstall uninstall-am >>> >>> >>> -# We need to lower the optimization for this module. >>> +# We need to lower the optimization for these modules. >>> tiger.o: $(srcdir)/tiger.c >>> `echo $(COMPILE) -c $(srcdir)/tiger.c | $(o_flag_munging) >>> ` >>> >>> tiger.lo: $(srcdir)/tiger.c >>> `echo $(LTCOMPILE) -c $(srcdir)/tiger.c | >>> $(o_flag_munging) ` >>> >>> +salsa20.o: $(srcdir)/salsa20.c >>> + `echo $(COMPILE) -c $(srcdir)/salsa20.c | >>> $(o_flag_munging) ` >>> + >>> +salsa20.lo: $(srcdir)/salsa20.c >>> + `echo $(LTCOMPILE) -c $(srcdir)/salsa20.c | >>> $(o_flag_munging) >>> ` >>> + >>> # Tell versions [3.59,3.63) of GNU make to not export all >>> variables. >>> # Otherwise a system limit (for SysV at least) may be exceeded. >>> .NOEXPORT: >>> >>> See bug 204323 for further details: >>> >>> https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=204323 >>> >>> Kind regards, >>> >>> >>> >>> _______________________________________________ >>> Gcrypt-devel mailing list >>> Gcrypt-devel at gnupg.org >>> http://lists.gnupg.org/mailman/listinfo/gcrypt-devel >>> >> From wk at gnupg.org Tue Feb 16 14:42:01 2016 From: wk at gnupg.org (Werner Koch) Date: Tue, 16 Feb 2016 14:42:01 +0100 Subject: building libgcrypt with --host x86_64-w64-mingw32 In-Reply-To: <87twl9jpwk.fsf@alice.fifthhorseman.net> (Daniel Kahn Gillmor's message of "Mon, 15 Feb 2016 22:27:23 -0500") References: <87twl9jpwk.fsf@alice.fifthhorseman.net> Message-ID: <87si0sg4ba.fsf@wheatstone.g10code.de> On Tue, 16 Feb 2016 04:27, dkg at fifthhorseman.net said: > i'm exploring building gcrypt 1.6.5 using mingw32 on debian, and i find This is how I build the GnuPG installer for Windows. > i can build it OK with i686-w64-mingw32-gcc (./configure --host > i686-w64-mingw32), but not with x86_64-w64-mingw32-gcc (./configure > --host x86_64-w64-mingw32). In particular: I am actually using x86_64-w64-mingw32-gcc (GCC) 4.9.1 w/o any problems. This is not Sid, though. See also gnupg/build-aux/speedo.mk for details. Note that the Windows code should be build with "./autogen.sh --build-w32" (or -w64) because that scripts tracks our knowledge of useful options. > * random/rndhw.c fails to build because it selects 32-bit assembler > because __x86_64__ and __LP64__ are not #define'd Hmmm. A mingw regression? > Has anyone built libgcrypt for 64-bit Windows with mingw? Is this a > targeted platform? If so, is there something i should try to get Not really because we have not yet looked at rndw32 to check whether it is okay to be used for Windows 64 bit. BTW we are abale to build for W64: libgpg-error libiconv gettext libassuan gpgex Shalom-Salam, Werner From smueller at chronox.de Tue Feb 16 22:04:53 2016 From: smueller at chronox.de (Stephan Mueller) Date: Tue, 16 Feb 2016 22:04:53 +0100 Subject: [PATCH 2/2] Remove ANSI X9.31 DRNG In-Reply-To: <1560889.z3jECahC7P@positron.chronox.de> References: <1560889.z3jECahC7P@positron.chronox.de> Message-ID: <21098844.9qhusP4UPz@positron.chronox.de> The ANSI X9.31 DRNG is removed as it is completely replaced with the SP800-90A DRBG. Signed-off-by: Stephan Mueller --- random/Makefile.am | 1 - random/rand-internal.h | 25 -- random/random-fips.c | 1124 ------------------------------------------------ 3 files changed, 1150 deletions(-) delete mode 100644 random/random-fips.c diff --git a/random/Makefile.am b/random/Makefile.am index e073fa4..0bf3879 100644 --- a/random/Makefile.am +++ b/random/Makefile.am @@ -34,7 +34,6 @@ librandom_la_SOURCES = \ random.c random.h \ rand-internal.h \ random-csprng.c \ -random-fips.c \ drbg.c \ random-system.c \ rndhw.c diff --git a/random/rand-internal.h b/random/rand-internal.h index 475351a..30a270a 100644 --- a/random/rand-internal.h +++ b/random/rand-internal.h @@ -63,31 +63,6 @@ void _gcry_rngcsprng_set_seed_file (const char *name); void _gcry_rngcsprng_update_seed_file (void); void _gcry_rngcsprng_fast_poll (void); -/*-- random-fips.c --*/ -void _gcry_rngfips_initialize (int full); -void _gcry_rngfips_close_fds (void); -void _gcry_rngfips_dump_stats (void); -int _gcry_rngfips_is_faked (void); -gcry_error_t _gcry_rngfips_add_bytes (const void *buf, size_t buflen, - int quality); -void _gcry_rngfips_randomize (void *buffer, size_t length, - enum gcry_random_level level); -void _gcry_rngfips_create_nonce (void *buffer, size_t length); - -gcry_error_t _gcry_rngfips_selftest (selftest_report_func_t report); - -gcry_err_code_t _gcry_rngfips_init_external_test (void **r_context, - unsigned int flags, - const void *key, - size_t keylen, - const void *seed, - size_t seedlen, - const void *dt, - size_t dtlen); -gcry_err_code_t _gcry_rngfips_run_external_test (void *context, - char *buffer, size_t buflen); -void _gcry_rngfips_deinit_external_test (void *context); - /* drbg.c */ void _gcry_drbg_init(int full); void _gcry_drbg_close_fds(void); diff --git a/random/random-fips.c b/random/random-fips.c deleted file mode 100644 index 3a641b2..0000000 --- a/random/random-fips.c +++ /dev/null @@ -1,1124 +0,0 @@ -/* random-fips.c - FIPS style random number generator - * Copyright (C) 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 . - */ - -/* - The core of this deterministic random number generator is - implemented according to the document "NIST-Recommended Random - Number Generator Based on ANSI X9.31 Appendix A.2.4 Using the 3-Key - Triple DES and AES Algorithms" (2005-01-31). This implementation - uses the AES variant. - - There are 3 random context which map to the different levels of - random quality: - - Generator Seed and Key Kernel entropy (init/reseed) - ------------------------------------------------------------ - GCRY_VERY_STRONG_RANDOM /dev/random 256/128 bits - GCRY_STRONG_RANDOM /dev/random 256/128 bits - gcry_create_nonce GCRY_STRONG_RANDOM n/a - - All random generators return their data in 128 bit blocks. If the - caller requested less bits, the extra bits are not used. The key - for each generator is only set once at the first time a generator - is used. The seed value is set with the key and again after 1000 - (SEED_TTL) output blocks; the re-seeding is disabled in test mode. - - The GCRY_VERY_STRONG_RANDOM and GCRY_STRONG_RANDOM generators are - keyed and seeded from the /dev/random device. Thus these - generators may block until the kernel has collected enough entropy. - - The gcry_create_nonce generator is keyed and seeded from the - GCRY_STRONG_RANDOM generator. It may also block if the - GCRY_STRONG_RANDOM generator has not yet been used before and thus - gets initialized on the first use by gcry_create_nonce. This - special treatment is justified by the weaker requirements for a - nonce generator and to save precious kernel entropy for use by the - real random generators. - - */ - -#include -#include -#include -#include -#include -#include -#ifdef HAVE_GETTIMEOFDAY -#include -#endif - -#include "g10lib.h" -#include "random.h" -#include "rand-internal.h" - -/* This is the lock we use to serialize access to this RNG. The extra - integer variable is only used to check the locking state; that is, - it is not meant to be thread-safe but merely as a failsafe feature - to assert proper locking. */ -GPGRT_LOCK_DEFINE (fips_rng_lock); -static int fips_rng_is_locked; - - -/* The required size for the temporary buffer of the x931_aes_driver - function and the buffer itself which will be allocated in secure - memory. This needs to be global variable for proper initialization - and to allow shutting down the RNG without leaking memory. May - only be used while holding the FIPS_RNG_LOCK. - - This variable is also used to avoid duplicate initialization. */ -#define TEMPVALUE_FOR_X931_AES_DRIVER_SIZE 48 -static unsigned char *tempvalue_for_x931_aes_driver; - - -/* After having retrieved this number of blocks from the RNG, we want - to do a reseeding. */ -#define SEED_TTL 1000 - - -/* The length of the key we use: 16 bytes (128 bit) for AES128. */ -#define X931_AES_KEYLEN 16 -/* A global buffer used to communicate between the x931_generate_key - and x931_generate_seed functions and the entropy_collect_cb - function. It may only be used by these functions. */ -static unsigned char *entropy_collect_buffer; /* Buffer. */ -static size_t entropy_collect_buffer_len; /* Used length. */ -static size_t entropy_collect_buffer_size; /* Allocated length. */ - - -/* This random context type is used to track properties of one random - generator. Thee context are usually allocated in secure memory so - that the seed value is well protected. There are a couble of guard - fields to help detecting applications accidentally overwriting parts - of the memory. */ -struct rng_context -{ - unsigned char guard_0[1]; - - /* The handle of the cipher used by the RNG. If this one is not - NULL a cipher handle along with a random key has been - established. */ - gcry_cipher_hd_t cipher_hd; - - /* If this flag is true, the SEED_V buffer below carries a valid - seed. */ - int is_seeded:1; - - /* The very first block generated is used to compare the result - against the last result. This flag indicates that such a block - is available. */ - int compare_value_valid:1; - - /* A counter used to trigger re-seeding. */ - unsigned int use_counter; - - unsigned char guard_1[1]; - - /* The buffer containing the seed value V. */ - unsigned char seed_V[16]; - - unsigned char guard_2[1]; - - /* The last result from the x931_aes function. Only valid if - compare_value_valid is set. */ - unsigned char compare_value[16]; - - unsigned char guard_3[1]; - - /* The external test may want to suppress the duplicate bock check. - This is done if the this flag is set. */ - unsigned char test_no_dup_check; - /* To implement a KAT we need to provide a know DT value. To - accomplish this the x931_get_dt function checks whether this - field is not NULL and then uses the 16 bytes at this address for - the DT value. However the last 4 bytes are replaced by the - value of field TEST_DT_COUNTER which will be incremented after - each invocation of x931_get_dt. We use a pointer and not a buffer - because there is no need to put this value into secure memory. */ - const unsigned char *test_dt_ptr; - u32 test_dt_counter; - - /* We need to keep track of the process which did the initialization - so that we can detect a fork. The volatile modifier is required - so that the compiler does not optimize it away in case the getpid - function is badly attributed. */ - pid_t key_init_pid; - pid_t seed_init_pid; -}; -typedef struct rng_context *rng_context_t; - - -/* The random context used for the nonce generator. May only be used - while holding the FIPS_RNG_LOCK. */ -static rng_context_t nonce_context; -/* The random context used for the standard random generator. May - only be used while holding the FIPS_RNG_LOCK. */ -static rng_context_t std_rng_context; -/* The random context used for the very strong random generator. May - only be used while holding the FIPS_RNG_LOCK. */ -static rng_context_t strong_rng_context; - - -/* --- Local prototypes --- */ -static void x931_reseed (rng_context_t rng_ctx); -static void get_random (void *buffer, size_t length, rng_context_t rng_ctx); - - - - -/* --- Functions --- */ - -/* Basic initialization is required to initialize mutexes and - do a few checks on the implementation. */ -static void -basic_initialization (void) -{ - static int initialized; - - if (initialized) - return; - initialized = 1; - - fips_rng_is_locked = 0; - - /* Make sure that we are still using the values we have - traditionally used for the random levels. */ - gcry_assert (GCRY_WEAK_RANDOM == 0 - && GCRY_STRONG_RANDOM == 1 - && GCRY_VERY_STRONG_RANDOM == 2); - -} - - -/* Acquire the fips_rng_lock. */ -static void -lock_rng (void) -{ - gpg_err_code_t rc; - - rc = gpgrt_lock_lock (&fips_rng_lock); - if (rc) - log_fatal ("failed to acquire the RNG lock: %s\n", gpg_strerror (rc)); - fips_rng_is_locked = 1; -} - - -/* Release the fips_rng_lock. */ -static void -unlock_rng (void) -{ - gpg_err_code_t rc; - - fips_rng_is_locked = 0; - rc = gpgrt_lock_unlock (&fips_rng_lock); - if (rc) - log_fatal ("failed to release the RNG lock: %s\n", gpg_strerror (rc)); -} - -static void -setup_guards (rng_context_t rng_ctx) -{ - /* Set the guards to some arbitrary values. */ - rng_ctx->guard_0[0] = 17; - rng_ctx->guard_1[0] = 42; - rng_ctx->guard_2[0] = 137; - rng_ctx->guard_3[0] = 252; -} - -static void -check_guards (rng_context_t rng_ctx) -{ - if ( rng_ctx->guard_0[0] != 17 - || rng_ctx->guard_1[0] != 42 - || rng_ctx->guard_2[0] != 137 - || rng_ctx->guard_3[0] != 252 ) - log_fatal ("memory corruption detected in RNG context %p\n", rng_ctx); -} - - -/* Get the DT vector for use with the core PRNG function. Buffer - needs to be provided by the caller with a size of at least LENGTH - bytes. RNG_CTX needs to be passed to allow for a KAT. The 16 byte - timestamp we construct is made up the real time and three counters: - - Buffer: 00112233445566778899AABBCCDDEEFF - !--+---!!-+-!!+!!--+---!!--+---! - seconds ---------/ | | | | - microseconds -----------/ | | | - counter2 -------------------/ | | - counter1 ------------------------/ | - counter0 --------------------------------/ - - Counter 2 is just 12 bits wide and used to track fractions of - milliseconds whereas counters 1 and 0 are combined to a free - running 64 bit counter. */ -static void -x931_get_dt (unsigned char *buffer, size_t length, rng_context_t rng_ctx) -{ - gcry_assert (length == 16); /* This length is required for use with AES. */ - gcry_assert (fips_rng_is_locked); - - /* If the random context indicates that a test DT should be used, - take the DT value from the context. For safety reasons we do - this only if the context is not one of the regular contexts. */ - if (rng_ctx->test_dt_ptr - && rng_ctx != nonce_context - && rng_ctx != std_rng_context - && rng_ctx != strong_rng_context) - { - memcpy (buffer, rng_ctx->test_dt_ptr, 16); - buffer[12] = (rng_ctx->test_dt_counter >> 24); - buffer[13] = (rng_ctx->test_dt_counter >> 16); - buffer[14] = (rng_ctx->test_dt_counter >> 8); - buffer[15] = rng_ctx->test_dt_counter; - rng_ctx->test_dt_counter++; - return; - } - - -#if HAVE_GETTIMEOFDAY - { - static u32 last_sec, last_usec; - static u32 counter1, counter0; - static u16 counter2; - - unsigned int usec; - struct timeval tv; - - if (!last_sec) - { - /* This is the very first time we are called: Set the counters - to an not so easy predictable value to avoid always - starting at 0. Not really needed but it doesn't harm. */ - counter1 = (u32)getpid (); -#ifndef HAVE_W32_SYSTEM - counter0 = (u32)getppid (); -#endif - } - - - if (gettimeofday (&tv, NULL)) - log_fatal ("gettimeofday() failed: %s\n", strerror (errno)); - - /* The microseconds part is always less than 1 million (0x0f4240). - Thus we don't care about the MSB and in addition shift it to - the left by 4 bits. */ - usec = tv.tv_usec; - usec <<= 4; - /* If we got the same time as by the last invocation, bump up - counter2 and save the time for the next invocation. */ - if (tv.tv_sec == last_sec && usec == last_usec) - { - counter2++; - counter2 &= 0x0fff; - } - else - { - counter2 = 0; - last_sec = tv.tv_sec; - last_usec = usec; - } - /* Fill the buffer with the timestamp. */ - buffer[0] = ((tv.tv_sec >> 24) & 0xff); - buffer[1] = ((tv.tv_sec >> 16) & 0xff); - buffer[2] = ((tv.tv_sec >> 8) & 0xff); - buffer[3] = (tv.tv_sec & 0xff); - buffer[4] = ((usec >> 16) & 0xff); - buffer[5] = ((usec >> 8) & 0xff); - buffer[6] = ((usec & 0xf0) | ((counter2 >> 8) & 0x0f)); - buffer[7] = (counter2 & 0xff); - /* Add the free running counter. */ - buffer[8] = ((counter1 >> 24) & 0xff); - buffer[9] = ((counter1 >> 16) & 0xff); - buffer[10] = ((counter1 >> 8) & 0xff); - buffer[11] = ((counter1) & 0xff); - buffer[12] = ((counter0 >> 24) & 0xff); - buffer[13] = ((counter0 >> 16) & 0xff); - buffer[14] = ((counter0 >> 8) & 0xff); - buffer[15] = ((counter0) & 0xff); - /* Bump up that counter. */ - if (!++counter0) - ++counter1; - } -#else - log_fatal ("gettimeofday() not available on this system\n"); -#endif - - /* log_printhex ("x931_get_dt: ", buffer, 16); */ -} - - -/* XOR the buffers A and B which are each of LENGTH bytes and store - the result at R. R needs to be provided by the caller with a size - of at least LENGTH bytes. */ -static void -xor_buffer (unsigned char *r, - const unsigned char *a, const unsigned char *b, size_t length) -{ - for ( ; length; length--, a++, b++, r++) - *r = (*a ^ *b); -} - - -/* Encrypt LENGTH bytes of INPUT to OUTPUT using KEY. LENGTH - needs to be 16. */ -static void -encrypt_aes (gcry_cipher_hd_t key, - unsigned char *output, const unsigned char *input, size_t length) -{ - gpg_error_t err; - - gcry_assert (length == 16); - - err = _gcry_cipher_encrypt (key, output, length, input, length); - if (err) - log_fatal ("AES encryption in RNG failed: %s\n", _gcry_strerror (err)); -} - - -/* The core ANSI X9.31, Appendix A.2.4 function using AES. The caller - needs to pass a 16 byte buffer for the result, the 16 byte - datetime_DT value and the 16 byte seed value V. The caller also - needs to pass an appropriate KEY and make sure to pass a valid - seed_V. The caller also needs to provide two 16 bytes buffer for - intermediate results, they may be reused by the caller later. - - On return the result is stored at RESULT_R and the SEED_V is - updated. May only be used while holding the lock. */ -static void -x931_aes (unsigned char result_R[16], - unsigned char datetime_DT[16], unsigned char seed_V[16], - gcry_cipher_hd_t key, - unsigned char intermediate_I[16], unsigned char temp_xor[16]) -{ - /* Let ede*X(Y) represent the AES encryption of Y under the key *X. - - Let V be a 128-bit seed value which is also kept secret, and XOR - be the exclusive-or operator. Let DT be a date/time vector which - is updated on each iteration. I is a intermediate value. - - I = ede*K(DT) */ - encrypt_aes (key, intermediate_I, datetime_DT, 16); - - /* R = ede*K(I XOR V) */ - xor_buffer (temp_xor, intermediate_I, seed_V, 16); - encrypt_aes (key, result_R, temp_xor, 16); - - /* V = ede*K(R XOR I). */ - xor_buffer (temp_xor, result_R, intermediate_I, 16); - encrypt_aes (key, seed_V, temp_xor, 16); - - /* Zero out temporary values. */ - wipememory (intermediate_I, 16); - wipememory (temp_xor, 16); -} - - -/* The high level driver to x931_aes. This one does the required - tests and calls the core function until the entire buffer has been - filled. OUTPUT is a caller provided buffer of LENGTH bytes to - receive the random, RNG_CTX is the context of the RNG. The context - must be properly initialized. Returns 0 on success. */ -static int -x931_aes_driver (unsigned char *output, size_t length, rng_context_t rng_ctx) -{ - unsigned char datetime_DT[16]; - unsigned char *intermediate_I, *temp_buffer, *result_buffer; - size_t nbytes; - - gcry_assert (fips_rng_is_locked); - gcry_assert (rng_ctx->cipher_hd); - gcry_assert (rng_ctx->is_seeded); - - gcry_assert (tempvalue_for_x931_aes_driver); - gcry_assert (TEMPVALUE_FOR_X931_AES_DRIVER_SIZE == 48); - intermediate_I = tempvalue_for_x931_aes_driver; - temp_buffer = tempvalue_for_x931_aes_driver + 16; - result_buffer = tempvalue_for_x931_aes_driver + 32; - - while (length) - { - /* Unless we are running with a test context, we require a new - seed after some time. */ - if (!rng_ctx->test_dt_ptr && rng_ctx->use_counter > SEED_TTL) - { - x931_reseed (rng_ctx); - rng_ctx->use_counter = 0; - } - - /* Due to the design of the RNG, we always receive 16 bytes (128 - bit) of random even if we require less. The extra bytes - returned are not used. Intheory we could save them for the - next invocation, but that would make the control flow harder - to read. */ - nbytes = length < 16? length : 16; - - x931_get_dt (datetime_DT, 16, rng_ctx); - x931_aes (result_buffer, - datetime_DT, rng_ctx->seed_V, rng_ctx->cipher_hd, - intermediate_I, temp_buffer); - rng_ctx->use_counter++; - - if (rng_ctx->test_no_dup_check - && rng_ctx->test_dt_ptr - && rng_ctx != nonce_context - && rng_ctx != std_rng_context - && rng_ctx != strong_rng_context) - { - /* This is a test context which does not want the duplicate - block check. */ - } - else - { - /* Do a basic check on the output to avoid a stuck generator. */ - if (!rng_ctx->compare_value_valid) - { - /* First time used, only save the result. */ - memcpy (rng_ctx->compare_value, result_buffer, 16); - rng_ctx->compare_value_valid = 1; - continue; - } - if (!memcmp (rng_ctx->compare_value, result_buffer, 16)) - { - /* Ooops, we received the same 128 bit block - that should - in theory never happen. The FIPS requirement says that - we need to put ourself into the error state in such - case. */ - fips_signal_error ("duplicate 128 bit block returned by RNG"); - return -1; - } - memcpy (rng_ctx->compare_value, result_buffer, 16); - } - - /* Append to outbut. */ - memcpy (output, result_buffer, nbytes); - wipememory (result_buffer, 16); - output += nbytes; - length -= nbytes; - } - - return 0; -} - - -/* Callback for x931_generate_key. Note that this callback uses the - global ENTROPY_COLLECT_BUFFER which has been setup by get_entropy. - ORIGIN is not used but required due to the design of entropy - gathering module. */ -static void -entropy_collect_cb (const void *buffer, size_t length, - enum random_origins origin) -{ - const unsigned char *p = buffer; - - (void)origin; - - gcry_assert (fips_rng_is_locked); - gcry_assert (entropy_collect_buffer); - - /* Note that we need to protect against gatherers returning more - than the requested bytes (e.g. rndw32). */ - while (length-- && entropy_collect_buffer_len < entropy_collect_buffer_size) - { - entropy_collect_buffer[entropy_collect_buffer_len++] ^= *p++; - } -} - - -/* Get NBYTES of entropy from the kernel device. The callers needs to - free the returned buffer. The function either succeeds or - terminates the process in case of a fatal error. */ -static void * -get_entropy (size_t nbytes) -{ - void *result; - int rc; - - gcry_assert (!entropy_collect_buffer); - entropy_collect_buffer = xmalloc_secure (nbytes); - entropy_collect_buffer_size = nbytes; - entropy_collect_buffer_len = 0; - -#if USE_RNDLINUX - rc = _gcry_rndlinux_gather_random (entropy_collect_cb, 0, - X931_AES_KEYLEN, - GCRY_VERY_STRONG_RANDOM); -#elif USE_RNDW32 - do - { - rc = _gcry_rndw32_gather_random (entropy_collect_cb, 0, - X931_AES_KEYLEN, - GCRY_VERY_STRONG_RANDOM); - } - while (rc >= 0 && entropy_collect_buffer_len < entropy_collect_buffer_size); -#else - rc = -1; -#endif - - if (rc < 0 || entropy_collect_buffer_len != entropy_collect_buffer_size) - { - xfree (entropy_collect_buffer); - entropy_collect_buffer = NULL; - log_fatal ("error getting entropy data\n"); - } - result = entropy_collect_buffer; - entropy_collect_buffer = NULL; - return result; -} - - -/* Generate a key for use with x931_aes. The function returns a - handle to the cipher context readily prepared for ECB encryption. - If FOR_NONCE is true, the key is retrieved by readong random from - the standard generator. On error NULL is returned. */ -static gcry_cipher_hd_t -x931_generate_key (int for_nonce) -{ - gcry_cipher_hd_t hd; - gpg_err_code_t rc; - void *buffer; - - gcry_assert (fips_rng_is_locked); - - /* Allocate a cipher context. */ - rc = _gcry_cipher_open (&hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB, - GCRY_CIPHER_SECURE); - if (rc) - { - log_error ("error creating cipher context for RNG: %s\n", - _gcry_strerror (rc)); - return NULL; - } - - /* Get a key from the standard RNG or from the entropy source. */ - if (for_nonce) - { - buffer = xmalloc (X931_AES_KEYLEN); - get_random (buffer, X931_AES_KEYLEN, std_rng_context); - } - else - { - buffer = get_entropy (X931_AES_KEYLEN); - } - - /* Set the key and delete the buffer because the key is now part of - the cipher context. */ - rc = _gcry_cipher_setkey (hd, buffer, X931_AES_KEYLEN); - wipememory (buffer, X931_AES_KEYLEN); - xfree (buffer); - if (rc) - { - log_error ("error creating key for RNG: %s\n", _gcry_strerror (rc)); - _gcry_cipher_close (hd); - return NULL; - } - - return hd; -} - - -/* Generate a key for use with x931_aes. The function copies a seed - of LENGTH bytes into SEED_BUFFER. LENGTH needs to by given as 16. */ -static void -x931_generate_seed (unsigned char *seed_buffer, size_t length) -{ - void *buffer; - - gcry_assert (fips_rng_is_locked); - gcry_assert (length == 16); - - buffer = get_entropy (X931_AES_KEYLEN); - - memcpy (seed_buffer, buffer, X931_AES_KEYLEN); - wipememory (buffer, X931_AES_KEYLEN); - xfree (buffer); -} - - - -/* Reseed a generator. This is also used for the initial seeding. */ -static void -x931_reseed (rng_context_t rng_ctx) -{ - gcry_assert (fips_rng_is_locked); - - if (rng_ctx == nonce_context) - { - /* The nonce context is special. It will be seeded using the - standard random generator. */ - get_random (rng_ctx->seed_V, 16, std_rng_context); - rng_ctx->is_seeded = 1; - rng_ctx->seed_init_pid = getpid (); - } - else - { - /* The other two generators are seeded from /dev/random. */ - x931_generate_seed (rng_ctx->seed_V, 16); - rng_ctx->is_seeded = 1; - rng_ctx->seed_init_pid = getpid (); - } -} - - -/* Core random function. This is used for both nonce and random - generator. The actual RNG to be used depends on the random context - RNG_CTX passed. Note that this function is called with the RNG not - yet locked. */ -static void -get_random (void *buffer, size_t length, rng_context_t rng_ctx) -{ - gcry_assert (buffer); - gcry_assert (rng_ctx); - - check_guards (rng_ctx); - - /* Initialize the cipher handle and thus setup the key if needed. */ - if (!rng_ctx->cipher_hd) - { - if (rng_ctx == nonce_context) - rng_ctx->cipher_hd = x931_generate_key (1); - else - rng_ctx->cipher_hd = x931_generate_key (0); - if (!rng_ctx->cipher_hd) - goto bailout; - rng_ctx->key_init_pid = getpid (); - } - - /* Initialize the seed value if needed. */ - if (!rng_ctx->is_seeded) - x931_reseed (rng_ctx); - - if (rng_ctx->key_init_pid != getpid () - || rng_ctx->seed_init_pid != getpid ()) - { - /* We are in a child of us. Because we have no way yet to do - proper re-initialization (including self-checks etc), the - only chance we have is to bail out. Obviusly a fork/exec - won't harm because the exec overwrites the old image. */ - fips_signal_error ("fork without proper re-initialization " - "detected in RNG"); - goto bailout; - } - - if (x931_aes_driver (buffer, length, rng_ctx)) - goto bailout; - - check_guards (rng_ctx); - return; - - bailout: - log_fatal ("severe error getting random\n"); - /*NOTREACHED*/ -} - - - -/* --- Public Functions --- */ - -/* Initialize this random subsystem. If FULL is false, this function - merely calls the basic initialization of the module and does not do - anything more. Doing this is not really required but when running - in a threaded environment we might get a race condition - otherwise. */ -void -_gcry_rngfips_initialize (int full) -{ - basic_initialization (); - if (!full) - return; - - /* Allocate temporary buffers. If that buffer already exists we - know that we are already initialized. */ - lock_rng (); - if (!tempvalue_for_x931_aes_driver) - { - tempvalue_for_x931_aes_driver - = xmalloc_secure (TEMPVALUE_FOR_X931_AES_DRIVER_SIZE); - - /* Allocate the random contexts. Note that we do not need to use - secure memory for the nonce context. */ - nonce_context = xcalloc (1, sizeof *nonce_context); - setup_guards (nonce_context); - - std_rng_context = xcalloc_secure (1, sizeof *std_rng_context); - setup_guards (std_rng_context); - - strong_rng_context = xcalloc_secure (1, sizeof *strong_rng_context); - setup_guards (strong_rng_context); - } - else - { - /* Already initialized. Do some sanity checks. */ - gcry_assert (!nonce_context->test_dt_ptr); - gcry_assert (!std_rng_context->test_dt_ptr); - gcry_assert (!strong_rng_context->test_dt_ptr); - check_guards (nonce_context); - check_guards (std_rng_context); - check_guards (strong_rng_context); - } - unlock_rng (); -} - - -/* Try to close the FDs of the random gather module. This is - currently only implemented for rndlinux. */ -void -_gcry_rngfips_close_fds (void) -{ - lock_rng (); -#if USE_RNDLINUX - _gcry_rndlinux_gather_random (NULL, 0, 0, 0); -#endif - unlock_rng (); -} - - -/* Print some statistics about the RNG. */ -void -_gcry_rngfips_dump_stats (void) -{ - /* Not yet implemented. */ -} - - -/* This function returns true if no real RNG is available or the - quality of the RNG has been degraded for test purposes. */ -int -_gcry_rngfips_is_faked (void) -{ - return 0; /* Faked random is not allowed. */ -} - - -/* Add BUFLEN bytes from BUF to the internal random pool. QUALITY - should be in the range of 0..100 to indicate the goodness of the - entropy added, or -1 for goodness not known. */ -gcry_error_t -_gcry_rngfips_add_bytes (const void *buf, size_t buflen, int quality) -{ - (void)buf; - (void)buflen; - (void)quality; - return 0; /* Not implemented. */ -} - - -/* Public function to fill the buffer with LENGTH bytes of - cryptographically strong random bytes. Level GCRY_WEAK_RANDOM is - here mapped to GCRY_STRONG_RANDOM, GCRY_STRONG_RANDOM is strong - enough for most usage, GCRY_VERY_STRONG_RANDOM is good for key - generation stuff but may be very slow. */ -void -_gcry_rngfips_randomize (void *buffer, size_t length, - enum gcry_random_level level) -{ - _gcry_rngfips_initialize (1); /* Auto-initialize if needed. */ - - lock_rng (); - if (level == GCRY_VERY_STRONG_RANDOM) - get_random (buffer, length, strong_rng_context); - else - get_random (buffer, length, std_rng_context); - unlock_rng (); -} - - -/* Create an unpredicable nonce of LENGTH bytes in BUFFER. */ -void -_gcry_rngfips_create_nonce (void *buffer, size_t length) -{ - _gcry_rngfips_initialize (1); /* Auto-initialize if needed. */ - - lock_rng (); - get_random (buffer, length, nonce_context); - unlock_rng (); -} - - -/* Run a Know-Answer-Test using a dedicated test context. Note that - we can't use the samples from the NISR RNGVS document because they - don't take the requirement to throw away the first block and use - that for duplicate check in account. Thus we made up our own test - vectors. */ -static gcry_err_code_t -selftest_kat (selftest_report_func_t report) -{ - static struct - { - const unsigned char key[16]; - const unsigned char dt[16]; - const unsigned char v[16]; - const unsigned char r[3][16]; - } tv[] = - { - { { 0xb9, 0xca, 0x7f, 0xd6, 0xa0, 0xf5, 0xd3, 0x42, - 0x19, 0x6d, 0x84, 0x91, 0x76, 0x1c, 0x3b, 0xbe }, - { 0x48, 0xb2, 0x82, 0x98, 0x68, 0xc2, 0x80, 0x00, - 0x00, 0x00, 0x28, 0x18, 0x00, 0x00, 0x25, 0x00 }, - { 0x52, 0x17, 0x8d, 0x29, 0xa2, 0xd5, 0x84, 0x12, - 0x9d, 0x89, 0x9a, 0x45, 0x82, 0x02, 0xf7, 0x77 }, - { { 0x42, 0x9c, 0x08, 0x3d, 0x82, 0xf4, 0x8a, 0x40, - 0x66, 0xb5, 0x49, 0x27, 0xab, 0x42, 0xc7, 0xc3 }, - { 0x0e, 0xb7, 0x61, 0x3c, 0xfe, 0xb0, 0xbe, 0x73, - 0xf7, 0x6e, 0x6d, 0x6f, 0x1d, 0xa3, 0x14, 0xfa }, - { 0xbb, 0x4b, 0xc1, 0x0e, 0xc5, 0xfb, 0xcd, 0x46, - 0xbe, 0x28, 0x61, 0xe7, 0x03, 0x2b, 0x37, 0x7d } } }, - { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { { 0xf7, 0x95, 0xbd, 0x4a, 0x52, 0xe2, 0x9e, 0xd7, - 0x13, 0xd3, 0x13, 0xfa, 0x20, 0xe9, 0x8d, 0xbc }, - { 0xc8, 0xd1, 0xe5, 0x11, 0x59, 0x52, 0xf7, 0xfa, - 0x37, 0x38, 0xb4, 0xc5, 0xce, 0xb2, 0xb0, 0x9a }, - { 0x0d, 0x9c, 0xc5, 0x0d, 0x16, 0xe1, 0xbc, 0xed, - 0xcf, 0x60, 0x62, 0x09, 0x9d, 0x20, 0x83, 0x7e } } }, - { { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - { 0x80, 0x00, 0x81, 0x01, 0x82, 0x02, 0x83, 0x03, - 0xa0, 0x20, 0xa1, 0x21, 0xa2, 0x22, 0xa3, 0x23 }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { { 0x96, 0xed, 0xcc, 0xc3, 0xdd, 0x04, 0x7f, 0x75, - 0x63, 0x19, 0x37, 0x6f, 0x15, 0x22, 0x57, 0x56 }, - { 0x7a, 0x14, 0x76, 0x77, 0x95, 0x17, 0x7e, 0xc8, - 0x92, 0xe8, 0xdd, 0x15, 0xcb, 0x1f, 0xbc, 0xb1 }, - { 0x25, 0x3e, 0x2e, 0xa2, 0x41, 0x1b, 0xdd, 0xf5, - 0x21, 0x48, 0x41, 0x71, 0xb3, 0x8d, 0x2f, 0x4c } } } - }; - int tvidx, ridx; - rng_context_t test_ctx; - gpg_err_code_t rc; - const char *errtxt = NULL; - unsigned char result[16]; - - gcry_assert (tempvalue_for_x931_aes_driver); - - test_ctx = xcalloc (1, sizeof *test_ctx); - setup_guards (test_ctx); - - lock_rng (); - - for (tvidx=0; tvidx < DIM (tv); tvidx++) - { - /* Setup the key. */ - rc = _gcry_cipher_open (&test_ctx->cipher_hd, - GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB, - GCRY_CIPHER_SECURE); - if (rc) - { - errtxt = "error creating cipher context for RNG"; - goto leave; - } - - rc = _gcry_cipher_setkey (test_ctx->cipher_hd, tv[tvidx].key, 16); - if (rc) - { - errtxt = "error setting key for RNG"; - goto leave; - } - test_ctx->key_init_pid = getpid (); - - /* Setup the seed. */ - memcpy (test_ctx->seed_V, tv[tvidx].v, 16); - test_ctx->is_seeded = 1; - test_ctx->seed_init_pid = getpid (); - - /* Setup a DT value. */ - test_ctx->test_dt_ptr = tv[tvidx].dt; - test_ctx->test_dt_counter = ( (tv[tvidx].dt[12] << 24) - |(tv[tvidx].dt[13] << 16) - |(tv[tvidx].dt[14] << 8) - |(tv[tvidx].dt[15]) ); - - /* Get and compare the first three results. */ - for (ridx=0; ridx < 3; ridx++) - { - /* Compute the next value. */ - if (x931_aes_driver (result, 16, test_ctx)) - { - errtxt = "X9.31 RNG core function failed"; - goto leave; - } - - /* Compare it to the known value. */ - if (memcmp (result, tv[tvidx].r[ridx], 16)) - { - /* log_printhex ("x931_aes got: ", result, 16); */ - /* log_printhex ("x931_aes exp: ", tv[tvidx].r[ridx], 16); */ - errtxt = "RNG output does not match known value"; - goto leave; - } - } - - /* This test is actual pretty pointless because we use a local test - context. */ - if (test_ctx->key_init_pid != getpid () - || test_ctx->seed_init_pid != getpid ()) - { - errtxt = "fork detection failed"; - goto leave; - } - - _gcry_cipher_close (test_ctx->cipher_hd); - test_ctx->cipher_hd = NULL; - test_ctx->is_seeded = 0; - check_guards (test_ctx); - } - - leave: - unlock_rng (); - _gcry_cipher_close (test_ctx->cipher_hd); - check_guards (test_ctx); - xfree (test_ctx); - if (report && errtxt) - report ("random", 0, "KAT", errtxt); - return errtxt? GPG_ERR_SELFTEST_FAILED : 0; -} - - -/* Run the self-tests. */ -gcry_error_t -_gcry_rngfips_selftest (selftest_report_func_t report) -{ - gcry_err_code_t ec; - -#if defined(USE_RNDLINUX) || defined(USE_RNDW32) - { - char buffer[8]; - - /* Do a simple test using the public interface. This will also - enforce full initialization of the RNG. We need to be fully - initialized due to the global requirement of the - tempvalue_for_x931_aes_driver stuff. */ - _gcry_randomize (buffer, sizeof buffer, GCRY_STRONG_RANDOM); - } - - ec = selftest_kat (report); - -#else /*!(USE_RNDLINUX||USE_RNDW32)*/ - report ("random", 0, "setup", "no entropy gathering module"); - ec = GPG_ERR_SELFTEST_FAILED; -#endif - return gpg_error (ec); -} - - -/* Create a new test context for an external RNG test driver. On - success the test context is stored at R_CONTEXT; on failure NULL is - stored at R_CONTEXT and an error code is returned. */ -gcry_err_code_t -_gcry_rngfips_init_external_test (void **r_context, unsigned int flags, - const void *key, size_t keylen, - const void *seed, size_t seedlen, - const void *dt, size_t dtlen) -{ - gpg_err_code_t rc; - rng_context_t test_ctx; - - _gcry_rngfips_initialize (1); /* Auto-initialize if needed. */ - - if (!r_context - || !key || keylen != 16 - || !seed || seedlen != 16 - || !dt || dtlen != 16 ) - return GPG_ERR_INV_ARG; - - test_ctx = xtrycalloc (1, sizeof *test_ctx + dtlen); - if (!test_ctx) - return gpg_err_code_from_syserror (); - setup_guards (test_ctx); - - /* Setup the key. */ - rc = _gcry_cipher_open (&test_ctx->cipher_hd, - GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB, - GCRY_CIPHER_SECURE); - if (rc) - goto leave; - - rc = _gcry_cipher_setkey (test_ctx->cipher_hd, key, keylen); - if (rc) - goto leave; - - test_ctx->key_init_pid = getpid (); - - /* Setup the seed. */ - memcpy (test_ctx->seed_V, seed, seedlen); - test_ctx->is_seeded = 1; - test_ctx->seed_init_pid = getpid (); - - /* Setup a DT value. Because our context structure only stores a - pointer we copy the DT value to the extra space we allocated in - the test_ctx and set the pointer to that address. */ - memcpy ((unsigned char*)test_ctx + sizeof *test_ctx, dt, dtlen); - test_ctx->test_dt_ptr = (unsigned char*)test_ctx + sizeof *test_ctx; - test_ctx->test_dt_counter = ( (test_ctx->test_dt_ptr[12] << 24) - |(test_ctx->test_dt_ptr[13] << 16) - |(test_ctx->test_dt_ptr[14] << 8) - |(test_ctx->test_dt_ptr[15]) ); - - if ( (flags & 1) ) - test_ctx->test_no_dup_check = 1; - - check_guards (test_ctx); - /* All fine. */ - rc = 0; - - leave: - if (rc) - { - _gcry_cipher_close (test_ctx->cipher_hd); - xfree (test_ctx); - *r_context = NULL; - } - else - *r_context = test_ctx; - return rc; -} - - -/* Get BUFLEN bytes from the RNG using the test CONTEXT and store them - at BUFFER. Return 0 on success or an error code. */ -gcry_err_code_t -_gcry_rngfips_run_external_test (void *context, char *buffer, size_t buflen) -{ - rng_context_t test_ctx = context; - - if (!test_ctx || !buffer || buflen != 16) - return GPG_ERR_INV_ARG; - - lock_rng (); - get_random (buffer, buflen, test_ctx); - unlock_rng (); - return 0; -} - -/* Release the test CONTEXT. */ -void -_gcry_rngfips_deinit_external_test (void *context) -{ - rng_context_t test_ctx = context; - - if (test_ctx) - { - _gcry_cipher_close (test_ctx->cipher_hd); - xfree (test_ctx); - } -} -- 2.5.0 From smueller at chronox.de Tue Feb 16 22:03:49 2016 From: smueller at chronox.de (Stephan Mueller) Date: Tue, 16 Feb 2016 22:03:49 +0100 Subject: [PATCH 0/2] SP800-90A DRBG Message-ID: <1560889.z3jECahC7P@positron.chronox.de> Hi, as the SP800-90A DRBG is considered for inclusion into 1.7, I ported the existing DRBG patch set in [1] to the current git tree of libgcrypt. The DRBG is fully CAVS tested. The following changes compared to [1] are present: * Addition of reseeding CAVS test support. * Addition of reseeding FIPS 140-2 power-on self test. * DRBG flags received the GCRY_ prefix to avoid namespace polution. * Removal of the FIPS 140-2 continuous self test due to the recent update of FIPS 140-2 IG 9.8 which allows skipping of this (nonsense) test for SP800-90A DRBGs. * Update the initialization logic to automatically initialize the DRBG if needed. * Update locking code. * CAVS test interface uses libgcrypt control interface 59. The second patch of this patchset removes the ANSI X9.31 DRNG as the DRBG completely supersedes the DRNG. I am not sure whether I should update the bug report [1] to include the updated patchset. Please advise of the current development regime for libgcrypt. [1] https://bugs.gnupg.org/gnupg/issue1701 Stephan Mueller (2): SP800-90A DRBG Remove ANSI X9.31 DRNG random/Makefile.am | 2 +- random/drbg.c | 2340 ++++++++++++++++++++++++++++++++++++++++++++++++ random/rand-internal.h | 34 +- random/random-fips.c | 1124 ----------------------- random/random.c | 59 +- random/random.h | 26 + src/gcrypt.h.in | 108 +++ src/global.c | 45 +- 8 files changed, 2513 insertions(+), 1225 deletions(-) create mode 100644 random/drbg.c delete mode 100644 random/random-fips.c -- 2.5.0 From dkg at fifthhorseman.net Tue Feb 16 22:08:03 2016 From: dkg at fifthhorseman.net (Daniel Kahn Gillmor) Date: Tue, 16 Feb 2016 16:08:03 -0500 Subject: building libgcrypt with --host x86_64-w64-mingw32 In-Reply-To: <87si0sg4ba.fsf@wheatstone.g10code.de> References: <87twl9jpwk.fsf@alice.fifthhorseman.net> <87si0sg4ba.fsf@wheatstone.g10code.de> Message-ID: <87io1oicss.fsf@alice.fifthhorseman.net> On Tue 2016-02-16 08:42:01 -0500, Werner Koch wrote: > On Tue, 16 Feb 2016 04:27, dkg at fifthhorseman.net said: > >> i'm exploring building gcrypt 1.6.5 using mingw32 on debian, and i find > > This is how I build the GnuPG installer for Windows. Great! hopefully some of the work i've been doing in debian will be able to automate parts of this process for you. >> i can build it OK with i686-w64-mingw32-gcc (./configure --host >> i686-w64-mingw32), but not with x86_64-w64-mingw32-gcc (./configure >> --host x86_64-w64-mingw32). In particular: > > I am actually using > > x86_64-w64-mingw32-gcc (GCC) 4.9.1 > > w/o any problems. This is not Sid, though. See also > gnupg/build-aux/speedo.mk for details. Note that the Windows code > should be build with "./autogen.sh --build-w32" (or -w64) because that > scripts tracks our knowledge of useful options. hm, my current approach has been to build it with the same refreshed autoreconf files as the non-windows ports, just to do an out-of-tree build for each targeted platform. The specific features that are disabled or re-pointed to different prefixes during the builds are selected during compilation in the same way. (this would likely be cleaner on debian if these packages were able to use pkg-config, but my understanding is that GnuPG and related tools are not going to be adopting pkg-config for platforms that support them any time soon) At any rate, i've managed to build a functioning gpgv.exe (and gpg.exe) using this approach :) >> * random/rndhw.c fails to build because it selects 32-bit assembler >> because __x86_64__ and __LP64__ are not #define'd > > Hmmm. A mingw regression? tc () { printf '#if defined(__%s__)\nhas "__%s__"\n#endif\n' "$1" "$1" ; } for cc in gcc i686-w64-mingw32-gcc x86_64-w64-mingw32-gcc; do "$cc" --version | head -n1 for x in x86_64 LP64; do tc "$x" | "$cc" -E - ; done | grep '^[^#]' done for me produces this on stretch/testing: gcc (Debian 5.3.1-8) 5.3.1 20160205 has "__x86_64__" has "__LP64__" i686-w64-mingw32-gcc (GCC) 5.3.1 20151207 x86_64-w64-mingw32-gcc (GCC) 5.3.1 20151207 has "__x86_64__" And i'm seeing the same thing on Jessie: gcc (Debian 4.9.2-10) 4.9.2 has "__x86_64__" has "__LP64__" i686-w64-mingw32-gcc (GCC) 4.9.1 x86_64-w64-mingw32-gcc (GCC) 4.9.1 has "__x86_64__" Are you seeing something different? --dkg From 4winter at informatik.uni-hamburg.de Tue Feb 16 12:36:54 2016 From: 4winter at informatik.uni-hamburg.de (Justus Winter) Date: Tue, 16 Feb 2016 12:36:54 +0100 Subject: Help needed : Error in compiling libgpg-error In-Reply-To: <402052700.10017577.1453484715323.JavaMail.yahoo@mail.yahoo.com> References: <402052700.10017577.1453484715323.JavaMail.yahoo.ref@mail.yahoo.com> <402052700.10017577.1453484715323.JavaMail.yahoo@mail.yahoo.com> Message-ID: <20160216113654.20726.85884@thinkbox.jade-hamburg.de> Hi, Quoting shilpa shilpa (2016-01-22 18:45:15) > We are trying to cross-compile libgpg-error for arm-platform, But > compilation is failing. See the confirure and make logs below: > [...] > arm-unknown-linux-gnueabi-gcc -E?? -P _mkerrcodes.h | grep GPG_ERR_ | \ > ?????????????? gawk -f ./mkerrcodes.awk >mkerrcodes.h > In file included from /soft/gnu/cross/linux_64/13/arm/arm-unknown-linux-gnueabi/usr/include/errno.h:28:0, > ???????????????? from _mkerrcodes.h:25: > /soft/gnu/cross/linux_64/13/arm/arm-unknown-linux-gnueabi/usr/include/features.h:327:4: warning: #warning _FORTIFY_SOURCE requires compiling with optimization (-O) [-Wcpp] > ?#? warning _FORTIFY_SOURCE requires compiling with optimization (-O) > ??? ^ It says what's wrong right here, you need to turn on the compiler optimizations. Justus From smueller at chronox.de Tue Feb 16 22:04:28 2016 From: smueller at chronox.de (Stephan Mueller) Date: Tue, 16 Feb 2016 22:04:28 +0100 Subject: [PATCH 1/2] SP800-90A DRBG In-Reply-To: <1560889.z3jECahC7P@positron.chronox.de> References: <1560889.z3jECahC7P@positron.chronox.de> Message-ID: <1455659039.ubOmUqvSm5@positron.chronox.de> This patch set adds the SP800-90A DRBG for AES128, AES192, AES256 with derivation function, SHA-1 through SHA-512 with derivation function, HMAC SHA-1 through HMAC SHA-512. All DRBGs are provided with and without prediction resistance. In addition, all DRBGs allow reseeding by the caller. The default DRBG is HMAC SHA-256 without prediction resistance. The caller may re-initialize the DRBG with the control GCRYCTL_DRBG_REINIT: The patch replaces the invocation of the existing ANSI X9.31 DRNG. This covers the control calls of 58 through 60. Control call 58 and 60 are simply deactivated. Control 59 is replaced with the DRBG CAVS test interface. Signed-off-by: Stephan Mueller --- random/Makefile.am | 1 + random/drbg.c | 2340 ++++++++++++++++++++++++++++++++++++++++++++++++ random/rand-internal.h | 9 + random/random.c | 59 +- random/random.h | 26 + src/gcrypt.h.in | 108 +++ src/global.c | 45 +- 7 files changed, 2513 insertions(+), 75 deletions(-) create mode 100644 random/drbg.c diff --git a/random/Makefile.am b/random/Makefile.am index c9d587a..e073fa4 100644 --- a/random/Makefile.am +++ b/random/Makefile.am @@ -35,6 +35,7 @@ random.c random.h \ rand-internal.h \ random-csprng.c \ random-fips.c \ +drbg.c \ random-system.c \ rndhw.c diff --git a/random/drbg.c b/random/drbg.c new file mode 100644 index 0000000..752eb65 --- /dev/null +++ b/random/drbg.c @@ -0,0 +1,2340 @@ +/* + * DRBG: Deterministic Random Bits Generator + * Based on NIST Recommended DRBG from NIST SP800-90A with the following + * properties: + * * CTR DRBG with DF with AES-128, AES-192, AES-256 cores + * * Hash DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores + * * HMAC DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores + * * with and without prediction resistance + * + * Copyright Stephan Mueller , 2014 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * ALTERNATIVELY, this product may be distributed under the terms of + * LGPLv2+, in which case the provisions of the LGPL are + * required INSTEAD OF the above restrictions. (This clause is + * necessary due to a potential bad interaction between the LGPL and + * the restrictions contained in a BSD-style copyright.) + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * + * gcry_control GCRYCTL_DRBG_REINIT + * ================================ + * This control request re-initializes the DRBG completely, i.e. the entire + * state of the DRBG is zeroized (with two exceptions listed in + * GCRYCTL_DRBG_SET_ENTROPY). + * + * The control request takes the following values which influences how the DRBG + * is re-initialized: + * * u32 flags: This variable specifies the DRBG type to be used for the + * next initialization. If set to 0, the previous DRBG type is + * used for the initialization. The DRBG type is an OR of the + * mandatory flags of the requested DRBG strength and DRBG + * cipher type. Optionally, the prediction resistance flag + * can be ORed into the flags variable. For example: + * - CTR-DRBG with AES-128 without prediction resistance: + * DRBG_CTRAES128 + * - HMAC-DRBG with SHA-512 with prediction resistance: + * DRBG_HMACSHA512 | DRBG_PREDICTION_RESIST + * * struct gcry_drbg_string *pers: personalization string to be used for + * initialization. + * The variable of flags is independent from the pers/perslen variables. If + * flags is set to 0 and perslen is set to 0, the current DRBG type is + * completely reset without using a personalization string. + * + * DRBG Usage + * ========== + * The SP 800-90A DRBG allows the user to specify a personalization string + * for initialization as well as an additional information string for each + * random number request. The following code fragments show how a caller + * uses the kernel crypto API to use the full functionality of the DRBG. + * + * Usage without any additional data + * --------------------------------- + * gcry_randomize(outbuf, OUTLEN, GCRY_STRONG_RANDOM); + * + * + * Usage with personalization string during initialization + * ------------------------------------------------------- + * struct gcry_drbg_string pers; + * char personalization[11] = "some-string"; + * + * gcry_drbg_string_fill(&pers, personalization, strlen(personalization)); + * // The reset completely re-initializes the DRBG with the provided + * // personalization string without changing the DRBG type + * ret = gcry_control(GCRYCTL_DRBG_REINIT, 0, &pers); + * gcry_randomize(outbuf, OUTLEN, GCRY_STRONG_RANDOM); + * + * + * Usage with additional information string during random number request + * --------------------------------------------------------------------- + * struct gcry_drbg_string addtl; + * char addtl_string[11] = "some-string"; + * + * gcry_drbg_string_fill(&addtl, addtl_string, strlen(addtl_string)); + * // The following call is a wrapper to gcry_randomize() and returns + * // the same error codes. + * gcry_randomize_drbg(outbuf, OUTLEN, GCRY_STRONG_RANDOM, &addtl); + * + * + * Usage with personalization and additional information strings + * ------------------------------------------------------------- + * Just mix both scenarios above. + * + * + * Switch the DRBG type to some other type + * --------------------------------------- + * // Switch to CTR DRBG AES-128 without prediction resistance + * ret = gcry_control(GCRYCTL_DRBG_REINIT, DRBG_NOPR_CTRAES128, NULL); + * gcry_randomize(outbuf, OUTLEN, GCRY_STRONG_RANDOM); + */ + +#include +#include +#include +#include +#include + +#include + +#include "g10lib.h" +#include "random.h" +#include "rand-internal.h" +#include "../cipher/bithelp.h" + +/****************************************************************** + * Common data structures + ******************************************************************/ + +struct gcry_drbg_state; + +struct gcry_drbg_core +{ + u32 flags; /* flags for the cipher */ + ushort statelen; /* maximum state length */ + ushort blocklen_bytes; /* block size of output in bytes */ + int backend_cipher; /* libgcrypt backend cipher */ +}; + +struct gcry_drbg_state_ops +{ + gpg_err_code_t (*update) (struct gcry_drbg_state * drbg, + struct gcry_drbg_string * seed, int reseed); + gpg_err_code_t (*generate) (struct gcry_drbg_state * drbg, + unsigned char *buf, unsigned int buflen, + struct gcry_drbg_string * addtl); +}; + +/* DRBG test data */ +struct gcry_drbg_test_data +{ + struct gcry_drbg_string *testentropy; /* TEST PARAMETER: test entropy */ + int fail_seed_source:1; /* if set, the seed function will return an error */ +}; + + +struct gcry_drbg_state +{ + unsigned char *V; /* internal state 10.1.1.1 1a) */ + unsigned char *C; /* hash: static value 10.1.1.1 1b) + * hmac / ctr: key */ + size_t reseed_ctr; /* Number of RNG requests since last reseed -- + * 10.1.1.1 1c) */ + unsigned char *scratchpad; /* some memory the DRBG can use for its + * operation -- allocated during init */ + int seeded:1; /* DRBG fully seeded? */ + int pr:1; /* Prediction resistance enabled? */ + /* Taken from libgcrypt ANSI X9.31 DRNG: We need to keep track of the + * process which did the initialization so that we can detect a fork. + * The volatile modifier is required so that the compiler does not + * optimize it away in case the getpid function is badly attributed. */ + pid_t seed_init_pid; + const struct gcry_drbg_state_ops *d_ops; + const struct gcry_drbg_core *core; + struct gcry_drbg_test_data *test_data; +}; + +enum gcry_drbg_prefixes +{ + DRBG_PREFIX0 = 0x00, + DRBG_PREFIX1, + DRBG_PREFIX2, + DRBG_PREFIX3 +}; + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + +/*************************************************************** + * Backend cipher definitions available to DRBG + ***************************************************************/ + +static const struct gcry_drbg_core gcry_drbg_cores[] = { + /* Hash DRBGs */ + {GCRY_DRBG_HASHSHA1, 55, 20, GCRY_MD_SHA1}, + {GCRY_DRBG_HASHSHA256, 55, 32, GCRY_MD_SHA256}, + {GCRY_DRBG_HASHSHA384, 111, 48, GCRY_MD_SHA384}, + {GCRY_DRBG_HASHSHA512, 111, 64, GCRY_MD_SHA512}, + /* HMAC DRBGs */ + {GCRY_DRBG_HASHSHA1 | GCRY_DRBG_HMAC, 20, 20, GCRY_MD_SHA1}, + {GCRY_DRBG_HASHSHA256 | GCRY_DRBG_HMAC, 32, 32, GCRY_MD_SHA256}, + {GCRY_DRBG_HASHSHA384 | GCRY_DRBG_HMAC, 48, 48, GCRY_MD_SHA384}, + {GCRY_DRBG_HASHSHA512 | GCRY_DRBG_HMAC, 64, 64, GCRY_MD_SHA512}, + /* block ciphers */ + {GCRY_DRBG_CTRAES | GCRY_DRBG_SYM128, 32, 16, GCRY_CIPHER_AES128}, + {GCRY_DRBG_CTRAES | GCRY_DRBG_SYM192, 40, 16, GCRY_CIPHER_AES192}, + {GCRY_DRBG_CTRAES | GCRY_DRBG_SYM256, 48, 16, GCRY_CIPHER_AES256}, +}; + +static gpg_err_code_t gcry_drbg_sym (struct gcry_drbg_state *drbg, + const unsigned char *key, + unsigned char *outval, + const struct gcry_drbg_string *buf); +static gpg_err_code_t gcry_drbg_hmac (struct gcry_drbg_state *drbg, + const unsigned char *key, + unsigned char *outval, + const struct gcry_drbg_string *buf); + +/****************************************************************** + ****************************************************************** + ****************************************************************** + * Generic DRBG code + ****************************************************************** + ****************************************************************** + ******************************************************************/ + +/****************************************************************** + * Generic helper functions + ******************************************************************/ + +#if 0 +#define dbg(x) do { log_debug x; } while(0) +#else +#define dbg(x) +#endif + +static inline ushort +gcry_drbg_statelen (struct gcry_drbg_state *drbg) +{ + if (drbg && drbg->core) + return drbg->core->statelen; + return 0; +} + +static inline ushort +gcry_drbg_blocklen (struct gcry_drbg_state *drbg) +{ + if (drbg && drbg->core) + return drbg->core->blocklen_bytes; + return 0; +} + +static inline ushort +gcry_drbg_keylen (struct gcry_drbg_state *drbg) +{ + if (drbg && drbg->core) + return (drbg->core->statelen - drbg->core->blocklen_bytes); + return 0; +} + +static inline size_t +gcry_drbg_max_request_bytes (void) +{ + /* SP800-90A requires the limit 2**19 bits, but we return bytes */ + return (1 << 16); +} + +static inline size_t +gcry_drbg_max_addtl (void) +{ + /* SP800-90A requires 2**35 bytes additional info str / pers str */ +#ifdef __LP64__ + return (1UL << 35); +#else + /* + * SP800-90A allows smaller maximum numbers to be returned -- we + * return SIZE_MAX - 1 to allow the verification of the enforcement + * of this value in gcry_drbg_healthcheck_sanity. + */ + return (SIZE_MAX - 1); +#endif +} + +static inline size_t +gcry_drbg_max_requests (void) +{ + /* SP800-90A requires 2**48 maximum requests before reseeding */ +#ifdef __LP64__ + return (1UL << 48); +#else + return SIZE_MAX; +#endif +} + +/* + * Return strength of DRBG according to SP800-90A section 8.4 + * + * flags: DRBG flags reference + * + * Return: normalized strength value or 32 as a default to counter + * programming errors + */ +static inline unsigned short +gcry_drbg_sec_strength (u32 flags) +{ + if ((flags & GCRY_DRBG_HASHSHA1) || (flags & GCRY_DRBG_SYM128)) + return 16; + else if (flags & GCRY_DRBG_SYM192) + return 24; + else if ((flags & GCRY_DRBG_SYM256) || (flags & GCRY_DRBG_HASHSHA256) || + (flags & GCRY_DRBG_HASHSHA384) || (flags & GCRY_DRBG_HASHSHA512)) + return 32; + else + return 32; +} + +/* + * Convert an integer into a byte representation of this integer. + * The byte representation is big-endian + * + * @val value to be converted + * @buf buffer holding the converted integer -- caller must ensure that + * buffer size is at least 32 bit + */ +static inline void +gcry_drbg_cpu_to_be32 (u32 val, unsigned char *buf) +{ + struct s + { + u32 conv; + }; + struct s *conversion = (struct s *) buf; + + conversion->conv = be_bswap32 (val); +} + +static void +gcry_drbg_add_buf (unsigned char *dst, size_t dstlen, + unsigned char *add, size_t addlen) +{ + /* implied: dstlen > addlen */ + unsigned char *dstptr, *addptr; + unsigned int remainder = 0; + size_t len = addlen; + + dstptr = dst + (dstlen - 1); + addptr = add + (addlen - 1); + while (len) + { + remainder += *dstptr + *addptr; + *dstptr = remainder & 0xff; + remainder >>= 8; + len--; + dstptr--; + addptr--; + } + len = dstlen - addlen; + while (len && remainder > 0) + { + remainder = *dstptr + 1; + *dstptr = remainder & 0xff; + remainder >>= 8; + len--; + dstptr--; + } +} + +/* Helper variables for read_cb(). + * + * The _gcry_rnd*_gather_random interface does not allow to provide a + * data pointer. Thus we need to use a global variable for + * communication. However, the then required locking is anyway a good + * idea because it does not make sense to have several readers of (say + * /dev/random). It is easier to serve them one after the other. */ +static unsigned char *read_cb_buffer; /* The buffer. */ +static size_t read_cb_size; /* Size of the buffer. */ +static size_t read_cb_len; /* Used length. */ + +/* Callback for generating seed from kernel device. */ +static void +gcry_drbg_read_cb (const void *buffer, size_t length, + enum random_origins origin) +{ + const unsigned char *p = buffer; + + (void) origin; + gcry_assert (read_cb_buffer); + + /* Note that we need to protect against gatherers returning more + * than the requested bytes (e.g. rndw32). */ + while (length-- && read_cb_len < read_cb_size) + read_cb_buffer[read_cb_len++] = *p++; +} + +static inline int +gcry_drbg_get_entropy (struct gcry_drbg_state *drbg, unsigned char *buffer, + size_t len) +{ + int rc = 0; + + /* Perform testing as defined in 11.3.2 */ + if (drbg->test_data && drbg->test_data->fail_seed_source) + return -1; + + read_cb_buffer = buffer; + read_cb_size = len; + read_cb_len = 0; +#if USE_RNDLINUX + rc = _gcry_rndlinux_gather_random (gcry_drbg_read_cb, 0, len, + GCRY_VERY_STRONG_RANDOM); +#elif USE_RNDUNIX + rc = _gcry_rndunix_gather_random (read_cb, 0, length, + GCRY_VERY_STRONG_RANDOM); +#elif USE_RNDW32 + do + { + rc = _gcry_rndw32_gather_random (read_cb, 0, length, + GCRY_VERY_STRONG_RANDOM); + } + while (rc >= 0 && read_cb_len < read_cb_size); +#else + rc = -1; +#endif + return rc; +} + +/****************************************************************** + * CTR DRBG callback functions + ******************************************************************/ + +/* BCC function for CTR DRBG as defined in 10.4.3 */ +static gpg_err_code_t +gcry_drbg_ctr_bcc (struct gcry_drbg_state *drbg, + unsigned char *out, const unsigned char *key, + struct gcry_drbg_string *in) +{ + gpg_err_code_t ret = GPG_ERR_GENERAL; + struct gcry_drbg_string *curr = in; + size_t inpos = curr->len; + const unsigned char *pos = curr->buf; + struct gcry_drbg_string data; + + gcry_drbg_string_fill (&data, out, gcry_drbg_blocklen (drbg)); + + /* 10.4.3 step 1 */ + memset (out, 0, gcry_drbg_blocklen (drbg)); + + /* 10.4.3 step 2 / 4 */ + while (inpos) + { + short cnt = 0; + /* 10.4.3 step 4.1 */ + for (cnt = 0; cnt < gcry_drbg_blocklen (drbg); cnt++) + { + out[cnt] ^= *pos; + pos++; + inpos--; + /* the following branch implements the linked list + * iteration. If we are at the end of the current data + * set, we have to start using the next data set if + * available -- the inpos value always points to the + * current byte and will be zero if we have processed + * the last byte of the last linked list member */ + if (0 == inpos) + { + curr = curr->next; + if (NULL != curr) + { + pos = curr->buf; + inpos = curr->len; + } + else + { + inpos = 0; + break; + } + } + } + /* 10.4.3 step 4.2 */ + ret = gcry_drbg_sym (drbg, key, out, &data); + if (ret) + return ret; + /* 10.4.3 step 2 */ + } + return 0; +} + + +/* + * scratchpad usage: gcry_drbg_ctr_update is interlinked with gcry_drbg_ctr_df + * (and gcry_drbg_ctr_bcc, but this function does not need any temporary buffers), + * the scratchpad is used as follows: + * gcry_drbg_ctr_update: + * temp + * start: drbg->scratchpad + * length: gcry_drbg_statelen(drbg) + gcry_drbg_blocklen(drbg) + * note: the cipher writing into this variable works + * blocklen-wise. Now, when the statelen is not a multiple + * of blocklen, the generateion loop below "spills over" + * by at most blocklen. Thus, we need to give sufficient + * memory. + * df_data + * start: drbg->scratchpad + + * gcry_drbg_statelen(drbg) + + * gcry_drbg_blocklen(drbg) + * length: gcry_drbg_statelen(drbg) + * + * gcry_drbg_ctr_df: + * pad + * start: df_data + gcry_drbg_statelen(drbg) + * length: gcry_drbg_blocklen(drbg) + * iv + * start: pad + gcry_drbg_blocklen(drbg) + * length: gcry_drbg_blocklen(drbg) + * temp + * start: iv + gcry_drbg_blocklen(drbg) + * length: gcry_drbg_satelen(drbg) + gcry_drbg_blocklen(drbg) + * note: temp is the buffer that the BCC function operates + * on. BCC operates blockwise. gcry_drbg_statelen(drbg) + * is sufficient when the DRBG state length is a multiple + * of the block size. For AES192 (and maybe other ciphers) + * this is not correct and the length for temp is + * insufficient (yes, that also means for such ciphers, + * the final output of all BCC rounds are truncated). + * Therefore, add gcry_drbg_blocklen(drbg) to cover all + * possibilities. + */ + +/* Derivation Function for CTR DRBG as defined in 10.4.2 */ +static gpg_err_code_t +gcry_drbg_ctr_df (struct gcry_drbg_state *drbg, unsigned char *df_data, + size_t bytes_to_return, struct gcry_drbg_string *addtl) +{ + gpg_err_code_t ret = GPG_ERR_GENERAL; + unsigned char L_N[8]; + /* S3 is input */ + struct gcry_drbg_string S1, S2, S4, cipherin; + struct gcry_drbg_string *tempstr = addtl; + unsigned char *pad = df_data + gcry_drbg_statelen (drbg); + unsigned char *iv = pad + gcry_drbg_blocklen (drbg); + unsigned char *temp = iv + gcry_drbg_blocklen (drbg); + size_t padlen = 0; + unsigned int templen = 0; + /* 10.4.2 step 7 */ + unsigned int i = 0; + /* 10.4.2 step 8 */ + const unsigned char *K = (unsigned char *) + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"; + unsigned char *X; + size_t generated_len = 0; + size_t inputlen = 0; + + memset (pad, 0, gcry_drbg_blocklen (drbg)); + memset (iv, 0, gcry_drbg_blocklen (drbg)); + memset (temp, 0, gcry_drbg_statelen (drbg)); + + /* 10.4.2 step 1 is implicit as we work byte-wise */ + + /* 10.4.2 step 2 */ + if ((512 / 8) < bytes_to_return) + return GPG_ERR_INV_ARG; + + /* 10.4.2 step 2 -- calculate the entire length of all input data */ + for (; NULL != tempstr; tempstr = tempstr->next) + inputlen += tempstr->len; + gcry_drbg_cpu_to_be32 (inputlen, &L_N[0]); + + /* 10.4.2 step 3 */ + gcry_drbg_cpu_to_be32 (bytes_to_return, &L_N[4]); + + /* 10.4.2 step 5: length is size of L_N, input_string, one byte, padding */ + padlen = (inputlen + sizeof (L_N) + 1) % (gcry_drbg_blocklen (drbg)); + /* wrap the padlen appropriately */ + if (padlen) + padlen = gcry_drbg_blocklen (drbg) - padlen; + /* pad / padlen contains the 0x80 byte and the following zero bytes, so + * add one for byte for 0x80 */ + padlen++; + pad[0] = 0x80; + + /* 10.4.2 step 4 -- first fill the linked list and then order it */ + gcry_drbg_string_fill (&S1, iv, gcry_drbg_blocklen (drbg)); + gcry_drbg_string_fill (&S2, L_N, sizeof (L_N)); + gcry_drbg_string_fill (&S4, pad, padlen); + S1.next = &S2; + S2.next = addtl; + + /* Splice in addtl between S2 and S4 -- we place S4 at the end of the + * input data chain. As this code is only triggered when addtl is not + * NULL, no NULL checks are necessary.*/ + tempstr = addtl; + while (tempstr->next) + tempstr = tempstr->next; + tempstr->next = &S4; + + /* 10.4.2 step 9 */ + while (templen < (gcry_drbg_keylen (drbg) + (gcry_drbg_blocklen (drbg)))) + { + /* 10.4.2 step 9.1 - the padding is implicit as the buffer + * holds zeros after allocation -- even the increment of i + * is irrelevant as the increment remains within length of i */ + gcry_drbg_cpu_to_be32 (i, iv); + /* 10.4.2 step 9.2 -- BCC and concatenation with temp */ + ret = gcry_drbg_ctr_bcc (drbg, temp + templen, K, &S1); + if (ret) + goto out; + /* 10.4.2 step 9.3 */ + i++; + templen += gcry_drbg_blocklen (drbg); + } + + /* 10.4.2 step 11 */ + /* implicit key len with seedlen - blocklen according to table 3 */ + X = temp + (gcry_drbg_keylen (drbg)); + gcry_drbg_string_fill (&cipherin, X, gcry_drbg_blocklen (drbg)); + + /* 10.4.2 step 12: overwriting of outval */ + + /* 10.4.2 step 13 */ + while (generated_len < bytes_to_return) + { + short blocklen = 0; + /* 10.4.2 step 13.1 */ + /* the truncation of the key length is implicit as the key + * is only gcry_drbg_blocklen in size -- check for the implementation + * of the cipher function callback */ + ret = gcry_drbg_sym (drbg, temp, X, &cipherin); + if (ret) + goto out; + blocklen = (gcry_drbg_blocklen (drbg) < + (bytes_to_return - generated_len)) ? + gcry_drbg_blocklen (drbg) : (bytes_to_return - generated_len); + /* 10.4.2 step 13.2 and 14 */ + memcpy (df_data + generated_len, X, blocklen); + generated_len += blocklen; + } + + ret = 0; + +out: + memset (iv, 0, gcry_drbg_blocklen (drbg)); + memset (temp, 0, gcry_drbg_statelen (drbg)); + memset (pad, 0, gcry_drbg_blocklen (drbg)); + return ret; +} + +/* + * update function of CTR DRBG as defined in 10.2.1.2 + * + * The reseed variable has an enhanced meaning compared to the update + * functions of the other DRBGs as follows: + * 0 => initial seed from initialization + * 1 => reseed via gcry_drbg_seed + * 2 => first invocation from gcry_drbg_ctr_update when addtl is present. In + * this case, the df_data scratchpad is not deleted so that it is + * available for another calls to prevent calling the DF function + * again. + * 3 => second invocation from gcry_drbg_ctr_update. When the update function + * was called with addtl, the df_data memory already contains the + * DFed addtl information and we do not need to call DF again. + */ +static gpg_err_code_t +gcry_drbg_ctr_update (struct gcry_drbg_state *drbg, + struct gcry_drbg_string *addtl, int reseed) +{ + gpg_err_code_t ret = GPG_ERR_GENERAL; + /* 10.2.1.2 step 1 */ + unsigned char *temp = drbg->scratchpad; + unsigned char *df_data = drbg->scratchpad + + gcry_drbg_statelen (drbg) + gcry_drbg_blocklen (drbg); + unsigned char *temp_p, *df_data_p; /* pointer to iterate over buffers */ + unsigned int len = 0; + struct gcry_drbg_string cipherin; + unsigned char prefix = DRBG_PREFIX1; + + memset (temp, 0, gcry_drbg_statelen (drbg) + gcry_drbg_blocklen (drbg)); + if (3 > reseed) + memset (df_data, 0, gcry_drbg_statelen (drbg)); + + /* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */ + /* TODO use reseed variable to avoid re-doing DF operation */ + (void) reseed; + if (addtl && 0 < addtl->len) + { + ret = + gcry_drbg_ctr_df (drbg, df_data, gcry_drbg_statelen (drbg), addtl); + if (ret) + goto out; + } + + gcry_drbg_string_fill (&cipherin, drbg->V, gcry_drbg_blocklen (drbg)); + /* 10.2.1.3.2 step 2 and 3 -- are already covered as we memset(0) + * all memory during initialization */ + while (len < (gcry_drbg_statelen (drbg))) + { + /* 10.2.1.2 step 2.1 */ + gcry_drbg_add_buf (drbg->V, gcry_drbg_blocklen (drbg), &prefix, 1); + /* 10.2.1.2 step 2.2 */ + /* using target of temp + len: 10.2.1.2 step 2.3 and 3 */ + ret = gcry_drbg_sym (drbg, drbg->C, temp + len, &cipherin); + if (ret) + goto out; + /* 10.2.1.2 step 2.3 and 3 */ + len += gcry_drbg_blocklen (drbg); + } + + /* 10.2.1.2 step 4 */ + temp_p = temp; + df_data_p = df_data; + for (len = 0; len < gcry_drbg_statelen (drbg); len++) + { + *temp_p ^= *df_data_p; + df_data_p++; + temp_p++; + } + + /* 10.2.1.2 step 5 */ + memcpy (drbg->C, temp, gcry_drbg_keylen (drbg)); + /* 10.2.1.2 step 6 */ + memcpy (drbg->V, temp + gcry_drbg_keylen (drbg), gcry_drbg_blocklen (drbg)); + ret = 0; + +out: + memset (temp, 0, gcry_drbg_statelen (drbg) + gcry_drbg_blocklen (drbg)); + if (2 != reseed) + memset (df_data, 0, gcry_drbg_statelen (drbg)); + return ret; +} + +/* + * scratchpad use: gcry_drbg_ctr_update is called independently from + * gcry_drbg_ctr_extract_bytes. Therefore, the scratchpad is reused + */ +/* Generate function of CTR DRBG as defined in 10.2.1.5.2 */ +static gpg_err_code_t +gcry_drbg_ctr_generate (struct gcry_drbg_state *drbg, + unsigned char *buf, unsigned int buflen, + struct gcry_drbg_string *addtl) +{ + gpg_err_code_t ret = 0; + unsigned int len = 0; + struct gcry_drbg_string data; + unsigned char prefix = DRBG_PREFIX1; + + memset (drbg->scratchpad, 0, gcry_drbg_blocklen (drbg)); + + /* 10.2.1.5.2 step 2 */ + if (addtl && 0 < addtl->len) + { + addtl->next = NULL; + ret = gcry_drbg_ctr_update (drbg, addtl, 2); + if (ret) + return ret; + } + + /* 10.2.1.5.2 step 4.1 */ + gcry_drbg_add_buf (drbg->V, gcry_drbg_blocklen (drbg), &prefix, 1); + gcry_drbg_string_fill (&data, drbg->V, gcry_drbg_blocklen (drbg)); + while (len < buflen) + { + unsigned int outlen = 0; + /* 10.2.1.5.2 step 4.2 */ + ret = gcry_drbg_sym (drbg, drbg->C, drbg->scratchpad, &data); + if (ret) + goto out; + outlen = (gcry_drbg_blocklen (drbg) < (buflen - len)) ? + gcry_drbg_blocklen (drbg) : (buflen - len); + /* 10.2.1.5.2 step 4.3 */ + memcpy (buf + len, drbg->scratchpad, outlen); + len += outlen; + /* 10.2.1.5.2 step 6 */ + if (len < buflen) + gcry_drbg_add_buf (drbg->V, gcry_drbg_blocklen (drbg), &prefix, 1); + } + + /* 10.2.1.5.2 step 6 */ + if (addtl) + addtl->next = NULL; + ret = gcry_drbg_ctr_update (drbg, addtl, 3); + +out: + memset (drbg->scratchpad, 0, gcry_drbg_blocklen (drbg)); + return ret; +} + +static struct gcry_drbg_state_ops gcry_drbg_ctr_ops = { + gcry_drbg_ctr_update, + gcry_drbg_ctr_generate, +}; + +/****************************************************************** + * HMAC DRBG callback functions + ******************************************************************/ + +static gpg_err_code_t +gcry_drbg_hmac_update (struct gcry_drbg_state *drbg, + struct gcry_drbg_string *seed, int reseed) +{ + gpg_err_code_t ret = GPG_ERR_GENERAL; + int i = 0; + struct gcry_drbg_string seed1, seed2, cipherin; + + if (!reseed) + /* 10.1.2.3 step 2 already implicitly covered with + * the initial memset(0) of drbg->C */ + memset (drbg->V, 1, gcry_drbg_statelen (drbg)); + + /* build linked list which implements the concatenation and fill + * first part*/ + gcry_drbg_string_fill (&seed1, drbg->V, gcry_drbg_statelen (drbg)); + /* buffer will be filled in for loop below with one byte */ + gcry_drbg_string_fill (&seed2, NULL, 1); + seed1.next = &seed2; + /* seed may be NULL */ + seed2.next = seed; + + gcry_drbg_string_fill (&cipherin, drbg->V, gcry_drbg_statelen (drbg)); + /* we execute two rounds of V/K massaging */ + for (i = 2; 0 < i; i--) + { + /* first round uses 0x0, second 0x1 */ + unsigned char prefix = DRBG_PREFIX0; + if (1 == i) + prefix = DRBG_PREFIX1; + /* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */ + seed2.buf = &prefix; + ret = gcry_drbg_hmac (drbg, drbg->C, drbg->C, &seed1); + if (ret) + return ret; + + /* 10.1.2.2 step 2 and 5 -- HMAC for V */ + ret = gcry_drbg_hmac (drbg, drbg->C, drbg->V, &cipherin); + if (ret) + return ret; + + /* 10.1.2.2 step 3 */ + if (!seed || 0 == seed->len) + return ret; + } + return 0; +} + +/* generate function of HMAC DRBG as defined in 10.1.2.5 */ +static gpg_err_code_t +gcry_drbg_hmac_generate (struct gcry_drbg_state *drbg, + unsigned char *buf, + unsigned int buflen, struct gcry_drbg_string *addtl) +{ + gpg_err_code_t ret = 0; + unsigned int len = 0; + struct gcry_drbg_string data; + + /* 10.1.2.5 step 2 */ + if (addtl && 0 < addtl->len) + { + addtl->next = NULL; + ret = gcry_drbg_hmac_update (drbg, addtl, 1); + if (ret) + return ret; + } + + gcry_drbg_string_fill (&data, drbg->V, gcry_drbg_statelen (drbg)); + while (len < buflen) + { + unsigned int outlen = 0; + /* 10.1.2.5 step 4.1 */ + ret = gcry_drbg_hmac (drbg, drbg->C, drbg->V, &data); + if (ret) + return ret; + outlen = (gcry_drbg_blocklen (drbg) < (buflen - len)) ? + gcry_drbg_blocklen (drbg) : (buflen - len); + + /* 10.1.2.5 step 4.2 */ + memcpy (buf + len, drbg->V, outlen); + len += outlen; + } + + /* 10.1.2.5 step 6 */ + if (addtl) + addtl->next = NULL; + ret = gcry_drbg_hmac_update (drbg, addtl, 1); + + return ret; +} + +static struct gcry_drbg_state_ops gcry_drbg_hmac_ops = { + gcry_drbg_hmac_update, + gcry_drbg_hmac_generate, +}; + +/****************************************************************** + * Hash DRBG callback functions + ******************************************************************/ + +/* + * scratchpad usage: as gcry_drbg_hash_update and gcry_drbg_hash_df are used + * interlinked, the scratchpad is used as follows: + * gcry_drbg_hash_update + * start: drbg->scratchpad + * length: gcry_drbg_statelen(drbg) + * gcry_drbg_hash_df: + * start: drbg->scratchpad + gcry_drbg_statelen(drbg) + * length: gcry_drbg_blocklen(drbg) + */ +/* Derivation Function for Hash DRBG as defined in 10.4.1 */ +static gpg_err_code_t +gcry_drbg_hash_df (struct gcry_drbg_state *drbg, + unsigned char *outval, size_t outlen, + struct gcry_drbg_string *entropy) +{ + gpg_err_code_t ret = 0; + size_t len = 0; + unsigned char input[5]; + unsigned char *tmp = drbg->scratchpad + gcry_drbg_statelen (drbg); + struct gcry_drbg_string data1; + + memset (tmp, 0, gcry_drbg_blocklen (drbg)); + + /* 10.4.1 step 3 */ + input[0] = 1; + gcry_drbg_cpu_to_be32 ((outlen * 8), &input[1]); + + /* 10.4.1 step 4.1 -- concatenation of data for input into hash */ + gcry_drbg_string_fill (&data1, input, 5); + data1.next = entropy; + + /* 10.4.1 step 4 */ + while (len < outlen) + { + short blocklen = 0; + /* 10.4.1 step 4.1 */ + ret = gcry_drbg_hmac (drbg, NULL, tmp, &data1); + if (ret) + goto out; + /* 10.4.1 step 4.2 */ + input[0]++; + blocklen = (gcry_drbg_blocklen (drbg) < (outlen - len)) ? + gcry_drbg_blocklen (drbg) : (outlen - len); + memcpy (outval + len, tmp, blocklen); + len += blocklen; + } + +out: + memset (tmp, 0, gcry_drbg_blocklen (drbg)); + return ret; +} + +/* update function for Hash DRBG as defined in 10.1.1.2 / 10.1.1.3 */ +static gpg_err_code_t +gcry_drbg_hash_update (struct gcry_drbg_state *drbg, + struct gcry_drbg_string *seed, int reseed) +{ + gpg_err_code_t ret = 0; + struct gcry_drbg_string data1, data2; + unsigned char *V = drbg->scratchpad; + unsigned char prefix = DRBG_PREFIX1; + + memset (drbg->scratchpad, 0, gcry_drbg_statelen (drbg)); + if (!seed) + return GPG_ERR_INV_ARG; + + if (reseed) + { + /* 10.1.1.3 step 1: string length is concatenation of + * 1 byte, V and seed (which is concatenated entropy/addtl + * input) + */ + memcpy (V, drbg->V, gcry_drbg_statelen (drbg)); + gcry_drbg_string_fill (&data1, &prefix, 1); + gcry_drbg_string_fill (&data2, V, gcry_drbg_statelen (drbg)); + data1.next = &data2; + data2.next = seed; + } + else + { + gcry_drbg_string_fill (&data1, seed->buf, seed->len); + data1.next = seed->next; + } + + /* 10.1.1.2 / 10.1.1.3 step 2 and 3 */ + ret = gcry_drbg_hash_df (drbg, drbg->V, gcry_drbg_statelen (drbg), &data1); + if (ret) + goto out; + + /* 10.1.1.2 / 10.1.1.3 step 4 -- concatenation */ + prefix = DRBG_PREFIX0; + gcry_drbg_string_fill (&data1, &prefix, 1); + gcry_drbg_string_fill (&data2, drbg->V, gcry_drbg_statelen (drbg)); + data1.next = &data2; + /* 10.1.1.2 / 10.1.1.3 step 4 -- df operation */ + ret = gcry_drbg_hash_df (drbg, drbg->C, gcry_drbg_statelen (drbg), &data1); + +out: + memset (drbg->scratchpad, 0, gcry_drbg_statelen (drbg)); + return ret; +} + +/* processing of additional information string for Hash DRBG */ +static gpg_err_code_t +gcry_drbg_hash_process_addtl (struct gcry_drbg_state *drbg, + struct gcry_drbg_string *addtl) +{ + gpg_err_code_t ret = 0; + struct gcry_drbg_string data1, data2; + struct gcry_drbg_string *data3; + unsigned char prefix = DRBG_PREFIX2; + + /* this is value w as per documentation */ + memset (drbg->scratchpad, 0, gcry_drbg_blocklen (drbg)); + + /* 10.1.1.4 step 2 */ + if (!addtl || 0 == addtl->len) + return 0; + + /* 10.1.1.4 step 2a -- concatenation */ + gcry_drbg_string_fill (&data1, &prefix, 1); + gcry_drbg_string_fill (&data2, drbg->V, gcry_drbg_statelen (drbg)); + data3 = addtl; + data1.next = &data2; + data2.next = data3; + data3->next = NULL; + /* 10.1.1.4 step 2a -- cipher invocation */ + ret = gcry_drbg_hmac (drbg, NULL, drbg->scratchpad, &data1); + if (ret) + goto out; + + /* 10.1.1.4 step 2b */ + gcry_drbg_add_buf (drbg->V, gcry_drbg_statelen (drbg), + drbg->scratchpad, gcry_drbg_blocklen (drbg)); + +out: + memset (drbg->scratchpad, 0, gcry_drbg_blocklen (drbg)); + return ret; +} + +/* + * Hashgen defined in 10.1.1.4 + */ +static gpg_err_code_t +gcry_drbg_hash_hashgen (struct gcry_drbg_state *drbg, + unsigned char *buf, unsigned int buflen) +{ + gpg_err_code_t ret = 0; + unsigned int len = 0; + unsigned char *src = drbg->scratchpad; + unsigned char *dst = drbg->scratchpad + gcry_drbg_statelen (drbg); + struct gcry_drbg_string data; + unsigned char prefix = DRBG_PREFIX1; + + /* use the scratchpad as a lookaside buffer */ + memset (src, 0, gcry_drbg_statelen (drbg)); + memset (dst, 0, gcry_drbg_blocklen (drbg)); + + /* 10.1.1.4 step hashgen 2 */ + memcpy (src, drbg->V, gcry_drbg_statelen (drbg)); + + gcry_drbg_string_fill (&data, src, gcry_drbg_statelen (drbg)); + while (len < buflen) + { + unsigned int outlen = 0; + /* 10.1.1.4 step hashgen 4.1 */ + ret = gcry_drbg_hmac (drbg, NULL, dst, &data); + if (ret) + goto out; + outlen = (gcry_drbg_blocklen (drbg) < (buflen - len)) ? + gcry_drbg_blocklen (drbg) : (buflen - len); + /* 10.1.1.4 step hashgen 4.2 */ + memcpy (buf + len, dst, outlen); + len += outlen; + /* 10.1.1.4 hashgen step 4.3 */ + if (len < buflen) + gcry_drbg_add_buf (src, gcry_drbg_statelen (drbg), &prefix, 1); + } + +out: + memset (drbg->scratchpad, 0, + (gcry_drbg_statelen (drbg) + gcry_drbg_blocklen (drbg))); + return ret; +} + +/* generate function for Hash DRBG as defined in 10.1.1.4 */ +static gpg_err_code_t +gcry_drbg_hash_generate (struct gcry_drbg_state *drbg, + unsigned char *buf, unsigned int buflen, + struct gcry_drbg_string *addtl) +{ + gpg_err_code_t ret = 0; + unsigned char prefix = DRBG_PREFIX3; + struct gcry_drbg_string data1, data2; + union + { + unsigned char req[8]; + u64 req_int; + } u; + + /* + * scratchpad usage: gcry_drbg_hash_process_addtl uses the scratchpad, but + * fully completes before returning. Thus, we can reuse the scratchpad + */ + /* 10.1.1.4 step 2 */ + ret = gcry_drbg_hash_process_addtl (drbg, addtl); + if (ret) + return ret; + /* 10.1.1.4 step 3 -- invocation of the Hashgen function defined in + * 10.1.1.4 */ + ret = gcry_drbg_hash_hashgen (drbg, buf, buflen); + if (ret) + return ret; + + /* this is the value H as documented in 10.1.1.4 */ + memset (drbg->scratchpad, 0, gcry_drbg_blocklen (drbg)); + /* 10.1.1.4 step 4 */ + gcry_drbg_string_fill (&data1, &prefix, 1); + gcry_drbg_string_fill (&data2, drbg->V, gcry_drbg_statelen (drbg)); + data1.next = &data2; + ret = gcry_drbg_hmac (drbg, NULL, drbg->scratchpad, &data1); + if (ret) + goto out; + + /* 10.1.1.4 step 5 */ + gcry_drbg_add_buf (drbg->V, gcry_drbg_statelen (drbg), + drbg->scratchpad, gcry_drbg_blocklen (drbg)); + gcry_drbg_add_buf (drbg->V, gcry_drbg_statelen (drbg), drbg->C, + gcry_drbg_statelen (drbg)); + u.req_int = be_bswap64 (drbg->reseed_ctr); + gcry_drbg_add_buf (drbg->V, gcry_drbg_statelen (drbg), u.req, + sizeof (u.req)); + +out: + memset (drbg->scratchpad, 0, gcry_drbg_blocklen (drbg)); + return ret; +} + +/* + * scratchpad usage: as update and generate are used isolated, both + * can use the scratchpad + */ +static struct gcry_drbg_state_ops gcry_drbg_hash_ops = { + gcry_drbg_hash_update, + gcry_drbg_hash_generate, +}; + +/****************************************************************** + * Functions common for DRBG implementations + ******************************************************************/ + +/* + * Seeding or reseeding of the DRBG + * + * @drbg: DRBG state struct + * @pers: personalization / additional information buffer + * @reseed: 0 for initial seed process, 1 for reseeding + * + * return: + * 0 on success + * error value otherwise + */ +static gpg_err_code_t +gcry_drbg_seed (struct gcry_drbg_state *drbg, struct gcry_drbg_string *pers, + int reseed) +{ + gpg_err_code_t ret = 0; + unsigned char *entropy = NULL; + size_t entropylen = 0; + struct gcry_drbg_string data1; + + /* 9.1 / 9.2 / 9.3.1 step 3 */ + if (pers && pers->len > (gcry_drbg_max_addtl ())) + { + dbg (("DRBG: personalization string too long %lu\n", pers->len)); + return GPG_ERR_INV_ARG; + } + if (drbg->test_data && drbg->test_data->testentropy) + { + gcry_drbg_string_fill (&data1, drbg->test_data->testentropy->buf, + drbg->test_data->testentropy->len); + dbg (("DRBG: using test entropy\n")); + } + else + { + /* Gather entropy equal to the security strength of the DRBG. + * With a derivation function, a nonce is required in addition + * to the entropy. A nonce must be at least 1/2 of the security + * strength of the DRBG in size. Thus, entropy * nonce is 3/2 + * of the strength. The consideration of a nonce is only + * applicable during initial seeding. */ + entropylen = gcry_drbg_sec_strength (drbg->core->flags); + if (!entropylen) + return GPG_ERR_GENERAL; + if (0 == reseed) + /* make sure we round up strength/2 in + * case it is not divisible by 2 */ + entropylen = ((entropylen + 1) / 2) * 3; + dbg (("DRBG: (re)seeding with %lu bytes of entropy\n", entropylen)); + entropy = xcalloc_secure (1, entropylen); + if (!entropy) + return GPG_ERR_ENOMEM; + ret = gcry_drbg_get_entropy (drbg, entropy, entropylen); + if (ret) + goto out; + gcry_drbg_string_fill (&data1, entropy, entropylen); + } + + /* concatenation of entropy with personalization str / addtl input) + * the variable pers is directly handed by the caller, check its + * contents whether it is appropriate */ + if (pers && pers->buf && 0 < pers->len && NULL == pers->next) + { + data1.next = pers; + dbg (("DRBG: using personalization string\n")); + } + + ret = drbg->d_ops->update (drbg, &data1, reseed); + dbg (("DRBG: state updated with seed\n")); + if (ret) + goto out; + drbg->seeded = 1; + /* 10.1.1.2 / 10.1.1.3 step 5 */ + drbg->reseed_ctr = 1; + +out: + xfree (entropy); + return ret; +} + +/************************************************************************* + * exported interfaces + *************************************************************************/ + +/* + * DRBG generate function as required by SP800-90A - this function + * generates random numbers + * + * @drbg DRBG state handle + * @buf Buffer where to store the random numbers -- the buffer must already + * be pre-allocated by caller + * @buflen Length of output buffer - this value defines the number of random + * bytes pulled from DRBG + * @addtl Additional input that is mixed into state, may be NULL -- note + * the entropy is pulled by the DRBG internally unconditionally + * as defined in SP800-90A. The additional input is mixed into + * the state in addition to the pulled entropy. + * + * return: generated number of bytes + */ +static gpg_err_code_t +gcry_drbg_generate (struct gcry_drbg_state *drbg, + unsigned char *buf, unsigned int buflen, + struct gcry_drbg_string *addtl) +{ + gpg_err_code_t ret = GPG_ERR_INV_ARG; + + if (0 == buflen || !buf) + { + dbg (("DRBG: no buffer provided\n")); + return ret; + } + if (addtl && NULL == addtl->buf && 0 < addtl->len) + { + dbg (("DRBG: wrong format of additional information\n")); + return ret; + } + + /* 9.3.1 step 2 */ + if (buflen > (gcry_drbg_max_request_bytes ())) + { + dbg (("DRBG: requested random numbers too large %u\n", buflen)); + return ret; + } + /* 9.3.1 step 3 is implicit with the chosen DRBG */ + /* 9.3.1 step 4 */ + if (addtl && addtl->len > (gcry_drbg_max_addtl ())) + { + dbg (("DRBG: additional information string too long %lu\n", + addtl->len)); + return ret; + } + /* 9.3.1 step 5 is implicit with the chosen DRBG */ + /* 9.3.1 step 6 and 9 supplemented by 9.3.2 step c -- the spec is a + * bit convoluted here, we make it simpler */ + if ((gcry_drbg_max_requests ()) < drbg->reseed_ctr) + drbg->seeded = 0; + + if (drbg->pr || !drbg->seeded) + { + dbg (("DRBG: reseeding before generation (prediction resistance: %s, state %s)\n", drbg->pr ? "true" : "false", drbg->seeded ? "seeded" : "unseeded")); + /* 9.3.1 steps 7.1 through 7.3 */ + ret = gcry_drbg_seed (drbg, addtl, 1); + if (ret) + return ret; + /* 9.3.1 step 7.4 */ + addtl = NULL; + } + + if (addtl && addtl->buf) + { + dbg (("DRBG: using additional information string\n")); + } + + /* 9.3.1 step 8 and 10 */ + ret = drbg->d_ops->generate (drbg, buf, buflen, addtl); + + /* 10.1.1.4 step 6, 10.1.2.5 step 7, 10.2.1.5.2 step 7 */ + drbg->reseed_ctr++; + if (ret) + return ret; + + /* 11.3.3 -- re-perform self tests after some generated random + * numbers, the chosen value after which self test is performed + * is arbitrary, but it should be reasonable */ + /* Here we do not perform the self tests because of the following + * reasons: it is mathematically impossible that the initial self tests + * were successfully and the following are not. If the initial would + * pass and the following would not, the system integrity is violated. + * In this case, the entire system operation is questionable and it + * is unlikely that the integrity violation only affects to the + * correct operation of the DRBG. + */ +#if 0 + if (drbg->reseed_ctr && !(drbg->reseed_ctr % 4096)) + { + dbg (("DRBG: start to perform self test\n")); + ret = gcry_drbg_healthcheck (); + if (ret) + { + log_fatal (("DRBG: self test failed\n")); + return ret; + } + else + { + dbg (("DRBG: self test successful\n")); + } + } +#endif + + return ret; +} + +/* + * Wrapper around gcry_drbg_generate which can pull arbitrary long strings + * from the DRBG without hitting the maximum request limitation. + * + * Parameters: see gcry_drbg_generate + * Return codes: see gcry_drbg_generate -- if one gcry_drbg_generate request fails, + * the entire gcry_drbg_generate_long request fails + */ +static gpg_err_code_t +gcry_drbg_generate_long (struct gcry_drbg_state *drbg, + unsigned char *buf, unsigned int buflen, + struct gcry_drbg_string *addtl) +{ + gpg_err_code_t ret = 0; + unsigned int slice = 0; + unsigned char *buf_p = buf; + unsigned len = 0; + do + { + unsigned int chunk = 0; + slice = ((buflen - len) / gcry_drbg_max_request_bytes ()); + chunk = slice ? gcry_drbg_max_request_bytes () : (buflen - len); + ret = gcry_drbg_generate (drbg, buf_p, chunk, addtl); + if (ret) + return ret; + buf_p += chunk; + len += chunk; + } + while (slice > 0 && (len < buflen)); + return ret; +} + +/* + * DRBG uninstantiate function as required by SP800-90A - this function + * frees all buffers and the DRBG handle + * + * @drbg DRBG state handle + * + * return + * 0 on success + */ +static gpg_err_code_t +gcry_drbg_uninstantiate (struct gcry_drbg_state *drbg) +{ + if (!drbg) + return GPG_ERR_INV_ARG; + xfree (drbg->V); + drbg->V = NULL; + xfree (drbg->C); + drbg->C = NULL; + drbg->reseed_ctr = 0; + xfree (drbg->scratchpad); + drbg->scratchpad = NULL; + drbg->seeded = 0; + drbg->pr = 0; + drbg->seed_init_pid = 0; + return 0; +} + +/* + * DRBG instantiation function as required by SP800-90A - this function + * sets up the DRBG handle, performs the initial seeding and all sanity + * checks required by SP800-90A + * + * @drbg memory of state -- if NULL, new memory is allocated + * @pers Personalization string that is mixed into state, may be NULL -- note + * the entropy is pulled by the DRBG internally unconditionally + * as defined in SP800-90A. The additional input is mixed into + * the state in addition to the pulled entropy. + * @coreref reference to core + * @flags Flags defining the requested DRBG type and cipher type. The flags + * are defined in drbg.h and may be XORed. Beware, if you XOR multiple + * cipher types together, the code picks the core on a first come first + * serve basis as it iterates through the available cipher cores and + * uses the one with the first match. The minimum required flags are: + * cipher type flag + * + * return + * 0 on success + * error value otherwise + */ +static gpg_err_code_t +gcry_drbg_instantiate (struct gcry_drbg_state *drbg, + struct gcry_drbg_string *pers, int coreref, int pr) +{ + gpg_err_code_t ret = GPG_ERR_ENOMEM; + unsigned int sb_size = 0; + + if (!drbg) + return GPG_ERR_INV_ARG; + + dbg (("DRBG: Initializing DRBG core %d with prediction resistance %s\n", + coreref, pr ? "enabled" : "disabled")); + drbg->core = &gcry_drbg_cores[coreref]; + drbg->pr = pr; + drbg->seeded = 0; + if (drbg->core->flags & GCRY_DRBG_HMAC) + drbg->d_ops = &gcry_drbg_hmac_ops; + else if (drbg->core->flags & GCRY_DRBG_HASH_MASK) + drbg->d_ops = &gcry_drbg_hash_ops; + else if (drbg->core->flags & GCRY_DRBG_CTR_MASK) + drbg->d_ops = &gcry_drbg_ctr_ops; + else + return GPG_ERR_GENERAL; + /* 9.1 step 1 is implicit with the selected DRBG type -- see + * gcry_drbg_sec_strength() */ + + /* 9.1 step 2 is implicit as caller can select prediction resistance + * and the flag is copied into drbg->flags -- + * all DRBG types support prediction resistance */ + + /* 9.1 step 4 is implicit in gcry_drbg_sec_strength */ + + /* no allocation of drbg as this is done by the kernel crypto API */ + drbg->V = xcalloc_secure (1, gcry_drbg_statelen (drbg)); + if (!drbg->V) + goto err; + drbg->C = xcalloc_secure (1, gcry_drbg_statelen (drbg)); + if (!drbg->C) + goto err; + /* scratchpad is only generated for CTR and Hash */ + if (drbg->core->flags & GCRY_DRBG_HMAC) + sb_size = 0; + else if (drbg->core->flags & GCRY_DRBG_CTR_MASK) + sb_size = gcry_drbg_statelen (drbg) + gcry_drbg_blocklen (drbg) + /* temp */ + gcry_drbg_statelen (drbg) + /* df_data */ + gcry_drbg_blocklen (drbg) + /* pad */ + gcry_drbg_blocklen (drbg) + /* iv */ + gcry_drbg_statelen (drbg) + gcry_drbg_blocklen (drbg); /* temp */ + else + sb_size = gcry_drbg_statelen (drbg) + gcry_drbg_blocklen (drbg); + + if (0 < sb_size) + { + drbg->scratchpad = xcalloc_secure (1, sb_size); + if (!drbg->scratchpad) + goto err; + } + dbg (("DRBG: state allocated with scratchpad size %u bytes\n", sb_size)); + + /* 9.1 step 6 through 11 */ + ret = gcry_drbg_seed (drbg, pers, 0); + if (ret) + goto err; + + dbg (("DRBG: core %d %s prediction resistance successfully initialized\n", + coreref, pr ? "with" : "without")); + return 0; + +err: + gcry_drbg_uninstantiate (drbg); + return ret; +} + +/* + * DRBG reseed function as required by SP800-90A + * + * @drbg DRBG state handle + * @addtl Additional input that is mixed into state, may be NULL -- note + * the entropy is pulled by the DRBG internally unconditionally + * as defined in SP800-90A. The additional input is mixed into + * the state in addition to the pulled entropy. + * + * return + * 0 on success + * error value otherwise + */ +static gpg_err_code_t +gcry_drbg_reseed (struct gcry_drbg_state *drbg, + struct gcry_drbg_string *addtl) +{ + gpg_err_code_t ret = 0; + ret = gcry_drbg_seed (drbg, addtl, 1); + return ret; +} + +/****************************************************************** + ****************************************************************** + ****************************************************************** + * libgcrypt integration code + ****************************************************************** + ****************************************************************** + ******************************************************************/ + +/*************************************************************** + * libgcrypt backend functions to the RNG API code + ***************************************************************/ + +/* global state variable holding the current instance of the DRBG -- the + * default DRBG type is defined in _gcry_gcry_drbg_init */ +static struct gcry_drbg_state *gcry_drbg = NULL; + +/* This is the lock we use to serialize access to this RNG. */ +GPGRT_LOCK_DEFINE(drbg_lock); + +static inline void +gcry_drbg_lock (void) +{ + gpg_err_code_t my_errno; + + my_errno = gpgrt_lock_lock (&drbg_lock); + if (my_errno) + log_fatal ("failed to acquire the RNG lock: %s\n", strerror (my_errno)); +} + +static inline void +gcry_drbg_unlock (void) +{ + gpg_err_code_t my_errno; + + my_errno = gpgrt_lock_unlock (&drbg_lock); + if (my_errno) + log_fatal ("failed to release the RNG lock: %s\n", strerror (my_errno)); +} + +/* Basic initialization is required to initialize mutexes and + do a few checks on the implementation. */ +static void +basic_initialization (void) +{ + static int initialized; + + if (initialized) + return; + initialized = 1; + + /* Make sure that we are still using the values we have + traditionally used for the random levels. */ + gcry_assert (GCRY_WEAK_RANDOM == 0 + && GCRY_STRONG_RANDOM == 1 + && GCRY_VERY_STRONG_RANDOM == 2); +} + +/****** helper functions where lock must be held by caller *****/ + +/* Check whether given flags are known to point to an applicable DRBG */ +static gpg_err_code_t +gcry_drbg_algo_available (u32 flags, int *coreref) +{ + int i = 0; + for (i = 0; ARRAY_SIZE (gcry_drbg_cores) > i; i++) + { + if ((gcry_drbg_cores[i].flags & GCRY_DRBG_CIPHER_MASK) == + (flags & GCRY_DRBG_CIPHER_MASK)) + { + *coreref = i; + return 0; + } + } + return GPG_ERR_GENERAL; +} + +static gpg_err_code_t +_gcry_drbg_init_internal (u32 flags, struct gcry_drbg_string *pers) +{ + gpg_err_code_t ret = 0; + static u32 oldflags = 0; + int coreref = 0; + int pr = 0; + + /* If a caller provides 0 as flags, use the flags of the previous + * initialization, otherwise use the current flags and remember them + * for the next invocation + */ + if (0 == flags) + flags = oldflags; + else + oldflags = flags; + + ret = gcry_drbg_algo_available (flags, &coreref); + if (ret) + return ret; + + if (NULL != gcry_drbg) + { + gcry_drbg_uninstantiate (gcry_drbg); + } + else + { + gcry_drbg = xcalloc_secure (1, sizeof (struct gcry_drbg_state)); + if (!gcry_drbg) + return GPG_ERR_ENOMEM; + } + if (flags & GCRY_DRBG_PREDICTION_RESIST) + pr = 1; + ret = gcry_drbg_instantiate (gcry_drbg, pers, coreref, pr); + if (ret) + fips_signal_error ("DRBG cannot be initialized"); + else + gcry_drbg->seed_init_pid = getpid (); + return ret; +} + +/************* calls available to common RNG code **************/ + +/* + * Initialize one DRBG invoked by the libgcrypt API + */ +void +_gcry_drbg_init (int full) +{ + /* default DRBG */ + u32 flags = GCRY_DRBG_NOPR_HMACSHA256; + basic_initialization (); + if (!full) + return; + gcry_drbg_lock (); + if (NULL == gcry_drbg) + _gcry_drbg_init_internal (flags, NULL); + gcry_drbg_unlock (); +} + +/* + * Backend handler function for GCRYCTL_DRBG_REINIT + * + * Select a different DRBG type and initialize it. + * Function checks whether requested DRBG type exists and returns an error in + * case it does not. In case of an error, the previous instantiated DRBG is + * left untouched and alive. Thus, in case of an error, a DRBG is always + * available, even if it is not the chosen one. + * + * Re-initialization will be performed in any case regardless whether flags + * or personalization string are set. + * + * If flags == 0, do not change current DRBG + * If personalization string is NULL or its length is 0, re-initialize without + * personalization string + */ +gpg_err_code_t +_gcry_drbg_reinit (u32 flags, struct gcry_drbg_string *pers) +{ + gpg_err_code_t ret = GPG_ERR_GENERAL; + dbg (("DRBG: reinitialize internal DRBG state with flags %u\n", flags)); + gcry_drbg_lock (); + ret = _gcry_drbg_init_internal (flags, pers); + gcry_drbg_unlock (); + return ret; +} + +/* Try to close the FDs of the random gather module. This is + * currently only implemented for rndlinux. */ +void +_gcry_drbg_close_fds (void) +{ +#if USE_RNDLINUX + gcry_drbg_lock (); + _gcry_rndlinux_gather_random (NULL, 0, 0, 0); + gcry_drbg_unlock (); +#endif +} + +/* Print some statistics about the RNG. */ +void +_gcry_drbg_dump_stats (void) +{ + /* Not yet implemented. */ + /* Maybe dumping of reseed counter? */ +} + +/* This function returns true if no real RNG is available or the + * quality of the RNG has been degraded for test purposes. */ +int +_gcry_drbg_is_faked (void) +{ + return 0; /* Faked random is not allowed. */ +} + +/* Add BUFLEN bytes from BUF to the internal random pool. QUALITY + * should be in the range of 0..100 to indicate the goodness of the + * entropy added, or -1 for goodness not known. */ +gcry_error_t +_gcry_drbg_add_bytes (const void *buf, size_t buflen, int quality) +{ + gpg_err_code_t ret = 0; + struct gcry_drbg_string seed; + (void) quality; + _gcry_drbg_init(1); /* Auto-initialize if needed */ + if (NULL == gcry_drbg) + return GPG_ERR_GENERAL; + gcry_drbg_string_fill (&seed, (unsigned char *) buf, buflen); + gcry_drbg_lock (); + ret = gcry_drbg_reseed (gcry_drbg, &seed); + gcry_drbg_unlock (); + return ret; +} + +/* This function is to be used for all types of random numbers, including + * nonces + */ +void +_gcry_drbg_randomize (void *buffer, size_t length, + enum gcry_random_level level) +{ + (void) level; + _gcry_drbg_init(1); /* Auto-initialize if needed */ + gcry_drbg_lock (); + if (NULL == gcry_drbg) + { + fips_signal_error ("DRBG is not initialized"); + goto bailout; + } + + /* As reseeding changes the entire state of the DRBG, including any + * key, either a re-init or a reseed is sufficient for a fork */ + if (gcry_drbg->seed_init_pid != getpid ()) + { + /* We are in a child of us. Perform a reseeding. */ + if (gcry_drbg_reseed (gcry_drbg, NULL)) + { + fips_signal_error ("reseeding upon fork failed"); + log_fatal ("severe error getting random\n"); + goto bailout; + } + } + /* potential integer overflow is covered by gcry_drbg_generate which + * ensures that length cannot overflow an unsigned int */ + if (0 < length) + { + if (!buffer) + goto bailout; + if (gcry_drbg_generate_long + (gcry_drbg, buffer, (unsigned int) length, NULL)) + log_fatal ("No random numbers generated\n"); + } + else + { + struct gcry_drbg_gen *data = (struct gcry_drbg_gen *) buffer; + /* catch NULL pointer */ + if (!data || !data->outbuf) + { + fips_signal_error ("No output buffer provided"); + goto bailout; + } + if (gcry_drbg_generate_long (gcry_drbg, data->outbuf, data->outlen, + data->addtl)) + log_fatal ("No random numbers generated\n"); + } +bailout: + gcry_drbg_unlock (); + return; + +} + +/*************************************************************** + * Self-test code + ***************************************************************/ + +/* + * Test vectors from + * http://csrc.nist.gov/groups/STM/cavp/documents/drbg/drbgtestvectors.zip + */ +struct gcry_drbg_test_vector gcry_drbg_test_pr[] = { + { + .flags = (GCRY_DRBG_PR_HASHSHA256), + .entropy = (unsigned char *) + "\x5d\xf2\x14\xbc\xf6\xb5\x4e\x0b\xf0\x0d\x6f\x2d" + "\xe2\x01\x66\x7b\xd0\xa4\x73\xa4\x21\xdd\xb0\xc0" + "\x51\x79\x09\xf4\xea\xa9\x08\xfa\xa6\x67\xe0\xe1" + "\xd1\x88\xa8\xad\xee\x69\x74\xb3\x55\x06\x9b\xf6", + .entropylen = 48, + .entpra = (unsigned char *) + "\xef\x48\x06\xa2\xc2\x45\xf1\x44\xfa\x34\x2c\xeb" + "\x8d\x78\x3c\x09\x8f\x34\x72\x20\xf2\xe7\xfd\x13" + "\x76\x0a\xf6\xdc\x3c\xf5\xc0\x15", + .entprb = (unsigned char *) + "\x4b\xbe\xe5\x24\xed\x6a\x2d\x0c\xdb\x73\x5e\x09" + "\xf9\xad\x67\x7c\x51\x47\x8b\x6b\x30\x2a\xc6\xde" + "\x76\xaa\x55\x04\x8b\x0a\x72\x95", + .entprlen = 32, + .expected = (unsigned char *) + "\x3b\x14\x71\x99\xa1\xda\xa0\x42\xe6\xc8\x85\x32" + "\x70\x20\x32\x53\x9a\xbe\xd1\x1e\x15\xef\xfb\x4c" + "\x25\x6e\x19\x3a\xf0\xb9\xcb\xde\xf0\x3b\xc6\x18" + "\x4d\x85\x5a\x9b\xf1\xe3\xc2\x23\x03\x93\x08\xdb" + "\xa7\x07\x4b\x33\x78\x40\x4d\xeb\x24\xf5\x6e\x81" + "\x4a\x1b\x6e\xa3\x94\x52\x43\xb0\xaf\x2e\x21\xf4" + "\x42\x46\x8e\x90\xed\x34\x21\x75\xea\xda\x67\xb6" + "\xe4\xf6\xff\xc6\x31\x6c\x9a\x5a\xdb\xb3\x97\x13" + "\x09\xd3\x20\x98\x33\x2d\x6d\xd7\xb5\x6a\xa8\xa9" + "\x9a\x5b\xd6\x87\x52\xa1\x89\x2b\x4b\x9c\x64\x60" + "\x50\x47\xa3\x63\x81\x16\xaf\x19", + .expectedlen = 128, + .addtla = (unsigned char *) + "\xbe\x13\xdb\x2a\xe9\xa8\xfe\x09\x97\xe1\xce\x5d" + "\xe8\xbb\xc0\x7c\x4f\xcb\x62\x19\x3f\x0f\xd2\xad" + "\xa9\xd0\x1d\x59\x02\xc4\xff\x70", + .addtlb = (unsigned char *) + "\x6f\x96\x13\xe2\xa7\xf5\x6c\xfe\xdf\x66\xe3\x31" + "\x63\x76\xbf\x20\x27\x06\x49\xf1\xf3\x01\x77\x41" + "\x9f\xeb\xe4\x38\xfe\x67\x00\xcd", + .addtllen = 32, + .pers = NULL, + .perslen = 0, + }, + { + .flags = (GCRY_DRBG_PR_HMACSHA256), + .entropy = (unsigned char *) + "\x13\x54\x96\xfc\x1b\x7d\x28\xf3\x18\xc9\xa7\x89" + "\xb6\xb3\xc8\x72\xac\x00\xd4\x59\x36\x25\x05\xaf" + "\xa5\xdb\x96\xcb\x3c\x58\x46\x87\xa5\xaa\xbf\x20" + "\x3b\xfe\x23\x0e\xd1\xc7\x41\x0f\x3f\xc9\xb3\x67", + .entropylen = 48, + .entpra = (unsigned char *) + "\xe2\xbd\xb7\x48\x08\x06\xf3\xe1\x93\x3c\xac\x79" + "\xa7\x2b\x11\xda\xe3\x2e\xe1\x91\xa5\x02\x19\x57" + "\x20\x28\xad\xf2\x60\xd7\xcd\x45", + .entprb = (unsigned char *) + "\x8b\xd4\x69\xfc\xff\x59\x95\x95\xc6\x51\xde\x71" + "\x68\x5f\xfc\xf9\x4a\xab\xec\x5a\xcb\xbe\xd3\x66" + "\x1f\xfa\x74\xd3\xac\xa6\x74\x60", + .entprlen = 32, + .expected = (unsigned char *) + "\x1f\x9e\xaf\xe4\xd2\x46\xb7\x47\x41\x4c\x65\x99" + "\x01\xe9\x3b\xbb\x83\x0c\x0a\xb0\xc1\x3a\xe2\xb3" + "\x31\x4e\xeb\x93\x73\xee\x0b\x26\xc2\x63\xa5\x75" + "\x45\x99\xd4\x5c\x9f\xa1\xd4\x45\x87\x6b\x20\x61" + "\x40\xea\x78\xa5\x32\xdf\x9e\x66\x17\xaf\xb1\x88" + "\x9e\x2e\x23\xdd\xc1\xda\x13\x97\x88\xa5\xb6\x5e" + "\x90\x14\x4e\xef\x13\xab\x5c\xd9\x2c\x97\x9e\x7c" + "\xd7\xf8\xce\xea\x81\xf5\xcd\x71\x15\x49\x44\xce" + "\x83\xb6\x05\xfb\x7d\x30\xb5\x57\x2c\x31\x4f\xfc" + "\xfe\x80\xb6\xc0\x13\x0c\x5b\x9b\x2e\x8f\x3d\xfc" + "\xc2\xa3\x0c\x11\x1b\x80\x5f\xf3", + .expectedlen = 128, + .addtla = NULL, + .addtlb = NULL, + .addtllen = 0, + .pers = (unsigned char *) + "\x64\xb6\xfc\x60\xbc\x61\x76\x23\x6d\x3f\x4a\x0f" + "\xe1\xb4\xd5\x20\x9e\x70\xdd\x03\x53\x6d\xbf\xce" + "\xcd\x56\x80\xbc\xb8\x15\xc8\xaa", + .perslen = 32, + }, + { + .flags = (GCRY_DRBG_PR_CTRAES128), + .entropy = (unsigned char *) + "\x92\x89\x8f\x31\xfa\x1c\xff\x6d\x18\x2f\x26\x06" + "\x43\xdf\xf8\x18\xc2\xa4\xd9\x72\xc3\xb9\xb6\x97", + .entropylen = 24, + .entpra = (unsigned char *) + "\x20\x72\x8a\x06\xf8\x6f\x8d\xd4\x41\xe2\x72\xb7" + "\xc4\x2c\xe8\x10", + .entprb = (unsigned char *) + "\x3d\xb0\xf0\x94\xf3\x05\x50\x33\x17\x86\x3e\x22" + "\x08\xf7\xa5\x01", + .entprlen = 16, + .expected = (unsigned char *) + "\x5a\x35\x39\x87\x0f\x4d\x22\xa4\x09\x24\xee\x71" + "\xc9\x6f\xac\x72\x0a\xd6\xf0\x88\x82\xd0\x83\x28" + "\x73\xec\x3f\x93\xd8\xab\x45\x23\xf0\x7e\xac\x45" + "\x14\x5e\x93\x9f\xb1\xd6\x76\x43\x3d\xb6\xe8\x08" + "\x88\xf6\xda\x89\x08\x77\x42\xfe\x1a\xf4\x3f\xc4" + "\x23\xc5\x1f\x68", + .expectedlen = 64, + .addtla = (unsigned char *) + "\x1a\x40\xfa\xe3\xcc\x6c\x7c\xa0\xf8\xda\xba\x59" + "\x23\x6d\xad\x1d", + .addtlb = (unsigned char *) + "\x9f\x72\x76\x6c\xc7\x46\xe5\xed\x2e\x53\x20\x12" + "\xbc\x59\x31\x8c", + .addtllen = 16, + .pers = (unsigned char *) + "\xea\x65\xee\x60\x26\x4e\x7e\xb6\x0e\x82\x68\xc4" + "\x37\x3c\x5c\x0b", + .perslen = 16, + }, +}; + +struct gcry_drbg_test_vector gcry_drbg_test_nopr[] = { + { + .flags = GCRY_DRBG_NOPR_HASHSHA256, + .entropy = (unsigned char *) + "\x73\xd3\xfb\xa3\x94\x5f\x2b\x5f\xb9\x8f\xf6\x9c" + "\x8a\x93\x17\xae\x19\xc3\x4c\xc3\xd6\xca\xa3\x2d" + "\x16\xfc\x42\xd2\x2d\xd5\x6f\x56\xcc\x1d\x30\xff" + "\x9e\x06\x3e\x09\xce\x58\xe6\x9a\x35\xb3\xa6\x56", + .entropylen = 48, + .expected = (unsigned char *) + "\x71\x7b\x93\x46\x1a\x40\xaa\x35\xa4\xaa\xc5\xe7" + "\x6d\x5b\x5b\x8a\xa0\xdf\x39\x7d\xae\x71\x58\x5b" + "\x3c\x7c\xb4\xf0\x89\xfa\x4a\x8c\xa9\x5c\x54\xc0" + "\x40\xdf\xbc\xce\x26\x81\x34\xf8\xba\x7d\x1c\xe8" + "\xad\x21\xe0\x74\xcf\x48\x84\x30\x1f\xa1\xd5\x4f" + "\x81\x42\x2f\xf4\xdb\x0b\x23\xf8\x73\x27\xb8\x1d" + "\x42\xf8\x44\x58\xd8\x5b\x29\x27\x0a\xf8\x69\x59" + "\xb5\x78\x44\xeb\x9e\xe0\x68\x6f\x42\x9a\xb0\x5b" + "\xe0\x4e\xcb\x6a\xaa\xe2\xd2\xd5\x33\x25\x3e\xe0" + "\x6c\xc7\x6a\x07\xa5\x03\x83\x9f\xe2\x8b\xd1\x1c" + "\x70\xa8\x07\x59\x97\xeb\xf6\xbe", + .expectedlen = 128, + .addtla = (unsigned char *) + "\xf4\xd5\x98\x3d\xa8\xfc\xfa\x37\xb7\x54\x67\x73" + "\xc7\xc3\xdd\x47\x34\x71\x02\x5d\xc1\xa0\xd3\x10" + "\xc1\x8b\xbd\xf5\x66\x34\x6f\xdd", + .addtlb = (unsigned char *) + "\xf7\x9e\x6a\x56\x0e\x73\xe9\xd9\x7a\xd1\x69\xe0" + "\x6f\x8c\x55\x1c\x44\xd1\xce\x6f\x28\xcc\xa4\x4d" + "\xa8\xc0\x85\xd1\x5a\x0c\x59\x40", + .addtllen = 32, + .pers = NULL, + .perslen = 0, + }, + { + .flags = GCRY_DRBG_NOPR_HMACSHA256, + .entropy = (unsigned char *) + "\x8d\xf0\x13\xb4\xd1\x03\x52\x30\x73\x91\x7d\xdf" + "\x6a\x86\x97\x93\x05\x9e\x99\x43\xfc\x86\x54\x54" + "\x9e\x7a\xb2\x2f\x7c\x29\xf1\x22\xda\x26\x25\xaf" + "\x2d\xdd\x4a\xbc\xce\x3c\xf4\xfa\x46\x59\xd8\x4e", + .entropylen = 48, + .expected = (unsigned char *) + "\xb9\x1c\xba\x4c\xc8\x4f\xa2\x5d\xf8\x61\x0b\x81" + "\xb6\x41\x40\x27\x68\xa2\x09\x72\x34\x93\x2e\x37" + "\xd5\x90\xb1\x15\x4c\xbd\x23\xf9\x74\x52\xe3\x10" + "\xe2\x91\xc4\x51\x46\x14\x7f\x0d\xa2\xd8\x17\x61" + "\xfe\x90\xfb\xa6\x4f\x94\x41\x9c\x0f\x66\x2b\x28" + "\xc1\xed\x94\xda\x48\x7b\xb7\xe7\x3e\xec\x79\x8f" + "\xbc\xf9\x81\xb7\x91\xd1\xbe\x4f\x17\x7a\x89\x07" + "\xaa\x3c\x40\x16\x43\xa5\xb6\x2b\x87\xb8\x9d\x66" + "\xb3\xa6\x0e\x40\xd4\xa8\xe4\xe9\xd8\x2a\xf6\xd2" + "\x70\x0e\x6f\x53\x5c\xdb\x51\xf7\x5c\x32\x17\x29" + "\x10\x37\x41\x03\x0c\xcc\x3a\x56", + .expectedlen = 128, + .addtla = NULL, + .addtlb = NULL, + .addtllen = 0, + .pers = (unsigned char *) + "\xb5\x71\xe6\x6d\x7c\x33\x8b\xc0\x7b\x76\xad\x37" + "\x57\xbb\x2f\x94\x52\xbf\x7e\x07\x43\x7a\xe8\x58" + "\x1c\xe7\xbc\x7c\x3a\xc6\x51\xa9", + .perslen = 32, + }, + { + .flags = GCRY_DRBG_NOPR_CTRAES128, + .entropy = (unsigned char *) + "\xc0\x70\x1f\x92\x50\x75\x8f\xcd\xf2\xbe\x73\x98" + "\x80\xdb\x66\xeb\x14\x68\xb4\xa5\x87\x9c\x2d\xa6", + .entropylen = 24, + .expected = (unsigned char *) + "\x97\xc0\xc0\xe5\xa0\xcc\xf2\x4f\x33\x63\x48\x8a" + "\xdb\x13\x0a\x35\x89\xbf\x80\x65\x62\xee\x13\x95" + "\x7c\x33\xd3\x7d\xf4\x07\x77\x7a\x2b\x65\x0b\x5f" + "\x45\x5c\x13\xf1\x90\x77\x7f\xc5\x04\x3f\xcc\x1a" + "\x38\xf8\xcd\x1b\xbb\xd5\x57\xd1\x4a\x4c\x2e\x8a" + "\x2b\x49\x1e\x5c", + .expectedlen = 64, + .addtla = (unsigned char *) + "\xf9\x01\xf8\x16\x7a\x1d\xff\xde\x8e\x3c\x83\xe2" + "\x44\x85\xe7\xfe", + .addtlb = (unsigned char *) + "\x17\x1c\x09\x38\xc2\x38\x9f\x97\x87\x60\x55\xb4" + "\x82\x16\x62\x7f", + .addtllen = 16, + .pers = (unsigned char *) + "\x80\x08\xae\xe8\xe9\x69\x40\xc5\x08\x73\xc7\x9f" + "\x8e\xcf\xe0\x02", + .perslen = 16, + }, + { + .flags = GCRY_DRBG_NOPR_HASHSHA1, + .entropy = (unsigned char *) + "\x16\x10\xb8\x28\xcc\xd2\x7d\xe0\x8c\xee\xa0\x32" + "\xa2\x0e\x92\x08\x49\x2c\xf1\x70\x92\x42\xf6\xb5", + .entropylen = 24, + .expected = (unsigned char *) + "\x56\xf3\x3d\x4f\xdb\xb9\xa5\xb6\x4d\x26\x23\x44" + "\x97\xe9\xdc\xb8\x77\x98\xc6\x8d\x08\xf7\xc4\x11" + "\x99\xd4\xbd\xdf\x97\xeb\xbf\x6c\xb5\x55\x0e\x5d" + "\x14\x9f\xf4\xd5\xbd\x0f\x05\xf2\x5a\x69\x88\xc1" + "\x74\x36\x39\x62\x27\x18\x4a\xf8\x4a\x56\x43\x35" + "\x65\x8e\x2f\x85\x72\xbe\xa3\x33\xee\xe2\xab\xff" + "\x22\xff\xa6\xde\x3e\x22\xac\xa2", + .expectedlen = 80, + .addtla = NULL, + .addtlb = NULL, + .addtllen = 0, + .pers = NULL, + .perslen = 0, + .entropyreseed = (unsigned char *) + "\x72\xd2\x8c\x90\x8e\xda\xf9\xa4\xd1\xe5\x26\xd8" + "\xf2\xde\xd5\x44", + .entropyreseed_len = 16, + .addtl_reseed = NULL, + .addtl_reseed_len = 0, + }, + { + .flags = GCRY_DRBG_NOPR_HASHSHA1, + .entropy = (unsigned char *) + "\xd9\xba\xb5\xce\xdc\xa9\x6f\x61\x78\xd6\x45\x09" + "\xa0\xdf\xdc\x5e\xda\xd8\x98\x94\x14\x45\x0e\x01", + .entropylen = 24, + .expected = (unsigned char *) + "\xc4\x8b\x89\xf9\xda\x3f\x74\x82\x45\x55\x5d\x5d" + "\x03\x3b\x69\x3d\xd7\x1a\x4d\xf5\x69\x02\x05\xce" + "\xfc\xd7\x20\x11\x3c\xc2\x4e\x09\x89\x36\xff\x5e" + "\x77\xb5\x41\x53\x58\x70\xb3\x39\x46\x8c\xdd\x8d" + "\x6f\xaf\x8c\x56\x16\x3a\x70\x0a\x75\xb2\x3e\x59" + "\x9b\x5a\xec\xf1\x6f\x3b\xaf\x6d\x5f\x24\x19\x97" + "\x1f\x24\xf4\x46\x72\x0f\xea\xbe", + .expectedlen = 80, + .addtla = (unsigned char *) + "\x04\xfa\x28\x95\xaa\x5a\x6f\x8c\x57\x43\x34\x3b" + "\x80\x5e\x5e\xa4", + .addtlb = (unsigned char *) + "\xdf\x5d\xc4\x59\xdf\xf0\x2a\xa2\xf0\x52\xd7\x21" + "\xec\x60\x72\x30", + .addtllen = 16, + .pers = NULL, + .perslen = 0, + .entropyreseed = (unsigned char *) + "\xc6\xba\xd0\x74\xc5\x90\x67\x86\xf5\xe1\xf3\x20" + "\x99\xf5\xb4\x91", + .entropyreseed_len = 16, + .addtl_reseed = (unsigned char *) + "\x3e\x6b\xf4\x6f\x4d\xaa\x38\x25\xd7\x19\x4e\x69" + "\x4e\x77\x52\xf7", + .addtl_reseed_len = 16, + }, +}; + + +/* + * Tests implement the CAVS test approach as documented in + * http://csrc.nist.gov/groups/STM/cavp/documents/drbg/DRBGVS.pdf + */ + +/* + * CAVS test + * + * This function is not static as it is needed for as a private API + * call for the CAVS test tool. + */ +gpg_err_code_t +gcry_drbg_cavs_test (struct gcry_drbg_test_vector *test, unsigned char *buf) +{ + gpg_err_code_t ret = 0; + struct gcry_drbg_state *drbg = NULL; + struct gcry_drbg_test_data test_data; + struct gcry_drbg_string addtl, pers, testentropy; + int coreref = 0; + int pr = 0; + + ret = gcry_drbg_algo_available (test->flags, &coreref); + if (ret) + goto outbuf; + + drbg = xcalloc_secure (1, sizeof (struct gcry_drbg_state)); + if (!drbg) + { + ret = GPG_ERR_ENOMEM; + goto outbuf; + } + + if (test->flags & GCRY_DRBG_PREDICTION_RESIST) + pr = 1; + + test_data.testentropy = &testentropy; + gcry_drbg_string_fill (&testentropy, test->entropy, test->entropylen); + drbg->test_data = &test_data; + gcry_drbg_string_fill (&pers, test->pers, test->perslen); + ret = gcry_drbg_instantiate (drbg, &pers, coreref, pr); + if (ret) + goto outbuf; + + if (test->entropyreseed) + { + gcry_drbg_string_fill (&testentropy, test->entropyreseed, + test->entropyreseed_len); + gcry_drbg_string_fill (&addtl, test->addtl_reseed, + test->addtl_reseed_len); + if (gcry_drbg_reseed (drbg, &addtl)) + goto outbuf; + } + + gcry_drbg_string_fill (&addtl, test->addtla, test->addtllen); + if (test->entpra) + { + gcry_drbg_string_fill (&testentropy, test->entpra, test->entprlen); + drbg->test_data = &test_data; + } + gcry_drbg_generate_long (drbg, buf, test->expectedlen, &addtl); + + gcry_drbg_string_fill (&addtl, test->addtlb, test->addtllen); + if (test->entprb) + { + gcry_drbg_string_fill (&testentropy, test->entprb, test->entprlen); + drbg->test_data = &test_data; + } + gcry_drbg_generate_long (drbg, buf, test->expectedlen, &addtl); + gcry_drbg_uninstantiate (drbg); + +outbuf: + xfree (drbg); + return ret; +} + +/* + * Invoke the CAVS test and perform the final check whether the + * calculated random value matches the expected one. + * + * This function is not static as it is needed for as a private API + * call for the CAVS test tool. + */ +gpg_err_code_t +gcry_drbg_healthcheck_one (struct gcry_drbg_test_vector * test) +{ + gpg_err_code_t ret = GPG_ERR_ENOMEM; + unsigned char *buf = xcalloc_secure (1, test->expectedlen); + if (!buf) + return GPG_ERR_ENOMEM; + + ret = gcry_drbg_cavs_test (test, buf); + ret = memcmp (test->expected, buf, test->expectedlen); + + xfree (buf); + return ret; +} + +/* + * Tests as defined in 11.3.2 in addition to the cipher tests: testing + * of the error handling. + * + * Note, testing the reseed counter is not done as an automatic reseeding + * is performed in gcry_drbg_generate when the reseed counter is too large. + */ +static gpg_err_code_t +gcry_drbg_healthcheck_sanity (struct gcry_drbg_test_vector *test) +{ + unsigned int len = 0; + struct gcry_drbg_state *drbg = NULL; + gpg_err_code_t ret = GPG_ERR_GENERAL; + gpg_err_code_t tmpret = GPG_ERR_GENERAL; + struct gcry_drbg_test_data test_data; + struct gcry_drbg_string addtl, testentropy; + int coreref = 0; + unsigned char *buf = NULL; + size_t max_addtllen, max_request_bytes; + + /* only perform test in FIPS mode */ + if (0 == fips_mode ()) + return 0; + + buf = xcalloc_secure (1, test->expectedlen); + if (!buf) + return GPG_ERR_ENOMEM; + tmpret = gcry_drbg_algo_available (test->flags, &coreref); + if (tmpret) + goto outbuf; + drbg = xcalloc_secure (1, sizeof (struct gcry_drbg_state)); + if (!drbg) + goto outbuf; + + /* if the following tests fail, it is likely that there is a buffer + * overflow and we get a SIGSEV */ + ret = gcry_drbg_instantiate (drbg, NULL, coreref, 1); + if (ret) + goto outbuf; + max_addtllen = gcry_drbg_max_addtl (); + max_request_bytes = gcry_drbg_max_request_bytes (); + /* overflow addtllen with additonal info string */ + gcry_drbg_string_fill (&addtl, test->addtla, (max_addtllen + 1)); + len = gcry_drbg_generate (drbg, buf, test->expectedlen, &addtl); + if (len) + goto outdrbg; + + /* overflow max_bits */ + len = gcry_drbg_generate (drbg, buf, (max_request_bytes + 1), NULL); + if (len) + goto outdrbg; + gcry_drbg_uninstantiate (drbg); + + /* test failing entropy source as defined in 11.3.2 */ + test_data.testentropy = NULL; + test_data.fail_seed_source = 1; + drbg->test_data = &test_data; + tmpret = gcry_drbg_instantiate (drbg, NULL, coreref, 0); + if (!tmpret) + goto outdrbg; + test_data.fail_seed_source = 0; + + test_data.testentropy = &testentropy; + gcry_drbg_string_fill (&testentropy, test->entropy, test->entropylen); + /* overflow max addtllen with personalization string */ + tmpret = gcry_drbg_instantiate (drbg, &addtl, coreref, 0); + if (!tmpret) + goto outdrbg; + + dbg (("DRBG: Sanity tests for failure code paths successfully completed\n")); + ret = 0; + +outdrbg: + gcry_drbg_uninstantiate (drbg); +outbuf: + xfree (buf); + xfree (drbg); + return ret; +} + +/* + * DRBG Healthcheck function as required in SP800-90A + * + * return: + * 0 on success (all tests pass) + * >0 on error (return code indicate the number of failures) + */ +static int +gcry_drbg_healthcheck (void) +{ + int ret = 0; + ret += gcry_drbg_healthcheck_one (&gcry_drbg_test_nopr[0]); + ret += gcry_drbg_healthcheck_one (&gcry_drbg_test_nopr[1]); + ret += gcry_drbg_healthcheck_one (&gcry_drbg_test_nopr[2]); + ret += gcry_drbg_healthcheck_one (&gcry_drbg_test_nopr[3]); + ret += gcry_drbg_healthcheck_one (&gcry_drbg_test_nopr[4]); + ret += gcry_drbg_healthcheck_one (&gcry_drbg_test_pr[0]); + ret += gcry_drbg_healthcheck_one (&gcry_drbg_test_pr[1]); + ret += gcry_drbg_healthcheck_one (&gcry_drbg_test_pr[2]); + ret += gcry_drbg_healthcheck_sanity (&gcry_drbg_test_nopr[0]); + return ret; +} + +/* Run the self-tests. */ +gcry_error_t +_gcry_drbg_selftest (selftest_report_func_t report) +{ + gcry_err_code_t ec; + const char *errtxt = NULL; + gcry_drbg_lock (); + if (0 != gcry_drbg_healthcheck ()) + errtxt = "RNG output does not match known value"; + gcry_drbg_unlock (); + if (report && errtxt) + report ("random", 0, "KAT", errtxt); + ec = errtxt ? GPG_ERR_SELFTEST_FAILED : 0; + return gpg_error (ec); +} + +/*************************************************************** + * Cipher invocations requested by DRBG + ***************************************************************/ + +static gpg_err_code_t +gcry_drbg_hmac (struct gcry_drbg_state *drbg, const unsigned char *key, + unsigned char *outval, const struct gcry_drbg_string *buf) +{ + gpg_error_t err; + gcry_md_hd_t hd; + + if (key) + { + err = + _gcry_md_open (&hd, drbg->core->backend_cipher, GCRY_MD_FLAG_HMAC); + if (err) + return err; + err = _gcry_md_setkey (hd, key, gcry_drbg_statelen (drbg)); + if (err) + return err; + } + else + { + err = _gcry_md_open (&hd, drbg->core->backend_cipher, 0); + if (err) + return err; + } + for (; NULL != buf; buf = buf->next) + _gcry_md_write (hd, buf->buf, buf->len); + _gcry_md_final (hd); + memcpy (outval, _gcry_md_read (hd, drbg->core->backend_cipher), + gcry_drbg_blocklen (drbg)); + _gcry_md_close (hd); + return 0; +} + +static gpg_err_code_t +gcry_drbg_sym (struct gcry_drbg_state *drbg, const unsigned char *key, + unsigned char *outval, const struct gcry_drbg_string *buf) +{ + gpg_error_t err; + gcry_cipher_hd_t hd; + + err = + _gcry_cipher_open (&hd, drbg->core->backend_cipher, GCRY_CIPHER_MODE_ECB, + 0); + if (err) + return err; + if (gcry_drbg_blocklen (drbg) != + _gcry_cipher_get_algo_blklen (drbg->core->backend_cipher)) + return -GPG_ERR_NO_ERROR; + if (gcry_drbg_blocklen (drbg) < buf->len) + return -GPG_ERR_NO_ERROR; + err = _gcry_cipher_setkey (hd, key, gcry_drbg_keylen (drbg)); + if (err) + return err; + /* in is only component */ + _gcry_cipher_encrypt (hd, outval, gcry_drbg_blocklen (drbg), buf->buf, + buf->len); + _gcry_cipher_close (hd); + return 0; +} diff --git a/random/rand-internal.h b/random/rand-internal.h index 79b23ac..475351a 100644 --- a/random/rand-internal.h +++ b/random/rand-internal.h @@ -88,6 +88,15 @@ gcry_err_code_t _gcry_rngfips_run_external_test (void *context, char *buffer, size_t buflen); void _gcry_rngfips_deinit_external_test (void *context); +/* drbg.c */ +void _gcry_drbg_init(int full); +void _gcry_drbg_close_fds(void); +void _gcry_drbg_dump_stats(void); +int _gcry_drbg_is_faked (void); +gcry_error_t _gcry_drbg_add_bytes (const void *buf, size_t buflen, int quality); +void _gcry_drbg_randomize (void *buffer, size_t length, + enum gcry_random_level level); +gcry_error_t _gcry_drbg_selftest (selftest_report_func_t report); /*-- random-system.c --*/ void _gcry_rngsystem_initialize (int full); diff --git a/random/random.c b/random/random.c index 41d4cb3..4475d3c 100644 --- a/random/random.c +++ b/random/random.c @@ -140,11 +140,11 @@ void _gcry_random_initialize (int full) { if (fips_mode ()) - _gcry_rngfips_initialize (full); + _gcry_drbg_init(full); else if (rng_types.standard) _gcry_rngcsprng_initialize (full); else if (rng_types.fips) - _gcry_rngfips_initialize (full); + _gcry_drbg_init(full); else if (rng_types.system) _gcry_rngsystem_initialize (full); else @@ -161,11 +161,11 @@ _gcry_random_close_fds (void) the entropy gatherer. */ if (fips_mode ()) - _gcry_rngfips_close_fds (); + _gcry_drbg_close_fds (); else if (rng_types.standard) _gcry_rngcsprng_close_fds (); else if (rng_types.fips) - _gcry_rngfips_close_fds (); + _gcry_drbg_close_fds (); else if (rng_types.system) _gcry_rngsystem_close_fds (); else @@ -199,7 +199,7 @@ void _gcry_random_dump_stats (void) { if (fips_mode ()) - _gcry_rngfips_dump_stats (); + _gcry_drbg_dump_stats (); else _gcry_rngcsprng_dump_stats (); } @@ -258,7 +258,7 @@ int _gcry_random_is_faked (void) { if (fips_mode ()) - return _gcry_rngfips_is_faked (); + return _gcry_drbg_is_faked (); else return _gcry_rngcsprng_is_faked (); } @@ -288,11 +288,11 @@ static void do_randomize (void *buffer, size_t length, enum gcry_random_level level) { if (fips_mode ()) - _gcry_rngfips_randomize (buffer, length, level); + _gcry_drbg_randomize (buffer, length, level); else if (rng_types.standard) _gcry_rngcsprng_randomize (buffer, length, level); else if (rng_types.fips) - _gcry_rngfips_randomize (buffer, length, level); + _gcry_drbg_randomize (buffer, length, level); else if (rng_types.system) _gcry_rngsystem_randomize (buffer, length, level); else /* default */ @@ -424,7 +424,7 @@ _gcry_create_nonce (void *buffer, size_t length) nonce generator which is seeded by the RNG actual in use. */ if (fips_mode ()) { - _gcry_rngfips_create_nonce (buffer, length); + _gcry_drbg_randomize (buffer, length, GCRY_WEAK_RANDOM); return; } @@ -501,46 +501,7 @@ gpg_error_t _gcry_random_selftest (selftest_report_func_t report) { if (fips_mode ()) - return _gcry_rngfips_selftest (report); + return _gcry_drbg_selftest (report); else return 0; /* No selftests yet. */ } - - -/* Create a new test context for an external RNG test driver. On - success the test context is stored at R_CONTEXT; on failure NULL is - stored at R_CONTEXT and an error code is returned. */ -gcry_err_code_t -_gcry_random_init_external_test (void **r_context, - unsigned int flags, - const void *key, size_t keylen, - const void *seed, size_t seedlen, - const void *dt, size_t dtlen) -{ - (void)flags; - if (fips_mode ()) - return _gcry_rngfips_init_external_test (r_context, flags, key, keylen, - seed, seedlen, - dt, dtlen); - else - return GPG_ERR_NOT_SUPPORTED; -} - -/* Get BUFLEN bytes from the RNG using the test CONTEXT and store them - at BUFFER. Return 0 on success or an error code. */ -gcry_err_code_t -_gcry_random_run_external_test (void *context, char *buffer, size_t buflen) -{ - if (fips_mode ()) - return _gcry_rngfips_run_external_test (context, buffer, buflen); - else - return GPG_ERR_NOT_SUPPORTED; -} - -/* Release the test CONTEXT. */ -void -_gcry_random_deinit_external_test (void *context) -{ - if (fips_mode ()) - _gcry_rngfips_deinit_external_test (context); -} diff --git a/random/random.h b/random/random.h index 2bc8cab..9623971 100644 --- a/random/random.h +++ b/random/random.h @@ -54,7 +54,33 @@ gcry_err_code_t _gcry_random_run_external_test (void *context, char *buffer, size_t buflen); void _gcry_random_deinit_external_test (void *context); +/*-- drbg.c --*/ +gpg_err_code_t _gcry_drbg_reinit (u32 flags, struct gcry_drbg_string *pers); +/* private interfaces for testing of DRBG */ +struct gcry_drbg_test_vector +{ + u32 flags; + unsigned char *entropy; + size_t entropylen; + unsigned char *entpra; + unsigned char *entprb; + size_t entprlen; + unsigned char *addtla; + unsigned char *addtlb; + size_t addtllen; + unsigned char *pers; + size_t perslen; + unsigned char *expected; + size_t expectedlen; + unsigned char *entropyreseed; + size_t entropyreseed_len; + unsigned char *addtl_reseed; + size_t addtl_reseed_len; +}; +gpg_err_code_t gcry_drbg_cavs_test (struct gcry_drbg_test_vector *test, + unsigned char *buf); +gpg_err_code_t gcry_drbg_healthcheck_one (struct gcry_drbg_test_vector *test); /*-- rndegd.c --*/ gpg_error_t _gcry_rndegd_set_socket_name (const char *name); diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index f48f04f..f1f1391 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -1722,6 +1722,114 @@ int gcry_is_secure (const void *a) _GCRY_GCC_ATTR_PURE; /* Return true if Libgcrypt is in FIPS mode. */ #define gcry_fips_mode_active() !!gcry_control (GCRYCTL_FIPS_MODE_P, 0) +/* DRBG input data structure for DRBG generate with additional information + * string */ +struct gcry_drbg_gen +{ + unsigned char *outbuf; /* output buffer for random numbers */ + unsigned int outlen; /* size of output buffer */ + struct gcry_drbg_string *addtl; /* input buffer for + * additional information string */ +}; + +/* + * Concatenation Helper and string operation helper + * + * SP800-90A requires the concatenation of different data. To avoid copying + * buffers around or allocate additional memory, the following data structure + * is used to point to the original memory with its size. In addition, it + * is used to build a linked list. The linked list defines the concatenation + * of individual buffers. The order of memory block referenced in that + * linked list determines the order of concatenation. + */ +/* DRBG string definition */ +struct gcry_drbg_string +{ + const unsigned char *buf; + size_t len; + struct gcry_drbg_string *next; +}; + +static inline void gcry_drbg_string_fill(struct gcry_drbg_string *string, + const unsigned char *buf, size_t len) +{ + string->buf = buf; + string->len = len; + string->next = NULL; +} + +/* this is a wrapper function for users of libgcrypt */ +static inline void gcry_randomize_drbg(void *outbuf, size_t outlen, + enum gcry_random_level level, + struct gcry_drbg_string *addtl) +{ + struct gcry_drbg_gen genbuf; + genbuf.outbuf = (unsigned char *)outbuf; + genbuf.outlen = outlen; + genbuf.addtl = addtl; + gcry_randomize(&genbuf, 0, level); +} + +/* + * DRBG flags bitmasks + * + * 31 (B) 28 19 (A) 0 + * +-+-+-+--------+---+-----------+-----+ + * |~|~|u|~~~~~~~~| 3 | 2 | 1 | + * +-+-+-+--------+- -+-----------+-----+ + * ctl flg| |drbg use selection flags + * + */ + +/* internal state control flags (B) */ +#define GCRY_DRBG_PREDICTION_RESIST ((u_int32_t)1<<28) + +/* CTR type modifiers (A.1)*/ +#define GCRY_DRBG_CTRAES ((u_int32_t)1<<0) +#define GCRY_DRBG_CTRSERPENT ((u_int32_t)1<<1) +#define GCRY_DRBG_CTRTWOFISH ((u_int32_t)1<<2) +#define GCRY_DRBG_CTR_MASK (GCRY_DRBG_CTRAES | GCRY_DRBG_CTRSERPENT | GCRY_DRBG_CTRTWOFISH) + +/* HASH type modifiers (A.2)*/ +#define GCRY_DRBG_HASHSHA1 ((u_int32_t)1<<4) +#define GCRY_DRBG_HASHSHA224 ((u_int32_t)1<<5) +#define GCRY_DRBG_HASHSHA256 ((u_int32_t)1<<6) +#define GCRY_DRBG_HASHSHA384 ((u_int32_t)1<<7) +#define GCRY_DRBG_HASHSHA512 ((u_int32_t)1<<8) +#define GCRY_DRBG_HASH_MASK (GCRY_DRBG_HASHSHA1 | GCRY_DRBG_HASHSHA224 | \ + GCRY_DRBG_HASHSHA256 | GCRY_DRBG_HASHSHA384 | \ + GCRY_DRBG_HASHSHA512) +/* type modifiers (A.3)*/ +#define GCRY_DRBG_HMAC ((u_int32_t)1<<12) +#define GCRY_DRBG_SYM128 ((u_int32_t)1<<13) +#define GCRY_DRBG_SYM192 ((u_int32_t)1<<14) +#define GCRY_DRBG_SYM256 ((u_int32_t)1<<15) +#define GCRY_DRBG_TYPE_MASK (GCRY_DRBG_HMAC | GCRY_DRBG_SYM128 | GCRY_DRBG_SYM192 | \ + GCRY_DRBG_SYM256) +#define GCRY_DRBG_CIPHER_MASK (GCRY_DRBG_CTR_MASK | GCRY_DRBG_HASH_MASK | GCRY_DRBG_TYPE_MASK) + +#define GCRY_DRBG_PR_CTRAES128 (GCRY_DRBG_PREDICTION_RESIST | GCRY_DRBG_CTRAES | GCRY_DRBG_SYM128) +#define GCRY_DRBG_PR_CTRAES192 (GCRY_DRBG_PREDICTION_RESIST | GCRY_DRBG_CTRAES | GCRY_DRBG_SYM192) +#define GCRY_DRBG_PR_CTRAES256 (GCRY_DRBG_PREDICTION_RESIST | GCRY_DRBG_CTRAES | GCRY_DRBG_SYM256) +#define GCRY_DRBG_NOPR_CTRAES128 (GCRY_DRBG_CTRAES | GCRY_DRBG_SYM128) +#define GCRY_DRBG_NOPR_CTRAES192 (GCRY_DRBG_CTRAES | GCRY_DRBG_SYM192) +#define GCRY_DRBG_NOPR_CTRAES256 (GCRY_DRBG_CTRAES | GCRY_DRBG_SYM256) +#define GCRY_DRBG_PR_HASHSHA1 (GCRY_DRBG_PREDICTION_RESIST | GCRY_DRBG_HASHSHA1) +#define GCRY_DRBG_PR_HASHSHA256 (GCRY_DRBG_PREDICTION_RESIST | GCRY_DRBG_HASHSHA256) +#define GCRY_DRBG_PR_HASHSHA384 (GCRY_DRBG_PREDICTION_RESIST | GCRY_DRBG_HASHSHA384) +#define GCRY_DRBG_PR_HASHSHA512 (GCRY_DRBG_PREDICTION_RESIST | GCRY_DRBG_HASHSHA512) +#define GCRY_DRBG_NOPR_HASHSHA1 (GCRY_DRBG_HASHSHA1) +#define GCRY_DRBG_NOPR_HASHSHA256 (GCRY_DRBG_HASHSHA256) +#define GCRY_DRBG_NOPR_HASHSHA384 (GCRY_DRBG_HASHSHA384) +#define GCRY_DRBG_NOPR_HASHSHA512 (GCRY_DRBG_HASHSHA512) +#define GCRY_DRBG_PR_HMACSHA1 (GCRY_DRBG_PREDICTION_RESIST | GCRY_DRBG_HASHSHA1 | GCRY_DRBG_HMAC) +#define GCRY_DRBG_PR_HMACSHA256 (GCRY_DRBG_PREDICTION_RESIST | GCRY_DRBG_HASHSHA256 | GCRY_DRBG_HMAC) +#define GCRY_DRBG_PR_HMACSHA384 (GCRY_DRBG_PREDICTION_RESIST | GCRY_DRBG_HASHSHA384 | GCRY_DRBG_HMAC) +#define GCRY_DRBG_PR_HMACSHA512 (GCRY_DRBG_PREDICTION_RESIST | GCRY_DRBG_HASHSHA512 | GCRY_DRBG_HMAC) +#define GCRY_DRBG_NOPR_HMACSHA1 (GCRY_DRBG_HASHSHA1 | GCRY_DRBG_HMAC) +#define GCRY_DRBG_NOPR_HMACSHA256 (GCRY_DRBG_HASHSHA256 | GCRY_DRBG_HMAC) +#define GCRY_DRBG_NOPR_HMACSHA384 (GCRY_DRBG_HASHSHA384 | GCRY_DRBG_HMAC) +#define GCRY_DRBG_NOPR_HMACSHA512 (GCRY_DRBG_HASHSHA512 | GCRY_DRBG_HMAC) #if 0 /* (Keep Emacsens' auto-indent happy.) */ { diff --git a/src/global.c b/src/global.c index 889de4c..e14d8c4 100644 --- a/src/global.c +++ b/src/global.c @@ -576,38 +576,22 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr) # pragma GCC diagnostic ignored "-Wswitch" #endif case 58: /* Init external random test. */ - { - void **rctx = va_arg (arg_ptr, void **); - unsigned int flags = va_arg (arg_ptr, unsigned int); - const void *key = va_arg (arg_ptr, const void *); - size_t keylen = va_arg (arg_ptr, size_t); - const void *seed = va_arg (arg_ptr, const void *); - size_t seedlen = va_arg (arg_ptr, size_t); - const void *dt = va_arg (arg_ptr, const void *); - size_t dtlen = va_arg (arg_ptr, size_t); - if (!fips_is_operational ()) - rc = fips_not_operational (); - else - rc = _gcry_random_init_external_test (rctx, flags, key, keylen, - seed, seedlen, dt, dtlen); - } + rc = GPG_ERR_NOT_SUPPORTED; break; - case 59: /* Run external random test. */ + case 59: /* Run external DRBG test. */ { - void *ctx = va_arg (arg_ptr, void *); - void *buffer = va_arg (arg_ptr, void *); - size_t buflen = va_arg (arg_ptr, size_t); - if (!fips_is_operational ()) - rc = fips_not_operational (); + struct gcry_drbg_test_vector *test = + va_arg (arg_ptr, struct gcry_drbg_test_vector *); + unsigned char *buf = va_arg (arg_ptr, unsigned char *); + + if (buf) + rc = gcry_drbg_cavs_test (test, buf); else - rc = _gcry_random_run_external_test (ctx, buffer, buflen); + rc = gcry_drbg_healthcheck_one (test); } break; case 60: /* Deinit external random test. */ - { - void *ctx = va_arg (arg_ptr, void *); - _gcry_random_deinit_external_test (ctx); - } + rc = GPG_ERR_NOT_SUPPORTED; break; case 61: /* Run external lock test */ rc = external_lock_test (va_arg (arg_ptr, int)); @@ -671,6 +655,15 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr) rc = GPG_ERR_NOT_IMPLEMENTED; break; + case GCRYCTL_DRBG_REINIT: + { + u32 flags = va_arg (arg_ptr, u32); + struct gcry_drbg_string *pers = va_arg (arg_ptr, + struct gcry_drbg_string *); + rc = _gcry_drbg_reinit(flags, pers); + } + break; + default: _gcry_set_preferred_rng_type (0); rc = GPG_ERR_INV_OP; -- 2.5.0 From jussi.kivilinna at iki.fi Tue Feb 16 22:46:17 2016 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 16 Feb 2016 23:46:17 +0200 Subject: building libgcrypt with --host x86_64-w64-mingw32 In-Reply-To: <87twl9jpwk.fsf@alice.fifthhorseman.net> References: <87twl9jpwk.fsf@alice.fifthhorseman.net> Message-ID: <56C398A9.2090106@iki.fi> Hello, On 16.02.2016 05:27, Daniel Kahn Gillmor wrote: > Hi Gcrypt devs-- > > i'm exploring building gcrypt 1.6.5 using mingw32 on debian, and i find > i can build it OK with i686-w64-mingw32-gcc (./configure --host > i686-w64-mingw32), but not with x86_64-w64-mingw32-gcc (./configure > --host x86_64-w64-mingw32). In particular: > > * random/rndhw.c fails to build because it selects 32-bit assembler > because __x86_64__ and __LP64__ are not #define'd > > * linking libgcrypt-20.dll fails because the underlying assembly isn't > produced, lots of errors like this one: > > mpi/mpi-inline.h:125: undefined reference to `_gcry_mpih_sub_n' > > Both of these changes are to do with assembler, i note. > > > By way of contrast, I'm successfully able to build libgpg-error-0.dll > using both toolchains, producing dlls recognized by /usr/bin/file as > corresponding to these platforms: > > i686-w64-mingw32/bin/libgpg-error-0.dll: PE32 executable (DLL) (console) Intel 80386, for MS Windows > x86_64-w64-mingw32/bin/libgpg-error-0.dll: PE32+ executable (DLL) (console) x86-64, for MS Windows > > Has anyone built libgcrypt for 64-bit Windows with mingw? Is this a > targeted platform? If so, is there something i should try to get > libgcrypt to cross-build cleanly for that target? Building for win64 have been fixed in development branch, but not backported to 1.6.x. * random/rndhw.c needs d5a7e00b6b222566a5650639ef29684b047c1909 * random/rndw32.c needs 0cdd24456b33defc7f8176fa82ab694fbc284385 ... and so on. -Jussi > > --dkg > > > > _______________________________________________ > Gcrypt-devel mailing list > Gcrypt-devel at gnupg.org > http://lists.gnupg.org/mailman/listinfo/gcrypt-devel > -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 258 bytes Desc: OpenPGP digital signature URL: From dkg at fifthhorseman.net Wed Feb 17 00:29:46 2016 From: dkg at fifthhorseman.net (Daniel Kahn Gillmor) Date: Tue, 16 Feb 2016 18:29:46 -0500 Subject: building libgcrypt with --host x86_64-w64-mingw32 In-Reply-To: <56C398A9.2090106@iki.fi> References: <87twl9jpwk.fsf@alice.fifthhorseman.net> <56C398A9.2090106@iki.fi> Message-ID: <871t8ci68l.fsf@alice.fifthhorseman.net> On Tue 2016-02-16 16:46:17 -0500, Jussi Kivilinna wrote: > Building for win64 have been fixed in development branch, but not > backported to 1.6.x. > > * random/rndhw.c needs d5a7e00b6b222566a5650639ef29684b047c1909 > * random/rndw32.c needs 0cdd24456b33defc7f8176fa82ab694fbc284385 > > ... and so on. Cool, thanks. For the moment, i'm working around this on the debian mingw toolchain with ./configure --disable-asm --disable-padlock-support for the cross-built platform. I'll happily to drop both of these options once they build cleanly on mingw32 upstream, though. --dkg From wk at gnupg.org Wed Feb 17 17:20:17 2016 From: wk at gnupg.org (Werner Koch) Date: Wed, 17 Feb 2016 17:20:17 +0100 Subject: [PATCH 0/2] SP800-90A DRBG In-Reply-To: <1560889.z3jECahC7P@positron.chronox.de> (Stephan Mueller's message of "Tue, 16 Feb 2016 22:03:49 +0100") References: <1560889.z3jECahC7P@positron.chronox.de> Message-ID: <878u2je2bi.fsf@wheatstone.g10code.de> Hi Stephan, On Tue, 16 Feb 2016 22:03, smueller at chronox.de said: > as the SP800-90A DRBG is considered for inclusion into 1.7, I ported the > existing DRBG patch set in [1] to the current git tree of libgcrypt. Thanks for that update. Actually integration of your code was on my short list. You added a new API gcry_randomize_drbg along with a new structure and a lot of new constants which seem to be only there to expose internal stuff. Why can't we just use a replacement for the current X9.31 generator? There should be just an RNG and not a way to configure it. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Wed Feb 17 17:28:33 2016 From: wk at gnupg.org (Werner Koch) Date: Wed, 17 Feb 2016 17:28:33 +0100 Subject: building libgcrypt with --host x86_64-w64-mingw32 In-Reply-To: <87io1oicss.fsf@alice.fifthhorseman.net> (Daniel Kahn Gillmor's message of "Tue, 16 Feb 2016 16:08:03 -0500") References: <87twl9jpwk.fsf@alice.fifthhorseman.net> <87si0sg4ba.fsf@wheatstone.g10code.de> <87io1oicss.fsf@alice.fifthhorseman.net> Message-ID: <874md7e1xq.fsf@wheatstone.g10code.de> On Tue, 16 Feb 2016 22:08, dkg at fifthhorseman.net said: > Great! hopefully some of the work i've been doing in debian will be > able to automate parts of this process for you. Well, it is a mere tar xjf gnupg-2.1.11.tar.bz2 make -f gnupg-2.1.11/build-aux/speedo.mk w32-release and 20 minutes of spare time. > use pkg-config, but my understanding is that GnuPG and related tools > are not going to be adopting pkg-config for platforms that support them > any time soon) Right. >>> * random/rndhw.c fails to build because it selects 32-bit assembler >>> because __x86_64__ and __LP64__ are not #define'd >> >> Hmmm. A mingw regression? > Are you seeing something different? I get the same. I'll run a build test later and get back to you. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From smueller at chronox.de Wed Feb 17 18:30:36 2016 From: smueller at chronox.de (Stephan Mueller) Date: Wed, 17 Feb 2016 18:30:36 +0100 Subject: [PATCH 0/2] SP800-90A DRBG In-Reply-To: <878u2je2bi.fsf@wheatstone.g10code.de> References: <1560889.z3jECahC7P@positron.chronox.de> <878u2je2bi.fsf@wheatstone.g10code.de> Message-ID: <2182674.MQOqS0qe72@tauon.atsec.com> Am Mittwoch, 17. Februar 2016, 17:20:17 schrieb Werner Koch: Hi Werner, >Hi Stephan, > >On Tue, 16 Feb 2016 22:03, smueller at chronox.de said: >> as the SP800-90A DRBG is considered for inclusion into 1.7, I ported the >> existing DRBG patch set in [1] to the current git tree of libgcrypt. > >Thanks for that update. Actually integration of your code was on my >short list. > >You added a new API gcry_randomize_drbg along with a new structure and a >lot of new constants which seem to be only there to expose internal >stuff. Why can't we just use a replacement for the current X9.31 >generator? There should be just an RNG and not a way to configure it. The question is what kind of support do you want to have with the DRBG. The implementation in the patch includes all bells and whistles defined in SP800-90A. The following listing enumerates options which may be removed from the current implementation: - implementation of either Hash, HMAC or CTR DRBG with only one cipher - remove prediction resistance - remove support for additional information - remove support for personalization string - remove reseed support All these items are options at the disposal of the caller. The mentioned function of gcry_randomize_drbg is a convenience wrapper to gcry_randomize as this function has no natural API for supplying an additional information string. I am happy to distill out the unwanted pieces. But I am not sure what I shall remove. Note, the default DRBG is the HMAC DRBG with SHA-256 core without prediction resistance. I favor the HMAC DRBGs as they are the leanest ones. Ciao Stephan From wk at gnupg.org Wed Feb 17 20:06:17 2016 From: wk at gnupg.org (Werner Koch) Date: Wed, 17 Feb 2016 20:06:17 +0100 Subject: building libgcrypt with --host x86_64-w64-mingw32 In-Reply-To: <87si0sg4ba.fsf@wheatstone.g10code.de> (Werner Koch's message of "Tue, 16 Feb 2016 14:42:01 +0100") References: <87twl9jpwk.fsf@alice.fifthhorseman.net> <87si0sg4ba.fsf@wheatstone.g10code.de> Message-ID: <87povvcg2e.fsf@wheatstone.g10code.de> Hi, sorry I mixed this up. I read you mail reporting that there is a build problem for a 32 bit Libgcrypt DLL and that the mentioned 64 bit problem was just a question. :-( And of course, I can replicate your problem building a 64 bit DLL. To fix the problem I backported two patches. WARNING: Do not use that 64 bit Libgcrypt DLL - I have doubts that the RNG gets sufficient entropy. I see no good reason to distribute 64 bit Windows binaries of GnuPG. For certain DLL it is required, for example when used by plugins for 64 bit Windows binaries. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From dkg at fifthhorseman.net Wed Feb 17 23:48:42 2016 From: dkg at fifthhorseman.net (Daniel Kahn Gillmor) Date: Wed, 17 Feb 2016 17:48:42 -0500 Subject: building libgcrypt with --host x86_64-w64-mingw32 In-Reply-To: <87povvcg2e.fsf@wheatstone.g10code.de> References: <87twl9jpwk.fsf@alice.fifthhorseman.net> <87si0sg4ba.fsf@wheatstone.g10code.de> <87povvcg2e.fsf@wheatstone.g10code.de> Message-ID: <87fuwrgdh1.fsf@alice.fifthhorseman.net> Hi Werner-- On Wed 2016-02-17 14:06:17 -0500, Werner Koch wrote: > sorry I mixed this up. I read you mail reporting that there is a build > problem for a 32 bit Libgcrypt DLL and that the mentioned 64 bit problem > was just a question. :-( > > And of course, I can replicate your problem building a 64 bit DLL. To > fix the problem I backported two patches. ah, thanks. > WARNING: Do not use that 64 bit Libgcrypt DLL - I have doubts that the > RNG gets sufficient entropy. this is troubling -- can you explain more about why you think the 64-bit version might get worse entropy inputs than the 32-bit version? > I see no good reason to distribute 64 bit Windows binaries of GnuPG. > For certain DLL it is required, for example when used by plugins for 64 > bit Windows binaries. right, but in that case developers probably do need a reliable 64-bit Windows DLL. If we can sort out the RNG business, that would be good. Should i open a ticket at https://bugs.gnupg.org/ to record the concern? --dkg From wk at gnupg.org Thu Feb 18 09:23:39 2016 From: wk at gnupg.org (Werner Koch) Date: Thu, 18 Feb 2016 09:23:39 +0100 Subject: building libgcrypt with --host x86_64-w64-mingw32 In-Reply-To: <87fuwrgdh1.fsf@alice.fifthhorseman.net> (Daniel Kahn Gillmor's message of "Wed, 17 Feb 2016 17:48:42 -0500") References: <87twl9jpwk.fsf@alice.fifthhorseman.net> <87si0sg4ba.fsf@wheatstone.g10code.de> <87povvcg2e.fsf@wheatstone.g10code.de> <87fuwrgdh1.fsf@alice.fifthhorseman.net> Message-ID: <87a8myctpw.fsf@wheatstone.g10code.de> On Wed, 17 Feb 2016 23:48, dkg at fifthhorseman.net said: > this is troubling -- can you explain more about why you think the 64-bit > version might get worse entropy inputs than the 32-bit version? I am simply not sure and I have not done ay test at all. An audit of the code with an emphasis on the 64 bit changes in Windows would be the Right Thing to do. The original idea was to use a new rndw64.c with all the old Windows pre-XP code removed but Jussi meanwhile fixed a couple of things in rndw32.c so it might now be easier to closely check the code and compare it to Peter' s latest version of Cryptlib (which was the original source of that code). > right, but in that case developers probably do need a reliable 64-bit > Windows DLL. If we can sort out the RNG business, that would be good. > Should i open a ticket at https://bugs.gnupg.org/ to record the concern? Right now we have no need for libgcrypt in 64 bit DLLs. The only 64 bit DLL we use is GpgEX which does not do any crypt but delegates that to GPA or Kleopatra. However, Andre is working on a 64 bit GpgOL and there we need a bit of crypto. So needs to be done by then. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From cvs at cvs.gnupg.org Fri Feb 19 15:52:44 2016 From: cvs at cvs.gnupg.org (by Stephan Mueller) Date: Fri, 19 Feb 2016 15:52:44 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-330-ge9b692d 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 e9b692d25d1c149b5417b70e18f2ce173bc25b6d (commit) from 934ba2ae5a95a96fdbb3b935b51ba43df66f11df (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 e9b692d25d1c149b5417b70e18f2ce173bc25b6d Author: Stephan Mueller Date: Tue Feb 16 22:04:53 2016 +0100 random: Remove ANSI X9.31 DRNG * random-fips.c: Remove. -- The ANSI X9.31 DRNG is removed as it is completely replaced with the SP800-90A DRBG. Signed-off-by: Stephan Mueller diff --git a/random/Makefile.am b/random/Makefile.am index 610387d..92aba20 100644 --- a/random/Makefile.am +++ b/random/Makefile.am @@ -34,7 +34,6 @@ librandom_la_SOURCES = \ random.c random.h \ rand-internal.h \ random-csprng.c \ -random-fips.c \ random-drbg.c \ random-system.c \ rndhw.c diff --git a/random/rand-internal.h b/random/rand-internal.h index dbd23df..8c8623e 100644 --- a/random/rand-internal.h +++ b/random/rand-internal.h @@ -63,31 +63,6 @@ void _gcry_rngcsprng_set_seed_file (const char *name); void _gcry_rngcsprng_update_seed_file (void); void _gcry_rngcsprng_fast_poll (void); -/*-- random-fips.c --*/ -void _gcry_rngfips_initialize (int full); -void _gcry_rngfips_close_fds (void); -void _gcry_rngfips_dump_stats (void); -int _gcry_rngfips_is_faked (void); -gcry_error_t _gcry_rngfips_add_bytes (const void *buf, size_t buflen, - int quality); -void _gcry_rngfips_randomize (void *buffer, size_t length, - enum gcry_random_level level); -void _gcry_rngfips_create_nonce (void *buffer, size_t length); - -gcry_error_t _gcry_rngfips_selftest (selftest_report_func_t report); - -gcry_err_code_t _gcry_rngfips_init_external_test (void **r_context, - unsigned int flags, - const void *key, - size_t keylen, - const void *seed, - size_t seedlen, - const void *dt, - size_t dtlen); -gcry_err_code_t _gcry_rngfips_run_external_test (void *context, - char *buffer, size_t buflen); -void _gcry_rngfips_deinit_external_test (void *context); - /*-- random-drbg.c --*/ void _gcry_rngdrbg_inititialize (int full); void _gcry_rngdrbg_close_fds (void); ----------------------------------------------------------------------- Summary of changes: random/Makefile.am | 1 - random/rand-internal.h | 25 ------------------------- 2 files changed, 26 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 Fri Feb 19 15:58:30 2016 From: wk at gnupg.org (Werner Koch) Date: Fri, 19 Feb 2016 15:58:30 +0100 Subject: [PATCH 0/2] SP800-90A DRBG In-Reply-To: <2182674.MQOqS0qe72@tauon.atsec.com> (Stephan Mueller's message of "Wed, 17 Feb 2016 18:30:36 +0100") References: <1560889.z3jECahC7P@positron.chronox.de> <878u2je2bi.fsf@wheatstone.g10code.de> <2182674.MQOqS0qe72@tauon.atsec.com> Message-ID: <87vb5kagrt.fsf@wheatstone.g10code.de> On Wed, 17 Feb 2016 18:30, smueller at chronox.de said: > The question is what kind of support do you want to have with the DRBG. The > implementation in the patch includes all bells and whistles defined in > SP800-90A. The following listing enumerates options which may be removed from > the current implementation: Thanks for the list. Meanwhile I hacked a bit on the code and I kept all algorithms except that SHA384 is not anymore accessible (does that make sense at all?) > - remove support for additional information > > - remove support for personalization string Keeping this would require a new API call. I do not really like the clever overloading trick fro gcry_randomize. However the code is still tehre and could be added in the future. > - remove reseed support I kept this one but with a change to the gcry_control API: Now a gcry_buffer_t is used instead of your internal string type. To use this one can do: char pers_string[] = "I'm a doctor, not an engineer."; gcry_buffer_t pers[1]; memset (pers, 0, sizeof pers); pers[0].data = pers_string; pers[0].len = strlen (pers_string); err = gcry_control (GCRYCTL_DRBG_REINIT, "aes sym128 pr", pers, 1, NULL); This also shows the use of the new API. tests/random.c has a couple of tests for that API. I also introduced a new gcrypt-testapi.h file which can be used for example by tests/fipsdrv.c to run the tests. That header also declares the test vector struct. Thanks for your contribution - I hope I did not broke too much. Salam-Shalom, Werner From smueller at chronox.de Fri Feb 19 16:47:39 2016 From: smueller at chronox.de (Stephan Mueller) Date: Fri, 19 Feb 2016 16:47:39 +0100 Subject: [PATCH 0/2] SP800-90A DRBG In-Reply-To: <87vb5kagrt.fsf@wheatstone.g10code.de> References: <1560889.z3jECahC7P@positron.chronox.de> <2182674.MQOqS0qe72@tauon.atsec.com> <87vb5kagrt.fsf@wheatstone.g10code.de> Message-ID: <1683545.TLPtMvLfRd@positron.chronox.de> Am Freitag, 19. Februar 2016, 15:58:30 schrieb Werner Koch: Hi Werner, > On Wed, 17 Feb 2016 18:30, smueller at chronox.de said: > > The question is what kind of support do you want to have with the DRBG. > > The > > implementation in the patch includes all bells and whistles defined in > > SP800-90A. The following listing enumerates options which may be removed > > from > > the current implementation: > Thanks for the list. Meanwhile I hacked a bit on the code and I kept > all algorithms except that SHA384 is not anymore accessible (does that > make sense at all?) It probably does not make sense for libgcrypt, you are right. > > > - remove support for additional information > > > > - remove support for personalization string > > Keeping this would require a new API call. I do not really like the > clever overloading trick fro gcry_randomize. However the code is still > tehre and could be added in the future. Perfectly fine. > > > - remove reseed support > > I kept this one but with a change to the gcry_control API: Now a > gcry_buffer_t is used instead of your internal string type. To use this > one can do: > > char pers_string[] = "I'm a doctor, not an engineer."; > gcry_buffer_t pers[1]; > > memset (pers, 0, sizeof pers); > pers[0].data = pers_string; > pers[0].len = strlen (pers_string); > > err = gcry_control (GCRYCTL_DRBG_REINIT, "aes sym128 pr", pers, 1, NULL); That call is perfectly fine. I only now have the question whether this change is visible to the API/ABI because people were in need of the DRBG for libgcrypt: The DRBG is out in the wild for quite some time now. RHEL and SLES use the DRBG code base in productive environments with the original code base from me. I would think it is visible to the API/ABI. > > This also shows the use of the new API. tests/random.c has a couple of > tests for that API. > > I also introduced a new gcrypt-testapi.h file which can be used for > example by tests/fipsdrv.c to run the tests. That header also declares > the test vector struct. > > Thanks for your contribution - I hope I did not broke too much. Thank you. I offer to perform a full CAVS test on your code changes. Where can I find your patch set? Ciao Stephan From steve at kelem.net Fri Feb 19 22:21:58 2016 From: steve at kelem.net (Steve Kelem) Date: Fri, 19 Feb 2016 13:21:58 -0800 Subject: Problems building gnupg Message-ID: I'm having trouble configuring gnupg. I downloaded gnupg and libgpg-error via git: % git describe gnupg-2.1.11-35-ge1ceff1 libgpg-error-1.21-8-g1e6c5a7 I built and installed libgpg-error with prefix /usr/local without error. (no pun intended) When I configure gnupg, I get the message: % ./configure \ --sysconfdir=/etc --enable-maintainer-mode \ --with-libgpg-error-prefix=/usr/local \ --prefix=/usr/local ... configure: *** *** You need libgpg-error to build this program. ** This library is for example available at *** ftp://ftp.gnupg.org/gcrypt/libgpg-error *** (at least version 1.21 is required.) *** configure: error: *** *** Required libraries not found. Please consult the above messages *** and install them before running configure again. *** % echo $LD_LIBRARY_PATH /usr/local/lib:/usr/lib:/lib Thanks for any help you can give, Steve -------------- next part -------------- An HTML attachment was scrubbed... URL: From ametzler at bebt.de Sat Feb 20 13:09:09 2016 From: ametzler at bebt.de (Andreas Metzler) Date: Sat, 20 Feb 2016 13:09:09 +0100 Subject: GIT head: tests/random drains entropy, never finishes Message-ID: <3k1mpc-7go.ln1@argenau.bebt.de> Hello, starting with 934ba2a (random: Add a test case for DRBG_REINIT.) the testsuite takes so long that I have not yet managed to wait it to finish. The hanging test is tests/random at ./tests/random --in-recursion --verbose --debug --prefer-fips-rng Stracing the process shows 25075 write(2, "checking DRBG_REINIT\n", 21) = 21 25075 open("/dev/random", O_RDONLY) = 3 25075 fcntl(3, F_GETFD) = 0 25075 fcntl(3, F_SETFD, FD_CLOEXEC) = 0 25075 select(4, [3], NULL, NULL, {0, 100000}) = 1 (in [3], left {0, 99996}) 25075 read(3, "\320\0\273\266\3\26\306{\352\246s\35J\34\3\260\v\343\354id%\30\337\364\222\226", 36) = 27 25075 select(4, [3], NULL, NULL, {0, 100000}) = 1 (in [3], left {0, 99998}) 25075 read(3, "\257\361d\231=\16", 9) = 6 25075 select(4, [3], NULL, NULL, {0, 100000}) = 1 (in [3], left {0, 99998}) 25075 read(3, "\272\370\347", 3) = 3 25075 getpid() = 25075 25075 select(4, [3], NULL, NULL, {0, 100000}) = 1 (in [3], left {0, 99998}) 25075 read(3, "\352 \267\\\330T\342\357\271bFC", 36) = 12 25075 select(4, [3], NULL, NULL, {0, 100000}) = 0 (Timeout) 25075 select(4, [3], NULL, NULL, {3, 0}) = 0 (Timeout) 25075 select(4, [3], NULL, NULL, {3, 0}) = 1 (in [3], left {1, 361342}) 25075 read(3, "D\213\264\255]}", 24) = 6 25075 select(4, [3], NULL, NULL, {3, 0}) = 0 (Timeout) 25075 select(4, [3], NULL, NULL, {3, 0}) = 1 (in [3], left {1, 468072}) 25075 read(3, "z\3641\314y\21", 18) = 6 and it continues like that. /proc/sys/kernel/random/entropy_avail shows that entropy is drained. 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' From cvs at cvs.gnupg.org Sat Feb 20 14:47:39 2016 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Sat, 20 Feb 2016 14:47:39 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-332-g839d12c 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 839d12c221430b60db5e0d6fbb107f22e0a6837f (commit) via 3b57e5a1ba68e26dcaea38b763287fddba9b6b7c (commit) from e9b692d25d1c149b5417b70e18f2ce173bc25b6d (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 839d12c221430b60db5e0d6fbb107f22e0a6837f Author: Werner Koch Date: Sat Feb 20 14:41:56 2016 +0100 tests: Do not test DRBG_REINIT from "make check" * tests/random.c (main): Run check_drbg_reinit only if the envvar GCRYPT_IN_REGRESSION_TEST is set. -- Without a hardware entropy generator (e.g. the moonbase token) running the regression suite would take too long. We better use a set of test vectors when run from "make check". Signed-off-by: Werner Koch diff --git a/tests/random.c b/tests/random.c index 8aa730b..2a4b698 100644 --- a/tests/random.c +++ b/tests/random.c @@ -666,7 +666,10 @@ main (int argc, char **argv) check_nonce_forking (); check_close_random_device (); } - check_drbg_reinit (); + /* For now we do not run the drgb_reinit check from "make check" due + to its high requirement for entropy. */ + if (!getenv ("GCRYPT_IN_REGRESSION_TEST")) + check_drbg_reinit (); check_rng_type_switching (); if (!in_recursion) commit 3b57e5a1ba68e26dcaea38b763287fddba9b6b7c Author: Werner Koch Date: Wed Feb 17 19:34:21 2016 +0100 doc: Fix possible dependency problem. * doc/Makefile.am (gcrypt.texi): Use the right traget. Signed-off-by: Werner Koch diff --git a/doc/Makefile.am b/doc/Makefile.am index 30330bb..6a7cc8e 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -83,7 +83,7 @@ $(myman_pages) : yat2m-stamp # Make sure that gcrypt.texi is touched if any other source file has # been modified. This is required so that the version.texi magic # updates the release date. -gnupg.texi : $(gcrypt_TEXINFOS) +gcrypt.texi : $(gcrypt_TEXINFOS) touch $(srcdir)/gcrypt.texi online: gcrypt.html gcrypt.pdf gcrypt.info ----------------------------------------------------------------------- Summary of changes: doc/Makefile.am | 2 +- tests/random.c | 5 ++++- 2 files changed, 5 insertions(+), 2 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 Sat Feb 20 14:44:59 2016 From: wk at gnupg.org (Werner Koch) Date: Sat, 20 Feb 2016 14:44:59 +0100 Subject: GIT head: tests/random drains entropy, never finishes In-Reply-To: <3k1mpc-7go.ln1@argenau.bebt.de> (Andreas Metzler's message of "Sat, 20 Feb 2016 13:09:09 +0100") References: <3k1mpc-7go.ln1@argenau.bebt.de> Message-ID: <8760xja42s.fsf@wheatstone.g10code.de> On Sat, 20 Feb 2016 13:09, ametzler at bebt.de said: > starting with 934ba2a (random: Add a test case for DRBG_REINIT.) the > testsuite takes so long that I have not yet managed to wait it to Well, that is due to the new DRBG. I just pushed a change to disable that specific test when run from "make check". Run tests/random directly will still run the test. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Sat Feb 20 14:49:46 2016 From: wk at gnupg.org (Werner Koch) Date: Sat, 20 Feb 2016 14:49:46 +0100 Subject: Problems building gnupg In-Reply-To: (Steve Kelem's message of "Fri, 19 Feb 2016 13:21:58 -0800") References: Message-ID: <871t87a3ut.fsf@wheatstone.g10code.de> On Fri, 19 Feb 2016 22:21, steve at kelem.net said: > *** You need libgpg-error to build this program. > ** This library is for example available at > *** ftp://ftp.gnupg.org/gcrypt/libgpg-error > *** (at least version 1.21 is required.) Somewhere above in the output of configure or in config.log you can find the libgpg-error version configure actually found. It will also show you the libgpg-error-config script it invoked. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From john at johnwarburton.net Sat Feb 20 18:12:09 2016 From: john at johnwarburton.net (John Warburton) Date: Sat, 20 Feb 2016 17:12:09 +0000 Subject: Compilation of random/random-drbg.c under mingw-w64 Message-ID: Hello, I'm experiencing a compilation error when my build process (gcc-5.3.0 on GNU/Linux with host=x86_64-w64-mingw32) meets the recently-added random-drbg.c code. Until these changes, libgcrypt has compiled flawlessly. The compiler is instructed to look for the header , which doesn't exist in Mingw-w64 and, as far as I know, the W32 platform. When manually adding #define u_int32_t in the code, I am then left with the compiler not finding the function read_cb(), which is in random-system.c Thanks for reading this, John -------------- next part -------------- An HTML attachment was scrubbed... URL: From cvs at cvs.gnupg.org Sat Feb 20 20:37:18 2016 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Sat, 20 Feb 2016 20:37:18 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-333-g531b25a 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 531b25aa94c58f6d2168a9537c8cea6c53d7bbe0 (commit) from 839d12c221430b60db5e0d6fbb107f22e0a6837f (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 531b25aa94c58f6d2168a9537c8cea6c53d7bbe0 Author: Jussi Kivilinna Date: Sat Feb 20 21:27:15 2016 +0200 Fix building random-drbg for Win32/64 * random/random-drbg.c: Remove include for sys/types.h and asm/types.h. (DRBG_PREDICTION_RESIST, DRBG_CTRAES, DRBG_CTRSERPENT, DRBG_CTRTWOFISH) (DRBG_HASHSHA1, DRBG_HASHSHA224, DRBG_HASHSHA256, DRBG_HASHSHA384) (DRBG_HASHSHA512, DRBG_HMAC, DRBG_SYM128, DRBG_SYM192) (DRBG_SYM256): Change 'u_int32_t' to 'u32'. (drbg_get_entropy) [USE_RNDUNIX, USE_RNDW32]: Fix parameters 'drbg_read_cb' and 'len'. -- Signed-off-by: Jussi Kivilinna diff --git a/random/random-drbg.c b/random/random-drbg.c index c7b6484..f9d11a3 100644 --- a/random/random-drbg.c +++ b/random/random-drbg.c @@ -146,8 +146,6 @@ * gcry_randomize(outbuf, OUTLEN, GCRY_STRONG_RANDOM); */ -#include -#include #include #include #include @@ -177,29 +175,29 @@ */ /* Internal state control flags (B) */ -#define DRBG_PREDICTION_RESIST ((u_int32_t)1<<28) +#define DRBG_PREDICTION_RESIST ((u32)1<<28) /* CTR type modifiers (A.1)*/ -#define DRBG_CTRAES ((u_int32_t)1<<0) -#define DRBG_CTRSERPENT ((u_int32_t)1<<1) -#define DRBG_CTRTWOFISH ((u_int32_t)1<<2) +#define DRBG_CTRAES ((u32)1<<0) +#define DRBG_CTRSERPENT ((u32)1<<1) +#define DRBG_CTRTWOFISH ((u32)1<<2) #define DRBG_CTR_MASK (DRBG_CTRAES | DRBG_CTRSERPENT \ | DRBG_CTRTWOFISH) /* HASH type modifiers (A.2)*/ -#define DRBG_HASHSHA1 ((u_int32_t)1<<4) -#define DRBG_HASHSHA224 ((u_int32_t)1<<5) -#define DRBG_HASHSHA256 ((u_int32_t)1<<6) -#define DRBG_HASHSHA384 ((u_int32_t)1<<7) -#define DRBG_HASHSHA512 ((u_int32_t)1<<8) +#define DRBG_HASHSHA1 ((u32)1<<4) +#define DRBG_HASHSHA224 ((u32)1<<5) +#define DRBG_HASHSHA256 ((u32)1<<6) +#define DRBG_HASHSHA384 ((u32)1<<7) +#define DRBG_HASHSHA512 ((u32)1<<8) #define DRBG_HASH_MASK (DRBG_HASHSHA1 | DRBG_HASHSHA224 \ | DRBG_HASHSHA256 | DRBG_HASHSHA384 \ | DRBG_HASHSHA512) /* type modifiers (A.3)*/ -#define DRBG_HMAC ((u_int32_t)1<<12) -#define DRBG_SYM128 ((u_int32_t)1<<13) -#define DRBG_SYM192 ((u_int32_t)1<<14) -#define DRBG_SYM256 ((u_int32_t)1<<15) +#define DRBG_HMAC ((u32)1<<12) +#define DRBG_SYM128 ((u32)1<<13) +#define DRBG_SYM192 ((u32)1<<14) +#define DRBG_SYM256 ((u32)1<<15) #define DRBG_TYPE_MASK (DRBG_HMAC | DRBG_SYM128 | DRBG_SYM192 \ | DRBG_SYM256) #define DRBG_CIPHER_MASK (DRBG_CTR_MASK | DRBG_HASH_MASK \ @@ -632,12 +630,12 @@ drbg_get_entropy (drbg_state_t drbg, unsigned char *buffer, rc = _gcry_rndlinux_gather_random (drbg_read_cb, 0, len, GCRY_VERY_STRONG_RANDOM); #elif USE_RNDUNIX - rc = _gcry_rndunix_gather_random (read_cb, 0, length, + rc = _gcry_rndunix_gather_random (drbg_read_cb, 0, len, GCRY_VERY_STRONG_RANDOM); #elif USE_RNDW32 do { - rc = _gcry_rndw32_gather_random (read_cb, 0, length, + rc = _gcry_rndw32_gather_random (drbg_read_cb, 0, len, GCRY_VERY_STRONG_RANDOM); } while (rc >= 0 && read_cb_len < read_cb_size); ----------------------------------------------------------------------- Summary of changes: random/random-drbg.c | 32 +++++++++++++++----------------- 1 file changed, 15 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 jussi.kivilinna at iki.fi Sat Feb 20 20:38:42 2016 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sat, 20 Feb 2016 21:38:42 +0200 Subject: Compilation of random/random-drbg.c under mingw-w64 In-Reply-To: References: Message-ID: <56C8C0C2.3010801@iki.fi> Hello, On 20.02.2016 19:12, John Warburton wrote: > Hello, > > I'm experiencing a compilation error when my build process (gcc-5.3.0 on > GNU/Linux with host=x86_64-w64-mingw32) meets the recently-added > random-drbg.c code. Until these changes, libgcrypt has compiled flawlessly. > > The compiler is instructed to look for the header , which > doesn't exist in Mingw-w64 and, as far as I know, the W32 platform. > > When manually adding #define u_int32_t in the code, I am then left with the > compiler not finding the function read_cb(), which is in random-system.c I pushed commit to fix building for win32/64. -Jussi > > Thanks for reading this, > John > > > > _______________________________________________ > Gcrypt-devel mailing list > Gcrypt-devel at gnupg.org > http://lists.gnupg.org/mailman/listinfo/gcrypt-devel > From ametzler at bebt.de Sun Feb 21 14:28:07 2016 From: ametzler at bebt.de (Andreas Metzler) Date: Sun, 21 Feb 2016 14:28:07 +0100 Subject: [patch] Do not ship generated header file gcrypt.h in tarball Message-ID: <20160221132807.GB31064@argenau.bebt.de> Hello, gcrypt.h is gnerated when running ./configure and therefore should not be shipped in the relase tarballs. Trivial patch attached. 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 -------------- A non-text attachment was scrubbed... Name: 0001-Do-not-ship-generated-header-file-in-tarball.patch Type: text/x-diff Size: 996 bytes Desc: not available URL: From cvs at cvs.gnupg.org Mon Feb 22 08:19:12 2016 From: cvs at cvs.gnupg.org (by Andreas Metzler) Date: Mon, 22 Feb 2016 08:19:12 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-334-g2b40a16 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 2b40a16333fa75f1cee85ab901a5aa9cff845a92 (commit) from 531b25aa94c58f6d2168a9537c8cea6c53d7bbe0 (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 2b40a16333fa75f1cee85ab901a5aa9cff845a92 Author: Andreas Metzler Date: Sun Feb 21 12:18:33 2016 +0100 Do not ship generated header file in tarball. * src/Makefile.am: Move gcrypt.h from include_HEADERS to nodist_include_HEADERS to prevent inclusion in release tarball. This could break out-of-tree-builds because the potentially outdated src/gcrypt.h was not updated but was in the compiler search path. diff --git a/src/Makefile.am b/src/Makefile.am index 4ef95cb..aee2828 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -26,7 +26,7 @@ EXTRA_DIST = libgcrypt-config.in libgcrypt.m4 libgcrypt.vers \ bin_SCRIPTS = libgcrypt-config m4datadir = $(datadir)/aclocal m4data_DATA = libgcrypt.m4 -include_HEADERS = gcrypt.h +nodist_include_HEADERS = gcrypt.h lib_LTLIBRARIES = libgcrypt.la bin_PROGRAMS = dumpsexp hmac256 mpicalc ----------------------------------------------------------------------- Summary of changes: src/Makefile.am | 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 wk at gnupg.org Mon Feb 22 08:14:31 2016 From: wk at gnupg.org (Werner Koch) Date: Mon, 22 Feb 2016 08:14:31 +0100 Subject: [patch] Do not ship generated header file gcrypt.h in tarball In-Reply-To: <20160221132807.GB31064@argenau.bebt.de> (Andreas Metzler's message of "Sun, 21 Feb 2016 14:28:07 +0100") References: <20160221132807.GB31064@argenau.bebt.de> Message-ID: <87mvqt8be0.fsf@wheatstone.g10code.de> On Sun, 21 Feb 2016 14:28, ametzler at bebt.de said: > gcrypt.h is gnerated when running ./configure and therefore should not > be shipped in the relase tarballs. Trivial patch attached. Thanks. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Mon Feb 22 08:15:52 2016 From: wk at gnupg.org (Werner Koch) Date: Mon, 22 Feb 2016 08:15:52 +0100 Subject: Compilation of random/random-drbg.c under mingw-w64 In-Reply-To: <56C8C0C2.3010801@iki.fi> (Jussi Kivilinna's message of "Sat, 20 Feb 2016 21:38:42 +0200") References: <56C8C0C2.3010801@iki.fi> Message-ID: <87io1h8bbr.fsf@wheatstone.g10code.de> On Sat, 20 Feb 2016 20:38, jussi.kivilinna at iki.fi said: > I pushed commit to fix building for win32/64. Thanks. It will also be important for other platforms. In contrast to GnuPG 2, Libgcrypt should be buildable by any ANSI C compiler. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Mon Feb 22 08:36:17 2016 From: wk at gnupg.org (Werner Koch) Date: Mon, 22 Feb 2016 08:36:17 +0100 Subject: [PATCH 0/2] SP800-90A DRBG In-Reply-To: <1683545.TLPtMvLfRd@positron.chronox.de> (Stephan Mueller's message of "Fri, 19 Feb 2016 16:47:39 +0100") References: <1560889.z3jECahC7P@positron.chronox.de> <2182674.MQOqS0qe72@tauon.atsec.com> <87vb5kagrt.fsf@wheatstone.g10code.de> <1683545.TLPtMvLfRd@positron.chronox.de> Message-ID: <87egc58adq.fsf@wheatstone.g10code.de> On Fri, 19 Feb 2016 16:47, smueller at chronox.de said: >> all algorithms except that SHA384 is not anymore accessible (does that >> make sense at all?) > > It probably does not make sense for libgcrypt, you are right. OTOH, it would be just one extra line in the flags parser table. > I only now have the question whether this change is visible to the API/ABI > because people were in need of the DRBG for libgcrypt: The DRBG is out in the > wild for quite some time now. RHEL and SLES use the DRBG code base in You mean, they use Libgcrypt with your patch? That would of course be a problem (for them). I recall that we agreed quite some time ago to add the GCRYCTL_DRBG_REINIT constant but we did not agree on any semantic. I guess that the introduction of the guard argumennt (last arg must be NULL) will catch most usages of the patched version of DRBG_REINIT. OTOH, 1.7 has not been officially released and if a vendor is using a patched version based on 1.6 they will run into ABI numbering problems: 1.5 uses C19/A8/Rx (.so.11.8.x (for most Linux based OS)) 1.6 uses C20/A0/Rx (.so.20.0.x) 1.7 will/uses C21/A1/R0 (.so.21.1.0) The LT version number for 1.7 is however already in use by at least anyone using Curve25519 (ECDH) and thus we can't change the LT version for 1.6 anymore. I doubt that it would be justified to change the major SO number for Libgcrypt 1.7 due to an unofficial and no-coordinated ABI change by one vendor. > Thank you. I offer to perform a full CAVS test on your code changes. Where can > I find your patch set? Given that we want to release 1.7 soonish I have pushed that to master. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From smueller at chronox.de Mon Feb 22 09:08:39 2016 From: smueller at chronox.de (Stephan Mueller) Date: Mon, 22 Feb 2016 09:08:39 +0100 Subject: [PATCH 0/2] SP800-90A DRBG In-Reply-To: <87egc58adq.fsf@wheatstone.g10code.de> References: <1560889.z3jECahC7P@positron.chronox.de> <1683545.TLPtMvLfRd@positron.chronox.de> <87egc58adq.fsf@wheatstone.g10code.de> Message-ID: <5133739.71tAEU7d7L@tauon.atsec.com> Am Montag, 22. Februar 2016, 08:36:17 schrieb Werner Koch: Hi Werner, > >> Thank you. I offer to perform a full CAVS test on your code changes. Where >> can I find your patch set? > >Given that we want to release 1.7 soonish I have pushed that to master. Thanks, I will test it hopefully today. Ciao Stephan From smueller at chronox.de Mon Feb 22 21:25:30 2016 From: smueller at chronox.de (Stephan Mueller) Date: Mon, 22 Feb 2016 21:25:30 +0100 Subject: [PATCH 0/2] SP800-90A DRBG In-Reply-To: <5133739.71tAEU7d7L@tauon.atsec.com> References: <1560889.z3jECahC7P@positron.chronox.de> <87egc58adq.fsf@wheatstone.g10code.de> <5133739.71tAEU7d7L@tauon.atsec.com> Message-ID: <6969568.uqJlWcB374@positron.chronox.de> Am Montag, 22. Februar 2016, 09:08:39 schrieb Stephan Mueller: Hi Werner, > Am Montag, 22. Februar 2016, 08:36:17 schrieb Werner Koch: > > Hi Werner, > > >> Thank you. I offer to perform a full CAVS test on your code changes. > >> Where > >> can I find your patch set? > > > >Given that we want to release 1.7 soonish I have pushed that to master. > > Thanks, I will test it hopefully today. CAVS testing of all DRBG types successfully completed. Ciao Stephan From smueller at chronox.de Mon Feb 22 21:27:49 2016 From: smueller at chronox.de (Stephan Mueller) Date: Mon, 22 Feb 2016 21:27:49 +0100 Subject: [PATCH] DRBG: remove stale comments Message-ID: <1711358.S1Qgm5eIhJ@positron.chronox.de> The removed comments are not applicable any more. Signed-off-by: Stephan Mueller --- random/random-drbg.c | 45 --------------------------------------------- 1 file changed, 45 deletions(-) diff --git a/random/random-drbg.c b/random/random-drbg.c index f9d11a3..f036719 100644 --- a/random/random-drbg.c +++ b/random/random-drbg.c @@ -99,51 +99,6 @@ * flags is set to 0 and perslen is set to 0, the current DRBG type is * completely reset without using a personalization string. * - * DRBG Usage - * ========== - * The SP 800-90A DRBG allows the user to specify a personalization string - * for initialization as well as an additional information string for each - * random number request. The following code fragments show how a caller - * uses the API to use the full functionality of the DRBG. - * - * Usage without any additional data - * --------------------------------- - * gcry_randomize(outbuf, OUTLEN, GCRY_STRONG_RANDOM); - * - * - * Usage with personalization string during initialization - * ------------------------------------------------------- - * drbg_string_t pers; - * char personalization[11] = "some-string"; - * - * drbg_string_fill(&pers, personalization, strlen(personalization)); - * // The reset completely re-initializes the DRBG with the provided - * // personalization string without changing the DRBG type - * ret = gcry_control(GCRYCTL_DRBG_REINIT, 0, &pers); - * gcry_randomize(outbuf, OUTLEN, GCRY_STRONG_RANDOM); - * - * - * Usage with additional information string during random number request - * --------------------------------------------------------------------- - * drbg_string_t addtl; - * char addtl_string[11] = "some-string"; - * - * drbg_string_fill(&addtl, addtl_string, strlen(addtl_string)); - * // The following call is a wrapper to gcry_randomize() and returns - * // the same error codes. - * gcry_randomize_drbg(outbuf, OUTLEN, GCRY_STRONG_RANDOM, &addtl); - * - * - * Usage with personalization and additional information strings - * ------------------------------------------------------------- - * Just mix both scenarios above. - * - * - * Switch the DRBG type to some other type - * --------------------------------------- - * // Switch to CTR DRBG AES-128 without prediction resistance - * ret = gcry_control(GCRYCTL_DRBG_REINIT, DRBG_NOPR_CTRAES128, NULL); - * gcry_randomize(outbuf, OUTLEN, GCRY_STRONG_RANDOM); */ #include -- 2.5.0 From gniibe at fsij.org Tue Feb 23 06:34:05 2016 From: gniibe at fsij.org (NIIBE Yutaka) Date: Tue, 23 Feb 2016 14:34:05 +0900 Subject: Issue 2256: mpi_powm Message-ID: <56CBEF4D.4030806@fsij.org> Hello, We have an issue: https://bugs.gnupg.org/gnupg/issue2256 libssh2 does D-H computation using gcry_mpi_powm (if configured with libgcrypt). When gcry_mpi_powm is called, EXPO can have a limb of all-zero as the most significant limb, which results undefined value by count_leading_zeros on IA-32. Here is a patch to fix both implementations of _gcry_mpi_powm. I would require the most significant bit to be 1 in the protocol to encourage constant-time computation by implementations, but that's another story. diff --git a/mpi/mpi-pow.c b/mpi/mpi-pow.c index 0be153f..a780ebd 100644 --- a/mpi/mpi-pow.c +++ b/mpi/mpi-pow.c @@ -83,6 +83,7 @@ _gcry_mpi_powm (gcry_mpi_t res, rp = res->d; ep = expo->d; + MPN_NORMALIZE(ep, esize); if (!msize) _gcry_divide_by_zero(); @@ -429,6 +430,9 @@ _gcry_mpi_powm (gcry_mpi_t res, size = 2 * msize; msign = mod->sign; + ep = expo->d; + MPN_NORMALIZE(ep, esize); + if (esize * BITS_PER_MPI_LIMB > 512) W = 5; else if (esize * BITS_PER_MPI_LIMB > 256) @@ -445,7 +449,6 @@ _gcry_mpi_powm (gcry_mpi_t res, bsec = mpi_is_secure(base); rp = res->d; - ep = expo->d; if (!msize) _gcry_divide_by_zero(); -- From wk at gnupg.org Tue Feb 23 21:24:40 2016 From: wk at gnupg.org (Werner Koch) Date: Tue, 23 Feb 2016 21:24:40 +0100 Subject: [PATCH] DRBG: remove stale comments In-Reply-To: <1711358.S1Qgm5eIhJ@positron.chronox.de> (Stephan Mueller's message of "Mon, 22 Feb 2016 21:27:49 +0100") References: <1711358.S1Qgm5eIhJ@positron.chronox.de> Message-ID: <87povn41kn.fsf@wheatstone.g10code.de> On Mon, 22 Feb 2016 21:27, smueller at chronox.de said: > The removed comments are not applicable any more. I know. I would like to keep them with a comment that the core supports these operations but that they are currently not exposed by the API. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Tue Feb 23 21:26:12 2016 From: wk at gnupg.org (Werner Koch) Date: Tue, 23 Feb 2016 21:26:12 +0100 Subject: [PATCH 0/2] SP800-90A DRBG In-Reply-To: <6969568.uqJlWcB374@positron.chronox.de> (Stephan Mueller's message of "Mon, 22 Feb 2016 21:25:30 +0100") References: <1560889.z3jECahC7P@positron.chronox.de> <87egc58adq.fsf@wheatstone.g10code.de> <5133739.71tAEU7d7L@tauon.atsec.com> <6969568.uqJlWcB374@positron.chronox.de> Message-ID: <87lh6b41i3.fsf@wheatstone.g10code.de> On Mon, 22 Feb 2016 21:25, smueller at chronox.de said: > CAVS testing of all DRBG types successfully completed. Cool. I am glad to hear that I did not broke too much. Thanks, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From cvs at cvs.gnupg.org Thu Feb 25 04:05:32 2016 From: cvs at cvs.gnupg.org (by NIIBE Yutaka) Date: Thu, 25 Feb 2016 04:05:32 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-335-gfdfa5bf 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 fdfa5bfefdde316688a3c8021bd3528c5273b0f4 (commit) from 2b40a16333fa75f1cee85ab901a5aa9cff845a92 (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 fdfa5bfefdde316688a3c8021bd3528c5273b0f4 Author: NIIBE Yutaka Date: Thu Feb 25 12:01:10 2016 +0900 mpi: Normalize EXPO for mpi_powm. * mpi/mpi-pow.c (gcry_mpi_powm): Normalize EP. -- Thanks to Dan Fandrich for the report with a reproducible test case. GnuPG-bug-id: 2256 Signed-off-by: NIIBE Yutaka diff --git a/mpi/mpi-pow.c b/mpi/mpi-pow.c index 0be153f..a780ebd 100644 --- a/mpi/mpi-pow.c +++ b/mpi/mpi-pow.c @@ -83,6 +83,7 @@ _gcry_mpi_powm (gcry_mpi_t res, rp = res->d; ep = expo->d; + MPN_NORMALIZE(ep, esize); if (!msize) _gcry_divide_by_zero(); @@ -429,6 +430,9 @@ _gcry_mpi_powm (gcry_mpi_t res, size = 2 * msize; msign = mod->sign; + ep = expo->d; + MPN_NORMALIZE(ep, esize); + if (esize * BITS_PER_MPI_LIMB > 512) W = 5; else if (esize * BITS_PER_MPI_LIMB > 256) @@ -445,7 +449,6 @@ _gcry_mpi_powm (gcry_mpi_t res, bsec = mpi_is_secure(base); rp = res->d; - ep = expo->d; if (!msize) _gcry_divide_by_zero(); ----------------------------------------------------------------------- Summary of changes: mpi/mpi-pow.c | 5 ++++- 1 file changed, 4 insertions(+), 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 gniibe at fsij.org Mon Feb 29 05:46:07 2016 From: gniibe at fsij.org (NIIBE Yutaka) Date: Mon, 29 Feb 2016 13:46:07 +0900 Subject: Curve25519 ECDH with ephemeral key input O Message-ID: <56D3CD0F.3080707@fsij.org> Hello, While Curve25519 computation is defined as "no input validation" required, I think that it is good for our ECDH implementation to have input validation against the point O. Let's consider a scenario with GnuPG. While current GnuPG has no possibility creating such a message, (by some other tool) I could create an encrypted message by Curve25519 ECDH with ephemeral key of point O. Suppose the function Curve25519(k, P) is defined as RFC 7748; The bit of next to msb and least significant bits of k will be tweaked before the computation of point multiplication. In the terms of RFC-6637 (page 7), it's like: Obtain the authenticated recipient public key R where (r, R): private key, public key Generate an ephemeral key pair {v, V=vG} Here, I chose V=O, although any value of k to Curve25519(k, P) cannot produce O if P != O (because of the tweak). Compute the shared point S = vR; And I proceed ECDH computation as if S = O. m = symm_alg_ID || session key || checksum || pkcs5_padding; curve_OID_len = (byte)len(curve_OID); Param = curve_OID_len || curve_OID || public_key_alg_ID || 03 || 01 || KDF_hash_ID || KEK_alg_ID for AESKeyWrap || "Anonymous Sender " || recipient_fingerprint; Z_len = the key size for the KEK_alg_ID used with AESKeyWrap Compute Z = KDF( S, Z_len, Param ); Compute C = AESKeyWrap( Z, m ) as per [RFC3394] VB = convert point V to the octet string Output (MPI(VB) || len(C) || C). I send the encrypted message to the recipient. The recipient gets the shared point by the computation of: S = rV = rvG With Curve25519 function, it is: S = Curve15519(r, V) = Curve15519(r, O) = O Then, the ECDH decryption will be done by recipient correctly. Note that if the ephemeral public key V = O, it can be also decrypted by anyone, because Curve15519(any-value, O) = O. The recipient usually assumes that it is only possible for owner of private key to decrypt. This violates this assumption. Current situation: GnuPG doesn't produce O as ephemeral public key, since it always sets second most significant bit and clears three least significant bits for the scalar v (the tweak). Current libgcrypt dumps core when it tries to compute S to be O. (Fatal: ecdh: Failed to get affine coordinates) So, it's considered safe. Possible improvement: Make libgcrypt return GPG_ERR_INV_DATA when input P=O for ecc_decrypt_raw. Possibly, also check scalar DATA against bit-tweak for ecc_encrypt_raw (or do the tweak by ecc_encrypt_raw itself) to make sure. -- From ian at cypherpunks.ca Mon Feb 29 14:17:00 2016 From: ian at cypherpunks.ca (Ian Goldberg) Date: Mon, 29 Feb 2016 08:17:00 -0500 Subject: Curve25519 ECDH with ephemeral key input O In-Reply-To: <56D3CD0F.3080707@fsij.org> References: <56D3CD0F.3080707@fsij.org> Message-ID: <20160229131700.GZ3611@yoink.cs.uwaterloo.ca> 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)?