File ed25519.diff of Package python-rpm.32607

--- 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:
openSUSE Build Service is sponsored by