diff options
-rw-r--r-- | cipher/ecc.c | 81 | ||||
-rw-r--r-- | cipher/pubkey-util.c | 146 | ||||
-rw-r--r-- | doc/gcrypt.texi | 38 | ||||
-rw-r--r-- | src/cipher.h | 2 | ||||
-rw-r--r-- | tests/keygen.c | 18 |
5 files changed, 201 insertions, 84 deletions
diff --git a/cipher/ecc.c b/cipher/ecc.c index dca04234..5a528298 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -423,14 +423,6 @@ ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey) return GPG_ERR_INV_OBJ; /* No curve name or value too large. */ } - /* Parse the optional transient-key flag. */ - l1 = gcry_sexp_find_token (genparms, "transient-key", 0); - if (l1) - { - flags |= PUBKEY_FLAG_TRANSIENT_KEY; - gcry_sexp_release (l1); - } - /* Parse the optional flags list. */ l1 = gcry_sexp_find_token (genparms, "flags", 0); if (l1) @@ -441,6 +433,14 @@ ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey) goto leave; } + /* Parse the deprecated optional transient-key flag. */ + l1 = gcry_sexp_find_token (genparms, "transient-key", 0); + if (l1) + { + flags |= PUBKEY_FLAG_TRANSIENT_KEY; + gcry_sexp_release (l1); + } + /* NBITS is required if no curve name has been given. */ if (!nbits && !curve_name) return GPG_ERR_NO_OBJ; /* No NBITS parameter. */ @@ -524,24 +524,43 @@ ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey) goto leave; } - if (ed25519_with_ecdsa) + if ((flags & PUBKEY_FLAG_NOPARAM) || ed25519_with_ecdsa) { - rc = gcry_sexp_build (&curve_flags, NULL, "(flags ecdsa)"); + rc = gcry_sexp_build + (&curve_flags, NULL, + ((flags & PUBKEY_FLAG_NOPARAM) && ed25519_with_ecdsa)? + "(flags noparam ecdsa)" : + ((flags & PUBKEY_FLAG_NOPARAM))? + "(flags noparam)" : + "(flags ecdsa)"); if (rc) goto leave; } - rc = gcry_sexp_build (r_skey, NULL, - "(key-data" - " (public-key" - " (ecc%S%S(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)))" - " (private-key" - " (ecc%S%S(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)(d%m)))" - " )", - curve_info, curve_flags, - sk.E.p, sk.E.a, sk.E.b, base, sk.E.n, public, - curve_info, curve_flags, - sk.E.p, sk.E.a, sk.E.b, base, sk.E.n, public, secret); + if ((flags & PUBKEY_FLAG_NOPARAM) && E.name) + rc = gcry_sexp_build (r_skey, NULL, + "(key-data" + " (public-key" + " (ecc%S%S(q%m)))" + " (private-key" + " (ecc%S%S(q%m)(d%m)))" + " )", + curve_info, curve_flags, + public, + curve_info, curve_flags, + public, secret); + else + rc = gcry_sexp_build (r_skey, NULL, + "(key-data" + " (public-key" + " (ecc%S%S(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)))" + " (private-key" + " (ecc%S%S(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)(d%m)))" + " )", + curve_info, curve_flags, + sk.E.p, sk.E.a, sk.E.b, base, sk.E.n, public, + curve_info, curve_flags, + sk.E.p, sk.E.a, sk.E.b, base, sk.E.n, public, secret); if (rc) goto leave; @@ -709,9 +728,13 @@ ecc_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms) /* * Extract the key. */ - rc = _gcry_sexp_extract_param (keyparms, NULL, "-p?a?b?g?n?/q?+d", - &sk.E.p, &sk.E.a, &sk.E.b, &mpi_g, &sk.E.n, - &mpi_q, &sk.d, NULL); + if ((ctx.flags & PUBKEY_FLAG_NOPARAM)) + rc = _gcry_sexp_extract_param (keyparms, NULL, "/q?+d", + &mpi_q, &sk.d, NULL); + else + rc = _gcry_sexp_extract_param (keyparms, NULL, "-p?a?b?g?n?/q?+d", + &sk.E.p, &sk.E.a, &sk.E.b, &mpi_g, &sk.E.n, + &mpi_q, &sk.d, NULL); if (rc) goto leave; if (mpi_g) @@ -871,9 +894,13 @@ ecc_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms) /* * Extract the key. */ - rc = _gcry_sexp_extract_param (s_keyparms, NULL, "-p?a?b?g?n?/q?", - &pk.E.p, &pk.E.a, &pk.E.b, &mpi_g, &pk.E.n, - &mpi_q, NULL); + if ((ctx.flags & PUBKEY_FLAG_NOPARAM)) + rc = _gcry_sexp_extract_param (s_keyparms, NULL, "/q", + &mpi_q, NULL); + else + rc = _gcry_sexp_extract_param (s_keyparms, NULL, "-p?a?b?g?n?/q", + &pk.E.p, &pk.E.a, &pk.E.b, &mpi_g, &pk.E.n, + &mpi_q, NULL); if (rc) goto leave; if (mpi_g) diff --git a/cipher/pubkey-util.c b/cipher/pubkey-util.c index 0db5840b..88d6bb69 100644 --- a/cipher/pubkey-util.c +++ b/cipher/pubkey-util.c @@ -47,7 +47,7 @@ pss_verify_cmp (void *opaque, gcry_mpi_t tmp) /* Parser for a flag list. On return the encoding is stored at - R_ENCODING and the flags are stored at R_FLAGS. if any of them is + R_ENCODING and the flags are stored at R_FLAGS. If any of them is not needed, NULL may be passed. The function returns 0 on success or an error code. */ gpg_err_code_t @@ -65,61 +65,99 @@ _gcry_pk_util_parse_flaglist (gcry_sexp_t list, { s = gcry_sexp_nth_data (list, i, &n); if (!s) - ; /* not a data element*/ - else if (n == 7 && !memcmp (s, "rfc6979", 7)) - { - flags |= PUBKEY_FLAG_RFC6979; - } - else if (n == 5 && !memcmp (s, "eddsa", 5)) - { - encoding = PUBKEY_ENC_RAW; - flags |= PUBKEY_FLAG_EDDSA; - } - else if (n == 5 && !memcmp (s, "ecdsa", 5)) - { - flags |= PUBKEY_FLAG_ECDSA; - } - else if (n == 4 && !memcmp (s, "gost", 4)) - { - encoding = PUBKEY_ENC_RAW; - flags |= PUBKEY_FLAG_GOST; - } - else if (n == 3 && !memcmp (s, "raw", 3) - && encoding == PUBKEY_ENC_UNKNOWN) - { - encoding = PUBKEY_ENC_RAW; - flags |= PUBKEY_FLAG_RAW_FLAG; /* Explicitly given. */ - } - else if (n == 5 && !memcmp (s, "pkcs1", 5) - && encoding == PUBKEY_ENC_UNKNOWN) - { - encoding = PUBKEY_ENC_PKCS1; - flags |= PUBKEY_FLAG_FIXEDLEN; - } - else if (n == 4 && !memcmp (s, "oaep", 4) - && encoding == PUBKEY_ENC_UNKNOWN) - { - encoding = PUBKEY_ENC_OAEP; - flags |= PUBKEY_FLAG_FIXEDLEN; - } - else if (n == 3 && !memcmp (s, "pss", 3) - && encoding == PUBKEY_ENC_UNKNOWN) + continue; /* Not a data element. */ + + switch (n) { - encoding = PUBKEY_ENC_PSS; - flags |= PUBKEY_FLAG_FIXEDLEN; + case 3: + if (!memcmp (s, "pss", 3) && encoding == PUBKEY_ENC_UNKNOWN) + { + encoding = PUBKEY_ENC_PSS; + flags |= PUBKEY_FLAG_FIXEDLEN; + } + else if (!memcmp (s, "raw", 3) && encoding == PUBKEY_ENC_UNKNOWN) + { + encoding = PUBKEY_ENC_RAW; + flags |= PUBKEY_FLAG_RAW_FLAG; /* Explicitly given. */ + } + else + rc = GPG_ERR_INV_FLAG; + break; + + case 4: + if (!memcmp (s, "comp", 4)) + flags |= PUBKEY_FLAG_COMP; + else if (!memcmp (s, "oaep", 4) && encoding == PUBKEY_ENC_UNKNOWN) + { + encoding = PUBKEY_ENC_OAEP; + flags |= PUBKEY_FLAG_FIXEDLEN; + } + else if (!memcmp (s, "gost", 4)) + { + encoding = PUBKEY_ENC_RAW; + flags |= PUBKEY_FLAG_GOST; + } + else + rc = GPG_ERR_INV_FLAG; + break; + + case 5: + if (!memcmp (s, "eddsa", 5)) + { + encoding = PUBKEY_ENC_RAW; + flags |= PUBKEY_FLAG_EDDSA; + } + else if (!memcmp (s, "ecdsa", 5)) + { + flags |= PUBKEY_FLAG_ECDSA; + } + else if (!memcmp (s, "pkcs1", 5) && encoding == PUBKEY_ENC_UNKNOWN) + { + encoding = PUBKEY_ENC_PKCS1; + flags |= PUBKEY_FLAG_FIXEDLEN; + } + else + rc = GPG_ERR_INV_FLAG; + break; + + case 7: + if (!memcmp (s, "rfc6979", 7)) + flags |= PUBKEY_FLAG_RFC6979; + else if (!memcmp (s, "noparam", 7)) + flags |= PUBKEY_FLAG_NOPARAM; + else + rc = GPG_ERR_INV_FLAG; + break; + + case 8: + if (!memcmp (s, "use-x931", 8)) + flags |= PUBKEY_FLAG_USE_X931; + else + rc = GPG_ERR_INV_FLAG; + break; + + case 11: + if (!memcmp (s, "no-blinding", 11)) + flags |= PUBKEY_FLAG_NO_BLINDING; + else if (!memcmp (s, "use-fips186", 11)) + flags |= PUBKEY_FLAG_USE_FIPS186; + else + rc = GPG_ERR_INV_FLAG; + break; + + case 13: + if (!memcmp (s, "use-fips186-2", 13)) + flags |= PUBKEY_FLAG_USE_FIPS186_2; + else if (!memcmp (s, "transient-key", 13)) + flags |= PUBKEY_FLAG_TRANSIENT_KEY; + else + rc = GPG_ERR_INV_FLAG; + break; + + default: + rc = GPG_ERR_INV_FLAG; + break; } - else if (n == 11 && ! memcmp (s, "no-blinding", 11)) - flags |= PUBKEY_FLAG_NO_BLINDING; - else if (n == 13 && ! memcmp (s, "transient-key", 13)) - flags |= PUBKEY_FLAG_TRANSIENT_KEY; - else if (n == 8 && ! memcmp (s, "use-x931", 8)) - flags |= PUBKEY_FLAG_USE_X931; - else if (n == 11 && ! memcmp (s, "use-fips186", 11)) - flags |= PUBKEY_FLAG_USE_FIPS186; - else if (n == 13 && ! memcmp (s, "use-fips186-2", 13)) - flags |= PUBKEY_FLAG_USE_FIPS186_2; - else - rc = GPG_ERR_INV_FLAG; } if (r_flags) diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index 6dcb4b13..4a202ddb 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -2230,6 +2230,14 @@ named `flags'. Flag names are case-sensitive. The following flags are known: @table @code + +@item comp +@cindex comp +If supported and not yet the default return ECC points in compact +(compressed) representation. The compact representation requires a +small overhead before a point can be used but halves the size of a to +be conveyed public key. + @item pkcs1 @cindex PKCS1 Use PKCS#1 block type 2 padding for encryption, block type 1 padding @@ -2264,6 +2272,16 @@ order to prevent leaking of secret information. Blinding is only implemented by RSA, but it might be implemented by other algorithms in the future as well, when necessary. +@item noparam +@cindex noparam +For ECC key generation do not return the domain parameters but only +the name of the curve. For ECC signing and verification ignore any +provided domain parameters of the public or private key and use only +the curve name. It is more secure to rely on the curve name and thus +use the curve parameters as known by Libgcrypt. This option shouild +have been the default but for backward compatibility reasons this is +not possible. It is best to always use this flag with ECC keys. + @item transient-key @cindex transient-key This flag is only meaningful for RSA, DSA, and ECC key generation. If @@ -2836,7 +2854,7 @@ is in general not recommended. @example (genkey (ecc - (flags transient-key ecdsa))) + (flags noparam transient-key ecdsa))) @end example @item transient-key @@ -2856,7 +2874,8 @@ private and public keys are returned in one container and may be accompanied by some miscellaneous information. @noindent -As an example, here is what the Elgamal key generation returns: +Here are two examples; the first for Elgamal and the second for +elliptic curve key generation: @example (key-data @@ -2875,6 +2894,21 @@ As an example, here is what the Elgamal key generation returns: (pm1-factors @var{n1 n2 ... nn})) @end example +@example +(key-data + (public-key + (ecc + (curve Ed25519) + (flags noparam) + (q @var{q-value}))) + (private-key + (ecc + (curve Ed25519) + (flags noparam) + (q @var{q-value}) + (d @var{d-value})))) +@end example + @noindent As you can see, some of the information is duplicated, but this provides an easy way to extract either the public or the private key. diff --git a/src/cipher.h b/src/cipher.h index 20818ba8..551dc66a 100644 --- a/src/cipher.h +++ b/src/cipher.h @@ -38,6 +38,8 @@ #define PUBKEY_FLAG_ECDSA (1 << 9) #define PUBKEY_FLAG_EDDSA (1 << 10) #define PUBKEY_FLAG_GOST (1 << 11) +#define PUBKEY_FLAG_NOPARAM (1 << 12) +#define PUBKEY_FLAG_COMP (1 << 12) enum pk_operation diff --git a/tests/keygen.c b/tests/keygen.c index 5ab8e9d6..18fe2117 100644 --- a/tests/keygen.c +++ b/tests/keygen.c @@ -375,7 +375,8 @@ check_ecc_keys (void) if (verbose) show ("creating ECC key using curve %s\n", curves[testno]); rc = gcry_sexp_build (&keyparm, NULL, - "(genkey(ecc(curve %s)))", curves[testno]); + "(genkey(ecc(curve %s)(flags noparam)))", + curves[testno]); if (rc) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); @@ -410,6 +411,21 @@ check_ecc_keys (void) if (verbose > 1) show_sexp ("ECC key:\n", key); + if (verbose) + show ("creating ECC key using curve Ed25519 for ECDSA\n"); + rc = gcry_sexp_build (&keyparm, NULL, + "(genkey(ecc(curve Ed25519)(flags noparam ecdsa)))"); + if (rc) + die ("error creating S-expression: %s\n", gpg_strerror (rc)); + rc = gcry_pk_genkey (&key, keyparm); + gcry_sexp_release (keyparm); + if (rc) + die ("error generating ECC key using curve Ed25519 for ECDSA: %s\n", + gpg_strerror (rc)); + + if (verbose > 1) + show_sexp ("ECC key:\n", key); + gcry_sexp_release (key); } |