summaryrefslogtreecommitdiffstats
path: root/scd
diff options
context:
space:
mode:
authorNIIBE Yutaka <gniibe@fsij.org>2020-12-03 07:04:14 +0100
committerNIIBE Yutaka <gniibe@fsij.org>2020-12-03 07:04:14 +0100
commita25c99b156ca9acaa7712e9c09a6df0a7a23c833 (patch)
tree59c7b57436b5791edf7dfd9f771ef63898f86c70 /scd
parentkbx: Better error message in case of a crippled Libgcrypt. (diff)
downloadgnupg2-a25c99b156ca9acaa7712e9c09a6df0a7a23c833.tar.xz
gnupg2-a25c99b156ca9acaa7712e9c09a6df0a7a23c833.zip
scd:openpgp: Fix writing ECC key to card.
* scd/app-openpgp.c (build_privkey_template): Adding another argument of ecc_d_fixed_len to handle variable-size MPI. -- GnuPG-bug-id: 5163 Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
Diffstat (limited to 'scd')
-rw-r--r--scd/app-openpgp.c33
1 files changed, 27 insertions, 6 deletions
diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index a30a8e8b5..7a2aebe70 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -3711,6 +3711,7 @@ build_privkey_template (app_t app, int keyno,
static gpg_error_t
build_ecc_privkey_template (app_t app, int keyno,
const unsigned char *ecc_d, size_t ecc_d_len,
+ size_t ecc_d_fixed_len,
const unsigned char *ecc_q, size_t ecc_q_len,
unsigned char **result, size_t *resultlen)
{
@@ -3726,6 +3727,18 @@ build_ecc_privkey_template (app_t app, int keyno,
size_t template_size;
int pubkey_required;
+ /* This case doesn't occur in GnuPG 2.3 or later, because
+ agent/sexp-secret.c does the fixup. */
+ if (ecc_d_fixed_len < ecc_d_len)
+ {
+ if (ecc_d_fixed_len != ecc_d_len - 1 || *ecc_d)
+ return gpg_error (GPG_ERR_INV_OBJ);
+
+ /* Remove the additional zero. */
+ ecc_d_len--;
+ ecc_d++;
+ }
+
pubkey_required = !!(app->app_local->keyattr[keyno].ecc.flags
& ECC_FLAG_PUBKEY);
@@ -3736,8 +3749,8 @@ build_ecc_privkey_template (app_t app, int keyno,
datalen = 0;
tp = privkey;
- tp += add_tlv (tp, 0x92, ecc_d_len);
- datalen += ecc_d_len;
+ tp += add_tlv (tp, 0x92, ecc_d_fixed_len);
+ datalen += ecc_d_fixed_len;
if (pubkey_required)
{
@@ -3780,8 +3793,14 @@ build_ecc_privkey_template (app_t app, int keyno,
memcpy (tp, suffix, suffix_len);
tp += suffix_len;
- memcpy (tp, ecc_d, ecc_d_len);
- tp += ecc_d_len;
+ if (ecc_d_fixed_len > ecc_d_len)
+ {
+ memset (tp, 0, ecc_d_fixed_len - ecc_d_len);
+ memcpy (tp + ecc_d_fixed_len - ecc_d_len, ecc_d, ecc_d_len);
+ }
+ else
+ memcpy (tp, ecc_d, ecc_d_len);
+ tp += ecc_d_fixed_len;
if (pubkey_required)
{
@@ -4406,6 +4425,7 @@ ecc_writekey (app_t app, ctrl_t ctrl,
unsigned int n;
size_t oid_len;
unsigned char fprbuf[20];
+ size_t ecc_d_fixed_len;
/* (private-key(ecc(curve%s)(q%m)(d%m))(created-at%d)):
curve = "NIST P-256" */
@@ -4548,7 +4568,8 @@ ecc_writekey (app_t app, ctrl_t ctrl,
else
algo = PUBKEY_ALGO_ECDSA;
- oidstr = openpgp_curve_to_oid (curve, NULL, NULL);
+ oidstr = openpgp_curve_to_oid (curve, &n, NULL);
+ ecc_d_fixed_len = (n+7)/8;
err = openpgp_oid_from_str (oidstr, &oid);
if (err)
goto leave;
@@ -4614,7 +4635,7 @@ ecc_writekey (app_t app, ctrl_t ctrl,
int exmode;
err = build_ecc_privkey_template (app, keyno,
- ecc_d, ecc_d_len,
+ ecc_d, ecc_d_len, ecc_d_fixed_len,
ecc_q, ecc_q_len,
&template, &template_len);
if (err)