mirror of
git://git.gnupg.org/gnupg.git
synced 2025-02-01 16:33:02 +01:00
scd: EdDSA support.
* scd/app-openpgp.c (KEY_TYPE_EDDSA, CURVE_ED25519): New. (struct app_local_s): Add eddsa. (get_algo_byte, store_fpr): Support KEY_TYPE_EDDSA. (get_ecc_key_parameters, get_curve_name): Support CURVE_ED25519. (send_key_attr, get_public_key): Support KEY_TYPE_EDDSA. (build_ecc_privkey_template): Rename as it supports both of ECDSA and EdDSA. (ecc_writekey): Rename. Support CURVE_ED25519, too. (do_writekey): Follow the change of ecc_writekey. (do_auth): Support KEY_TYPE_EDDSA. (parse_ecc_curve): Support CURVE_ED25519. Bug fix for other curves. (parse_algorithm_attribute): Bug fix for ECDH. Support EdDSA.
This commit is contained in:
parent
db85feceaf
commit
3132bd90dc
@ -122,6 +122,7 @@ typedef enum
|
|||||||
{
|
{
|
||||||
KEY_TYPE_ECDH,
|
KEY_TYPE_ECDH,
|
||||||
KEY_TYPE_ECDSA,
|
KEY_TYPE_ECDSA,
|
||||||
|
KEY_TYPE_EDDSA,
|
||||||
KEY_TYPE_RSA,
|
KEY_TYPE_RSA,
|
||||||
}
|
}
|
||||||
key_type_t;
|
key_type_t;
|
||||||
@ -146,7 +147,8 @@ enum
|
|||||||
CURVE_NIST_P384,
|
CURVE_NIST_P384,
|
||||||
CURVE_NIST_P521,
|
CURVE_NIST_P521,
|
||||||
CURVE_SEC_P256K1,
|
CURVE_SEC_P256K1,
|
||||||
CURVE_UNKOWN,
|
CURVE_ED25519,
|
||||||
|
CURVE_UNKNOWN,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -235,6 +237,9 @@ struct app_local_s {
|
|||||||
struct {
|
struct {
|
||||||
int curve;
|
int curve;
|
||||||
} ecdsa;
|
} ecdsa;
|
||||||
|
struct {
|
||||||
|
int curve;
|
||||||
|
} eddsa;
|
||||||
struct {
|
struct {
|
||||||
int curve;
|
int curve;
|
||||||
int hashalgo;
|
int hashalgo;
|
||||||
@ -746,6 +751,8 @@ get_algo_byte (key_type_t key_type)
|
|||||||
return 19;
|
return 19;
|
||||||
else if (key_type == KEY_TYPE_ECDH)
|
else if (key_type == KEY_TYPE_ECDH)
|
||||||
return 18;
|
return 18;
|
||||||
|
else if (key_type == KEY_TYPE_EDDSA)
|
||||||
|
return 105; /* (experimental) */
|
||||||
else
|
else
|
||||||
return 1; /* RSA */
|
return 1; /* RSA */
|
||||||
}
|
}
|
||||||
@ -770,7 +777,8 @@ store_fpr (app_t app, int keynumber, u32 timestamp,
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
n = 6; /* key packet version, 4-byte timestamps, and algorithm */
|
n = 6; /* key packet version, 4-byte timestamps, and algorithm */
|
||||||
if (key_type == KEY_TYPE_RSA || key_type == KEY_TYPE_ECDSA)
|
if (key_type == KEY_TYPE_RSA || key_type == KEY_TYPE_ECDSA
|
||||||
|
|| key_type == KEY_TYPE_EDDSA)
|
||||||
argc = 2;
|
argc = 2;
|
||||||
else if (key_type == KEY_TYPE_ECDH)
|
else if (key_type == KEY_TYPE_ECDH)
|
||||||
argc = 3;
|
argc = 3;
|
||||||
@ -935,11 +943,21 @@ get_ecc_key_parameters (int curve, int *r_n_bits, const char **r_curve_oid)
|
|||||||
*r_n_bits = 521;
|
*r_n_bits = 521;
|
||||||
*r_curve_oid = "1.3.132.0.35";
|
*r_curve_oid = "1.3.132.0.35";
|
||||||
}
|
}
|
||||||
else
|
else if (curve == CURVE_SEC_P256K1)
|
||||||
{
|
{
|
||||||
*r_n_bits = 256;
|
*r_n_bits = 256;
|
||||||
*r_curve_oid = "1.3.132.0.10";
|
*r_curve_oid = "1.3.132.0.10";
|
||||||
}
|
}
|
||||||
|
else if (curve == CURVE_ED25519)
|
||||||
|
{
|
||||||
|
*r_n_bits = 255;
|
||||||
|
*r_curve_oid = "1.3.6.1.4.1.11591.15.1";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*r_n_bits = 0;
|
||||||
|
*r_curve_oid = "1.3.6.1.4.1.11591.2.12242973"; /* gnu.gnupg.badoid */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -973,6 +991,13 @@ send_key_attr (ctrl_t ctrl, app_t app, const char *keyword, int number)
|
|||||||
app->app_local->keyattr[number].ecdh.hashalgo,
|
app->app_local->keyattr[number].ecdh.hashalgo,
|
||||||
app->app_local->keyattr[number].ecdh.cipheralgo);
|
app->app_local->keyattr[number].ecdh.cipheralgo);
|
||||||
}
|
}
|
||||||
|
else if (app->app_local->keyattr[number].key_type == KEY_TYPE_EDDSA)
|
||||||
|
{
|
||||||
|
get_ecc_key_parameters (app->app_local->keyattr[number].eddsa.curve,
|
||||||
|
&n_bits, &curve_oid);
|
||||||
|
snprintf (buffer, sizeof buffer, "%d 105 %u %s",
|
||||||
|
number+1, n_bits, curve_oid);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
snprintf (buffer, sizeof buffer, "0 0 UNKNOWN");
|
snprintf (buffer, sizeof buffer, "0 0 UNKNOWN");
|
||||||
|
|
||||||
@ -1282,8 +1307,12 @@ get_curve_name (int curve)
|
|||||||
return "NIST P-384";
|
return "NIST P-384";
|
||||||
else if (curve == CURVE_NIST_P521)
|
else if (curve == CURVE_NIST_P521)
|
||||||
return "NIST P-521";
|
return "NIST P-521";
|
||||||
else
|
else if (curve == CURVE_SEC_P256K1)
|
||||||
return "secp256k1";
|
return "secp256k1";
|
||||||
|
else if (curve == CURVE_ED25519)
|
||||||
|
return "Ed25519";
|
||||||
|
else
|
||||||
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1455,7 +1484,8 @@ get_public_key (app_t app, int keyno)
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
/* Prepend numbers with a 0 if needed. */
|
/* Prepend numbers with a 0 if needed. */
|
||||||
if (mlen && (*m & 0x80))
|
if (app->app_local->keyattr[keyno].key_type != KEY_TYPE_EDDSA
|
||||||
|
&& mlen && (*m & 0x80))
|
||||||
{
|
{
|
||||||
*mbuf = 0;
|
*mbuf = 0;
|
||||||
memcpy (mbuf+1, m, mlen);
|
memcpy (mbuf+1, m, mlen);
|
||||||
@ -1511,6 +1541,29 @@ get_public_key (app_t app, int keyno)
|
|||||||
|
|
||||||
len = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, NULL, 0);
|
len = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, NULL, 0);
|
||||||
|
|
||||||
|
keybuf = xtrymalloc (len);
|
||||||
|
if (!keybuf)
|
||||||
|
{
|
||||||
|
gcry_sexp_release (s_pkey);
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, keybuf, len);
|
||||||
|
gcry_sexp_release (s_pkey);
|
||||||
|
}
|
||||||
|
else if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_EDDSA)
|
||||||
|
{
|
||||||
|
const char *curve_name
|
||||||
|
= get_curve_name (app->app_local->keyattr[keyno].eddsa.curve);
|
||||||
|
|
||||||
|
err = gcry_sexp_build (&s_pkey, NULL,
|
||||||
|
"(public-key(ecc(curve%s)(flags eddsa)(q%b)))",
|
||||||
|
curve_name, mlen, mbuf);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
len = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, NULL, 0);
|
||||||
|
|
||||||
keybuf = xtrymalloc (len);
|
keybuf = xtrymalloc (len);
|
||||||
if (!keybuf)
|
if (!keybuf)
|
||||||
{
|
{
|
||||||
@ -2695,9 +2748,9 @@ build_privkey_template (app_t app, int keyno,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
build_ecdsa_privkey_template (app_t app, int keyno,
|
build_ecc_privkey_template (app_t app, int keyno,
|
||||||
const unsigned char *ecc_d, size_t ecc_d_len,
|
const unsigned char *ecc_d, size_t ecc_d_len,
|
||||||
unsigned char **result, size_t *resultlen)
|
unsigned char **result, size_t *resultlen)
|
||||||
{
|
{
|
||||||
unsigned char privkey[2];
|
unsigned char privkey[2];
|
||||||
size_t privkey_len;
|
size_t privkey_len;
|
||||||
@ -3189,9 +3242,9 @@ ecdh_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **),
|
|||||||
|
|
||||||
|
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
ecdsa_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **),
|
ecc_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **),
|
||||||
void *pincb_arg, int keyno,
|
void *pincb_arg, int keyno,
|
||||||
const unsigned char *buf, size_t buflen, int depth)
|
const unsigned char *buf, size_t buflen, int depth)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
const unsigned char *tok;
|
const unsigned char *tok;
|
||||||
@ -3204,10 +3257,14 @@ ecdsa_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **),
|
|||||||
size_t template_len;
|
size_t template_len;
|
||||||
unsigned char fprbuf[20];
|
unsigned char fprbuf[20];
|
||||||
u32 created_at = 0;
|
u32 created_at = 0;
|
||||||
int curve = CURVE_UNKOWN;
|
int curve = CURVE_UNKNOWN;
|
||||||
|
|
||||||
/* (private-key(ecdsa(curve%s)(q%m)(d%m))): curve = "1.2.840.10045.3.1.7" */
|
/* (private-key(ecdsa(curve%s)(q%m)(d%m))(created-at%d)):
|
||||||
/* (private-key(ecc(curve%s)(q%m)(d%m))): curve = "secp256k1" */
|
curve = "1.2.840.10045.3.1.7" */
|
||||||
|
/* (private-key(ecc(curve%s)(q%m)(d%m))(created-at%d)):
|
||||||
|
curve = "secp256k1" */
|
||||||
|
/* (private-key(ecc(curve%s)(flags eddsa)(q%m)(d%m))(created-at%d)):
|
||||||
|
curve = "Ed25519" */
|
||||||
last_depth1 = depth;
|
last_depth1 = depth;
|
||||||
while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))
|
while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))
|
||||||
&& depth && depth >= last_depth1)
|
&& depth && depth >= last_depth1)
|
||||||
@ -3229,33 +3286,34 @@ ecdsa_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **),
|
|||||||
curve = CURVE_NIST_P256;
|
curve = CURVE_NIST_P256;
|
||||||
else if (tok && toklen == 9 && !memcmp (tok, "secp256k1", 9))
|
else if (tok && toklen == 9 && !memcmp (tok, "secp256k1", 9))
|
||||||
curve = CURVE_SEC_P256K1;
|
curve = CURVE_SEC_P256K1;
|
||||||
|
else if (tok && toklen == 7 && !memcmp (tok, "Ed25519", 7))
|
||||||
|
curve = CURVE_ED25519;
|
||||||
}
|
}
|
||||||
else if (tok && toklen == 1)
|
else if (tok && toklen == 1)
|
||||||
{
|
{
|
||||||
const unsigned char **mpi;
|
const unsigned char **buf2;
|
||||||
size_t *mpi_len;
|
size_t *buf2len;
|
||||||
|
|
||||||
switch (*tok)
|
switch (*tok)
|
||||||
{
|
{
|
||||||
case 'q': mpi = &ecc_q; mpi_len = &ecc_q_len; break;
|
case 'q': buf2 = &ecc_q; buf2len = &ecc_q_len; break;
|
||||||
case 'd': mpi = &ecc_d; mpi_len = &ecc_d_len; break;
|
case 'd': buf2 = &ecc_d; buf2len = &ecc_d_len; break;
|
||||||
default: mpi = NULL; mpi_len = NULL; break;
|
default: buf2 = NULL; buf2len = NULL; break;
|
||||||
}
|
}
|
||||||
if (mpi && *mpi)
|
if (buf2 && *buf2)
|
||||||
{
|
{
|
||||||
err = gpg_error (GPG_ERR_DUP_VALUE);
|
err = gpg_error (GPG_ERR_DUP_VALUE);
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
|
if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
|
||||||
goto leave;
|
goto leave;
|
||||||
if (tok && mpi)
|
if (tok && buf2 && curve != CURVE_ED25519)
|
||||||
{
|
/* It's MPI. Strip off leading zero bytes and save. */
|
||||||
/* Strip off leading zero bytes and save. */
|
for (;toklen && !*tok; toklen--, tok++)
|
||||||
for (;toklen && !*tok; toklen--, tok++)
|
;
|
||||||
;
|
|
||||||
*mpi = tok;
|
*buf2 = tok;
|
||||||
*mpi_len = toklen;
|
*buf2len = toklen;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* Skip until end of list. */
|
/* Skip until end of list. */
|
||||||
last_depth2 = depth;
|
last_depth2 = depth;
|
||||||
@ -3322,9 +3380,9 @@ ecdsa_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **),
|
|||||||
the OpenPGP card specs version 2.0. */
|
the OpenPGP card specs version 2.0. */
|
||||||
int exmode;
|
int exmode;
|
||||||
|
|
||||||
err = build_ecdsa_privkey_template (app, keyno,
|
err = build_ecc_privkey_template (app, keyno,
|
||||||
ecc_d, ecc_d_len,
|
ecc_d, ecc_d_len,
|
||||||
&template, &template_len);
|
&template, &template_len);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
@ -3353,11 +3411,14 @@ ecdsa_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **),
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = store_fpr (app, keyno, created_at, fprbuf, app->card_version,
|
err = store_fpr (app, keyno, created_at, fprbuf, app->card_version,
|
||||||
KEY_TYPE_ECDSA,
|
curve == CURVE_ED25519 ? KEY_TYPE_EDDSA : KEY_TYPE_ECDSA,
|
||||||
curve == CURVE_NIST_P256?
|
curve == CURVE_ED25519 ?
|
||||||
|
"\x09\x2b\x06\x01\x04\x01\xda\x47\x0f\x01"
|
||||||
|
: curve == CURVE_NIST_P256 ?
|
||||||
"\x08\x2a\x86\x48\xce\x3d\x03\x01\x07"
|
"\x08\x2a\x86\x48\xce\x3d\x03\x01\x07"
|
||||||
: "\05\x2b\x81\x04\x00\x0a",
|
: "\05\x2b\x81\x04\x00\x0a",
|
||||||
curve == CURVE_NIST_P256? 9 : 6,
|
curve == CURVE_ED25519 ? 10
|
||||||
|
: curve == CURVE_NIST_P256? 9 : 6,
|
||||||
ecc_q, ecc_q_len);
|
ecc_q, ecc_q_len);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
@ -3435,7 +3496,7 @@ do_writekey (app_t app, ctrl_t ctrl,
|
|||||||
else if ((tok && toklen == 3 && memcmp ("ecc", tok, toklen) == 0
|
else if ((tok && toklen == 3 && memcmp ("ecc", tok, toklen) == 0
|
||||||
&& (keyno == 0 || keyno == 2))
|
&& (keyno == 0 || keyno == 2))
|
||||||
|| (tok && toklen == 5 && memcmp ("ecdsa", tok, toklen) == 0))
|
|| (tok && toklen == 5 && memcmp ("ecdsa", tok, toklen) == 0))
|
||||||
ecdsa_writekey (app, pincb, pincb_arg, keyno, buf, buflen, depth);
|
ecc_writekey (app, pincb, pincb_arg, keyno, buf, buflen, depth);
|
||||||
else if ((tok && toklen == 3 && memcmp ("ecc", tok, toklen) == 0
|
else if ((tok && toklen == 3 && memcmp ("ecc", tok, toklen) == 0
|
||||||
&& keyno == 1)
|
&& keyno == 1)
|
||||||
|| (tok && toklen == 4 && memcmp ("ecdh", tok, toklen) == 0))
|
|| (tok && toklen == 4 && memcmp ("ecdh", tok, toklen) == 0))
|
||||||
@ -3922,7 +3983,8 @@ do_auth (app_t app, const char *keyidstr,
|
|||||||
|
|
||||||
if (!keyidstr || !*keyidstr)
|
if (!keyidstr || !*keyidstr)
|
||||||
return gpg_error (GPG_ERR_INV_VALUE);
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
if (indatalen > 101) /* For a 2048 bit key. */
|
if (app->app_local->keyattr[2].key_type == KEY_TYPE_RSA
|
||||||
|
&& indatalen > 101) /* For a 2048 bit key. */
|
||||||
return gpg_error (GPG_ERR_INV_VALUE);
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
|
||||||
if (app->app_local->keyattr[2].key_type == KEY_TYPE_ECDSA
|
if (app->app_local->keyattr[2].key_type == KEY_TYPE_ECDSA
|
||||||
@ -3932,6 +3994,12 @@ do_auth (app_t app, const char *keyidstr,
|
|||||||
indata = p;
|
indata = p;
|
||||||
indatalen -= 19;
|
indatalen -= 19;
|
||||||
}
|
}
|
||||||
|
else if (app->app_local->keyattr[2].key_type == KEY_TYPE_EDDSA)
|
||||||
|
{
|
||||||
|
const char *p = (const char *)indata + 15;
|
||||||
|
indata = p;
|
||||||
|
indatalen -= 15;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check whether an OpenPGP card of any version has been requested. */
|
/* Check whether an OpenPGP card of any version has been requested. */
|
||||||
if (!strcmp (keyidstr, "OPENPGP.3"))
|
if (!strcmp (keyidstr, "OPENPGP.3"))
|
||||||
@ -4308,14 +4376,18 @@ parse_ecc_curve (const unsigned char *buffer, size_t buflen)
|
|||||||
{
|
{
|
||||||
int curve;
|
int curve;
|
||||||
|
|
||||||
if (buflen == 6 && buffer[5] == 0x22)
|
if (buflen == 5 && buffer[5] == 0x22)
|
||||||
curve = CURVE_NIST_P384;
|
curve = CURVE_NIST_P384;
|
||||||
else if (buflen == 6 && buffer[5] == 0x23)
|
else if (buflen == 5 && buffer[5] == 0x23)
|
||||||
curve = CURVE_NIST_P521;
|
curve = CURVE_NIST_P521;
|
||||||
else if (buflen == 9)
|
else if (buflen == 8)
|
||||||
curve = CURVE_NIST_P256;
|
curve = CURVE_NIST_P256;
|
||||||
else
|
else if (buflen == 5 && buffer[5] == 0x0a)
|
||||||
curve = CURVE_SEC_P256K1;
|
curve = CURVE_SEC_P256K1;
|
||||||
|
else if (buflen == 9)
|
||||||
|
curve = CURVE_ED25519;
|
||||||
|
else
|
||||||
|
curve = CURVE_UNKNOWN;
|
||||||
|
|
||||||
return curve;
|
return curve;
|
||||||
}
|
}
|
||||||
@ -4384,10 +4456,16 @@ parse_algorithm_attribute (app_t app, int keyno)
|
|||||||
else if (*buffer == 18 && buflen == 11) /* ECDH */
|
else if (*buffer == 18 && buflen == 11) /* ECDH */
|
||||||
{
|
{
|
||||||
app->app_local->keyattr[keyno].key_type = KEY_TYPE_ECDH;
|
app->app_local->keyattr[keyno].key_type = KEY_TYPE_ECDH;
|
||||||
app->app_local->keyattr[keyno].ecdh.curve
|
|
||||||
= parse_ecc_curve (buffer + 1, buflen - 1);
|
|
||||||
app->app_local->keyattr[keyno].ecdh.hashalgo = buffer[1];
|
app->app_local->keyattr[keyno].ecdh.hashalgo = buffer[1];
|
||||||
app->app_local->keyattr[keyno].ecdh.cipheralgo = buffer[2];
|
app->app_local->keyattr[keyno].ecdh.cipheralgo = buffer[2];
|
||||||
|
app->app_local->keyattr[keyno].ecdh.curve
|
||||||
|
= parse_ecc_curve (buffer + 3, buflen - 3);
|
||||||
|
}
|
||||||
|
else if (*buffer == 105) /* EdDSA (experimental) */
|
||||||
|
{
|
||||||
|
app->app_local->keyattr[keyno].key_type = KEY_TYPE_EDDSA;
|
||||||
|
app->app_local->keyattr[keyno].eddsa.curve
|
||||||
|
= parse_ecc_curve (buffer + 1, buflen - 1);
|
||||||
}
|
}
|
||||||
else if (opt.verbose)
|
else if (opt.verbose)
|
||||||
log_printhex ("", buffer, buflen);
|
log_printhex ("", buffer, buflen);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user