mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-23 15:07:03 +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
|
#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
|
static gpg_error_t
|
||||||
store_fpr (app_t app, int keynumber, u32 timestamp, unsigned char *fpr,
|
store_fpr (app_t app, int update, int keynumber, u32 timestamp,
|
||||||
int algo, ...)
|
unsigned char *fpr, int algo, ...)
|
||||||
{
|
{
|
||||||
unsigned int n, nbits;
|
unsigned int n, nbits;
|
||||||
unsigned char *buffer, *p;
|
unsigned char *buffer, *p;
|
||||||
@ -892,6 +894,9 @@ store_fpr (app_t app, int keynumber, u32 timestamp, unsigned char *fpr,
|
|||||||
|
|
||||||
xfree (buffer);
|
xfree (buffer);
|
||||||
|
|
||||||
|
if (!update)
|
||||||
|
return 0;
|
||||||
|
|
||||||
tag = (app->appversion > 0x0007? 0xC7 : 0xC6) + keynumber;
|
tag = (app->appversion > 0x0007? 0xC7 : 0xC6) + keynumber;
|
||||||
flush_cache_item (app, 0xC5);
|
flush_cache_item (app, 0xC5);
|
||||||
tag2 = 0xCE + keynumber;
|
tag2 = 0xCE + keynumber;
|
||||||
@ -1539,7 +1544,8 @@ retrieve_key_material (FILE *fp, const char *hexkeyid,
|
|||||||
|
|
||||||
|
|
||||||
static gpg_error_t
|
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)
|
const unsigned char *data, size_t datalen, gcry_sexp_t *r_sexp)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
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];
|
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);
|
m, mlen, e, elen);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
@ -1638,6 +1648,8 @@ ecdh_params (const char *curve)
|
|||||||
0x01: Version for this parameter format
|
0x01: Version for this parameter format
|
||||||
KDF hash algo
|
KDF hash algo
|
||||||
KEK symmetric cipher 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)
|
if (nbits <= 256)
|
||||||
return (const unsigned char*)"\x03\x01\x08\x07";
|
return (const unsigned char*)"\x03\x01\x08\x07";
|
||||||
@ -1648,7 +1660,8 @@ ecdh_params (const char *curve)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gpg_error_t
|
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)
|
const unsigned char *data, size_t datalen, gcry_sexp_t *r_sexp)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
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];
|
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);
|
qbuf, ecc_q_len, ecdh_params (curve), (size_t)4);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
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
|
/* 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
|
* length. Key of KEYNO in APP is updated with an S-expression of
|
||||||
public key. When CTRL is not NULL, fingerprint is computed with
|
* public key. If CTRL is not NULL, the fingerprint is computed with
|
||||||
CREATED_AT, and fingerprint is written to the card, and key data
|
* CREATED_AT and key data and fingerprint are send back to the client
|
||||||
and fingerprint are send back to the client side.
|
* side. If also META_UPDATE is true the fingerprint and the creation
|
||||||
|
* date are also written to the card.
|
||||||
*/
|
*/
|
||||||
static gpg_error_t
|
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)
|
const unsigned char *buffer, size_t buflen)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
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)
|
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);
|
data, datalen, &s_pkey);
|
||||||
else if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_ECC)
|
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);
|
data, datalen, &s_pkey);
|
||||||
else
|
else
|
||||||
err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
||||||
@ -1897,7 +1917,11 @@ get_public_key (app_t app, int keyno)
|
|||||||
goto leave;
|
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
|
else
|
||||||
{
|
{
|
||||||
@ -4156,7 +4180,7 @@ rsa_writekey (app_t app, ctrl_t ctrl,
|
|||||||
goto leave;
|
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);
|
rsa_n, rsa_n_len, rsa_e, rsa_e_len);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
@ -4181,6 +4205,8 @@ ecc_writekey (app_t app, ctrl_t ctrl,
|
|||||||
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;
|
||||||
|
const unsigned char *ecdh_param = NULL;
|
||||||
|
size_t ecdh_param_len = 0;
|
||||||
const char *curve = NULL;
|
const char *curve = NULL;
|
||||||
u32 created_at = 0;
|
u32 created_at = 0;
|
||||||
const char *oidstr;
|
const char *oidstr;
|
||||||
@ -4193,7 +4219,7 @@ ecc_writekey (app_t app, ctrl_t ctrl,
|
|||||||
unsigned char fprbuf[20];
|
unsigned char fprbuf[20];
|
||||||
size_t ecc_d_fixed_len;
|
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" */
|
curve = "NIST P-256" */
|
||||||
/* (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 = "secp256k1" */
|
curve = "secp256k1" */
|
||||||
@ -4292,6 +4318,7 @@ ecc_writekey (app_t app, ctrl_t ctrl,
|
|||||||
}
|
}
|
||||||
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 ("created-at", tok, toklen))
|
if (tok && toklen == 10 && !memcmp ("created-at", tok, toklen))
|
||||||
{
|
{
|
||||||
if ((err = parse_sexp (&buf,&buflen,&depth,&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');
|
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. */
|
/* Skip until end of list. */
|
||||||
last_depth2 = depth;
|
last_depth2 = depth;
|
||||||
while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))
|
while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))
|
||||||
@ -4334,6 +4372,20 @@ ecc_writekey (app_t app, ctrl_t ctrl,
|
|||||||
else
|
else
|
||||||
algo = PUBKEY_ALGO_ECDSA;
|
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);
|
oidstr = openpgp_curve_to_oid (curve, &n, NULL);
|
||||||
ecc_d_fixed_len = (n+7)/8;
|
ecc_d_fixed_len = (n+7)/8;
|
||||||
err = openpgp_oid_from_str (oidstr, &oid);
|
err = openpgp_oid_from_str (oidstr, &oid);
|
||||||
@ -4435,8 +4487,8 @@ ecc_writekey (app_t app, ctrl_t ctrl,
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = store_fpr (app, keyno, created_at, fprbuf, algo, oidbuf, oid_len,
|
err = store_fpr (app, 1, keyno, created_at, fprbuf, algo, oidbuf, oid_len,
|
||||||
ecc_q, ecc_q_len, ecdh_params (curve), (size_t)4);
|
ecc_q, ecc_q_len, ecdh_param, ecdh_param_len);
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
gcry_mpi_release (oid);
|
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",
|
send_status_info (ctrl, "KEY-CREATED-AT",
|
||||||
numbuf, (size_t)strlen(numbuf), NULL, 0);
|
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:
|
leave:
|
||||||
xfree (buffer);
|
xfree (buffer);
|
||||||
return err;
|
return err;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user