mirror of
git://git.gnupg.org/gnupg.git
synced 2025-07-02 22:46:30 +02:00
Curve25519 support.
* agent/cvt-openpgp.c (get_keygrip): Handle Curve25519. (convert_secret_key, convert_transfer_key): Ditto. * common/openpgp-oid.c (oidtable): Add Curve25519. (oid_crv25519, openpgp_oid_is_crv25519): New. * common/util.h (openpgp_oid_is_crv25519): New. * g10/ecdh.c (pk_ecdh_encrypt_with_shared_point): Handle the case with Montgomery curve which uses x-only coordinate. * g10/keygen.c (gen_ecc): Handle Curve25519. (ask_curve): Change the API and second arg is to return subkey algo. (generate_keypair, generate_subkeypair): Follow chage of ask_curve. * g10/keyid.c (keygrip_from_pk): Handle Curve25519. * g10/pkglue.c (pk_encrypt): Handle Curve25519. * g10/pubkey-enc.c (get_it): Handle the case with Montgomery curve. * scd/app-openpgp.c (ECC_FLAG_DJB_TWEAK): New. (send_key_attr): Work with general ECC, Ed25519, and Curve25519. (get_public_key): Likewise. (ecc_writekey): Handle flag_djb_tweak. -- When libgcrypt has Curve25519, GnuPG now supports Curve25519.
This commit is contained in:
parent
a6e4053089
commit
e5891a82c3
9 changed files with 181 additions and 105 deletions
|
@ -235,7 +235,7 @@ struct app_local_s {
|
|||
} keyattr[3];
|
||||
};
|
||||
|
||||
#define ECC_FLAG_EDDSA (1 << 0)
|
||||
#define ECC_FLAG_DJB_TWEAK (1 << 0)
|
||||
|
||||
|
||||
/***** Local prototypes *****/
|
||||
|
@ -909,8 +909,9 @@ send_key_attr (ctrl_t ctrl, app_t app, const char *keyword, int keyno)
|
|||
{
|
||||
snprintf (buffer, sizeof buffer, "%d %d %s",
|
||||
keyno+1,
|
||||
app->app_local->keyattr[keyno].ecc.flags? PUBKEY_ALGO_EDDSA:
|
||||
(keyno==1? PUBKEY_ALGO_ECDH: PUBKEY_ALGO_ECDSA),
|
||||
keyno==1? PUBKEY_ALGO_ECDH :
|
||||
app->app_local->keyattr[keyno].ecc.flags?
|
||||
PUBKEY_ALGO_EDDSA : PUBKEY_ALGO_ECDSA,
|
||||
openpgp_oid_to_curve (app->app_local->keyattr[keyno].ecc.oid, 0));
|
||||
}
|
||||
else
|
||||
|
@ -1378,59 +1379,52 @@ get_public_key (app_t app, int keyno)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
mbuf = xtrymalloc ( mlen + 1);
|
||||
mbuf = xtrymalloc (mlen + 1);
|
||||
if (!mbuf)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
/* Prepend numbers with a 0 if needed. */
|
||||
|
||||
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))
|
||||
&& 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)
|
||||
{ /* Prepend 0x40 prefix. */
|
||||
*mbuf = 0x40;
|
||||
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);
|
||||
|
||||
if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_RSA)
|
||||
{
|
||||
err = gcry_sexp_build (&s_pkey, NULL, "(public-key(rsa(n%b)(e%b)))",
|
||||
(int)mlen, mbuf, (int)elen, ebuf);
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
len = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, NULL, 0);
|
||||
keybuf = xtrymalloc (len);
|
||||
if (!keybuf)
|
||||
ebuf = xtrymalloc (elen + 1);
|
||||
if (!ebuf)
|
||||
{
|
||||
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);
|
||||
/* 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)))",
|
||||
(int)mlen, mbuf, (int)elen, ebuf);
|
||||
}
|
||||
else if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_ECC)
|
||||
{
|
||||
|
@ -1438,32 +1432,32 @@ get_public_key (app_t app, int keyno)
|
|||
|
||||
if (!app->app_local->keyattr[keyno].ecc.flags)
|
||||
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,
|
||||
openpgp_oid_to_curve (app->app_local->keyattr[keyno].ecc.oid, 1),
|
||||
(int)mlen, mbuf);
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
len = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, NULL, 0);
|
||||
|
||||
keybuf = xtrymalloc (len);
|
||||
if (!keybuf)
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
||||
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
len = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, NULL, 0);
|
||||
|
||||
keybuf = xtrymalloc (len);
|
||||
if (!keybuf)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
||||
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].keylen = len - 1; /* Decrement for trailing '\0' */
|
||||
|
@ -3171,7 +3165,7 @@ ecc_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **),
|
|||
size_t ecc_q_len, ecc_d_len;
|
||||
u32 created_at = 0;
|
||||
const char *oidstr = NULL;
|
||||
int flag_eddsa = 0;
|
||||
int flag_djb_tweak = 0;
|
||||
int algo;
|
||||
|
||||
/* (private-key(ecc(curve%s)(q%m)(d%m))(created-at%d)):
|
||||
|
@ -3216,8 +3210,12 @@ ecc_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **),
|
|||
if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
|
||||
goto leave;
|
||||
|
||||
if (tok && toklen == 5 && !memcmp (tok, "eddsa", 5))
|
||||
flag_eddsa = 1;
|
||||
if (tok)
|
||||
{
|
||||
if ((toklen == 5 && !memcmp (tok, "eddsa", 5))
|
||||
|| (toklen == 9 && !memcmp (tok, "djb-tweak", 9)))
|
||||
flag_djb_tweak = 1;
|
||||
}
|
||||
}
|
||||
else if (tok && toklen == 1)
|
||||
{
|
||||
|
@ -3237,7 +3235,7 @@ ecc_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **),
|
|||
}
|
||||
if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
|
||||
goto leave;
|
||||
if (tok && buf2 && !flag_eddsa)
|
||||
if (tok && buf2 && !flag_djb_tweak)
|
||||
/* It's MPI. Strip off leading zero bytes and save. */
|
||||
for (;toklen && !*tok; toklen--, tok++)
|
||||
;
|
||||
|
@ -3300,7 +3298,7 @@ ecc_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **),
|
|||
err = gpg_error (GPG_ERR_INV_VALUE);
|
||||
goto leave;
|
||||
}
|
||||
if (flag_eddsa && keyno != 1)
|
||||
if (flag_djb_tweak && keyno != 1)
|
||||
algo = PUBKEY_ALGO_EDDSA;
|
||||
else if (keyno == 1)
|
||||
algo = PUBKEY_ALGO_ECDH;
|
||||
|
@ -3309,7 +3307,7 @@ ecc_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **),
|
|||
|
||||
if (app->app_local->keyattr[keyno].key_type != KEY_TYPE_ECC
|
||||
|| app->app_local->keyattr[keyno].ecc.oid != oidstr
|
||||
|| app->app_local->keyattr[keyno].ecc.flags != flag_eddsa)
|
||||
|| app->app_local->keyattr[keyno].ecc.flags != flag_djb_tweak)
|
||||
{
|
||||
log_error ("key attribute on card doesn't match\n");
|
||||
err = gpg_error (GPG_ERR_INV_VALUE);
|
||||
|
@ -4469,11 +4467,18 @@ parse_algorithm_attribute (app_t app, int keyno)
|
|||
{
|
||||
app->app_local->keyattr[keyno].key_type = KEY_TYPE_ECC;
|
||||
app->app_local->keyattr[keyno].ecc.oid = oid;
|
||||
app->app_local->keyattr[keyno].ecc.flags = (*buffer == PUBKEY_ALGO_EDDSA);
|
||||
if (*buffer == PUBKEY_ALGO_EDDSA
|
||||
|| (*buffer == PUBKEY_ALGO_ECDH
|
||||
&& !strcmp (app->app_local->keyattr[keyno].ecc.oid,
|
||||
"1.3.6.1.4.1.3029.1.5.1")))
|
||||
app->app_local->keyattr[keyno].ecc.flags = ECC_FLAG_DJB_TWEAK;
|
||||
else
|
||||
app->app_local->keyattr[keyno].ecc.flags = 0;
|
||||
if (opt.verbose)
|
||||
log_printf
|
||||
("ECC, curve=%s%s\n", app->app_local->keyattr[keyno].ecc.oid,
|
||||
app->app_local->keyattr[keyno].ecc.flags ? " (eddsa)": "");
|
||||
!app->app_local->keyattr[keyno].ecc.flags ? "":
|
||||
keyno==1? " (djb-tweak)": " (eddsa)");
|
||||
}
|
||||
}
|
||||
else if (opt.verbose)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue