1
0
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:
Werner Koch 2023-10-10 16:09:26 +02:00
parent d25e960652
commit b262a21c61
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B

View File

@ -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;