mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-09 12:54:23 +01:00
scd:openpgp: Support the ecdh-params arg for writing keys.
* scd/app-openpgp.c (ecc_writekey): Use provided ECDH params to compute the fingerprint. Add a default for use by gnupg 2.2. (store_fpr): Add arg update. (rsa_read_pubkey, ecc_read_pubkey): Add arg meta_update and avoid writing the fingerprint back to the card if not set. (read_public_key): Also add arg meta_update. (get_public_key): Do not pass it as true here... (do_genkey): ... but here. -- This is based on commit c03ba92576e34f791430ab1c68814ff16c81407b and done here to ease backporting. There is no functional change. GnuPG-bug-id: 6378
This commit is contained in:
parent
d25e960652
commit
b262a21c61
@ -824,10 +824,12 @@ parse_login_data (app_t app)
|
||||
|
||||
#define MAX_ARGS_STORE_FPR 3
|
||||
|
||||
/* Note, that FPR must be at least 20 bytes. */
|
||||
/* Note, that FPR must be at least 20 bytes. If UPDATE is not set,
|
||||
* the fingerprint and the creation date is not actually stored but
|
||||
* the fingerprint is only returned in FPR. */
|
||||
static gpg_error_t
|
||||
store_fpr (app_t app, int keynumber, u32 timestamp, unsigned char *fpr,
|
||||
int algo, ...)
|
||||
store_fpr (app_t app, int update, int keynumber, u32 timestamp,
|
||||
unsigned char *fpr, int algo, ...)
|
||||
{
|
||||
unsigned int n, nbits;
|
||||
unsigned char *buffer, *p;
|
||||
@ -892,6 +894,9 @@ store_fpr (app_t app, int keynumber, u32 timestamp, unsigned char *fpr,
|
||||
|
||||
xfree (buffer);
|
||||
|
||||
if (!update)
|
||||
return 0;
|
||||
|
||||
tag = (app->appversion > 0x0007? 0xC7 : 0xC6) + keynumber;
|
||||
flush_cache_item (app, 0xC5);
|
||||
tag2 = 0xCE + keynumber;
|
||||
@ -1539,7 +1544,8 @@ retrieve_key_material (FILE *fp, const char *hexkeyid,
|
||||
|
||||
|
||||
static gpg_error_t
|
||||
rsa_read_pubkey (app_t app, ctrl_t ctrl, u32 created_at, int keyno,
|
||||
rsa_read_pubkey (app_t app, ctrl_t ctrl, int meta_update,
|
||||
u32 created_at, int keyno,
|
||||
const unsigned char *data, size_t datalen, gcry_sexp_t *r_sexp)
|
||||
{
|
||||
gpg_error_t err;
|
||||
@ -1576,7 +1582,11 @@ rsa_read_pubkey (app_t app, ctrl_t ctrl, u32 created_at, int keyno,
|
||||
{
|
||||
unsigned char fprbuf[20];
|
||||
|
||||
err = store_fpr (app, keyno, created_at, fprbuf, PUBKEY_ALGO_RSA,
|
||||
/* If META_UPDATE is not set we only compute but not store the
|
||||
* fingerprint. This might return a wrong fingerprint if
|
||||
* CREATED_AT is not set. */
|
||||
err = store_fpr (app, meta_update, keyno,
|
||||
created_at, fprbuf, PUBKEY_ALGO_RSA,
|
||||
m, mlen, e, elen);
|
||||
if (err)
|
||||
return err;
|
||||
@ -1638,6 +1648,8 @@ ecdh_params (const char *curve)
|
||||
0x01: Version for this parameter format
|
||||
KDF hash algo
|
||||
KEK symmetric cipher algo
|
||||
Take care: They should match the parameters as used in g10/ecdh.c
|
||||
as long as the ecdh-param is not fully support (as in gnupg 2.2).
|
||||
*/
|
||||
if (nbits <= 256)
|
||||
return (const unsigned char*)"\x03\x01\x08\x07";
|
||||
@ -1648,7 +1660,8 @@ ecdh_params (const char *curve)
|
||||
}
|
||||
|
||||
static gpg_error_t
|
||||
ecc_read_pubkey (app_t app, ctrl_t ctrl, u32 created_at, int keyno,
|
||||
ecc_read_pubkey (app_t app, ctrl_t ctrl, int meta_update,
|
||||
u32 created_at, int keyno,
|
||||
const unsigned char *data, size_t datalen, gcry_sexp_t *r_sexp)
|
||||
{
|
||||
gpg_error_t err;
|
||||
@ -1724,7 +1737,12 @@ ecc_read_pubkey (app_t app, ctrl_t ctrl, u32 created_at, int keyno,
|
||||
{
|
||||
unsigned char fprbuf[20];
|
||||
|
||||
err = store_fpr (app, keyno, created_at, fprbuf, algo, oidbuf, oid_len,
|
||||
/* If META_UPDATE is not set we only compute but not store the
|
||||
* fingerprint. This might return a wrong fingerprint if
|
||||
* CREATED_AT is not set or the ECDH params do not match the
|
||||
* current defaults. */
|
||||
err = store_fpr (app, meta_update, keyno,
|
||||
created_at, fprbuf, algo, oidbuf, oid_len,
|
||||
qbuf, ecc_q_len, ecdh_params (curve), (size_t)4);
|
||||
if (err)
|
||||
goto leave;
|
||||
@ -1768,13 +1786,15 @@ store_keygrip (app_t app, int keyno)
|
||||
|
||||
|
||||
/* 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.
|
||||
* length. Key of KEYNO in APP is updated with an S-expression of
|
||||
* public key. If CTRL is not NULL, the fingerprint is computed with
|
||||
* CREATED_AT and key data and fingerprint are send back to the client
|
||||
* side. If also META_UPDATE is true the fingerprint and the creation
|
||||
* date are also written to the card.
|
||||
*/
|
||||
static gpg_error_t
|
||||
read_public_key (app_t app, ctrl_t ctrl, u32 created_at, int keyno,
|
||||
read_public_key (app_t app, ctrl_t ctrl, int meta_update,
|
||||
u32 created_at, int keyno,
|
||||
const unsigned char *buffer, size_t buflen)
|
||||
{
|
||||
gpg_error_t err;
|
||||
@ -1790,10 +1810,10 @@ read_public_key (app_t app, ctrl_t ctrl, u32 created_at, int keyno,
|
||||
}
|
||||
|
||||
if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_RSA)
|
||||
err = rsa_read_pubkey (app, ctrl, created_at, keyno,
|
||||
err = rsa_read_pubkey (app, ctrl, meta_update, 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,
|
||||
err = ecc_read_pubkey (app, ctrl, meta_update, created_at, keyno,
|
||||
data, datalen, &s_pkey);
|
||||
else
|
||||
err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
||||
@ -1897,7 +1917,11 @@ get_public_key (app_t app, int keyno)
|
||||
goto leave;
|
||||
}
|
||||
|
||||
err = read_public_key (app, NULL, 0U, keyno, buffer, buflen);
|
||||
/* Note that we use 0 for the creation date and thus the - via
|
||||
* status lines - returned fingerprint will only be valid if the
|
||||
* key has also been created with that date. A similar problem
|
||||
* occurs with the ECDH params which are fixed in the code. */
|
||||
err = read_public_key (app, NULL, 0, 0U, keyno, buffer, buflen);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -4156,7 +4180,7 @@ rsa_writekey (app_t app, ctrl_t ctrl,
|
||||
goto leave;
|
||||
}
|
||||
|
||||
err = store_fpr (app, keyno, created_at, fprbuf, PUBKEY_ALGO_RSA,
|
||||
err = store_fpr (app, 1, keyno, created_at, fprbuf, PUBKEY_ALGO_RSA,
|
||||
rsa_n, rsa_n_len, rsa_e, rsa_e_len);
|
||||
if (err)
|
||||
goto leave;
|
||||
@ -4181,6 +4205,8 @@ ecc_writekey (app_t app, ctrl_t ctrl,
|
||||
const unsigned char *ecc_q = NULL;
|
||||
const unsigned char *ecc_d = NULL;
|
||||
size_t ecc_q_len, ecc_d_len;
|
||||
const unsigned char *ecdh_param = NULL;
|
||||
size_t ecdh_param_len = 0;
|
||||
const char *curve = NULL;
|
||||
u32 created_at = 0;
|
||||
const char *oidstr;
|
||||
@ -4193,7 +4219,7 @@ ecc_writekey (app_t app, ctrl_t ctrl,
|
||||
unsigned char fprbuf[20];
|
||||
size_t ecc_d_fixed_len;
|
||||
|
||||
/* (private-key(ecc(curve%s)(q%m)(d%m))(created-at%d)):
|
||||
/* (private-key(ecc(curve%s)(q%m)(d%m))(created-at%d)(ecdh-params%s)):
|
||||
curve = "NIST P-256" */
|
||||
/* (private-key(ecc(curve%s)(q%m)(d%m))(created-at%d)):
|
||||
curve = "secp256k1" */
|
||||
@ -4292,6 +4318,7 @@ ecc_writekey (app_t app, ctrl_t ctrl,
|
||||
}
|
||||
if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
|
||||
goto leave;
|
||||
|
||||
if (tok && toklen == 10 && !memcmp ("created-at", tok, toklen))
|
||||
{
|
||||
if ((err = parse_sexp (&buf,&buflen,&depth,&tok,&toklen)))
|
||||
@ -4303,6 +4330,17 @@ ecc_writekey (app_t app, ctrl_t ctrl,
|
||||
created_at = created_at*10 + (*tok - '0');
|
||||
}
|
||||
}
|
||||
else if (tok && toklen == 11 && !memcmp ("ecdh-params", tok, toklen))
|
||||
{
|
||||
if ((err = parse_sexp (&buf,&buflen,&depth,&tok,&toklen)))
|
||||
goto leave;
|
||||
if (tok)
|
||||
{
|
||||
ecdh_param = tok;
|
||||
ecdh_param_len = toklen;
|
||||
}
|
||||
}
|
||||
|
||||
/* Skip until end of list. */
|
||||
last_depth2 = depth;
|
||||
while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))
|
||||
@ -4334,6 +4372,20 @@ ecc_writekey (app_t app, ctrl_t ctrl,
|
||||
else
|
||||
algo = PUBKEY_ALGO_ECDSA;
|
||||
|
||||
/* Not provided by GnuPG 2.2 - take the default value. */
|
||||
if (algo == PUBKEY_ALGO_ECDH && !ecdh_param)
|
||||
{
|
||||
ecdh_param = ecdh_params (curve);
|
||||
ecdh_param_len = 4;
|
||||
}
|
||||
|
||||
if (algo == PUBKEY_ALGO_ECDH && !ecdh_param)
|
||||
{
|
||||
log_error ("opgp: ecdh parameters missing\n");
|
||||
err = gpg_error (GPG_ERR_INV_VALUE);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
oidstr = openpgp_curve_to_oid (curve, &n, NULL);
|
||||
ecc_d_fixed_len = (n+7)/8;
|
||||
err = openpgp_oid_from_str (oidstr, &oid);
|
||||
@ -4435,8 +4487,8 @@ ecc_writekey (app_t app, ctrl_t ctrl,
|
||||
goto leave;
|
||||
}
|
||||
|
||||
err = store_fpr (app, keyno, created_at, fprbuf, algo, oidbuf, oid_len,
|
||||
ecc_q, ecc_q_len, ecdh_params (curve), (size_t)4);
|
||||
err = store_fpr (app, 1, keyno, created_at, fprbuf, algo, oidbuf, oid_len,
|
||||
ecc_q, ecc_q_len, ecdh_param, ecdh_param_len);
|
||||
|
||||
leave:
|
||||
gcry_mpi_release (oid);
|
||||
@ -4661,7 +4713,7 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keyref, const char *keyalgo,
|
||||
send_status_info (ctrl, "KEY-CREATED-AT",
|
||||
numbuf, (size_t)strlen(numbuf), NULL, 0);
|
||||
|
||||
err = read_public_key (app, ctrl, created_at, keyno, buffer, buflen);
|
||||
err = read_public_key (app, ctrl, 1, created_at, keyno, buffer, buflen);
|
||||
leave:
|
||||
xfree (buffer);
|
||||
return err;
|
||||
|
Loading…
x
Reference in New Issue
Block a user