File ed25519.diff of Package rpm
--- rpmio/digest.h.orig 2017-10-05 10:04:57.554602041 +0000
+++ rpmio/digest.h 2022-07-12 08:54:37.514921377 +0000
@@ -14,6 +14,7 @@ struct pgpDigAlg_s {
setmpifunc setmpi;
verifyfunc verify;
freefunc free;
+ int curve;
int mpis;
void *data; /*!< algorithm specific private data */
};
@@ -42,7 +43,7 @@ struct pgpDigParams_s {
pgpDigAlg alg;
};
-pgpDigAlg pgpPubkeyNew(int algo);
+pgpDigAlg pgpPubkeyNew(int algo, int curve);
pgpDigAlg pgpSignatureNew(int algo);
--- rpmio/digest_beecrypt.c.orig 2017-08-10 08:08:07.145108694 +0000
+++ rpmio/digest_beecrypt.c 2022-07-12 08:54:37.514921377 +0000
@@ -461,7 +461,7 @@ static int pgpVerifyNULL(pgpDigAlg pgpke
return 1;
}
-pgpDigAlg pgpPubkeyNew(int algo)
+pgpDigAlg pgpPubkeyNew(int algo, int curve)
{
pgpDigAlg ka = xcalloc(1, sizeof(*ka));;
--- rpmio/digest_libgcrypt.c.orig 2022-07-12 08:42:10.384358864 +0000
+++ rpmio/digest_libgcrypt.c 2022-07-12 08:56:07.498742115 +0000
@@ -346,6 +346,115 @@ static void pgpFreeKeyDSA(pgpDigAlg pgpk
}
+/****************************** EDDSA **************************************/
+
+struct pgpDigSigEDDSA_s {
+ gcry_mpi_t r;
+ gcry_mpi_t s;
+};
+
+struct pgpDigKeyEDDSA_s {
+ gcry_mpi_t q;
+};
+
+static int pgpSetSigMpiEDDSA(pgpDigAlg pgpsig, int num, const uint8_t *p)
+{
+ struct pgpDigSigEDDSA_s *sig = pgpsig->data;
+ int mlen = pgpMpiLen(p);
+ int rc = 1;
+
+ if (!sig)
+ sig = pgpsig->data = xcalloc(1, sizeof(*sig));
+
+ switch (num) {
+ case 0:
+ if (!gcry_mpi_scan(&sig->r, GCRYMPI_FMT_PGP, p, mlen, NULL))
+ rc = 0;
+ break;
+ case 1:
+ if (!gcry_mpi_scan(&sig->s, GCRYMPI_FMT_PGP, p, mlen, NULL))
+ rc = 0;
+ break;
+ }
+ return rc;
+}
+
+static int pgpSetKeyMpiEDDSA(pgpDigAlg pgpkey, int num, const uint8_t *p)
+{
+ struct pgpDigKeyEDDSA_s *key = pgpkey->data;
+ int mlen = pgpMpiLen(p);
+ int rc = 1;
+
+ if (!key)
+ key = pgpkey->data = xcalloc(1, sizeof(*key));
+
+ switch (num) {
+ case 0:
+ if (!gcry_mpi_scan(&key->q, GCRYMPI_FMT_PGP, p, mlen, NULL))
+ rc = 0;
+ break;
+ }
+ return rc;
+}
+
+static int
+ed25519_zero_extend(gcry_mpi_t x, unsigned char *buf, int bufl)
+{
+ int n = (gcry_mpi_get_nbits(x) + 7) / 8;
+ if (n == 0 || n > bufl)
+ return 1;
+ n = bufl - n;
+ if (n)
+ memset(buf, 0, n);
+ gcry_mpi_print(GCRYMPI_FMT_USG, buf + n, bufl - n, NULL, x);
+ return 0;
+}
+
+static int pgpVerifySigEDDSA(pgpDigAlg pgpkey, pgpDigAlg pgpsig, uint8_t *hash, size_t hashlen, int hash_algo)
+{
+ struct pgpDigKeyEDDSA_s *key = pgpkey->data;
+ struct pgpDigSigEDDSA_s *sig = pgpsig->data;
+ gcry_sexp_t sexp_sig = NULL, sexp_data = NULL, sexp_pkey = NULL;
+ int rc = 1;
+ unsigned char buf_r[32], buf_s[32];
+
+ if (!sig || !key)
+ return rc;
+ if (pgpkey->curve != PGPCURVE_ED25519)
+ return rc;
+ if (ed25519_zero_extend(sig->r, buf_r, 32) || ed25519_zero_extend(sig->s, buf_s, 32))
+ return rc;
+ gcry_sexp_build(&sexp_sig, NULL, "(sig-val (eddsa (r %b) (s %b)))", 32, (const char *)buf_r, 32, (const char *)buf_s, 32);
+ gcry_sexp_build(&sexp_data, NULL, "(data (flags eddsa) (hash-algo sha512) (value %b))", (int)hashlen, (const char *)hash);
+ gcry_sexp_build(&sexp_pkey, NULL, "(public-key (ecc (curve \"Ed25519\") (flags eddsa) (q %M)))", key->q);
+ if (sexp_sig && sexp_data && sexp_pkey)
+ rc = gcry_pk_verify(sexp_sig, sexp_data, sexp_pkey) == 0 ? 0 : 1;
+ gcry_sexp_release(sexp_sig);
+ gcry_sexp_release(sexp_data);
+ gcry_sexp_release(sexp_pkey);
+ return rc;
+}
+
+static void pgpFreeSigEDDSA(pgpDigAlg pgpsig)
+{
+ struct pgpDigSigEDDSA_s *sig = pgpsig->data;
+ if (sig) {
+ gcry_mpi_release(sig->r);
+ gcry_mpi_release(sig->s);
+ pgpsig->data = _free(sig);
+ }
+}
+
+static void pgpFreeKeyEDDSA(pgpDigAlg pgpkey)
+{
+ struct pgpDigKeyEDDSA_s *key = pgpkey->data;
+ if (key) {
+ gcry_mpi_release(key->q);
+ pgpkey->data = _free(key);
+ }
+}
+
+
/****************************** NULL **************************************/
static int pgpSetMpiNULL(pgpDigAlg pgpkey, int num, const uint8_t *p)
@@ -359,7 +468,24 @@ static int pgpVerifyNULL(pgpDigAlg pgpke
return 1;
}
-pgpDigAlg pgpPubkeyNew(int algo)
+static int pgpSupportedCurve(int curve)
+{
+ if (curve == PGPCURVE_ED25519) {
+ static int supported_ed25519;
+ if (!supported_ed25519) {
+ gcry_sexp_t sexp = NULL;
+ unsigned int nbits;
+ gcry_sexp_build(&sexp, NULL, "(public-key (ecc (curve \"Ed25519\")))");
+ nbits = gcry_pk_get_nbits(sexp);
+ gcry_sexp_release(sexp);
+ supported_ed25519 = nbits > 0 ? 1 : -1;
+ }
+ return supported_ed25519 > 0;
+ }
+ return 0;
+}
+
+pgpDigAlg pgpPubkeyNew(int algo, int curve)
{
pgpDigAlg ka = xcalloc(1, sizeof(*ka));;
@@ -374,6 +500,17 @@ pgpDigAlg pgpPubkeyNew(int algo)
ka->free = pgpFreeKeyDSA;
ka->mpis = 4;
break;
+ case PGPPUBKEYALGO_EDDSA:
+ if (!pgpSupportedCurve(curve)) {
+ ka->setmpi = pgpSetMpiNULL;
+ ka->mpis = -1;
+ break;
+ }
+ ka->setmpi = pgpSetKeyMpiEDDSA;
+ ka->free = pgpFreeKeyEDDSA;
+ ka->mpis = 1;
+ ka->curve = curve;
+ break;
default:
ka->setmpi = pgpSetMpiNULL;
ka->mpis = -1;
@@ -402,6 +539,12 @@ pgpDigAlg pgpSignatureNew(int algo)
sa->verify = pgpVerifySigDSA;
sa->mpis = 2;
break;
+ case PGPPUBKEYALGO_EDDSA:
+ sa->setmpi = pgpSetSigMpiEDDSA;
+ sa->free = pgpFreeSigEDDSA;
+ sa->verify = pgpVerifySigEDDSA;
+ sa->mpis = 2;
+ break;
default:
sa->setmpi = pgpSetMpiNULL;
sa->verify = pgpVerifyNULL;
--- rpmio/digest_nss.c.orig 2017-10-05 10:04:57.554602041 +0000
+++ rpmio/digest_nss.c 2022-07-12 08:54:37.514921377 +0000
@@ -479,7 +479,7 @@ static int pgpVerifyNULL(pgpDigAlg pgpke
return 1;
}
-pgpDigAlg pgpPubkeyNew(int algo)
+pgpDigAlg pgpPubkeyNew(int algo, int curve)
{
pgpDigAlg ka = xcalloc(1, sizeof(*ka));;
--- rpmio/digest_openssl.c.orig 2017-10-05 10:04:57.554602041 +0000
+++ rpmio/digest_openssl.c 2022-07-12 08:54:37.514921377 +0000
@@ -786,7 +786,7 @@ static int pgpVerifyNULL(pgpDigAlg pgpke
}
/****************************** PGP **************************************/
-pgpDigAlg pgpPubkeyNew(int algo)
+pgpDigAlg pgpPubkeyNew(int algo, int curve)
{
pgpDigAlg ka = xcalloc(1, sizeof(*ka));;
--- rpmio/rpmpgp.c.orig 2017-10-05 10:04:57.569602038 +0000
+++ rpmio/rpmpgp.c 2022-07-12 08:54:37.514921377 +0000
@@ -58,6 +58,7 @@ static struct pgpValTbl_s const pgpPubke
{ PGPPUBKEYALGO_ECDSA, "ECDSA" },
{ PGPPUBKEYALGO_ELGAMAL, "Elgamal" },
{ PGPPUBKEYALGO_DH, "Diffie-Hellman (X9.42)" },
+ { PGPPUBKEYALGO_EDDSA, "EdDSA" },
{ -1, "Unknown public key algorithm" },
};
@@ -683,15 +684,42 @@ char * pgpHexStr(const uint8_t *p, size_
return str;
}
+static uint8_t curve_oids[] = {
+ PGPCURVE_NIST_P_256, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07,
+ PGPCURVE_NIST_P_384, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22,
+ PGPCURVE_NIST_P_521, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23,
+ PGPCURVE_BRAINPOOL_P256R1, 0x09, 0x2b, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07,
+ PGPCURVE_BRAINPOOL_P512R1, 0x09, 0x2b, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0d,
+ PGPCURVE_ED25519, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xda, 0x47, 0x0f, 0x01,
+ PGPCURVE_CURVE25519, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01,
+ 0,
+};
+
+static int pgpCurveByOid(const uint8_t *p, int l)
+{
+ uint8_t *curve;
+ for (curve = curve_oids; *curve; curve += 2 + curve[1])
+ if (l == (int)curve[1] && !memcmp(p, curve + 2, l))
+ return (int)curve[0];
+ return 0;
+}
+
static int pgpPrtPubkeyParams(uint8_t pubkey_algo,
const uint8_t *p, const uint8_t *h, size_t hlen,
pgpDigParams keyp)
{
int rc = 1;
const uint8_t *pend = h + hlen;
- int i;
- pgpDigAlg keyalg = pgpPubkeyNew(pubkey_algo);
-
+ int i, curve = 0;
+ pgpDigAlg keyalg;
+ if (pubkey_algo == PGPPUBKEYALGO_EDDSA) {
+ int len = p + 1 < pend ? p[0] : 0;
+ if (len == 0 || len == 0xff || p + 1 + len > pend)
+ goto exit;
+ curve = pgpCurveByOid(p + 1, len);
+ p += len + 1;
+ }
+ keyalg = pgpPubkeyNew(pubkey_algo, curve);
for (i = 0; i < keyalg->mpis && p + 2 <= pend; i++) {
int mpil = pgpMpiLen(p);
if (p + mpil > pend)
@@ -713,6 +741,7 @@ static int pgpPrtPubkeyParams(uint8_t pu
else
pgpDigAlgFree(keyalg);
+exit:
return rc;
}
@@ -793,10 +822,20 @@ int pgpPubkeyFingerprint(const uint8_t *
case PGPPUBKEYALGO_DSA:
mpis = 4;
break;
+ case PGPPUBKEYALGO_EDDSA:
+ mpis = 1;
+ break;
}
}
se = (uint8_t *)(v + 1);
+ /* EdDSA has a curve id before the MPIs */
+ if (v->pubkey_algo == PGPPUBKEYALGO_EDDSA) {
+ if (se < pend && se[0] != 0x00 && se[0] != 0xff)
+ se += 1 + se[0];
+ else
+ se = pend; /* error out when reading the MPI */
+ }
while (se < pend && mpis-- > 0)
se += pgpMpiLen(se);
--- rpmio/rpmpgp.h.orig 2017-10-05 10:04:57.569602038 +0000
+++ rpmio/rpmpgp.h 2022-07-12 08:54:37.514921377 +0000
@@ -8,6 +8,10 @@
*
* Text from RFC-2440 in comments is
* Copyright (C) The Internet Society (1998). All Rights Reserved.
+ *
+ * EdDSA algorithm identifier value taken from
+ * https://datatracker.ietf.org/doc/draft-ietf-openpgp-rfc4880bis/
+ * This value is used in gnupg since version 2.1.0
*/
#include <string.h>
@@ -152,6 +156,7 @@ typedef enum pgpSigType_e {
20 - Elgamal (Encrypt or Sign)
21 - Reserved for Diffie-Hellman (X9.42,
as defined for IETF-S/MIME)
+ 22 - EdDSA
100 to 110 - Private/Experimental algorithm.
\endverbatim
*
@@ -168,7 +173,8 @@ typedef enum pgpPubkeyAlgo_e {
PGPPUBKEYALGO_EC = 18, /*!< Elliptic Curve */
PGPPUBKEYALGO_ECDSA = 19, /*!< ECDSA */
PGPPUBKEYALGO_ELGAMAL = 20, /*!< Elgamal */
- PGPPUBKEYALGO_DH = 21 /*!< Diffie-Hellman (X9.42) */
+ PGPPUBKEYALGO_DH = 21, /*!< Diffie-Hellman (X9.42) */
+ PGPPUBKEYALGO_EDDSA = 22 /*!< EdDSA */
} pgpPubkeyAlgo;
/** \ingroup rpmpgp
@@ -269,6 +275,22 @@ typedef enum pgpHashAlgo_e {
} pgpHashAlgo;
/** \ingroup rpmpgp
+ * ECC Curves
+ *
+ * The following curve ids are private to rpm. PGP uses
+ * oids to identify a curve.
+ */
+typedef enum pgpCurveId_e {
+ PGPCURVE_NIST_P_256 = 1, /*!< NIST P-256 */
+ PGPCURVE_NIST_P_384 = 2, /*!< NIST P-384 */
+ PGPCURVE_NIST_P_521 = 3, /*!< NIST P-521 */
+ PGPCURVE_BRAINPOOL_P256R1 = 4, /*!< brainpoolP256r1 */
+ PGPCURVE_BRAINPOOL_P512R1 = 5, /*!< brainpoolP512r1 */
+ PGPCURVE_ED25519 = 6, /*!< Ed25519 */
+ PGPCURVE_CURVE25519 = 7, /*!< Curve25519 */
+} pgpCurveId;
+
+/** \ingroup rpmpgp
* 5.2.2. Version 3 Signature Packet Format
*
* The body of a version 3 Signature Packet contains:
@@ -285,7 +307,7 @@ typedef enum pgpHashAlgo_e {
* Algorithm Specific Fields for RSA signatures:
* - multiprecision integer (MPI) of RSA signature value m**d.
*
- * Algorithm Specific Fields for DSA signatures:
+ * Algorithm Specific Fields for DSA and EdDSA signatures:
* - MPI of DSA value r.
* - MPI of DSA value s.
*/
@@ -642,6 +664,11 @@ typedef struct pgpPktKeyV3_s {
* - MPI of Elgamal public key value y (= g**x where x is
* secret).
*
+ * Algorithm Specific Fields for EdDSA public keys:
+ * - variable length field containing a curve OID
+ * - MPI of an EC point representing a public key Q
+ * (a compressed point prefixed with the octet 0x40)
+ *
*/
typedef struct pgpPktKeyV4_s {
uint8_t version; /*!< version number (4). */
--- sign/rpmgensig.c.orig 2017-10-05 10:04:57.588602034 +0000
+++ sign/rpmgensig.c 2022-07-12 08:56:37.398682115 +0000
@@ -212,6 +212,7 @@ static rpmtd makeSigTag(Header sigh, int
pubkey_algo = pgpDigParamsAlgo(sigp, PGPVAL_PUBKEYALGO);
switch (pubkey_algo) {
case PGPPUBKEYALGO_DSA:
+ case PGPPUBKEYALGO_EDDSA:
sigtag = ishdr ? RPMSIGTAG_DSA : RPMSIGTAG_GPG;
break;
case PGPPUBKEYALGO_RSA: