mirror of
git://git.gnupg.org/gnupg.git
synced 2025-04-17 15:44:34 +02:00
scd: GENKEY updates the public key in APP.
* scd/app-openpgp.c (rsa_read_pubkey, ecc_read_pubkey): New. (read_public_key): New. (get_public_key, do_genkey): Use read_public_key. -- With this change, since GENKEY updates the public key (pk[keyno].key) in APP, READKEY will be possible after the command even for the old card (version <= 0x0100). Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
parent
980c037bed
commit
b680f79cc1
@ -1221,6 +1221,246 @@ retrieve_key_material (FILE *fp, const char *hexkeyid,
|
|||||||
#endif /*GNUPG_MAJOR_VERSION > 1*/
|
#endif /*GNUPG_MAJOR_VERSION > 1*/
|
||||||
|
|
||||||
|
|
||||||
|
static gpg_error_t
|
||||||
|
rsa_read_pubkey (app_t app, ctrl_t ctrl, u32 created_at, int keyno,
|
||||||
|
const unsigned char *data, size_t datalen, gcry_sexp_t *r_sexp)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
const unsigned char *m, *e;
|
||||||
|
size_t mlen, elen;
|
||||||
|
unsigned char *mbuf = NULL, *ebuf = NULL;
|
||||||
|
|
||||||
|
m = find_tlv (data, datalen, 0x0081, &mlen);
|
||||||
|
if (!m)
|
||||||
|
{
|
||||||
|
log_error (_("response does not contain the RSA modulus\n"));
|
||||||
|
return gpg_error (GPG_ERR_CARD);
|
||||||
|
}
|
||||||
|
|
||||||
|
e = find_tlv (data, datalen, 0x0082, &elen);
|
||||||
|
if (!e)
|
||||||
|
{
|
||||||
|
log_error (_("response does not contain the RSA public exponent\n"));
|
||||||
|
return gpg_error (GPG_ERR_CARD);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctrl)
|
||||||
|
{
|
||||||
|
send_key_data (ctrl, "n", m, mlen);
|
||||||
|
send_key_data (ctrl, "e", e, elen);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; mlen && !*m; mlen--, m++) /* strip leading zeroes */
|
||||||
|
;
|
||||||
|
for (; elen && !*e; elen--, e++) /* strip leading zeroes */
|
||||||
|
;
|
||||||
|
|
||||||
|
if (ctrl)
|
||||||
|
{
|
||||||
|
unsigned char fprbuf[20];
|
||||||
|
|
||||||
|
err = store_fpr (app, keyno, created_at, fprbuf, PUBKEY_ALGO_RSA,
|
||||||
|
m, mlen, e, elen);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
send_fpr_if_not_null (ctrl, "KEY-FPR", -1, fprbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
mbuf = xtrymalloc (mlen + 1);
|
||||||
|
if (!mbuf)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
/* Prepend numbers with a 0 if needed. */
|
||||||
|
if (mlen && (*m & 0x80))
|
||||||
|
{
|
||||||
|
*mbuf = 0;
|
||||||
|
memcpy (mbuf+1, m, mlen);
|
||||||
|
mlen++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
memcpy (mbuf, m, mlen);
|
||||||
|
|
||||||
|
ebuf = xtrymalloc (elen + 1);
|
||||||
|
if (!ebuf)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
/* Prepend numbers with a 0 if needed. */
|
||||||
|
if (elen && (*e & 0x80))
|
||||||
|
{
|
||||||
|
*ebuf = 0;
|
||||||
|
memcpy (ebuf+1, e, elen);
|
||||||
|
elen++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
memcpy (ebuf, e, elen);
|
||||||
|
|
||||||
|
err = gcry_sexp_build (r_sexp, NULL, "(public-key(rsa(n%b)(e%b)))",
|
||||||
|
(int)mlen, mbuf, (int)elen, ebuf);
|
||||||
|
leave:
|
||||||
|
xfree (mbuf);
|
||||||
|
xfree (ebuf);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gpg_error_t
|
||||||
|
ecc_read_pubkey (app_t app, ctrl_t ctrl, u32 created_at, int keyno,
|
||||||
|
const unsigned char *data, size_t datalen, gcry_sexp_t *r_sexp)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
unsigned char *qbuf;
|
||||||
|
const unsigned char *ecc_q;
|
||||||
|
size_t ecc_q_len;
|
||||||
|
gcry_mpi_t oid;
|
||||||
|
int n;
|
||||||
|
const unsigned char *oidbuf;
|
||||||
|
size_t oid_len;
|
||||||
|
int algo;
|
||||||
|
const char *format;
|
||||||
|
const char *curve;
|
||||||
|
|
||||||
|
ecc_q = find_tlv (data, datalen, 0x0086, &ecc_q_len);
|
||||||
|
if (!ecc_q)
|
||||||
|
{
|
||||||
|
log_error (_("response does not contain the EC public key\n"));
|
||||||
|
return gpg_error (GPG_ERR_CARD);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = openpgp_oid_from_str (app->app_local->keyattr[keyno].ecc.oid, &oid);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
oidbuf = gcry_mpi_get_opaque (oid, &n);
|
||||||
|
if (!oidbuf)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
gcry_mpi_release (oid);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
gcry_mpi_release (oid);
|
||||||
|
oid_len = (n+7)/8;
|
||||||
|
|
||||||
|
qbuf = xtrymalloc (ecc_q_len + 1);
|
||||||
|
if (!qbuf)
|
||||||
|
return gpg_error_from_syserror ();
|
||||||
|
|
||||||
|
if ((app->app_local->keyattr[keyno].ecc.flags & ECC_FLAG_DJB_TWEAK))
|
||||||
|
{ /* Prepend 0x40 prefix. */
|
||||||
|
*qbuf = 0x40;
|
||||||
|
memcpy (qbuf+1, ecc_q, ecc_q_len);
|
||||||
|
ecc_q_len++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
memcpy (qbuf, ecc_q, ecc_q_len);
|
||||||
|
|
||||||
|
if (ctrl)
|
||||||
|
{
|
||||||
|
send_key_data (ctrl, "q", ecc_q, ecc_q_len);
|
||||||
|
send_key_data (ctrl, "curve", oidbuf, oid_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyno == 1)
|
||||||
|
{
|
||||||
|
if (ctrl)
|
||||||
|
send_key_data (ctrl, "kdf", "\x03\x01\x08\x07", (size_t)4);
|
||||||
|
algo = PUBKEY_ALGO_ECDH;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((app->app_local->keyattr[keyno].ecc.flags & ECC_FLAG_DJB_TWEAK))
|
||||||
|
algo = PUBKEY_ALGO_EDDSA;
|
||||||
|
else
|
||||||
|
algo = PUBKEY_ALGO_ECDSA;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctrl)
|
||||||
|
{
|
||||||
|
unsigned char fprbuf[20];
|
||||||
|
|
||||||
|
err = store_fpr (app, keyno, created_at, fprbuf, algo, oidbuf, oid_len,
|
||||||
|
qbuf, ecc_q_len, "\x03\x01\x08\x07", (size_t)4);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
send_fpr_if_not_null (ctrl, "KEY-FPR", -1, fprbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(app->app_local->keyattr[keyno].ecc.flags & ECC_FLAG_DJB_TWEAK))
|
||||||
|
format = "(public-key(ecc(curve%s)(q%b)))";
|
||||||
|
else if (keyno == 1)
|
||||||
|
format = "(public-key(ecc(curve%s)(flags djb-tweak)(q%b)))";
|
||||||
|
else
|
||||||
|
format = "(public-key(ecc(curve%s)(flags eddsa)(q%b)))";
|
||||||
|
|
||||||
|
curve = openpgp_oid_to_curve (app->app_local->keyattr[keyno].ecc.oid, 1);
|
||||||
|
err = gcry_sexp_build (r_sexp, NULL, format, curve, (int)ecc_q_len, qbuf);
|
||||||
|
leave:
|
||||||
|
xfree (qbuf);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Parse tag-length-value data for public key in BUFFER of BUFLEN
|
||||||
|
length. Key of KEYNO in APP is updated with an S-expression of
|
||||||
|
public key. When CTRL is not NULL, fingerprint is computed with
|
||||||
|
CREATED_AT, and fingerprint is written to the card, and key data
|
||||||
|
and fingerprint are send back to the client side.
|
||||||
|
*/
|
||||||
|
static gpg_error_t
|
||||||
|
read_public_key (app_t app, ctrl_t ctrl, u32 created_at, int keyno,
|
||||||
|
const unsigned char *buffer, size_t buflen)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
const unsigned char *data;
|
||||||
|
size_t datalen;
|
||||||
|
gcry_sexp_t s_pkey = NULL;
|
||||||
|
|
||||||
|
data = find_tlv (buffer, buflen, 0x7F49, &datalen);
|
||||||
|
if (!data)
|
||||||
|
{
|
||||||
|
log_error (_("response does not contain the public key data\n"));
|
||||||
|
return gpg_error (GPG_ERR_CARD);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_RSA)
|
||||||
|
err = rsa_read_pubkey (app, ctrl, created_at, keyno,
|
||||||
|
data, datalen, &s_pkey);
|
||||||
|
else if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_ECC)
|
||||||
|
err = ecc_read_pubkey (app, ctrl, created_at, keyno,
|
||||||
|
data, datalen, &s_pkey);
|
||||||
|
else
|
||||||
|
err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
||||||
|
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
unsigned char *keybuf;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
len = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, NULL, 0);
|
||||||
|
keybuf = xtrymalloc (len);
|
||||||
|
if (!data)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
gcry_sexp_release (s_pkey);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, keybuf, len);
|
||||||
|
gcry_sexp_release (s_pkey);
|
||||||
|
|
||||||
|
app->app_local->pk[keyno].key = keybuf;
|
||||||
|
/* Decrement for trailing '\0' */
|
||||||
|
app->app_local->pk[keyno].keylen = len - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* 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
|
||||||
@ -1237,12 +1477,10 @@ get_public_key (app_t app, int keyno)
|
|||||||
{
|
{
|
||||||
gpg_error_t err = 0;
|
gpg_error_t err = 0;
|
||||||
unsigned char *buffer;
|
unsigned char *buffer;
|
||||||
const unsigned char *keydata, *m, *e;
|
const unsigned char *m, *e;
|
||||||
size_t buflen, keydatalen;
|
size_t buflen;
|
||||||
size_t mlen = 0;
|
size_t mlen = 0;
|
||||||
size_t elen = 0;
|
size_t elen = 0;
|
||||||
unsigned char *mbuf = NULL;
|
|
||||||
unsigned char *ebuf = NULL;
|
|
||||||
char *keybuf = NULL;
|
char *keybuf = NULL;
|
||||||
gcry_sexp_t s_pkey;
|
gcry_sexp_t s_pkey;
|
||||||
size_t len;
|
size_t len;
|
||||||
@ -1286,42 +1524,7 @@ get_public_key (app_t app, int keyno)
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
keydata = find_tlv (buffer, buflen, 0x7F49, &keydatalen);
|
err = read_public_key (app, NULL, 0U, keyno, buffer, buflen);
|
||||||
if (!keydata)
|
|
||||||
{
|
|
||||||
err = gpg_error (GPG_ERR_CARD);
|
|
||||||
log_error (_("response does not contain the public key data\n"));
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_RSA)
|
|
||||||
{
|
|
||||||
m = find_tlv (keydata, keydatalen, 0x0081, &mlen);
|
|
||||||
if (!m)
|
|
||||||
{
|
|
||||||
err = gpg_error (GPG_ERR_CARD);
|
|
||||||
log_error (_("response does not contain the RSA modulus\n"));
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
e = find_tlv (keydata, keydatalen, 0x0082, &elen);
|
|
||||||
if (!e)
|
|
||||||
{
|
|
||||||
err = gpg_error (GPG_ERR_CARD);
|
|
||||||
log_error (_("response does not contain the RSA public exponent\n"));
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m = find_tlv (keydata, keydatalen, 0x0086, &mlen);
|
|
||||||
if (!m)
|
|
||||||
{
|
|
||||||
err = gpg_error (GPG_ERR_CARD);
|
|
||||||
log_error (_("response does not contain the EC public key\n"));
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1375,98 +1578,35 @@ get_public_key (app_t app, int keyno)
|
|||||||
gpg_strerror (err));
|
gpg_strerror (err));
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
mbuf = xtrymalloc (mlen + 1);
|
|
||||||
if (!mbuf)
|
|
||||||
{
|
|
||||||
err = gpg_error_from_syserror ();
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 & ECC_FLAG_DJB_TWEAK)))
|
|
||||||
&& mlen && (*m & 0x80))
|
|
||||||
{ /* Prepend numbers with a 0 if needed for MPI. */
|
|
||||||
*mbuf = 0;
|
|
||||||
memcpy (mbuf+1, m, mlen);
|
|
||||||
mlen++;
|
|
||||||
}
|
|
||||||
else if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_ECC
|
|
||||||
&& (app->app_local->keyattr[keyno].ecc.flags & ECC_FLAG_DJB_TWEAK))
|
|
||||||
{ /* Prepend 0x40 prefix. */
|
|
||||||
*mbuf = 0x40;
|
|
||||||
memcpy (mbuf+1, m, mlen);
|
|
||||||
mlen++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
memcpy (mbuf, m, mlen);
|
|
||||||
|
|
||||||
if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_RSA)
|
|
||||||
{
|
|
||||||
ebuf = xtrymalloc (elen + 1);
|
|
||||||
if (!ebuf)
|
|
||||||
{
|
|
||||||
err = gpg_error_from_syserror ();
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
/* Prepend numbers with a 0 if needed. */
|
|
||||||
if (elen && (*e & 0x80))
|
|
||||||
{
|
|
||||||
*ebuf = 0;
|
|
||||||
memcpy (ebuf+1, e, elen);
|
|
||||||
elen++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
memcpy (ebuf, e, elen);
|
|
||||||
|
|
||||||
err = gcry_sexp_build (&s_pkey, NULL, "(public-key(rsa(n%b)(e%b)))",
|
err = gcry_sexp_build (&s_pkey, NULL, "(public-key(rsa(n%b)(e%b)))",
|
||||||
(int)mlen, mbuf, (int)elen, ebuf);
|
(int)mlen, m, (int)elen, e);
|
||||||
}
|
if (err)
|
||||||
else if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_ECC)
|
goto leave;
|
||||||
{
|
|
||||||
char *format;
|
|
||||||
|
|
||||||
if (!(app->app_local->keyattr[keyno].ecc.flags & ECC_FLAG_DJB_TWEAK))
|
len = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, NULL, 0);
|
||||||
format = "(public-key(ecc(curve%s)(q%b)))";
|
|
||||||
else if (keyno == 1)
|
|
||||||
format = "(public-key(ecc(curve%s)(flags djb-tweak)(q%b)))";
|
|
||||||
else
|
|
||||||
format = "(public-key(ecc(curve%s)(flags eddsa)(q%b)))";
|
|
||||||
|
|
||||||
err = gcry_sexp_build (&s_pkey, NULL, format,
|
keybuf = xtrymalloc (len);
|
||||||
openpgp_oid_to_curve (app->app_local->keyattr[keyno].ecc.oid, 1),
|
if (!keybuf)
|
||||||
(int)mlen, mbuf);
|
{
|
||||||
}
|
err = gpg_error_from_syserror ();
|
||||||
else
|
gcry_sexp_release (s_pkey);
|
||||||
err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
if (err)
|
gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, keybuf, len);
|
||||||
goto leave;
|
|
||||||
|
|
||||||
len = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, NULL, 0);
|
|
||||||
|
|
||||||
keybuf = xtrymalloc (len);
|
|
||||||
if (!keybuf)
|
|
||||||
{
|
|
||||||
gcry_sexp_release (s_pkey);
|
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);
|
|
||||||
|
|
||||||
app->app_local->pk[keyno].key = (unsigned char*)keybuf;
|
app->app_local->pk[keyno].key = (unsigned char*)keybuf;
|
||||||
app->app_local->pk[keyno].keylen = len - 1; /* Decrement for trailing '\0' */
|
/* Decrement for trailing '\0' */
|
||||||
|
app->app_local->pk[keyno].keylen = len - 1;
|
||||||
|
}
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
/* Set a flag to indicate that we tried to read the key. */
|
/* Set a flag to indicate that we tried to read the key. */
|
||||||
app->app_local->pk[keyno].read_done = 1;
|
app->app_local->pk[keyno].read_done = 1;
|
||||||
|
|
||||||
xfree (buffer);
|
xfree (buffer);
|
||||||
xfree (mbuf);
|
|
||||||
xfree (ebuf);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
#endif /* GNUPG_MAJOR_VERSION > 1 */
|
#endif /* GNUPG_MAJOR_VERSION > 1 */
|
||||||
@ -3533,7 +3673,6 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags,
|
|||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
char numbuf[30];
|
char numbuf[30];
|
||||||
unsigned char fprbuf[20];
|
|
||||||
unsigned char *buffer = NULL;
|
unsigned char *buffer = NULL;
|
||||||
const unsigned char *keydata;
|
const unsigned char *keydata;
|
||||||
size_t buflen, keydatalen;
|
size_t buflen, keydatalen;
|
||||||
@ -3623,117 +3762,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);
|
||||||
|
|
||||||
if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_RSA)
|
err = read_public_key (app, ctrl, created_at, keyno, buffer, buflen);
|
||||||
{
|
|
||||||
const unsigned char *m, *e;
|
|
||||||
size_t mlen, elen;
|
|
||||||
|
|
||||||
m = find_tlv (keydata, keydatalen, 0x0081, &mlen);
|
|
||||||
if (!m)
|
|
||||||
{
|
|
||||||
err = gpg_error (GPG_ERR_CARD);
|
|
||||||
log_error (_("response does not contain the RSA modulus\n"));
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
/* log_printhex ("RSA n:", m, mlen); */
|
|
||||||
send_key_data (ctrl, "n", m, mlen);
|
|
||||||
|
|
||||||
e = find_tlv (keydata, keydatalen, 0x0082, &elen);
|
|
||||||
if (!e)
|
|
||||||
{
|
|
||||||
err = gpg_error (GPG_ERR_CARD);
|
|
||||||
log_error (_("response does not contain the RSA public exponent\n"));
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
/* log_printhex ("RSA e:", e, elen); */
|
|
||||||
send_key_data (ctrl, "e", e, elen);
|
|
||||||
|
|
||||||
for (; mlen && !*m; mlen--, m++) /* strip leading zeroes */
|
|
||||||
;
|
|
||||||
for (; elen && !*e; elen--, e++) /* strip leading zeroes */
|
|
||||||
;
|
|
||||||
|
|
||||||
err = store_fpr (app, keyno, created_at, fprbuf, PUBKEY_ALGO_RSA,
|
|
||||||
m, mlen, e, elen);
|
|
||||||
}
|
|
||||||
else if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_ECC)
|
|
||||||
{
|
|
||||||
const unsigned char *ecc_q;
|
|
||||||
size_t ecc_q_len;
|
|
||||||
gcry_mpi_t oid;
|
|
||||||
int n;
|
|
||||||
const unsigned char *oidbuf;
|
|
||||||
size_t oid_len;
|
|
||||||
int algo;
|
|
||||||
|
|
||||||
ecc_q = find_tlv (keydata, keydatalen, 0x0086, &ecc_q_len);
|
|
||||||
if (!ecc_q)
|
|
||||||
{
|
|
||||||
err = gpg_error (GPG_ERR_CARD);
|
|
||||||
log_error (_("response does not contain the EC public key\n"));
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = openpgp_oid_from_str (app->app_local->keyattr[keyno].ecc.oid, &oid);
|
|
||||||
if (err)
|
|
||||||
goto leave;
|
|
||||||
|
|
||||||
oidbuf = gcry_mpi_get_opaque (oid, &n);
|
|
||||||
if (!oidbuf)
|
|
||||||
{
|
|
||||||
err = gpg_error_from_syserror ();
|
|
||||||
gcry_mpi_release (oid);
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
gcry_mpi_release (oid);
|
|
||||||
oid_len = (n+7)/8;
|
|
||||||
|
|
||||||
if ((app->app_local->keyattr[keyno].ecc.flags & ECC_FLAG_DJB_TWEAK))
|
|
||||||
{ /* Prepend 0x40 prefix. */
|
|
||||||
unsigned char *q = xtrymalloc (ecc_q_len + 1);
|
|
||||||
|
|
||||||
if (!q)
|
|
||||||
{
|
|
||||||
err = gpg_error_from_syserror ();
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
*q = 0x40;
|
|
||||||
memcpy (q+1, ecc_q, ecc_q_len);
|
|
||||||
send_key_data (ctrl, "q", q, ecc_q_len + 1);
|
|
||||||
xfree (q);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* strip leading zeroes */
|
|
||||||
for (; ecc_q_len && !*ecc_q; ecc_q_len--, ecc_q++)
|
|
||||||
;
|
|
||||||
send_key_data (ctrl, "q", ecc_q, ecc_q_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
send_key_data (ctrl, "curve", oidbuf, oid_len);
|
|
||||||
|
|
||||||
if (keyno == 1)
|
|
||||||
{
|
|
||||||
send_key_data (ctrl, "kdf", "\x03\x01\x08\x07", (size_t)4);
|
|
||||||
algo = PUBKEY_ALGO_ECDH;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((app->app_local->keyattr[keyno].ecc.flags & ECC_FLAG_DJB_TWEAK))
|
|
||||||
algo = PUBKEY_ALGO_EDDSA;
|
|
||||||
else
|
|
||||||
algo = PUBKEY_ALGO_ECDSA;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = store_fpr (app, keyno, created_at, fprbuf, algo, oidbuf, oid_len,
|
|
||||||
ecc_q, ecc_q_len, "\x03\x01\x08\x07", (size_t)4);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err)
|
|
||||||
goto leave;
|
|
||||||
send_fpr_if_not_null (ctrl, "KEY-FPR", -1, fprbuf);
|
|
||||||
|
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
xfree (buffer);
|
xfree (buffer);
|
||||||
return err;
|
return err;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user