1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-06-10 17:51:04 +02:00

scd: support any curves defined by libgcrypt.

* g10/call-agent.h (struct agent_card_info_s): Add curve field.
* g10/call-agent.c (learn_status_cb): Use curve name.
* g10/card-util.c (card_status): Show pubkey name.
* scd/app-openpgp.c (struct app_local_s): Record OID and flags.
(store_fpr): Use ALGO instead of key type.
(send_key_attr): Use curve name instead of OID.
(get_public_key): Clean up by OID to curve name.
(ecc_writekey): Support any curves in libgcrypt.
(do_genkey, do_auth, ): Follow the change.
(ecc_oid): New.
(parse_algorithm_attribute): Show OID here.
This commit is contained in:
NIIBE Yutaka 2015-07-25 12:09:23 +09:00
parent 4ee4b99837
commit ef080d5c7f
4 changed files with 180 additions and 232 deletions

View File

@ -645,14 +645,32 @@ learn_status_cb (void *opaque, const char *line)
} }
else if (keywordlen == 8 && !memcmp (keyword, "KEY-ATTR", keywordlen)) else if (keywordlen == 8 && !memcmp (keyword, "KEY-ATTR", keywordlen))
{ {
int keyno, algo, nbits; int keyno = 0;
int algo = PUBKEY_ALGO_RSA;
int n = 0;
sscanf (line, "%d %d %d", &keyno, &algo, &nbits); sscanf (line, "%d %d %n", &keyno, &algo, &n);
keyno--; keyno--;
if (keyno >= 0 && keyno < DIM (parm->key_attr)) if (keyno < 0 || keyno >= DIM (parm->key_attr))
return 0;
parm->key_attr[keyno].algo = algo;
if (algo == PUBKEY_ALGO_RSA)
parm->key_attr[keyno].nbits = strtoul (line+n+3, NULL, 10);
else if (algo == PUBKEY_ALGO_ECDH || algo == PUBKEY_ALGO_ECDSA
|| algo == PUBKEY_ALGO_EDDSA)
{ {
parm->key_attr[keyno].algo = algo; const char *curve;
parm->key_attr[keyno].nbits = nbits;
i = 0;
do
{
curve = openpgp_enum_curves (&i);
if (!strcmp (curve, line+n))
break;
}
while (curve != NULL);
parm->key_attr[keyno].curve = curve;
} }
} }
else if (keywordlen == 12 && !memcmp (keyword, "PRIVATE-DO-", 11) else if (keywordlen == 12 && !memcmp (keyword, "PRIVATE-DO-", 11)

View File

@ -55,7 +55,10 @@ struct agent_card_info_s
int chvretry[3]; /* Allowed retries for the CHV; 0 = blocked. */ int chvretry[3]; /* Allowed retries for the CHV; 0 = blocked. */
struct { /* Array with key attributes. */ struct { /* Array with key attributes. */
int algo; /* Algorithm identifier. */ int algo; /* Algorithm identifier. */
unsigned int nbits; /* Supported keysize. */ union {
unsigned int nbits; /* Supported keysize. */
const char *curve; /* Name of curve. */
};
} key_attr[3]; } key_attr[3];
struct { struct {
unsigned int ki:1; /* Key import available. */ unsigned int ki:1; /* Key import available. */

View File

@ -471,9 +471,14 @@ card_status (estream_t fp, char *serialno, size_t serialnobuflen)
es_fprintf (fp, "forcepin:%d:::\n", !info.chv1_cached); es_fprintf (fp, "forcepin:%d:::\n", !info.chv1_cached);
for (i=0; i < DIM (info.key_attr); i++) for (i=0; i < DIM (info.key_attr); i++)
if (info.key_attr[0].algo) if (info.key_attr[0].algo == PUBKEY_ALGO_RSA)
es_fprintf (fp, "keyattr:%d:%d:%u:\n", i+1, es_fprintf (fp, "keyattr:%d:%d:%u:\n", i+1,
info.key_attr[i].algo, info.key_attr[i].nbits); info.key_attr[i].algo, info.key_attr[i].nbits);
else if (info.key_attr[i].algo == PUBKEY_ALGO_ECDH
|| info.key_attr[i].algo == PUBKEY_ALGO_ECDSA
|| info.key_attr[i].algo == PUBKEY_ALGO_EDDSA)
es_fprintf (fp, "keyattr:%d:%d:%s:\n", i+1,
info.key_attr[i].algo, info.key_attr[i].curve);
es_fprintf (fp, "maxpinlen:%d:%d:%d:\n", es_fprintf (fp, "maxpinlen:%d:%d:%d:\n",
info.chvmaxlen[0], info.chvmaxlen[1], info.chvmaxlen[2]); info.chvmaxlen[0], info.chvmaxlen[1], info.chvmaxlen[2]);
es_fprintf (fp, "pinretry:%d:%d:%d:\n", es_fprintf (fp, "pinretry:%d:%d:%d:\n",
@ -553,12 +558,12 @@ card_status (estream_t fp, char *serialno, size_t serialnobuflen)
{ {
tty_fprintf (fp, "Key attributes ...:"); tty_fprintf (fp, "Key attributes ...:");
for (i=0; i < DIM (info.key_attr); i++) for (i=0; i < DIM (info.key_attr); i++)
tty_fprintf (fp, " %u%c", if (info.key_attr[i].algo == PUBKEY_ALGO_RSA)
info.key_attr[i].nbits, tty_fprintf (fp, " rsa%u", info.key_attr[i].nbits);
info.key_attr[i].algo == 1? 'R': else if (info.key_attr[i].algo == PUBKEY_ALGO_ECDH
info.key_attr[i].algo == 17? 'D': || info.key_attr[i].algo == PUBKEY_ALGO_ECDSA
info.key_attr[i].algo == 18? 'e': || info.key_attr[i].algo == PUBKEY_ALGO_EDDSA)
info.key_attr[i].algo == 19? 'E': '?'); tty_fprintf (fp, " %s", info.key_attr[i].curve);
tty_fprintf (fp, "\n"); tty_fprintf (fp, "\n");
} }
tty_fprintf (fp, "Max. PIN lengths .: %d %d %d\n", tty_fprintf (fp, "Max. PIN lengths .: %d %d %d\n",

View File

@ -126,7 +126,6 @@ static struct {
typedef enum typedef enum
{ {
KEY_TYPE_ECC, KEY_TYPE_ECC,
KEY_TYPE_EDDSA,
KEY_TYPE_RSA, KEY_TYPE_RSA,
} }
key_type_t; key_type_t;
@ -144,18 +143,6 @@ typedef enum
rsa_key_format_t; rsa_key_format_t;
/* Elliptic Curves. */
enum
{
CURVE_NIST_P256,
CURVE_NIST_P384,
CURVE_NIST_P521,
CURVE_SEC_P256K1,
CURVE_ED25519,
CURVE_UNKNOWN,
};
/* One cache item for DOs. */ /* One cache item for DOs. */
struct cache_s { struct cache_s {
struct cache_s *next; struct cache_s *next;
@ -241,15 +228,14 @@ struct app_local_s {
rsa_key_format_t format; rsa_key_format_t format;
} rsa; } rsa;
struct { struct {
int curve; const char *oid;
int flags;
} ecc; } ecc;
struct {
int curve;
} eddsa;
}; };
} keyattr[3]; } keyattr[3];
}; };
#define ECC_FLAG_EDDSA (1 << 0)
/***** Local prototypes *****/ /***** Local prototypes *****/
@ -745,25 +731,12 @@ parse_login_data (app_t app)
} }
static unsigned char
get_algo_byte (int keynumber, key_type_t key_type)
{
if (key_type == KEY_TYPE_ECC && keynumber != 1)
return PUBKEY_ALGO_ECDSA;
else if (key_type == KEY_TYPE_ECC && keynumber == 1)
return PUBKEY_ALGO_ECDH;
else if (key_type == KEY_TYPE_EDDSA)
return PUBKEY_ALGO_EDDSA;
else
return PUBKEY_ALGO_RSA;
}
#define MAX_ARGS_STORE_FPR 3 #define MAX_ARGS_STORE_FPR 3
/* Note, that FPR must be at least 20 bytes. */ /* Note, that FPR must be at least 20 bytes. */
static gpg_error_t static gpg_error_t
store_fpr (app_t app, int keynumber, u32 timestamp, unsigned char *fpr, store_fpr (app_t app, int keynumber, u32 timestamp, unsigned char *fpr,
key_type_t key_type, ...) int algo, ...)
{ {
unsigned int n, nbits; unsigned int n, nbits;
unsigned char *buffer, *p; unsigned char *buffer, *p;
@ -776,21 +749,17 @@ store_fpr (app_t app, int keynumber, u32 timestamp, unsigned char *fpr,
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 (keynumber == 1 && key_type == KEY_TYPE_ECC) if (algo == PUBKEY_ALGO_ECDH)
argc = 3; argc = 3;
else else
argc = 2; argc = 2;
va_start (ap, key_type); va_start (ap, algo);
for (i = 0; i < argc; i++) for (i = 0; i < argc; i++)
{ {
m[i] = va_arg (ap, const unsigned char *); m[i] = va_arg (ap, const unsigned char *);
mlen[i] = va_arg (ap, size_t); mlen[i] = va_arg (ap, size_t);
if (key_type != KEY_TYPE_EDDSA) if (algo == PUBKEY_ALGO_RSA || i == 1)
/* strip off leading zeroes */
for (; mlen[i] && !*m[i]; mlen[i]--, m[i]++)
;
if (key_type == KEY_TYPE_RSA || i == 1)
n += 2; n += 2;
n += mlen[i]; n += mlen[i];
} }
@ -808,11 +777,11 @@ store_fpr (app_t app, int keynumber, u32 timestamp, unsigned char *fpr,
*p++ = timestamp >> 16; *p++ = timestamp >> 16;
*p++ = timestamp >> 8; *p++ = timestamp >> 8;
*p++ = timestamp; *p++ = timestamp;
*p++ = get_algo_byte (keynumber, key_type); *p++ = algo;
for (i = 0; i < argc; i++) for (i = 0; i < argc; i++)
{ {
if (key_type == KEY_TYPE_RSA || i == 1) if (algo == PUBKEY_ALGO_RSA || i == 1)
{ {
nbits = count_bits (m[i], mlen[i]); nbits = count_bits (m[i], mlen[i]);
*p++ = nbits >> 8; *p++ = nbits >> 8;
@ -924,70 +893,25 @@ send_key_data (ctrl_t ctrl, const char *name,
static void static void
get_ecc_key_parameters (int curve, int *r_n_bits, const char **r_curve_oid) send_key_attr (ctrl_t ctrl, app_t app, const char *keyword, int keyno)
{
if (curve == CURVE_NIST_P256)
{
*r_n_bits = 256;
*r_curve_oid = "1.2.840.10045.3.1.7";
}
else if (curve == CURVE_NIST_P384)
{
*r_n_bits = 384;
*r_curve_oid = "1.3.132.0.34";
}
else if (curve == CURVE_NIST_P521)
{
*r_n_bits = 521;
*r_curve_oid = "1.3.132.0.35";
}
else if (curve == CURVE_SEC_P256K1)
{
*r_n_bits = 256;
*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
send_key_attr (ctrl_t ctrl, app_t app, const char *keyword, int number)
{ {
char buffer[200]; char buffer[200];
int n_bits;
const char *curve_oid;
assert (number >=0 && number < DIM(app->app_local->keyattr)); assert (keyno >=0 && keyno < DIM(app->app_local->keyattr));
if (app->app_local->keyattr[number].key_type == KEY_TYPE_RSA) if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_RSA)
snprintf (buffer, sizeof buffer, "%d 1 %u %u %d", snprintf (buffer, sizeof buffer, "%d 1 rsa%u %u %d",
number+1, keyno+1,
app->app_local->keyattr[number].rsa.n_bits, app->app_local->keyattr[keyno].rsa.n_bits,
app->app_local->keyattr[number].rsa.e_bits, app->app_local->keyattr[keyno].rsa.e_bits,
app->app_local->keyattr[number].rsa.format); app->app_local->keyattr[keyno].rsa.format);
else if (app->app_local->keyattr[number].key_type == KEY_TYPE_ECC) else if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_ECC)
{ {
get_ecc_key_parameters (app->app_local->keyattr[number].ecc.curve, snprintf (buffer, sizeof buffer, "%d %d %s",
&n_bits, &curve_oid); keyno+1,
snprintf (buffer, sizeof buffer, "%d %d %u %s", app->app_local->keyattr[keyno].ecc.flags? PUBKEY_ALGO_EDDSA:
number+1, (keyno==1? PUBKEY_ALGO_ECDH: PUBKEY_ALGO_ECDSA),
number==1? PUBKEY_ALGO_ECDH: PUBKEY_ALGO_ECDSA, openpgp_oid_to_curve (app->app_local->keyattr[keyno].ecc.oid));
n_bits, curve_oid);
}
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 22 %u %s",
number+1, n_bits, curve_oid);
} }
else else
snprintf (buffer, sizeof buffer, "0 0 UNKNOWN"); snprintf (buffer, sizeof buffer, "0 0 UNKNOWN");
@ -1295,24 +1219,6 @@ retrieve_key_material (FILE *fp, const char *hexkeyid,
#endif /*GNUPG_MAJOR_VERSION > 1*/ #endif /*GNUPG_MAJOR_VERSION > 1*/
static const char *
get_curve_name (int curve)
{
if (curve == CURVE_NIST_P256)
return "NIST P-256";
else if (curve == CURVE_NIST_P384)
return "NIST P-384";
else if (curve == CURVE_NIST_P521)
return "NIST P-521";
else if (curve == CURVE_SEC_P256K1)
return "secp256k1";
else if (curve == CURVE_ED25519)
return "Ed25519";
else
return "unknown";
}
/* Get the public key for KEYNO and store it as an S-expresion with /* Get the public key for KEYNO and store it as an S-expresion with
the APP handle. On error that field gets cleared. If we already the APP handle. On error that field gets cleared. If we already
know about the public key we will just return. Note that this does know about the public key we will just return. Note that this does
@ -1480,7 +1386,9 @@ 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 (app->app_local->keyattr[keyno].key_type != KEY_TYPE_EDDSA if ((app->app_local->keyattr[keyno].key_type == KEY_TYPE_RSA
|| (app->app_local->keyattr[keyno].key_type == KEY_TYPE_ECC
&& !app->app_local->keyattr[keyno].ecc.flags))
&& mlen && (*m & 0x80)) && mlen && (*m & 0x80))
{ {
*mbuf = 0; *mbuf = 0;
@ -1526,35 +1434,12 @@ get_public_key (app_t app, int keyno)
} }
else if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_ECC) else if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_ECC)
{ {
const char *curve_name
= get_curve_name (app->app_local->keyattr[keyno].ecc.curve);
err = gcry_sexp_build (&s_pkey, NULL, err = gcry_sexp_build (&s_pkey, NULL,
"(public-key(ecc(curve%s)(q%b)))", "(public-key(ecc(curve%s)%s(q%b)))",
curve_name, (int)mlen, mbuf); openpgp_oid_to_curve (app->app_local->keyattr[keyno].ecc.oid),
if (err) app->app_local->keyattr[keyno].ecc.flags?
goto leave; "(flags eddsa)" : "",
(int)mlen, mbuf);
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, (int)mlen, mbuf);
if (err) if (err)
goto leave; goto leave;
@ -3256,7 +3141,7 @@ rsa_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **),
goto leave; goto leave;
} }
err = store_fpr (app, keyno, created_at, fprbuf, KEY_TYPE_RSA, err = store_fpr (app, keyno, created_at, fprbuf, PUBKEY_ALGO_RSA,
rsa_n, rsa_n_len, rsa_e, rsa_e_len); rsa_n, rsa_n_len, rsa_e, rsa_e_len);
if (err) if (err)
goto leave; goto leave;
@ -3280,11 +3165,10 @@ ecc_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **),
const unsigned char *ecc_q = NULL; const unsigned char *ecc_q = NULL;
const unsigned char *ecc_d = NULL; const unsigned char *ecc_d = NULL;
size_t ecc_q_len, ecc_d_len; size_t ecc_q_len, ecc_d_len;
unsigned char *template = NULL;
size_t template_len;
unsigned char fprbuf[20];
u32 created_at = 0; u32 created_at = 0;
int curve = CURVE_UNKNOWN; const char *oidstr = NULL;
int flag_eddsa = 0;
int algo;
/* (private-key(ecc(curve%s)(q%m)(d%m))(created-at%d)): /* (private-key(ecc(curve%s)(q%m)(d%m))(created-at%d)):
curve = "NIST P-256" */ curve = "NIST P-256" */
@ -3306,21 +3190,30 @@ ecc_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **),
if (tok && toklen == 5 && !memcmp (tok, "curve", 5)) if (tok && toklen == 5 && !memcmp (tok, "curve", 5))
{ {
unsigned char *curve;
if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
goto leave; goto leave;
if (tok && toklen == 10 && !memcmp (tok, "NIST P-256", 10)) curve = xtrymalloc (toklen+1);
curve = CURVE_NIST_P256; if (!curve)
else if (tok && toklen == 9 && !memcmp (tok, "secp256k1", 9))
curve = CURVE_SEC_P256K1;
else if (tok && toklen == 7 && !memcmp (tok, "Ed25519", 7))
curve = CURVE_ED25519;
else
{ {
log_error (_("unsupported curve\n")); err = gpg_error_from_syserror ();
err = gpg_error (GPG_ERR_INV_VALUE);
goto leave; goto leave;
} }
memcpy (curve, tok, toklen);
curve[toklen] = 0;
oidstr = openpgp_curve_to_oid (curve, NULL);
xfree (curve);
}
else if (tok && toklen == 5 && !memcmp (tok, "flags", 5))
{
if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
goto leave;
if (tok && toklen == 5 && !memcmp (tok, "eddsa", 5))
flag_eddsa = 1;
} }
else if (tok && toklen == 1) else if (tok && toklen == 1)
{ {
@ -3340,7 +3233,7 @@ ecc_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **),
} }
if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
goto leave; goto leave;
if (tok && buf2 && curve != CURVE_ED25519) if (tok && buf2 && !flag_eddsa)
/* It's MPI. Strip off leading zero bytes and save. */ /* It's MPI. Strip off leading zero bytes and save. */
for (;toklen && !*tok; toklen--, tok++) for (;toklen && !*tok; toklen--, tok++)
; ;
@ -3391,12 +3284,33 @@ ecc_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **),
/* Check that we have all parameters and that they match the card /* Check that we have all parameters and that they match the card
description. */ description. */
if (!oidstr)
{
log_error (_("unsupported curve\n"));
err = gpg_error (GPG_ERR_INV_VALUE);
goto leave;
}
if (!created_at) if (!created_at)
{ {
log_error (_("creation timestamp missing\n")); log_error (_("creation timestamp missing\n"));
err = gpg_error (GPG_ERR_INV_VALUE); err = gpg_error (GPG_ERR_INV_VALUE);
goto leave; goto leave;
} }
if (flag_eddsa && keyno != 1)
algo = PUBKEY_ALGO_EDDSA;
else if (keyno == 1)
algo = PUBKEY_ALGO_ECDH;
else
algo = PUBKEY_ALGO_ECDSA;
if (app->app_local->keyattr[keyno].key_type != KEY_TYPE_ECC
|| app->app_local->keyattr[keyno].ecc.oid != oidstr
|| app->app_local->keyattr[keyno].ecc.flags != flag_eddsa)
{
log_error ("key attribute on card doesn't match\n");
err = gpg_error (GPG_ERR_INV_VALUE);
goto leave;
}
if (opt.verbose) if (opt.verbose)
log_info ("ECC private key size is %u bytes\n", (unsigned int)ecc_d_len); log_info ("ECC private key size is %u bytes\n", (unsigned int)ecc_d_len);
@ -3411,6 +3325,8 @@ ecc_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **),
{ {
/* Build the private key template as described in section 4.3.3.7 of /* Build the private key template as described in section 4.3.3.7 of
the OpenPGP card specs version 2.0. */ the OpenPGP card specs version 2.0. */
unsigned char *template;
size_t template_len;
int exmode; int exmode;
err = build_ecc_privkey_template (app, keyno, err = build_ecc_privkey_template (app, keyno,
@ -3422,7 +3338,10 @@ ecc_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **),
/* Prepare for storing the key. */ /* Prepare for storing the key. */
err = verify_chv3 (app, pincb, pincb_arg); err = verify_chv3 (app, pincb, pincb_arg);
if (err) if (err)
goto leave; {
xfree (template);
goto leave;
}
/* Store the key. */ /* Store the key. */
if (app->app_local->cardcap.ext_lc_le && template_len > 254) if (app->app_local->cardcap.ext_lc_le && template_len > 254)
@ -3433,32 +3352,41 @@ ecc_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **),
exmode = 0; exmode = 0;
err = iso7816_put_data_odd (app->slot, exmode, 0x3fff, err = iso7816_put_data_odd (app->slot, exmode, 0x3fff,
template, template_len); template, template_len);
xfree (template);
} }
else else
return gpg_error (GPG_ERR_NOT_SUPPORTED); err = gpg_error (GPG_ERR_NOT_SUPPORTED);
if (err) if (err)
{ {
log_error (_("failed to store the key: %s\n"), gpg_strerror (err)); log_error (_("failed to store the key: %s\n"), gpg_strerror (err));
goto leave; goto leave;
} }
else
{
gcry_mpi_t oid;
const unsigned char *oidbuf;
size_t oid_len;
unsigned char fprbuf[20];
err = store_fpr (app, keyno, created_at, fprbuf, err = openpgp_oid_from_str (oidstr, &oid);
curve == CURVE_ED25519 ? KEY_TYPE_EDDSA : KEY_TYPE_ECC, if (err)
curve == CURVE_ED25519 ? goto leave;
"\x09\x2b\x06\x01\x04\x01\xda\x47\x0f\x01"
: curve == CURVE_NIST_P256 ?
"\x08\x2a\x86\x48\xce\x3d\x03\x01\x07"
: "\x05\x2b\x81\x04\x00\x0a",
(size_t)(curve == CURVE_ED25519 ? 10
: curve == CURVE_NIST_P256? 9 : 6),
ecc_q, ecc_q_len, "\x03\x01\x08\x07", (size_t)4);
if (err)
goto leave;
oidbuf = gcry_mpi_get_opaque (oid, &oid_len);
if (!oidbuf)
{
err = gpg_error_from_syserror ();
gcry_mpi_release (oid);
goto leave;
}
err = store_fpr (app, keyno, created_at, fprbuf, algo,
oidbuf, oid_len, ecc_q, ecc_q_len,
"\x03\x01\x08\x07", (size_t)4);
gcry_mpi_release (oid);
}
leave: leave:
xfree (template);
return err; return err;
} }
@ -3661,7 +3589,7 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags,
send_status_info (ctrl, "KEY-CREATED-AT", send_status_info (ctrl, "KEY-CREATED-AT",
numbuf, (size_t)strlen(numbuf), NULL, 0); numbuf, (size_t)strlen(numbuf), NULL, 0);
rc = store_fpr (app, keyno, (u32)created_at, fprbuf, KEY_TYPE_RSA, rc = store_fpr (app, keyno, (u32)created_at, fprbuf, PUBKEY_ALGO_RSA,
m, mlen, e, elen); m, mlen, e, elen);
if (rc) if (rc)
goto leave; goto leave;
@ -4014,18 +3942,21 @@ do_auth (app_t app, const char *keyidstr,
&& indatalen > 101) /* For a 2048 bit key. */ && 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_ECC if (app->app_local->keyattr[2].key_type == KEY_TYPE_ECC)
&& (indatalen == 51 || indatalen == 67 || indatalen == 83))
{ {
const char *p = (const char *)indata + 19; if (!app->app_local->keyattr[2].ecc.flags
indata = p; && (indatalen == 51 || indatalen == 67 || indatalen == 83))
indatalen -= 19; {
} const char *p = (const char *)indata + 19;
else if (app->app_local->keyattr[2].key_type == KEY_TYPE_EDDSA) indata = p;
{ indatalen -= 19;
const char *p = (const char *)indata + 15; }
indata = p; else
indatalen -= 15; {
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. */
@ -4429,25 +4360,25 @@ parse_historical (struct app_local_s *apploc,
} }
static int static const char *
parse_ecc_curve (const unsigned char *buffer, size_t buflen) ecc_oid (unsigned char *buf, size_t buflen)
{ {
int curve; gcry_mpi_t oid;
char *oidstr;
const char *result;
if (buflen == 5 && buffer[5] == 0x22) oid = gcry_mpi_set_opaque (NULL, buf, buflen * 8);
curve = CURVE_NIST_P384; if (!oid)
else if (buflen == 5 && buffer[5] == 0x23) return NULL;
curve = CURVE_NIST_P521;
else if (buflen == 8)
curve = CURVE_NIST_P256;
else if (buflen == 5 && buffer[5] == 0x0a)
curve = CURVE_SEC_P256K1;
else if (buflen == 9)
curve = CURVE_ED25519;
else
curve = CURVE_UNKNOWN;
return curve; oidstr = openpgp_oid_to_str (oid);
gcry_mpi_release (oid);
if (!oidstr)
return NULL;
result = openpgp_curve_to_oid (oidstr, NULL);
xfree (oidstr);
return result;
} }
@ -4505,25 +4436,16 @@ parse_algorithm_attribute (app_t app, int keyno)
app->app_local->keyattr[keyno].rsa.format == RSA_CRT? "crt" : app->app_local->keyattr[keyno].rsa.format == RSA_CRT? "crt" :
app->app_local->keyattr[keyno].rsa.format == RSA_CRT_N?"crt+n":"?"); app->app_local->keyattr[keyno].rsa.format == RSA_CRT_N?"crt+n":"?");
} }
else if (*buffer == PUBKEY_ALGO_ECDH || *buffer == PUBKEY_ALGO_ECDSA) else if (*buffer == PUBKEY_ALGO_ECDH || *buffer == PUBKEY_ALGO_ECDSA
|| *buffer == PUBKEY_ALGO_EDDSA)
{ {
app->app_local->keyattr[keyno].key_type = KEY_TYPE_ECC; app->app_local->keyattr[keyno].key_type = KEY_TYPE_ECC;
app->app_local->keyattr[keyno].ecc.curve app->app_local->keyattr[keyno].ecc.oid = ecc_oid (buffer + 1, buflen - 1);
= parse_ecc_curve (buffer + 1, buflen - 1); app->app_local->keyattr[keyno].ecc.flags = (*buffer == PUBKEY_ALGO_EDDSA);
if (opt.verbose) if (opt.verbose)
log_printf log_printf
("ECC, curve=%s\n", ("ECC, curve=%s%s\n", app->app_local->keyattr[keyno].ecc.oid,
get_curve_name (app->app_local->keyattr[keyno].ecc.curve)); app->app_local->keyattr[keyno].ecc.flags ? " (eddsa)": "");
}
else if (*buffer == PUBKEY_ALGO_EDDSA)
{
app->app_local->keyattr[keyno].key_type = KEY_TYPE_EDDSA;
app->app_local->keyattr[keyno].eddsa.curve
= parse_ecc_curve (buffer + 1, buflen - 1);
if (opt.verbose)
log_printf
("EdDSA, curve=%s\n",
get_curve_name (app->app_local->keyattr[keyno].eddsa.curve));
} }
else if (opt.verbose) else if (opt.verbose)
log_printhex ("", buffer, buflen); log_printhex ("", buffer, buflen);