3
0
forked from pool/libgcrypt
libgcrypt/libgcrypt-PCT-ECC.patch
Pedro Monreal Gonzalez dea0435690 Accepting request 868925 from home:pmonrealgonzalez:branches:devel:libraries:c_c++
- Update to 1.9.1
   * *Fix exploitable bug* in hash functions introduced with
     1.9.0. [bsc#1181632, CVE-2021-3345]
   * Return an error if a negative MPI is used with sexp scan
     functions.
   * Check for operational FIPS in the random and KDF functions.
   * Fix compile error on ARMv7 with NEON disabled.
   * Fix self-test in KDF module.
   * Improve assembler checks for better LTO support.
   * Fix 32-bit cross build on x86.
   * Fix non-NEON ARM assembly implementation for SHA512.
   * Fix build problems with the cipher_bulk_ops_t typedef.
   * Fix Ed25519 private key handling for preceding ZEROs.
   * Fix overflow in modular inverse implementation.
   * Fix register access for AVX/AVX2 implementations of Blake2.
   * Add optimized cipher and hash functions for s390x/zSeries.
   * Use hardware bit counting functionx when available.
   * Update DSA functions to match FIPS 186-3.
   * New self-tests for CMACs and KDFs.
   * Add bulk cipher functions for OFB and GCM modes.
- Update libgpg-error required version

- Use the suffix variable correctly in get_hmac_path()
- Rebase libgcrypt-fips_selftest_trigger_file.patch

- Add the global config file /etc/gcrypt/random.conf
  * This file can be used to globally change parameters of the random
    generator with the options: only-urandom and disable-jent.

- Update to 1.9.0:

OBS-URL: https://build.opensuse.org/request/show/868925
OBS-URL: https://build.opensuse.org/package/show/devel:libraries:c_c++/libgcrypt?expand=0&rev=142
2021-02-03 12:44:42 +00:00

343 lines
9.6 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Index: libgcrypt-1.9.0/cipher/ecc.c
===================================================================
--- libgcrypt-1.9.0.orig/cipher/ecc.c
+++ libgcrypt-1.9.0/cipher/ecc.c
@@ -100,7 +100,7 @@ static void *progress_cb_data;
/* Local prototypes. */
-static void test_keys (mpi_ec_t ec, unsigned int nbits);
+static int test_keys (mpi_ec_t ec, unsigned int nbits);
static void test_ecdh_only_keys (mpi_ec_t ec, unsigned int nbits, int flags);
static unsigned int ecc_get_nbits (gcry_sexp_t parms);
@@ -256,8 +256,10 @@ nist_generate_key (mpi_ec_t ec, int flag
else if (ec->model == MPI_EC_MONTGOMERY)
test_ecdh_only_keys (ec, ec->nbits - 63, flags);
else
- test_keys (ec, ec->nbits - 64);
-
+ {
+ if (test_keys (ec, ec->nbits - 64))
+ return GPG_ERR_BAD_SIGNATURE;
+ }
return 0;
}
@@ -268,9 +270,10 @@ nist_generate_key (mpi_ec_t ec, int flag
* test if the information is recuperated.
* Second, test with the sign and verify functions.
*/
-static void
+static int
test_keys (mpi_ec_t ec, unsigned int nbits)
{
+ int result = -1; /* Default to failure. */
gcry_mpi_t test = mpi_new (nbits);
mpi_point_struct R_;
gcry_mpi_t c = mpi_new (nbits);
@@ -285,23 +288,205 @@ test_keys (mpi_ec_t ec, unsigned int nbi
_gcry_mpi_randomize (test, nbits, GCRY_WEAK_RANDOM);
- if (_gcry_ecc_ecdsa_sign (test, ec, r, s, 0, 0) )
- log_fatal ("ECDSA operation: sign failed\n");
+ /* Use the gcry_pk_sign_md API in order to comply with FIPS 140-2,
+ * which requires full signature operation for PCT (hashing +
+ * asymmetric operation). */
+ gcry_sexp_t r_sig = NULL;
+ gcry_sexp_t s_skey = NULL;
+ gcry_sexp_t s_pkey = NULL;
+ gcry_sexp_t s_hash = NULL;
+ gcry_mpi_t s_sig_mpi = NULL;
+ gcry_md_hd_t hd = NULL;
+ unsigned char *buf = NULL;
+ size_t buflen;
+ mpi_ec_t ctx;
+ int flags = 0;
+
+ if (_gcry_md_open (&hd, GCRY_MD_SHA256, 0))
+ {
+ if (DBG_CIPHER)
+ log_debug ("gcry_pk_sign failed: _gcry_md_open\n");
+ }
+
+ _gcry_mpi_aprint (GCRYMPI_FMT_STD, &buf, &buflen, test);
+ _gcry_md_write (hd, buf, buflen);
+
+ xfree (buf);
+ buf = NULL;
- if (_gcry_ecc_ecdsa_verify (test, ec, r, s))
+ sexp_build (&s_hash, NULL, "(data (flags rfc6979)(hash-algo sha256))");
+
+ /* Assemble the point Q from affine coordinates by simple
+ * concatenation. */
+ gcry_mpi_t Qx = NULL;
+ gcry_mpi_t Qy = NULL;
+ Qx = mpi_new (0);
+ Qy = mpi_new (0);
+ ctx = _gcry_mpi_ec_p_internal_new (ec->model, ec->dialect, flags,
+ ec->p, ec->a, ec->b);
+ if (_gcry_mpi_ec_get_affine (Qx, Qy, ec->Q, ctx))
+ {
+ if (DBG_CIPHER)
+ log_debug ("ecdh: Failed to get affine coordinates for Q\n");
+ }
+
+ unsigned char *rawqx, *rawqy;
+ unsigned int rawqxlen, rawqylen;
+ rawqx = _gcry_mpi_get_buffer (Qx, 0, &rawqxlen, NULL);
+ rawqy = _gcry_mpi_get_buffer (Qy, 0, &rawqylen, NULL);
+
+ if (rawqxlen != rawqylen)
+ {
+ if (rawqxlen < rawqylen)
+ {
+ size_t diff = rawqylen - rawqxlen;
+ unsigned char *zeros = xmalloc (rawqxlen + diff);
+ memset (zeros, 0, rawqxlen + diff);
+ memmove (zeros + diff, rawqx, rawqxlen);
+ xfree (rawqx);
+ rawqx = zeros;
+ rawqxlen += diff;
+ }
+ if (rawqylen < rawqxlen)
+ {
+ size_t diff = rawqxlen - rawqylen;
+ unsigned char *zeros = xmalloc (rawqylen + diff);
+ memset (zeros, 0, rawqylen + diff);
+ memmove (zeros + diff, rawqy, rawqylen);
+ xfree (rawqy);
+ rawqy = zeros;
+ rawqylen += diff;
+ }
+ }
+
+ unsigned char q[1 + rawqxlen + rawqxlen];
+ size_t qlen;
+ memset (&q, 0, sizeof(q));
+ *q = 4;
+ memcpy (q + 1, rawqx, rawqxlen);
+ memcpy (q + 1 + rawqxlen, rawqy, rawqylen);
+ qlen = 1 + rawqxlen + rawqylen;
+
+ _gcry_mpi_release (Qx);
+ _gcry_mpi_release (Qy);
+ xfree (rawqx);
+ xfree (rawqy);
+
+ /* build ECC private key sexp in s_skey */
+ if (ec->name)
+ {
+ if (sexp_build (&s_skey, NULL,
+ "(private-key (ecc (curve %s)(d %m)(q %b)))",
+ ec->name, ec->d, qlen, q))
+ {
+ if (DBG_CIPHER)
+ log_debug ("ecc: Failed to build sexp for private key.\n");
+ }
+ }
+ else
+ {
+ if (sexp_build (&s_skey, NULL,
+ "(private-key"
+ " (ecc (curve %s)(d %m)(p %m)(a %m)(b %m)(n %m)(h %m)(q %b)))",
+ "NIST P-512", ec->d, ec->p, ec->a, ec->b, ec->n, ec->h,
+ qlen, q))
+ {
+ if (DBG_CIPHER)
+ log_debug ("ecc: Failed to build sexp for private key.\n");
+ }
+ }
+ if (_gcry_pk_sign_md (&r_sig, hd, s_hash, s_skey))
{
- log_fatal ("ECDSA operation: sign, verify failed\n");
+ if (DBG_CIPHER)
+ log_debug ("ecc: gcry_pk_sign failed\n");
+ goto leave;
+ }
+
+ /* Check that the signature and the original test differ. */
+ if (_gcry_sexp_extract_param (r_sig, NULL, "s", &s_sig_mpi, NULL))
+ {
+ if (DBG_CIPHER)
+ log_debug ("extracting signature data failed\n");
+ goto leave;
+ }
+
+ if (!mpi_cmp (s_sig_mpi, test))
+ {
+ if (DBG_CIPHER)
+ log_debug ("Signature failed\n");
+ goto leave; /* Signature and test match but should not. */
+ }
+
+ /* verify */
+ /* build public key sexp in s_pkey */
+ if (ec->name)
+ {
+ if (sexp_build (&s_pkey, NULL,
+ "(public-key (ecc (curve %s)(q %b)))", ec->name, qlen, q))
+ {
+ if (DBG_CIPHER)
+ log_debug ("ecc: Failed to build sexp for public key.\n");
+ }
+ }
+ else
+ {
+ if (sexp_build (&s_pkey, NULL,
+ "(public-key"
+ " (ecc (curve %s)(p %m)(a %m)(b %m)(n %m)(h %m)(q %b)))",
+ "NIST P-512", ec->p, ec->a, ec->b, ec->n, ec->h, qlen, q))
+ {
+ if (DBG_CIPHER)
+ log_debug ("ecc: Failed to build sexp for private key.\n");
+ }
+ }
+
+ _gcry_md_close (hd);
+
+ if (_gcry_md_open (&hd, GCRY_MD_SHA256, 0))
+ {
+ if (DBG_CIPHER)
+ log_debug ("gcry_pk_verify failed: _gcry_md_open\n");
+ }
+
+ _gcry_mpi_aprint (GCRYMPI_FMT_STD, &buf, &buflen, test);
+ _gcry_md_write (hd, buf, buflen);
+
+ xfree (buf);
+ buf = NULL;
+
+ /* verify the signature */
+ if (_gcry_pk_verify_md (r_sig, hd, s_hash, s_pkey))
+ {
+ if (DBG_CIPHER)
+ log_debug ("ecc: gcry_pk_verify failed\n");
+ goto leave; /* Signature does not match. */
}
if (DBG_CIPHER)
- log_debug ("ECDSA operation: sign, verify ok.\n");
+ {
+ if (DBG_CIPHER)
+ log_debug ("ECDSA operation: sign, verify ok.\n");
+ }
+
+ result = 0; /* The test succeeded. */
+ leave:
point_free (&R_);
mpi_free (s);
mpi_free (r);
mpi_free (out);
mpi_free (c);
mpi_free (test);
+
+ _gcry_sexp_release (r_sig);
+ _gcry_sexp_release (s_skey);
+ _gcry_sexp_release (s_pkey);
+ _gcry_sexp_release (s_hash);
+ _gcry_mpi_release (s_sig_mpi);
+ _gcry_md_close (hd);
+ xfree (ctx);
+
+ return result;
}
Index: libgcrypt-1.9.0/cipher/pubkey.c
===================================================================
--- libgcrypt-1.9.0.orig/cipher/pubkey.c
+++ libgcrypt-1.9.0/cipher/pubkey.c
@@ -390,6 +390,7 @@ calculate_hash (gcry_md_hd_t hd, gcry_se
gcry_err_code_t rc;
const unsigned char *digest;
int algo;
+ const char *flags;
if (!hd)
return 0;
@@ -398,16 +399,21 @@ calculate_hash (gcry_md_hd_t hd, gcry_se
if (rc)
return rc;
+ rc = _gcry_pk_util_get_flags (*s_hash, &flags);
+ if (rc)
+ return rc;
+
digest = _gcry_md_read(hd, algo);
if (!digest)
return GPG_ERR_DIGEST_ALGO;
rc = _gcry_sexp_build (s_hash, NULL,
- "(data (flags pkcs1)(hash %s %b))",
+ "(data (flags %s)(hash %s %b))", flags,
_gcry_md_algo_name(algo),
(int) _gcry_md_get_algo_dlen(algo),
digest);
+ xfree ((void *)flags);
return rc;
}
Index: libgcrypt-1.9.0/cipher/pubkey-internal.h
===================================================================
--- libgcrypt-1.9.0.orig/cipher/pubkey-internal.h
+++ libgcrypt-1.9.0/cipher/pubkey-internal.h
@@ -45,6 +45,8 @@ gcry_err_code_t _gcry_pk_util_data_to_mp
struct pk_encoding_ctx *ctx);
gcry_err_code_t _gcry_pk_util_get_algo (gcry_sexp_t input,
int *algo);
+gcry_err_code_t _gcry_pk_util_get_flags (gcry_sexp_t input,
+ const char **flags);
Index: libgcrypt-1.9.0/cipher/pubkey-util.c
===================================================================
--- libgcrypt-1.9.0.orig/cipher/pubkey-util.c
+++ libgcrypt-1.9.0/cipher/pubkey-util.c
@@ -1159,6 +1159,40 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t i
return rc;
}
+gcry_err_code_t
+_gcry_pk_util_get_flags (gcry_sexp_t input, const char **flags)
+{
+ gcry_err_code_t rc = 0;
+ gcry_sexp_t ldata, list = NULL;
+
+ ldata = sexp_find_token (input, "data", 0);
+ if (!ldata)
+ {
+ rc = GPG_ERR_INV_OBJ;
+ goto leave;
+ }
+
+ list = sexp_find_token (ldata, "flags", 0);
+ if (!list)
+ {
+ rc = GPG_ERR_INV_OBJ;
+ goto leave;
+ }
+
+ /* FIXME: gets only the first flag */
+ *flags = sexp_nth_string (list, 1);
+ if (!*flags)
+ {
+ rc = GPG_ERR_NO_OBJ;
+ goto leave;
+ }
+
+ leave:
+ sexp_release (ldata);
+ sexp_release (list);
+
+ return rc;
+}
gcry_err_code_t
_gcry_pk_util_get_algo (gcry_sexp_t input, int *algo)