summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cipher/ecc.c81
-rw-r--r--cipher/pubkey-util.c146
-rw-r--r--doc/gcrypt.texi38
-rw-r--r--src/cipher.h2
-rw-r--r--tests/keygen.c18
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);
}