Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Leap:15.2:Staging:N
libgcrypt
libgcrypt-PCT-ECC.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File libgcrypt-PCT-ECC.patch of Package libgcrypt
Index: libgcrypt-1.8.2/cipher/ecc.c =================================================================== --- libgcrypt-1.8.2.orig/cipher/ecc.c +++ libgcrypt-1.8.2/cipher/ecc.c @@ -99,7 +99,7 @@ static void *progress_cb_data; /* Local prototypes. */ -static void test_keys (ECC_secret_key * sk, unsigned int nbits); +static int test_keys (ECC_secret_key * sk, unsigned int nbits); static void test_ecdh_only_keys (ECC_secret_key * sk, unsigned int nbits, int flags); static unsigned int ecc_get_nbits (gcry_sexp_t parms); @@ -152,6 +152,7 @@ nist_generate_key (ECC_secret_key *sk, e gcry_random_level_t random_level; gcry_mpi_t x, y; const unsigned int pbits = mpi_get_nbits (E->p); + int free_skEname = 0; point_init (&Q); @@ -176,7 +177,6 @@ nist_generate_key (ECC_secret_key *sk, e else sk->d = _gcry_dsa_gen_k (E->n, random_level); - /* Compute Q. */ _gcry_mpi_ec_mul_point (&Q, sk->d, &E->G, ctx); @@ -190,6 +190,12 @@ nist_generate_key (ECC_secret_key *sk, e point_set (&sk->E.G, &E->G); sk->E.n = mpi_copy (E->n); sk->E.h = mpi_copy (E->h); + if (E->name) + { + free_skEname = 1; + sk->E.name = _gcry_xstrdup(E->name); + } + point_init (&sk->Q); x = mpi_new (pbits); @@ -261,10 +267,16 @@ nist_generate_key (ECC_secret_key *sk, e if ((flags & PUBKEY_FLAG_NO_KEYTEST)) ; /* User requested to skip the test. */ else if (sk->E.model != MPI_EC_MONTGOMERY) - test_keys (sk, nbits - 64); + { + if (test_keys (sk, nbits - 64)) + return GPG_ERR_BAD_SIGNATURE; + } else test_ecdh_only_keys (sk, nbits - 64, flags); + if (free_skEname) + xfree ((void*)sk->E.name); + return 0; } @@ -275,9 +287,10 @@ nist_generate_key (ECC_secret_key *sk, e * test if the information is recuperated. * Second, test with the sign and verify functions. */ -static void +static int test_keys (ECC_secret_key *sk, unsigned int nbits) { + int result = -1; /* Default to failure. */ ECC_public_key pk; gcry_mpi_t test = mpi_new (nbits); mpi_point_struct R_; @@ -297,17 +310,190 @@ test_keys (ECC_secret_key *sk, unsigned _gcry_mpi_randomize (test, nbits, GCRY_WEAK_RANDOM); - if (_gcry_ecc_ecdsa_sign (test, sk, 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, &pk, 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 (sk->E.model, sk->E.dialect, flags, + sk->E.p, sk->E.a, sk->E.b); + if (_gcry_mpi_ec_get_affine (Qx, Qy, &(sk->Q), ctx)) { - log_fatal ("ECDSA operation: sign, verify failed\n"); + 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 (sk->E.name) + { + if (sexp_build (&s_skey, NULL, + "(private-key (ecc (curve %s)(d %m)(q %b)))", + sk->E.name, sk->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", sk->d, sk->E.p, sk->E.a, sk->E.b, sk->E.n, sk->E.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)) + { + 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 (pk.E.name) + { + if (sexp_build (&s_pkey, NULL, + "(public-key (ecc (curve %s)(q %b)))", pk.E.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", pk.E.p, pk.E.a, pk.E.b, pk.E.n, pk.E.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 (&pk.Q); _gcry_ecc_curve_free (&pk.E); @@ -317,6 +503,16 @@ test_keys (ECC_secret_key *sk, unsigned 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.8.2/cipher/pubkey.c =================================================================== --- libgcrypt-1.8.2.orig/cipher/pubkey.c +++ libgcrypt-1.8.2/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.8.2/cipher/pubkey-internal.h =================================================================== --- libgcrypt-1.8.2.orig/cipher/pubkey-internal.h +++ libgcrypt-1.8.2/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.8.2/cipher/pubkey-util.c =================================================================== --- libgcrypt-1.8.2.orig/cipher/pubkey-util.c +++ libgcrypt-1.8.2/cipher/pubkey-util.c @@ -1120,6 +1120,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)
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor