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:
parent
4ee4b99837
commit
ef080d5c7f
@ -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)
|
||||||
|
@ -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. */
|
||||||
|
@ -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",
|
||||||
|
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user