mirror of
git://git.gnupg.org/gnupg.git
synced 2025-04-17 15:44:34 +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
@ -83,14 +83,25 @@ get_keygrip (int pubkey_algo, const char *curve, gcry_mpi_t *pkey,
|
|||||||
case GCRY_PK_ECC:
|
case GCRY_PK_ECC:
|
||||||
if (!curve)
|
if (!curve)
|
||||||
err = gpg_error (GPG_ERR_BAD_SECKEY);
|
err = gpg_error (GPG_ERR_BAD_SECKEY);
|
||||||
else if (!strcmp (curve, openpgp_curve_to_oid ("Ed25519", NULL)))
|
|
||||||
err = gcry_sexp_build (&s_pkey, NULL,
|
|
||||||
"(public-key(ecc(curve %s)(flags eddsa)(q%m)))",
|
|
||||||
"Ed25519", pkey[0]);
|
|
||||||
else
|
else
|
||||||
err = gcry_sexp_build (&s_pkey, NULL,
|
{
|
||||||
"(public-key(ecc(curve %s)(q%m)))",
|
const char *format;
|
||||||
curve, pkey[0]);
|
|
||||||
|
if (!strcmp (curve, openpgp_curve_to_oid ("Ed25519", NULL)))
|
||||||
|
{
|
||||||
|
format = "(public-key(ecc(curve %s)(flags eddsa)(q%m)))";
|
||||||
|
curve = "Ed25519";
|
||||||
|
}
|
||||||
|
else if (!strcmp (curve, openpgp_curve_to_oid ("Curve25519", NULL)))
|
||||||
|
{
|
||||||
|
format = "(public-key(ecc(curve %s)(flags djb-tweak)(q%m)))";
|
||||||
|
curve = "Curve25519";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
format = "(public-key(ecc(curve %s)(q%m)))";
|
||||||
|
|
||||||
|
err = gcry_sexp_build (&s_pkey, NULL, format, curve, pkey[0]);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -146,19 +157,27 @@ convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey,
|
|||||||
case GCRY_PK_ECC:
|
case GCRY_PK_ECC:
|
||||||
if (!curve)
|
if (!curve)
|
||||||
err = gpg_error (GPG_ERR_BAD_SECKEY);
|
err = gpg_error (GPG_ERR_BAD_SECKEY);
|
||||||
else if (!strcmp (curve, openpgp_curve_to_oid ("Ed25519", NULL)))
|
else
|
||||||
|
{
|
||||||
|
const char *format;
|
||||||
|
|
||||||
|
if (!strcmp (curve, openpgp_curve_to_oid ("Ed25519", NULL)))
|
||||||
{
|
{
|
||||||
/* Do not store the OID as name but the real name and the
|
/* Do not store the OID as name but the real name and the
|
||||||
EdDSA flag. */
|
EdDSA flag. */
|
||||||
err = gcry_sexp_build (&s_skey, NULL,
|
format = "(private-key(ecc(curve %s)(flags eddsa)(q%m)(d%m)))";
|
||||||
"(private-key(ecc(curve%s)(flags eddsa)"
|
curve = "Ed25519";
|
||||||
"(q%m)(d%m)))",
|
}
|
||||||
"Ed25519", skey[0], skey[1]);
|
else if (!strcmp (curve, openpgp_curve_to_oid ("Curve25519", NULL)))
|
||||||
|
{
|
||||||
|
format = "(private-key(ecc(curve %s)(flags djb-tweak)(q%m)(d%m)))";
|
||||||
|
curve = "Curve25519";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
err = gcry_sexp_build (&s_skey, NULL,
|
format = "(private-key(ecc(curve %s)(q%m)(d%m)))";
|
||||||
"(private-key(ecc(curve%s)(q%m)(d%m)))",
|
|
||||||
curve, skey[0], skey[1]);
|
err = gcry_sexp_build (&s_skey, NULL, format, curve, skey[0], skey[1]);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -216,22 +235,30 @@ convert_transfer_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey,
|
|||||||
case GCRY_PK_ECC:
|
case GCRY_PK_ECC:
|
||||||
if (!curve)
|
if (!curve)
|
||||||
err = gpg_error (GPG_ERR_BAD_SECKEY);
|
err = gpg_error (GPG_ERR_BAD_SECKEY);
|
||||||
else if (!strcmp (curve, openpgp_curve_to_oid ("Ed25519", NULL)))
|
else
|
||||||
|
{
|
||||||
|
const char *format;
|
||||||
|
|
||||||
|
if (!strcmp (curve, openpgp_curve_to_oid ("Ed25519", NULL)))
|
||||||
{
|
{
|
||||||
/* Do not store the OID as name but the real name and the
|
/* Do not store the OID as name but the real name and the
|
||||||
EdDSA flag. */
|
EdDSA flag. */
|
||||||
err = gcry_sexp_build
|
format = "(protected-private-key(ecc(curve %s)(flags eddsa)(q%m)"
|
||||||
(&s_skey, NULL,
|
"(protected openpgp-native%S)))";
|
||||||
"(protected-private-key(ecc(curve%s)(flags eddsa)(q%m)"
|
curve = "Ed25519";
|
||||||
"(protected openpgp-native%S)))",
|
}
|
||||||
"Ed25519", skey[0], transfer_key);
|
else if (!strcmp (curve, openpgp_curve_to_oid ("Curve25519", NULL)))
|
||||||
|
{
|
||||||
|
format = "(protected-private-key(ecc(curve %s)(flags djb-tweak)(q%m)"
|
||||||
|
"(protected openpgp-native%S)))";
|
||||||
|
curve = "Curve25519";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
err = gcry_sexp_build
|
format = "(protected-private-key(ecc(curve %s)(q%m)"
|
||||||
(&s_skey, NULL,
|
"(protected openpgp-native%S)))";
|
||||||
"(protected-private-key(ecc(curve%s)(q%m)"
|
|
||||||
"(protected openpgp-native%S)))",
|
err = gcry_sexp_build (&s_skey, NULL, format, curve, skey[0], transfer_key);
|
||||||
curve, skey[0], transfer_key);
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -45,6 +45,7 @@ static struct {
|
|||||||
const char *alias; /* NULL or alternative name of the curve. */
|
const char *alias; /* NULL or alternative name of the curve. */
|
||||||
} oidtable[] = {
|
} oidtable[] = {
|
||||||
|
|
||||||
|
{ "Curve25519", "1.3.6.1.4.1.3029.1.5.1", 255, "crv25519" },
|
||||||
{ "Ed25519", "1.3.6.1.4.1.11591.15.1", 255, "ed25519" },
|
{ "Ed25519", "1.3.6.1.4.1.11591.15.1", 255, "ed25519" },
|
||||||
|
|
||||||
{ "NIST P-256", "1.2.840.10045.3.1.7", 256, "nistp256" },
|
{ "NIST P-256", "1.2.840.10045.3.1.7", 256, "nistp256" },
|
||||||
@ -65,6 +66,10 @@ static struct {
|
|||||||
static const char oid_ed25519[] =
|
static const char oid_ed25519[] =
|
||||||
{ 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xda, 0x47, 0x0f, 0x01 };
|
{ 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xda, 0x47, 0x0f, 0x01 };
|
||||||
|
|
||||||
|
/* The OID for Curve25519 in OpenPGP format. */
|
||||||
|
static const char oid_crv25519[] =
|
||||||
|
{ 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01 };
|
||||||
|
|
||||||
|
|
||||||
/* Helper for openpgp_oid_from_str. */
|
/* Helper for openpgp_oid_from_str. */
|
||||||
static size_t
|
static size_t
|
||||||
@ -291,6 +296,22 @@ openpgp_oid_is_ed25519 (gcry_mpi_t a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
openpgp_oid_is_crv25519 (gcry_mpi_t a)
|
||||||
|
{
|
||||||
|
const unsigned char *buf;
|
||||||
|
unsigned int nbits;
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
if (!a || !gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
buf = gcry_mpi_get_opaque (a, &nbits);
|
||||||
|
n = (nbits+7)/8;
|
||||||
|
return (n == DIM (oid_crv25519)
|
||||||
|
&& !memcmp (buf, oid_crv25519, DIM (oid_crv25519)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Map the Libgcrypt ECC curve NAME to an OID. If R_NBITS is not NULL
|
/* Map the Libgcrypt ECC curve NAME to an OID. If R_NBITS is not NULL
|
||||||
store the bit size of the curve there. Returns NULL for unknown
|
store the bit size of the curve there. Returns NULL for unknown
|
||||||
|
@ -322,6 +322,7 @@ size_t percent_unescape_inplace (char *string, int nulrepl);
|
|||||||
gpg_error_t openpgp_oid_from_str (const char *string, gcry_mpi_t *r_mpi);
|
gpg_error_t openpgp_oid_from_str (const char *string, gcry_mpi_t *r_mpi);
|
||||||
char *openpgp_oid_to_str (gcry_mpi_t a);
|
char *openpgp_oid_to_str (gcry_mpi_t a);
|
||||||
int openpgp_oid_is_ed25519 (gcry_mpi_t a);
|
int openpgp_oid_is_ed25519 (gcry_mpi_t a);
|
||||||
|
int openpgp_oid_is_crv25519 (gcry_mpi_t a);
|
||||||
const char *openpgp_curve_to_oid (const char *name, unsigned int *r_nbits);
|
const char *openpgp_curve_to_oid (const char *name, unsigned int *r_nbits);
|
||||||
const char *openpgp_oid_to_curve (const char *oid, int canon);
|
const char *openpgp_oid_to_curve (const char *oid, int canon);
|
||||||
const char *openpgp_enum_curves (int *idxp);
|
const char *openpgp_enum_curves (int *idxp);
|
||||||
|
@ -134,8 +134,11 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
|
|||||||
}
|
}
|
||||||
|
|
||||||
secret_x_size = (nbits+7)/8;
|
secret_x_size = (nbits+7)/8;
|
||||||
assert (nbytes > secret_x_size);
|
assert (nbytes >= secret_x_size);
|
||||||
|
if ((nbytes & 1))
|
||||||
|
/* Remove the "04" prefix of non-compressed format. */
|
||||||
memmove (secret_x, secret_x+1, secret_x_size);
|
memmove (secret_x, secret_x+1, secret_x_size);
|
||||||
|
if (nbytes - secret_x_size)
|
||||||
memset (secret_x+secret_x_size, 0, nbytes-secret_x_size);
|
memset (secret_x+secret_x_size, 0, nbytes-secret_x_size);
|
||||||
|
|
||||||
if (DBG_CRYPTO)
|
if (DBG_CRYPTO)
|
||||||
|
22
g10/keygen.c
22
g10/keygen.c
@ -1520,6 +1520,13 @@ gen_ecc (int algo, const char *curve, kbnode_t pub_root,
|
|||||||
(((keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
|
(((keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
|
||||||
&& (keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
|
&& (keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
|
||||||
" transient-key" : ""));
|
" transient-key" : ""));
|
||||||
|
else if (algo == PUBKEY_ALGO_ECDH && !strcmp (curve, "Curve25519"))
|
||||||
|
keyparms = xtryasprintf
|
||||||
|
("(genkey(ecc(curve %zu:%s)(flags djb-tweak comp%s)))",
|
||||||
|
strlen (curve), curve,
|
||||||
|
(((keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
|
||||||
|
&& (keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
|
||||||
|
" transient-key" : ""));
|
||||||
else
|
else
|
||||||
keyparms = xtryasprintf
|
keyparms = xtryasprintf
|
||||||
("(genkey(ecc(curve %zu:%s)(flags nocomp%s)))",
|
("(genkey(ecc(curve %zu:%s)(flags nocomp%s)))",
|
||||||
@ -2125,7 +2132,7 @@ ask_keysize (int algo, unsigned int primary_keysize)
|
|||||||
function may adjust. Returns a malloced string with the name of
|
function may adjust. Returns a malloced string with the name of
|
||||||
the curve. BOTH tells that gpg creates a primary and subkey. */
|
the curve. BOTH tells that gpg creates a primary and subkey. */
|
||||||
static char *
|
static char *
|
||||||
ask_curve (int *algo, int both)
|
ask_curve (int *algo, int *subkey_algo)
|
||||||
{
|
{
|
||||||
struct {
|
struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
@ -2176,7 +2183,7 @@ ask_curve (int *algo, int both)
|
|||||||
continue;
|
continue;
|
||||||
if (!gcry_pk_get_curve (keyparms, 0, NULL))
|
if (!gcry_pk_get_curve (keyparms, 0, NULL))
|
||||||
continue;
|
continue;
|
||||||
if (both && curves[idx].fix_curve)
|
if (subkey_algo && curves[idx].fix_curve)
|
||||||
{
|
{
|
||||||
/* Both Curve 25519 keys are to be created. Check that
|
/* Both Curve 25519 keys are to be created. Check that
|
||||||
Libgcrypt also supports the real Curve25519. */
|
Libgcrypt also supports the real Curve25519. */
|
||||||
@ -2241,6 +2248,11 @@ ask_curve (int *algo, int both)
|
|||||||
if ((*algo == PUBKEY_ALGO_ECDSA || *algo == PUBKEY_ALGO_EDDSA)
|
if ((*algo == PUBKEY_ALGO_ECDSA || *algo == PUBKEY_ALGO_EDDSA)
|
||||||
&& curves[idx].fix_curve)
|
&& curves[idx].fix_curve)
|
||||||
{
|
{
|
||||||
|
if (subkey_algo && *subkey_algo == PUBKEY_ALGO_ECDSA)
|
||||||
|
{
|
||||||
|
*subkey_algo = PUBKEY_ALGO_EDDSA;
|
||||||
|
result = xstrdup ("Ed25519");
|
||||||
|
}
|
||||||
*algo = PUBKEY_ALGO_EDDSA;
|
*algo = PUBKEY_ALGO_EDDSA;
|
||||||
result = xstrdup ("Ed25519");
|
result = xstrdup ("Ed25519");
|
||||||
}
|
}
|
||||||
@ -3672,7 +3684,7 @@ generate_keypair (ctrl_t ctrl, int full, const char *fname,
|
|||||||
|| algo == PUBKEY_ALGO_EDDSA
|
|| algo == PUBKEY_ALGO_EDDSA
|
||||||
|| algo == PUBKEY_ALGO_ECDH)
|
|| algo == PUBKEY_ALGO_ECDH)
|
||||||
{
|
{
|
||||||
curve = ask_curve (&algo, both);
|
curve = ask_curve (&algo, &subkey_algo);
|
||||||
r = xmalloc_clear( sizeof *r + 20 );
|
r = xmalloc_clear( sizeof *r + 20 );
|
||||||
r->key = pKEYTYPE;
|
r->key = pKEYTYPE;
|
||||||
sprintf( r->u.value, "%d", algo);
|
sprintf( r->u.value, "%d", algo);
|
||||||
@ -3743,7 +3755,7 @@ generate_keypair (ctrl_t ctrl, int full, const char *fname,
|
|||||||
|| algo == PUBKEY_ALGO_EDDSA
|
|| algo == PUBKEY_ALGO_EDDSA
|
||||||
|| algo == PUBKEY_ALGO_ECDH)
|
|| algo == PUBKEY_ALGO_ECDH)
|
||||||
{
|
{
|
||||||
curve = ask_curve (&algo, 0);
|
curve = ask_curve (&algo, NULL);
|
||||||
nbits = 0;
|
nbits = 0;
|
||||||
r = xmalloc_clear (sizeof *r + strlen (curve));
|
r = xmalloc_clear (sizeof *r + strlen (curve));
|
||||||
r->key = pKEYCURVE;
|
r->key = pKEYCURVE;
|
||||||
@ -4292,7 +4304,7 @@ generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock)
|
|||||||
else if (algo == PUBKEY_ALGO_ECDSA
|
else if (algo == PUBKEY_ALGO_ECDSA
|
||||||
|| algo == PUBKEY_ALGO_EDDSA
|
|| algo == PUBKEY_ALGO_EDDSA
|
||||||
|| algo == PUBKEY_ALGO_ECDH)
|
|| algo == PUBKEY_ALGO_ECDH)
|
||||||
curve = ask_curve (&algo, 0);
|
curve = ask_curve (&algo, NULL);
|
||||||
else
|
else
|
||||||
nbits = ask_keysize (algo, 0);
|
nbits = ask_keysize (algo, 0);
|
||||||
|
|
||||||
|
@ -767,8 +767,11 @@ keygrip_from_pk (PKT_public_key *pk, unsigned char *array)
|
|||||||
{
|
{
|
||||||
err = gcry_sexp_build (&s_pkey, NULL,
|
err = gcry_sexp_build (&s_pkey, NULL,
|
||||||
pk->pubkey_algo == PUBKEY_ALGO_EDDSA?
|
pk->pubkey_algo == PUBKEY_ALGO_EDDSA?
|
||||||
"(public-key(ecc(curve%s)(flags eddsa)(q%m)))"
|
"(public-key(ecc(curve%s)(flags eddsa)(q%m)))":
|
||||||
: "(public-key(ecc(curve%s)(q%m)))",
|
(pk->pubkey_algo == PUBKEY_ALGO_ECDH
|
||||||
|
&& openpgp_oid_is_crv25519 (pk->pkey[0]))?
|
||||||
|
"(public-key(ecc(curve%s)(flags djb-tweak)(q%m)))":
|
||||||
|
"(public-key(ecc(curve%s)(q%m)))",
|
||||||
curve, pk->pkey[1]);
|
curve, pk->pkey[1]);
|
||||||
xfree (curve);
|
xfree (curve);
|
||||||
}
|
}
|
||||||
|
@ -228,9 +228,13 @@ pk_encrypt (pubkey_algo_t algo, gcry_mpi_t *resarr, gcry_mpi_t data,
|
|||||||
rc = gpg_error_from_syserror ();
|
rc = gpg_error_from_syserror ();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
int with_djb_tweak_flag = openpgp_oid_is_crv25519 (pkey[0]);
|
||||||
|
|
||||||
/* Now use the ephemeral secret to compute the shared point. */
|
/* Now use the ephemeral secret to compute the shared point. */
|
||||||
rc = gcry_sexp_build (&s_pkey, NULL,
|
rc = gcry_sexp_build (&s_pkey, NULL,
|
||||||
"(public-key(ecdh(curve%s)(q%m)))",
|
with_djb_tweak_flag ?
|
||||||
|
"(public-key(ecdh(curve%s)(flags djb-tweak)(q%m)))"
|
||||||
|
: "(public-key(ecdh(curve%s)(q%m)))",
|
||||||
curve, pkey[1]);
|
curve, pkey[1]);
|
||||||
xfree (curve);
|
xfree (curve);
|
||||||
/* Put K into a simplified S-expression. */
|
/* Put K into a simplified S-expression. */
|
||||||
|
@ -250,8 +250,8 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid)
|
|||||||
if(err)
|
if(err)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
/* Reuse NFRAME, which size is sufficient to include the session key. */
|
xfree (frame);
|
||||||
err = gcry_mpi_print (GCRYMPI_FMT_USG, frame, nframe, &nframe, decoded);
|
err = gcry_mpi_aprint (GCRYMPI_FMT_USG, &frame, &nframe, decoded);
|
||||||
mpi_release (decoded);
|
mpi_release (decoded);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
@ -235,7 +235,7 @@ struct app_local_s {
|
|||||||
} keyattr[3];
|
} keyattr[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ECC_FLAG_EDDSA (1 << 0)
|
#define ECC_FLAG_DJB_TWEAK (1 << 0)
|
||||||
|
|
||||||
|
|
||||||
/***** Local prototypes *****/
|
/***** 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",
|
snprintf (buffer, sizeof buffer, "%d %d %s",
|
||||||
keyno+1,
|
keyno+1,
|
||||||
app->app_local->keyattr[keyno].ecc.flags? PUBKEY_ALGO_EDDSA:
|
keyno==1? PUBKEY_ALGO_ECDH :
|
||||||
(keyno==1? PUBKEY_ALGO_ECDH: PUBKEY_ALGO_ECDSA),
|
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));
|
openpgp_oid_to_curve (app->app_local->keyattr[keyno].ecc.oid, 0));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1378,26 +1379,34 @@ get_public_key (app_t app, int keyno)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mbuf = xtrymalloc (mlen + 1);
|
mbuf = xtrymalloc (mlen + 1);
|
||||||
if (!mbuf)
|
if (!mbuf)
|
||||||
{
|
{
|
||||||
err = gpg_error_from_syserror ();
|
err = gpg_error_from_syserror ();
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
/* Prepend numbers with a 0 if needed. */
|
|
||||||
if ((app->app_local->keyattr[keyno].key_type == KEY_TYPE_RSA
|
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].key_type == KEY_TYPE_ECC
|
||||||
&& !app->app_local->keyattr[keyno].ecc.flags))
|
&& !app->app_local->keyattr[keyno].ecc.flags))
|
||||||
&& mlen && (*m & 0x80))
|
&& mlen && (*m & 0x80))
|
||||||
{
|
{ /* Prepend numbers with a 0 if needed for MPI. */
|
||||||
*mbuf = 0;
|
*mbuf = 0;
|
||||||
memcpy (mbuf+1, m, mlen);
|
memcpy (mbuf+1, m, mlen);
|
||||||
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
|
else
|
||||||
memcpy (mbuf, m, mlen);
|
memcpy (mbuf, m, mlen);
|
||||||
|
|
||||||
|
if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_RSA)
|
||||||
|
{
|
||||||
ebuf = xtrymalloc (elen + 1);
|
ebuf = xtrymalloc (elen + 1);
|
||||||
if (!ebuf)
|
if (!ebuf)
|
||||||
{
|
{
|
||||||
@ -1414,23 +1423,8 @@ get_public_key (app_t app, int keyno)
|
|||||||
else
|
else
|
||||||
memcpy (ebuf, e, elen);
|
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)))",
|
err = gcry_sexp_build (&s_pkey, NULL, "(public-key(rsa(n%b)(e%b)))",
|
||||||
(int)mlen, mbuf, (int)elen, ebuf);
|
(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)
|
|
||||||
{
|
|
||||||
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 if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_ECC)
|
else if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_ECC)
|
||||||
{
|
{
|
||||||
@ -1438,12 +1432,18 @@ get_public_key (app_t app, int keyno)
|
|||||||
|
|
||||||
if (!app->app_local->keyattr[keyno].ecc.flags)
|
if (!app->app_local->keyattr[keyno].ecc.flags)
|
||||||
format = "(public-key(ecc(curve%s)(q%b)))";
|
format = "(public-key(ecc(curve%s)(q%b)))";
|
||||||
|
else if (keyno == 1)
|
||||||
|
format = "(public-key(ecc(curve%s)(flags djb-tweak)(q%b)))";
|
||||||
else
|
else
|
||||||
format = "(public-key(ecc(curve%s)(flags eddsa)(q%b)))";
|
format = "(public-key(ecc(curve%s)(flags eddsa)(q%b)))";
|
||||||
|
|
||||||
err = gcry_sexp_build (&s_pkey, NULL, format,
|
err = gcry_sexp_build (&s_pkey, NULL, format,
|
||||||
openpgp_oid_to_curve (app->app_local->keyattr[keyno].ecc.oid, 1),
|
openpgp_oid_to_curve (app->app_local->keyattr[keyno].ecc.oid, 1),
|
||||||
(int)mlen, mbuf);
|
(int)mlen, mbuf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
@ -1458,12 +1458,6 @@ get_public_key (app_t app, int keyno)
|
|||||||
}
|
}
|
||||||
gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, keybuf, len);
|
gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, keybuf, len);
|
||||||
gcry_sexp_release (s_pkey);
|
gcry_sexp_release (s_pkey);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
app->app_local->pk[keyno].key = (unsigned char*)keybuf;
|
app->app_local->pk[keyno].key = (unsigned char*)keybuf;
|
||||||
app->app_local->pk[keyno].keylen = len - 1; /* Decrement for trailing '\0' */
|
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;
|
size_t ecc_q_len, ecc_d_len;
|
||||||
u32 created_at = 0;
|
u32 created_at = 0;
|
||||||
const char *oidstr = NULL;
|
const char *oidstr = NULL;
|
||||||
int flag_eddsa = 0;
|
int flag_djb_tweak = 0;
|
||||||
int algo;
|
int algo;
|
||||||
|
|
||||||
/* (private-key(ecc(curve%s)(q%m)(d%m))(created-at%d)):
|
/* (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)))
|
if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
if (tok && toklen == 5 && !memcmp (tok, "eddsa", 5))
|
if (tok)
|
||||||
flag_eddsa = 1;
|
{
|
||||||
|
if ((toklen == 5 && !memcmp (tok, "eddsa", 5))
|
||||||
|
|| (toklen == 9 && !memcmp (tok, "djb-tweak", 9)))
|
||||||
|
flag_djb_tweak = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (tok && toklen == 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)))
|
if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
|
||||||
goto leave;
|
goto leave;
|
||||||
if (tok && buf2 && !flag_eddsa)
|
if (tok && buf2 && !flag_djb_tweak)
|
||||||
/* It's MPI. Strip off leading zero bytes and save. */
|
/* It's MPI. Strip off leading zero bytes and save. */
|
||||||
for (;toklen && !*tok; toklen--, tok++)
|
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);
|
err = gpg_error (GPG_ERR_INV_VALUE);
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
if (flag_eddsa && keyno != 1)
|
if (flag_djb_tweak && keyno != 1)
|
||||||
algo = PUBKEY_ALGO_EDDSA;
|
algo = PUBKEY_ALGO_EDDSA;
|
||||||
else if (keyno == 1)
|
else if (keyno == 1)
|
||||||
algo = PUBKEY_ALGO_ECDH;
|
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
|
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.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");
|
log_error ("key attribute on card doesn't match\n");
|
||||||
err = gpg_error (GPG_ERR_INV_VALUE);
|
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].key_type = KEY_TYPE_ECC;
|
||||||
app->app_local->keyattr[keyno].ecc.oid = oid;
|
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)
|
if (opt.verbose)
|
||||||
log_printf
|
log_printf
|
||||||
("ECC, curve=%s%s\n", app->app_local->keyattr[keyno].ecc.oid,
|
("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)
|
else if (opt.verbose)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user