Imported Upstream version 0.7.14 upstream/0.7.14
authorDongHun Kwak <dh0128.kwak@samsung.com>
Fri, 27 Nov 2020 05:49:28 +0000 (14:49 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Fri, 27 Nov 2020 05:49:28 +0000 (14:49 +0900)
12 files changed:
CMakeLists.txt
NEWS
VERSION.cmake
ext/repo_pubkey.c
ext/repo_pubkey.h
ext/repo_rpmdb_librpm.h
ext/solv_ed25519.h [new file with mode: 0644]
ext/solv_pgpvrfy.c
package/libsolv.changes
src/policy.c
src/problems.c
src/rules.c

index 347bb0d..767aa66 100644 (file)
@@ -248,7 +248,6 @@ IF (ENABLE_RPMDB OR ENABLE_RPMPKG_LIBRPM)
   ENDIF (ENABLE_RPMDB)
 
   INCLUDE (CheckLibraryExists)
-  CHECK_LIBRARY_EXISTS(rpmio pgpDigGetParams "" HAVE_PGPDIGGETPARAMS)
   CHECK_LIBRARY_EXISTS(rpm rpmdbNextIteratorHeaderBlob "" HAVE_RPMDBNEXTITERATORHEADERBLOB)
   CHECK_LIBRARY_EXISTS(rpm rpmdbFStat "" HAVE_RPMDBFSTAT)
 ENDIF (ENABLE_RPMDB OR ENABLE_RPMPKG_LIBRPM)
@@ -283,7 +282,7 @@ ENDIF (${CMAKE_MAJOR_VERSION} GREATER 2)
 
 # should create config.h with #cmakedefine instead...
 FOREACH (VAR HAVE_STRCHRNUL HAVE_FOPENCOOKIE HAVE_FUNOPEN WORDS_BIGENDIAN
-  HAVE_RPM_DB_H HAVE_PGPDIGGETPARAMS HAVE_RPMDBNEXTITERATORHEADERBLOB HAVE_RPMDBFSTAT
+  HAVE_RPM_DB_H HAVE_RPMDBNEXTITERATORHEADERBLOB HAVE_RPMDBFSTAT
   WITH_LIBXML2 WITHOUT_COOKIEOPEN)
   IF(${VAR})
     ADD_DEFINITIONS (-D${VAR}=1)
diff --git a/NEWS b/NEWS
index 7ed259d..69a5c4b 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,14 @@
 This file contains the major changes between
 libsolv versions:
 
+Version 0.7.14
+- added support for ed25519 signatures
+- selected bug fixes:
+  * Support blacklisted packages in solver_findproblemrule()
+  * Support rules with multiple negative literals in choice rule
+    generation
+  * Also detect rpmdb.sqlite in /usr/share/rpm
+
 Version 0.7.13
 - fix solvable swapping messing up uninternalized idarrays
 
index 80aed44..0bf518b 100644 (file)
@@ -49,5 +49,5 @@ SET(LIBSOLVEXT_SOVERSION "1")
 
 SET(LIBSOLV_MAJOR "0")
 SET(LIBSOLV_MINOR "7")
-SET(LIBSOLV_PATCH "13")
+SET(LIBSOLV_PATCH "14")
 
index eb83839..883e13a 100644 (file)
@@ -503,11 +503,12 @@ static int
 parsepubkey(Solvable *s, Repodata *data, unsigned char *p, int pl, int flags)
 {
   Repo *repo = s->repo;
+  Pool *pool = repo->pool;
   unsigned char *pstart = p;
   int tag, l;
   unsigned char keyid[8];
   char subkeyofstr[17];
-  unsigned int kcr = 0, maxex = 0, maxsigcr = 0;
+  unsigned int kcr = 0, maxex = 0, maxsigcr = 0, rpmsigcr = 0;
   unsigned char *pubkey = 0;
   int pubkeyl = 0;
   int insubkey = 0;
@@ -524,10 +525,10 @@ parsepubkey(Solvable *s, Repodata *data, unsigned char *p, int pl, int flags)
        {
          /* finish old key */
          if (kcr)
-           repodata_set_num(data, s - repo->pool->solvables, SOLVABLE_BUILDTIME, kcr);
+           repodata_set_num(data, s - pool->solvables, SOLVABLE_BUILDTIME, kcr);
          if (maxex && maxex != -1)
-           repodata_set_num(data, s - repo->pool->solvables, PUBKEY_EXPIRES, maxex);
-         s->name = pool_str2id(s->repo->pool, insubkey ? "gpg-subkey" : "gpg-pubkey", 1);
+           repodata_set_num(data, s - pool->solvables, PUBKEY_EXPIRES, maxex);
+         s->name = pool_str2id(pool, insubkey ? "gpg-subkey" : "gpg-pubkey", 1);
          s->evr = 1;
          s->arch = 1;
          if (userid && useridl)
@@ -535,7 +536,7 @@ parsepubkey(Solvable *s, Repodata *data, unsigned char *p, int pl, int flags)
              char *useridstr = solv_malloc(useridl + 1);
              memcpy(useridstr, userid, useridl);
              useridstr[useridl] = 0;
-             setutf8string(data, s - repo->pool->solvables, SOLVABLE_SUMMARY, useridstr);
+             setutf8string(data, s - pool->solvables, SOLVABLE_SUMMARY, useridstr);
              free(useridstr);
            }
          if (pubdata)
@@ -543,16 +544,16 @@ parsepubkey(Solvable *s, Repodata *data, unsigned char *p, int pl, int flags)
              char keyidstr[17];
              char evr[8 + 1 + 8 + 1];
              solv_bin2hex(keyid, 8, keyidstr);
-             repodata_set_str(data, s - repo->pool->solvables, PUBKEY_KEYID, keyidstr);
+             repodata_set_str(data, s - pool->solvables, PUBKEY_KEYID, keyidstr);
              /* build rpm-style evr */
              strcpy(evr, keyidstr + 8);
-             sprintf(evr + 8, "-%08x", maxsigcr);
-             s->evr = pool_str2id(repo->pool, evr, 1);
+             sprintf(evr + 8, "-%08x", (flags & USE_RPM_PUBKEY_BUILTTIME) ? rpmsigcr : maxsigcr);
+             s->evr = pool_str2id(pool, evr, 1);
            }
          if (insubkey && *subkeyofstr)
-           repodata_set_str(data, s - repo->pool->solvables, PUBKEY_SUBKEYOF, subkeyofstr);
+           repodata_set_str(data, s - pool->solvables, PUBKEY_SUBKEYOF, subkeyofstr);
          if (pubdata)          /* set data blob */
-           repodata_set_binary(data, s - repo->pool->solvables, PUBKEY_DATA, pubdata, pubdatal);
+           repodata_set_binary(data, s - pool->solvables, PUBKEY_DATA, pubdata, pubdatal);
          if (!pl)
            break;
          if (!hl)
@@ -565,7 +566,7 @@ parsepubkey(Solvable *s, Repodata *data, unsigned char *p, int pl, int flags)
          if (tag == 14 && pubdata && !insubkey)
            solv_bin2hex(keyid, 8, subkeyofstr);
          /* create new solvable for subkey */
-         s = pool_id2solvable(repo->pool, repo_add_solvable(repo));
+         s = pool_id2solvable(pool, repo_add_solvable(repo));
        }
       p += hl;
       pl -= hl;
@@ -616,7 +617,7 @@ parsepubkey(Solvable *s, Repodata *data, unsigned char *p, int pl, int flags)
                          solv_chksum_add(h, q + 2, ql2);
                          solv_chksum_free(h, fp);
                          solv_bin2hex(fp, 16, fpx);
-                         repodata_set_str(data, s - s->repo->pool->solvables, PUBKEY_FINGERPRINT, fpx);
+                         repodata_set_str(data, s - pool->solvables, PUBKEY_FINGERPRINT, fpx);
                        }
                    }
                  pubdata = p + 7;
@@ -640,7 +641,7 @@ parsepubkey(Solvable *s, Repodata *data, unsigned char *p, int pl, int flags)
              solv_chksum_add(h, p, l);
              solv_chksum_free(h, fp);
              solv_bin2hex(fp, 20, fpx);
-             repodata_set_str(data, s - s->repo->pool->solvables, PUBKEY_FINGERPRINT, fpx);
+             repodata_set_str(data, s - pool->solvables, PUBKEY_FINGERPRINT, fpx);
              memcpy(keyid, fp + 12, 8);        /* keyid is last 64 bits of fingerprint */
              pubdata = p + 5;
              pubdatal = l - 5;
@@ -664,6 +665,8 @@ parsepubkey(Solvable *s, Repodata *data, unsigned char *p, int pl, int flags)
              pgpsig_makesigdata(&sig, p, l, pubkey, pubkeyl, userid, useridl, h);
              solv_chksum_free(h, 0);
            }
+         if (!rpmsigcr)
+           rpmsigcr = sig.created;
          if (!memcmp(keyid, sig.issuer, 8))
            {
 #ifdef ENABLE_PGPVRFY
@@ -694,7 +697,7 @@ parsepubkey(Solvable *s, Repodata *data, unsigned char *p, int pl, int flags)
                repodata_set_num(data, shandle, SIGNATURE_EXPIRES, sig.created + sig.expires);
              if (sig.sigdata)
                repodata_set_binary(data, shandle, SIGNATURE_DATA, sig.sigdata, sig.sigdatal);
-             repodata_add_flexarray(data, s - s->repo->pool->solvables, PUBKEY_SIGNATURES, shandle);
+             repodata_add_flexarray(data, s - pool->solvables, PUBKEY_SIGNATURES, shandle);
            }
          solv_free(sig.sigdata);
        }
@@ -711,83 +714,6 @@ parsepubkey(Solvable *s, Repodata *data, unsigned char *p, int pl, int flags)
   return p ? p - pstart : 0;
 }
 
-
-#ifdef ENABLE_RPMDB
-
-/* this is private to rpm, but rpm lacks an interface to retrieve
- * the values. Sigh. */
-struct pgpDigParams_s {
-    const char * userid;
-    const unsigned char * hash;
-#ifndef HAVE_PGPDIGGETPARAMS
-    const char * params[4];
-#endif
-    unsigned char tag;
-    unsigned char version;               /*!< version number. */
-    unsigned char time[4];               /*!< time that the key was created. */
-    unsigned char pubkey_algo;           /*!< public key algorithm. */
-    unsigned char hash_algo;
-    unsigned char sigtype;
-    unsigned char hashlen;
-    unsigned char signhash16[2];
-    unsigned char signid[8];
-    unsigned char saved;
-};
-
-#ifndef HAVE_PGPDIGGETPARAMS
-struct pgpDig_s {
-    struct pgpDigParams_s signature;
-    struct pgpDigParams_s pubkey;
-};
-#endif
-
-
-/* only rpm knows how to do the release calculation, we don't dare
- * to recreate all the bugs in libsolv */
-static void
-parsepubkey_rpm(Solvable *s, Repodata *data, unsigned char *pkts, int pktsl)
-{
-  Pool *pool = s->repo->pool;
-  struct pgpDigParams_s *digpubkey;
-  pgpDig dig = 0;
-  char keyid[16 + 1];
-  char evrbuf[8 + 1 + 8 + 1];
-  unsigned int btime;
-
-#ifndef RPM5
-  dig = pgpNewDig();
-#else
-  dig = pgpDigNew(RPMVSF_DEFAULT, 0);
-#endif
-  (void) pgpPrtPkts(pkts, pktsl, dig, 0);
-#ifdef HAVE_PGPDIGGETPARAMS
-  digpubkey = pgpDigGetParams(dig, PGPTAG_PUBLIC_KEY);
-#else
-  digpubkey = &dig->pubkey;
-#endif
-  if (digpubkey)
-    {
-      btime = digpubkey->time[0] << 24 | digpubkey->time[1] << 16 | digpubkey->time[2] << 8 | digpubkey->time[3];
-      solv_bin2hex(digpubkey->signid, 8, keyid);
-      solv_bin2hex(digpubkey->signid + 4, 4, evrbuf);
-      evrbuf[8] = '-';
-      solv_bin2hex(digpubkey->time, 4, evrbuf + 9);
-      s->evr = pool_str2id(pool, evrbuf, 1);
-      repodata_set_str(data, s - s->repo->pool->solvables, PUBKEY_KEYID, keyid);
-      if (digpubkey->userid)
-       setutf8string(data, s - s->repo->pool->solvables, SOLVABLE_SUMMARY, digpubkey->userid);
-      if (btime)
-       repodata_set_num(data, s - s->repo->pool->solvables, SOLVABLE_BUILDTIME, btime);
-    }
-#ifndef RPM5
-  (void)pgpFreeDig(dig);
-#else
-  (void)pgpDigFree(dig);
-#endif
-}
-
-#endif /* ENABLE_RPMDB */
-
 /* parse an ascii armored pubkey
  * adds multiple pubkeys if ADD_MULTIPLE_PUBKEYS is set */
 static int
@@ -809,9 +735,6 @@ pubkey2solvable(Pool *pool, Id p, Repodata *data, char *pubkey, int flags)
        {
          setutf8string(data, p, SOLVABLE_DESCRIPTION, pubkey);
          pl = parsepubkey(pool->solvables + p, data, pkts, pktsl, flags);
-#ifdef ENABLE_RPMDB
-         parsepubkey_rpm(pool->solvables + p, data, pkts, pktsl);
-#endif
          if (!pl || !(flags & ADD_MULTIPLE_PUBKEYS))
            break;
        }
@@ -988,9 +911,6 @@ add_one_pubkey(Pool *pool, Repo *repo, Repodata *data, unsigned char *pbuf, int
   char *descr = armor(pbuf, pbufl, "-----BEGIN PGP PUBLIC KEY BLOCK-----", "-----END PGP PUBLIC KEY BLOCK-----", solvversion);
   setutf8string(data, p, SOLVABLE_DESCRIPTION, descr);
   parsepubkey(pool->solvables + p, data, pbuf, pbufl, flags);
-#ifdef ENABLE_RPMDB
-  parsepubkey_rpm(pool->solvables + p, data, pbuf, pbufl);
-#endif
 }
 
 int
index 26cf0e1..51946bf 100644 (file)
@@ -12,6 +12,7 @@
 #define ADD_WITH_SUBKEYS               (1 << 9)
 #define ADD_MULTIPLE_PUBKEYS           (1 << 10)
 #define ADD_WITH_KEYSIGNATURES         (1 << 11)
+#define USE_RPM_PUBKEY_BUILTTIME       (1 << 12)
 
 extern int repo_add_rpmdb_pubkeys(Repo *repo, int flags);
 extern Id repo_add_pubkey(Repo *repo, const char *keyfile, int flags);
index 34e6698..35a46fa 100644 (file)
@@ -46,7 +46,7 @@ static void
 detect_dbpath(struct rpmdbstate *state)
 {
   state->dbpath = access_rootdir(state, "/var/lib/rpm", W_OK) == -1
-                  && access_rootdir(state, "/usr/share/rpm/Packages", R_OK) == 0
+                  && (access_rootdir(state, "/usr/share/rpm/Packages", R_OK) == 0 || access_rootdir(state, "/usr/share/rpm/rpmdb.sqlite", R_OK) == 0)
                   ? "/usr/share/rpm" : "/var/lib/rpm";
 }
 
diff --git a/ext/solv_ed25519.h b/ext/solv_ed25519.h
new file mode 100644 (file)
index 0000000..0772cee
--- /dev/null
@@ -0,0 +1,408 @@
+/*
+ * Copyright (c) 2020, SUSE LLC.
+ *
+ * This program is licensed under the BSD license, read LICENSE.BSD
+ * for further information
+ */
+
+/* simple and slow ed25519 verification code. */
+
+#ifndef LIBSOLV_CHKSUM_H
+#include "chksum.h"
+#endif
+
+#define MPED25519_LEN (32 / MP_T_BYTES)
+
+#if MP_T_BYTES == 4
+# define MPED25519_CONST1(x) (mp_t)x
+#elif MP_T_BYTES == 1
+# define MPED25519_CONST1(x) (mp_t)(x >> 0), (mp_t)(x >> 8), (mp_t)(x >> 16), (mp_t)(x >> 24)
+#endif
+
+#define MPED25519_CONST(a, b, c, d, e, f, g, h) { \
+  MPED25519_CONST1(h), MPED25519_CONST1(g), MPED25519_CONST1(f), MPED25519_CONST1(e), \
+  MPED25519_CONST1(d), MPED25519_CONST1(c), MPED25519_CONST1(b), MPED25519_CONST1(a) \
+}
+
+static mp_t ed25519_q[] =              /* mod prime */
+  MPED25519_CONST(0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFED);
+static mp_t ed25519_d[] =              /* -(121665/121666) */
+  MPED25519_CONST(0x52036CEE, 0x2B6FFE73, 0x8CC74079, 0x7779E898, 0x00700A4D, 0x4141D8AB, 0x75EB4DCA, 0x135978A3);
+static mp_t ed25519_sqrtm1[] =         /* sqrt(-1) */
+  MPED25519_CONST(0x2B832480, 0x4FC1DF0B, 0x2B4D0099, 0x3DFBD7A7, 0x2F431806, 0xAD2FE478, 0xC4EE1B27, 0x4A0EA0B0);
+static mp_t ed25519_l[] =              /* order of base point */
+  MPED25519_CONST(0x10000000, 0x00000000, 0x00000000, 0x00000000, 0x14DEF9DE, 0xA2F79CD6, 0x5812631A, 0x5CF5D3ED);
+static mp_t ed25519_gx[] =             /* base point */
+  MPED25519_CONST(0x216936D3, 0xCD6E53FE, 0xC0A4E231, 0xFDD6DC5C, 0x692CC760, 0x9525A7B2, 0xC9562D60, 0x8F25D51A);
+static mp_t ed25519_gy[] =             /* base point */
+  MPED25519_CONST(0x66666666, 0x66666666, 0x66666666, 0x66666666, 0x66666666, 0x66666666, 0x66666666, 0x66666658);
+static mp_t ed25519_one[] =            /* 1 */
+  MPED25519_CONST(0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001);
+
+/* small helpers to save some typing */
+static inline void
+mped25519_add(mp_t *target, mp_t *m1, mp_t *m2)
+{
+  mpadd(MPED25519_LEN, target, m1, m2, ed25519_q);
+}
+
+static inline void
+mped25519_sub(mp_t *target, mp_t *m1, mp_t *m2)
+{
+  mpsub(MPED25519_LEN, target, m1, m2, ed25519_q);
+}
+
+/* target = 512 bit input modulo ed25519_q */
+static void
+mped25519_reduce512(mp_t *target, mp_t *a)
+{
+  int i;
+  mp2_t x;
+
+  for (x = 0, i = 0; i < MPED25519_LEN; i++)
+    {
+      x += (mp2_t)a[i] + (mp2_t)a[i + MPED25519_LEN] * 38;
+      target[i] = x;
+      x >>= MP_T_BITS;
+    }
+  x *= 38;
+  if ((target[MPED25519_LEN - 1] & (1 << (MP_T_BITS - 1))) != 0)
+    {
+      x += 19;
+      target[MPED25519_LEN - 1] -= 1 << (MP_T_BITS - 1);
+    }
+  for (i = 0; x && i < MPED25519_LEN; i++)
+    {
+      x += (mp2_t)target[i];
+      target[i] = x;
+      x >>= MP_T_BITS;
+    }
+  if (target[MPED25519_LEN - 1] > ed25519_q[MPED25519_LEN - 1] ||
+      (target[MPED25519_LEN - 1] == ed25519_q[MPED25519_LEN - 1] && !mpisless(MPED25519_LEN - 1, target, ed25519_q)))
+    mpsubmod(MPED25519_LEN, target, ed25519_q);
+}
+
+static void
+mped25519_mul(mp_t *target, mp_t *m1, mp_t *m2)
+{
+  mp_t tmp[MPED25519_LEN * 2];
+  int i, j;
+  mp2_t x;
+
+  mpzero(MPED25519_LEN * 2, tmp);
+  for (i = 0; i < MPED25519_LEN; i++)
+    {
+      for (x = 0, j = 0; j < MPED25519_LEN; j++)
+       {
+         x += (mp2_t)tmp[i + j] + (mp2_t)m1[i] * m2[j];
+         tmp[i + j] = x;
+         x >>= MP_T_BITS;
+       }
+      tmp[i + j] = x;
+    }
+  mped25519_reduce512(target, tmp);
+}
+
+static inline void
+mped25519_sqr(mp_t *target, mp_t *m)
+{
+  mped25519_mul(target, m, m);
+}
+
+/* target = a ^ (2^252 - 4), a11 = a ^ 11 */
+static void
+mped25519_pow_252_4(mp_t *target, mp_t *a, mp_t *a_11)
+{
+  static const int todo[16] = { 0, 5, 1, 10, 2, 20, 3, 10, 2, 50, 5, 100, 6, 50, 5, 2 };
+  mp_t data[9][MPED25519_LEN];
+  int i, j;
+
+  mpcpy(MPED25519_LEN, target, a);
+  mped25519_sqr(target, target);
+  mpcpy(MPED25519_LEN, a_11, target);
+  mped25519_sqr(target, target);
+  mped25519_sqr(target, target);
+  mped25519_mul(data[0], target, a);           /* data[0] = 9 */
+  mped25519_mul(a_11, data[0], a_11);          /* a_11 = 11 */
+  mped25519_mul(target, a_11, a_11);           /* target = 22 */
+  for (i = 0; i < 8; i++)
+    {
+      mped25519_mul(target, target, data[todo[i * 2]]);
+      mpcpy(MPED25519_LEN, data[i + 1], target);
+      for (j = todo[i * 2 + 1]; j-- > 0;)
+        mped25519_sqr(target, target);
+    }
+}
+
+/* target = a ^ (2^252 - 3) */
+static void
+mped25519_pow_252_3(mp_t *target, mp_t *a)
+{
+  mp_t t11[MPED25519_LEN];
+  mped25519_pow_252_4(target, a, t11);
+  mped25519_mul(target, target, a);
+}
+
+/* target = a ^ -1 = a ^ (2^255 - 21) */
+static void
+mped25519_inv(mp_t *target, mp_t *a)
+{
+  mp_t t[MPED25519_LEN], t11[MPED25519_LEN];
+  mped25519_pow_252_4(t, a, t11);
+  mped25519_sqr(t, t);
+  mped25519_sqr(t, t);
+  mped25519_sqr(t, t);         /* 2^255 - 32 */
+  mped25519_mul(target, t, t11);
+}
+
+static void
+mped25519_reduce512_l(mp_t *target, mp_t *a)
+{
+  mp_t tmp[MPED25519_LEN];
+  mpzero(MPED25519_LEN, target);
+  mpmul_add(MPED25519_LEN, target, ed25519_one, MPED25519_LEN * 2, a, tmp, ed25519_l);
+}
+
+/* recover x coordinate from y and sign */
+static int
+mped25519_recover_x(mp_t *x, mp_t *y, int sign)
+{
+  mp_t num[MPED25519_LEN], den[MPED25519_LEN];
+  mp_t tmp1[MPED25519_LEN], tmp2[MPED25519_LEN];
+
+  if (!mpisless(MPED25519_LEN, y, ed25519_q))
+    return 0;
+  /* calculate num=y^2-1 and den=dy^2+1 */
+  mped25519_sqr(num, y);
+  mped25519_mul(den, num, ed25519_d);
+  mped25519_sub(num, num, ed25519_one);
+  mped25519_add(den, den, ed25519_one);
+
+  /* calculate x = num*den^3 * (num*den^7)^((q-5)/8) */
+  mped25519_sqr(tmp1, den);            /* tmp1 = den^2 */
+  mped25519_mul(tmp2, tmp1, den);      /* tmp2 = den^3 */
+  mped25519_sqr(tmp1, tmp2);           /* tmp1 = den^6 */
+  mped25519_mul(x, tmp1, den);         /* x = den^7 */
+  mped25519_mul(tmp1, x, num);         /* tmp1 = num * den^7 */
+  mped25519_pow_252_3(x, tmp1);                /* x = tmp1^((q-5)/8) */
+  mped25519_mul(tmp1, x, tmp2);                /* tmp1 = x * den^3 */
+  mped25519_mul(x, tmp1, num);         /* x = tmp1 * num */
+
+  /* check if den*x^2 == num */
+  mped25519_sqr(tmp2, x);
+  mped25519_mul(tmp1, tmp2, den);
+  if (!mpisequal(MPED25519_LEN, tmp1, num)) {
+    mped25519_mul(x, x, ed25519_sqrtm1);       /* x = x * sqrt(-1) */
+    mped25519_sqr(tmp2, x);
+    mped25519_mul(tmp1, tmp2, den);
+    if (!mpisequal(MPED25519_LEN, tmp1, num))
+      return 0;
+  }
+  if (mpiszero(MPED25519_LEN, x))
+    return 0;                          /* (0,1) is bad */
+  if ((x[0] & 1) != sign)
+    mped25519_sub(x, ed25519_q, x);
+  return 1;
+}
+
+/* see https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html */
+/* M=7 add=6 */
+static void
+mped25519_ptdouble(mp_t *p_x, mp_t *p_y, mp_t *p_z)
+{
+  mp_t B[MPED25519_LEN], C[MPED25519_LEN], D[MPED25519_LEN];
+  mp_t F[MPED25519_LEN], H[MPED25519_LEN], J[MPED25519_LEN];
+  
+  mped25519_add(C, p_x, p_y);
+  mped25519_sqr(B, C);
+  mped25519_sqr(C, p_x);
+  mped25519_sqr(D, p_y);
+  mped25519_sub(F, C, D);
+  mped25519_sqr(H, p_z);
+  mped25519_add(H, H, H);
+  mped25519_add(J, F, H);
+  mped25519_add(H, C, D);
+  mped25519_mul(p_y, H, F);
+  mped25519_mul(p_z, J, F);
+  mped25519_sub(H, H, B);
+  mped25519_mul(p_x, J, H);
+}
+
+/* M=12 add=7 */
+static void
+mped25519_ptadd(mp_t *p_x, mp_t *p_y, mp_t *p_z, mp_t *q_x, mp_t *q_y, mp_t *q_z)
+{
+  mp_t A[MPED25519_LEN], B[MPED25519_LEN], C[MPED25519_LEN];
+  mp_t D[MPED25519_LEN], E[MPED25519_LEN], F[MPED25519_LEN];
+  mp_t G[MPED25519_LEN], H[MPED25519_LEN], J[MPED25519_LEN];
+  
+  mped25519_mul(A, p_z, q_z);
+  mped25519_sqr(B, A);
+  mped25519_mul(C, p_x, q_x);
+  mped25519_mul(D, p_y, q_y);
+  mped25519_mul(F, ed25519_d, C);
+  mped25519_mul(E, F, D);
+  mped25519_sub(F, B, E);
+  mped25519_add(G, B, E);
+  mped25519_add(H, p_x, p_y);
+  mped25519_add(J, q_x, q_y);
+  mped25519_mul(p_x, H, J);
+  mped25519_sub(p_x, p_x, C);
+  mped25519_sub(p_x, p_x, D);
+  mped25519_mul(H, p_x, F);
+  mped25519_mul(p_x, H, A);
+  mped25519_add(H, D, C);
+  mped25519_mul(J, H, G);
+  mped25519_mul(p_y, J, A);
+  mped25519_mul(p_z, F, G);
+}
+
+static inline void
+mped25519_ptcpy(mp_t *p_x, mp_t *p_y, mp_t *p_z, mp_t *q_x, mp_t *q_y, mp_t *q_z)
+{
+  mpcpy(MPED25519_LEN, p_x, q_x);
+  mpcpy(MPED25519_LEN, p_y, q_y);
+  mpcpy(MPED25519_LEN, p_z, q_z);
+}
+
+#if 0
+static void
+mped25519_mpdump(mp_t *p, char *s, int c)
+{
+  if (c)
+    fprintf(stderr, "%c.", c);
+  mpdump(MPED25519_LEN, p, s);
+}
+
+static void
+mped25519_ptdump(mp_t *p_x, mp_t *p_y, mp_t *p_z, char *s)
+{
+  mp_t zi[MPED25519_LEN], px[MPED25519_LEN], py[MPED25519_LEN];
+  mped25519_mpdump(p_x, s, 'X');
+  mped25519_mpdump(p_y, s, 'Y');
+  mped25519_mpdump(p_z, s, 'Z');
+  mped25519_inv(zi, p_z);
+  mped25519_mul(px, p_x, zi);
+  mped25519_mul(py, p_y, zi);
+  mped25519_mpdump(px, s, 'x');
+  mped25519_mpdump(py, s, 'y');
+}
+#endif
+
+
+/* scalar multiplication and add: r = s1*p1 + s2*p2 */
+/* needs about 13 + (256 - 32) / 2 = 125 point additions */
+static int
+mped25519_scmult2(mp_t *r_x, mp_t *r_y, mp_t *s1, mp_t *p1_x, mp_t * p1_y, mp_t *s2, mp_t *p2_x, mp_t * p2_y)
+{
+  mp_t p_x[MPED25519_LEN], p_y[MPED25519_LEN], p_z[MPED25519_LEN];
+  mp_t pi_z[MPED25519_LEN];
+  mp_t tabx[16][MPED25519_LEN], taby[16][MPED25519_LEN], tabz[16][MPED25519_LEN];
+  int i, x, dodouble = 0;
+
+  mpzero(MPED25519_LEN, p_x);
+  mpzero(MPED25519_LEN, p_y);
+  mpzero(MPED25519_LEN, p_z);
+  p_y[0] = p_z[0] = 1;
+  
+  /* setup table: tab[i * 4 + j] = i * p1 + j * p2 */
+  mped25519_ptcpy(tabx[0], taby[0], tabz[0], p_x, p_y, p_z);
+  for (i = 4; i < 16; i += 4)
+    mped25519_ptcpy(tabx[i], taby[i], tabz[i], p1_x, p1_y, ed25519_one);
+  mped25519_ptdouble(tabx[8], taby[8], tabz[8]);
+  mped25519_ptadd(tabx[12], taby[12], tabz[12], tabx[8], taby[8], tabz[8]);
+  mped25519_ptcpy(tabx[1], taby[1], tabz[1], p2_x, p2_y, ed25519_one);
+  for (i = 2; i < 16; i++)
+    {
+      if ((i & 3) == 0)
+       continue;
+      mped25519_ptcpy(tabx[i], taby[i], tabz[i], tabx[i - 1], taby[i - 1], tabz[i - 1]);
+      mped25519_ptadd(tabx[i], taby[i], tabz[i], p2_x, p2_y, ed25519_one);
+    }
+  /* now do the scalar multiplication */
+  for (i = 255; i >= 0; i--)
+    {
+      if (dodouble)
+        mped25519_ptdouble(p_x, p_y, p_z);
+      x  = s1[i / MP_T_BITS] & (1 << (i % MP_T_BITS)) ? 4 : 0;
+      x |= s2[i / MP_T_BITS] & (1 << (i % MP_T_BITS)) ? 1 : 0;
+      if (!x)
+       continue;
+      if (i > 0)
+       {
+         i--;
+         if (dodouble)
+           mped25519_ptdouble(p_x, p_y, p_z);
+         x <<= 1;
+         x |= s1[i / MP_T_BITS] & (1 << (i % MP_T_BITS)) ? 4 : 0;
+         x |= s2[i / MP_T_BITS] & (1 << (i % MP_T_BITS)) ? 1 : 0;
+       }
+      mped25519_ptadd(p_x, p_y, p_z, tabx[x], taby[x], tabz[x]);
+      dodouble = 1;
+    }
+#if 0
+  mped25519_ptdump(p_x, p_y, p_z, "r   = ");
+#endif
+  mped25519_inv(pi_z, p_z);
+  mped25519_mul(r_x, p_x, pi_z);
+  mped25519_mul(r_y, p_y, pi_z);
+  return mpiszero(MPED25519_LEN, p_z) ? 0 : 1;
+}
+
+static void
+mped25519_setfromle(int len, mp_t *out, const unsigned char *buf, int bufl, int highmask)
+{
+  unsigned char bebuf[64];     /* bufl must be <= 64 */
+  int i;
+  for (i = 0; i < bufl; i++)
+    bebuf[bufl - 1 - i] = buf[i];
+  bebuf[0] &= highmask;
+  mpsetfrombe(len, out, bebuf, bufl);
+}
+
+static int
+mped25519(const unsigned char *pub, const unsigned char *sig, const unsigned char *data, unsigned int datal)
+{
+  unsigned char hbuf[64], rbuf[32];
+  int i;
+  mp_t pub_x[MPED25519_LEN], pub_y[MPED25519_LEN];
+  mp_t h[MPED25519_LEN], s[MPED25519_LEN], h2[MPED25519_LEN * 2];
+  mp_t r_x[MPED25519_LEN], r_y[MPED25519_LEN];
+  Chksum *chk;
+
+  mped25519_setfromle(MPED25519_LEN, s, sig + 32, 32, 0xff);
+  if (!mpisless(MPED25519_LEN, s, ed25519_l))
+    return 0;          /* bad s */
+  /* uncompress pubkey, we invert the sign to get -pub */
+  mped25519_setfromle(MPED25519_LEN, pub_y, pub, 32, 0x7f);
+  if (!mped25519_recover_x(pub_x, pub_y, pub[31] & 0x80 ? 0 : 1))
+    return 0;          /* bad pubkey */
+#if 0
+  mped25519_mpdump(pub_x, "-pubx = ", 0);
+  mped25519_mpdump(pub_y, "puby  = ", 0);
+#endif
+  /* calculate h = H(sig[0..31]|pub|data) mod l */
+  chk = solv_chksum_create(REPOKEY_TYPE_SHA512);
+  if (!chk)
+    return 0;
+  solv_chksum_add(chk, sig, 32);
+  solv_chksum_add(chk, pub, 32);
+  solv_chksum_add(chk, data, datal);
+  solv_chksum_free(chk, hbuf);
+  mped25519_setfromle(MPED25519_LEN * 2, h2, hbuf, 64, 0xff);
+  mped25519_reduce512_l(h, h2);
+#if 0
+  mped25519_mpdump(s, "s     = ", 0);
+  mped25519_mpdump(h, "h     = ", 0);
+#endif
+  /* calculate r = s * G - h * pub */
+  if (!mped25519_scmult2(r_x, r_y, s, ed25519_gx, ed25519_gy, h, pub_x, pub_y))
+    return 0;
+  /* compress r into rbuf and verify that it matches sig */
+  for (i = 0; i < 32; i++)
+    rbuf[i] = r_y[i / MP_T_BYTES] >> (8 * (i % MP_T_BYTES));
+  if ((r_x[0] & 1) != 0)
+    rbuf[31] |= 0x80;
+  return memcmp(sig, rbuf, 32) == 0 ? 1 : 0;
+}
+
index 9bc256c..8fec835 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * Copyright (c) 2013, SUSE Inc.
+ * Copyright (c) 2013-2020, SUSE LLC.
  *
  * This program is licensed under the BSD license, read LICENSE.BSD
  * for further information
  */
 
-/* simple and slow rsa/dsa verification code. */
+/* simple and slow pgp signature verification code. */
 
 #include <stdio.h>
 #include <stdlib.h>
 #include "util.h"
 #include "solv_pgpvrfy.h"
 
+#ifndef ENABLE_PGPVRFY_ED25519
+#define ENABLE_PGPVRFY_ED25519 1
+#endif
+
 typedef unsigned int mp_t;
 typedef unsigned long long mp2_t;
 #define MP_T_BYTES 4
 
 #define MP_T_BITS (MP_T_BYTES * 8)
 
-static inline void
-mpzero(int len, mp_t *target)
-{
-  memset(target, 0, MP_T_BYTES * len);
-}
-
 static inline mp_t *
 mpnew(int len)
 {
@@ -33,11 +31,58 @@ mpnew(int len)
 }
 
 static inline void
+mpzero(int len, mp_t *target)
+{
+  memset(target, 0, MP_T_BYTES * len);
+}
+
+static inline void
 mpcpy(int len, mp_t *target, mp_t *source)
 {
   memcpy(target, source, len * MP_T_BYTES);
 }
 
+static void
+mpsetfrombe(int len, mp_t *target, const unsigned char *buf, int bufl)
+{
+  int i, mpl = len * MP_T_BYTES;
+  buf += bufl;
+  if (bufl >= mpl)
+    bufl = mpl;
+  if (mpl)
+    memset(target, 0, mpl);
+  for (i = 0; bufl > 0; bufl--, i++)
+    target[i / MP_T_BYTES] |= (int)(*--buf) << (8 * (i % MP_T_BYTES));
+}
+
+static int
+mpisless(int len, mp_t *a, mp_t *b)
+{
+  int i;
+  for (i = len - 1; i >= 0; i--)
+    if (a[i] < b[i])
+      return 1;
+    else if (a[i] > b[i])
+      return 0;
+  return 0;
+}
+
+static int
+mpisequal(int len, mp_t *a, mp_t *b)
+{
+  return memcmp(a, b, len * MP_T_BYTES) == 0;
+}
+
+static int
+mpiszero(int len, mp_t *a)
+{
+  int i;
+  for (i = 0; i < len; i++)
+    if (a[i])
+      return 0;
+  return 1;
+}
+
 #if 0
 static void mpdump(int l, mp_t *a, char *s)
 {
@@ -50,6 +95,19 @@ static void mpdump(int l, mp_t *a, char *s)
 }
 #endif
 
+/* subtract mod from target. target >= mod */
+static inline void mpsubmod(int len, mp_t *target, mp_t *mod)
+{
+  int i;
+  mp2_t n;
+  for (n = 0, i = 0; i < len; i++)
+    {
+      mp2_t n2 = (mp2_t)mod[i] + n;
+      n = n2 > target[i] ? 1 : 0;
+      target[i] -= (mp_t)n2;
+    }
+}
+
 /* target[len] = x, target = target % mod
  * assumes that target < (mod << MP_T_BITS)! */
 static void
@@ -86,31 +144,13 @@ mpdomod(int len, mp_t *target, mp2_t x, mp_t *mod)
       x -= n;
     }
   target[i] = x;
-  if (x >= mod[i])
-    {
-      mp_t n;
-      if (x == mod[i])
-       {
-         for (j = i - 1; j >= 0; j--)
-           if (target[j] < mod[j])
-             return;
-           else if (target[j] > mod[j])
-             break;
-       }
-      /* target >= mod, subtract mod */
-      n = 0;
-      for (j = 0; j <= i; j++)
-       {
-         mp2_t n2 = mod[j] + n;
-         n = n2 > target[j] ? 1 : 0;
-         target[j] -= (mp_t)n2;
-       }
-    }
+  if (x > mod[i] || (x == mod[i] && !mpisless(i, target, mod)))
+    mpsubmod(i + 1, target, mod);
 }
 
 /* target += src * m */
 static void
-mpmult_add_int(int len, mp_t *target, mp_t *src, mp2_t m, mp_t *mod)
+mpmul_add_int(int len, mp_t *target, mp_t *src, mp2_t m, mp_t *mod)
 {
   int i;
   mp2_t x = 0;
@@ -139,7 +179,7 @@ mpshift(int len, mp_t *target, mp_t *mod)
 
 /* target += m1 * m2 */
 static void
-mpmult_add(int len, mp_t *target, mp_t *m1, int m2len, mp_t *m2, mp_t *tmp, mp_t *mod)
+mpmul_add(int len, mp_t *target, mp_t *m1, int m2len, mp_t *m2, mp_t *tmp, mp_t *mod)
 {
   int i, j;
   for (j = m2len - 1; j >= 0; j--)
@@ -151,19 +191,19 @@ mpmult_add(int len, mp_t *target, mp_t *m1, int m2len, mp_t *m2, mp_t *tmp, mp_t
   for (i = 0; i < j; i++)
     {
       if (m2[i])
-        mpmult_add_int(len, target, tmp, m2[i], mod);
+       mpmul_add_int(len, target, tmp, m2[i], mod);
       mpshift(len, tmp, mod);
     }
   if (m2[i])
-    mpmult_add_int(len, target, tmp, m2[i], mod);
+    mpmul_add_int(len, target, tmp, m2[i], mod);
 }
 
 /* target = target * m */
 static void
-mpmult_inplace(int len, mp_t *target, mp_t *m, mp_t *tmp1, mp_t *tmp2, mp_t *mod)
+mpmul_inplace(int len, mp_t *target, mp_t *m, mp_t *tmp1, mp_t *tmp2, mp_t *mod)
 {
   mpzero(len, tmp1);
-  mpmult_add(len, tmp1, target, len, m, tmp2, mod);
+  mpmul_add(len, tmp1, target, len, m, tmp2, mod);
   mpcpy(len, target, tmp1);
 }
 
@@ -172,15 +212,15 @@ static void
 mppow_int(int len, mp_t *target, mp_t *t, mp_t *mod, int e)
 {
   mp_t *t2 = t + len * 16;
-  mpmult_inplace(len, target, target, t, t2, mod);
-  mpmult_inplace(len, target, target, t, t2, mod);
-  mpmult_inplace(len, target, target, t, t2, mod);
-  mpmult_inplace(len, target, target, t, t2, mod);
+  mpmul_inplace(len, target, target, t, t2, mod);
+  mpmul_inplace(len, target, target, t, t2, mod);
+  mpmul_inplace(len, target, target, t, t2, mod);
+  mpmul_inplace(len, target, target, t, t2, mod);
   if (e)
-    mpmult_inplace(len, target, t + len * e, t, t2, mod);
+    mpmul_inplace(len, target, t + len * e, t, t2, mod);
 }
 
-/* target = b ^ e (b has to be < mod) */
+/* target = b ^ e (b < mod) */
 static void
 mppow(int len, mp_t *target, mp_t *b, int elen, mp_t *e, mp_t *mod)
 {
@@ -196,7 +236,7 @@ mppow(int len, mp_t *target, mp_t *b, int elen, mp_t *e, mp_t *mod)
   t = mpnew(len * 17);
   mpcpy(len, t + len, b);
   for (j = 2; j < 16; j++)
-    mpmult_add(len, t + len * j, b, len, t + len * j - len, t + len * 16, mod);
+    mpmul_add(len, t + len * j, b, len, t + len * j - len, t + len * 16, mod);
   for (; i >= 0; i--)
     {
 #if MP_T_BYTES == 4
@@ -216,48 +256,67 @@ mppow(int len, mp_t *target, mp_t *b, int elen, mp_t *e, mp_t *mod)
   free(t);
 }
 
-/* target = m1 * m2 (m1 has to be < mod) */
+/* target = m1 * m2 (m1 < mod) */
 static void
-mpmult(int len, mp_t *target, mp_t *m1, int m2len, mp_t *m2, mp_t *mod)
+mpmul(int len, mp_t *target, mp_t *m1, int m2len, mp_t *m2, mp_t *mod)
 {
   mp_t *tmp = mpnew(len);
   mpzero(len, target);
-  mpmult_add(len, target, m1, m2len, m2, tmp, mod);
+  mpmul_add(len, target, m1, m2len, m2, tmp, mod);
   free(tmp);
 }
 
-static int
-mpisless(int len, mp_t *a, mp_t *b)
+static void
+mpdec(int len, mp_t *a)
 {
   int i;
-  for (i = len - 1; i >= 0; i--)
-    if (a[i] < b[i])
-      return 1;
-    else if (a[i] > b[i])
-      return 0;
-  return 0;
+  for (i = 0; i < len; i++)
+    if (a[i]--)
+      return;
 }
 
-static int
-mpiszero(int len, mp_t *a)
+#if ENABLE_PGPVRFY_ED25519
+/* target = m1 + m2 (m1, m2 < mod). target may be m1 or m2 */
+static void
+mpadd(int len, mp_t *target, mp_t *m1, mp_t *m2, mp_t *mod)
 {
   int i;
+  mp2_t x = 0;
   for (i = 0; i < len; i++)
-    if (a[i])
-      return 0;
-  return 1;
+    {
+      x += (mp2_t)m1[i] + m2[i];
+      target[i] = x;
+      x >>= MP_T_BITS;
+    }
+  if (x || target[len - 1] > mod[len - 1] ||
+      (target[len -1 ] == mod[len - 1] && !mpisless(len - 1, target, mod)))
+    mpsubmod(len, target, mod);
 }
 
+/* target = m1 - m2 (m1, m2 < mod). target may be m1 or m2 */
 static void
-mpdec(int len, mp_t *a)
+mpsub(int len, mp_t *target, mp_t *m1, mp_t *m2, mp_t *mod)
 {
   int i;
+  mp2_t x = 0;
   for (i = 0; i < len; i++)
-    if (a[i]--)
-      return;
-    else
-      a[i] = -(mp_t)1;
+    {
+      x = (mp2_t)m1[i] - m2[i] - x;
+      target[i] = x;
+      x = x & ((mp2_t)1 << MP_T_BITS) ? 1 : 0;
+    }
+  if (x)
+    {
+      for (x = 0, i = 0; i < len; i++)
+       {
+         x += (mp2_t)target[i] + mod[i];
+         target[i] = x;
+         x >>= MP_T_BITS;
+       }
+    }
 }
+#endif
+
 
 static int
 mpdsa(int pl, mp_t *p, int ql, mp_t *q, mp_t *g, mp_t *y, mp_t *r, mp_t *s, int hl, mp_t *h)
@@ -266,6 +325,7 @@ mpdsa(int pl, mp_t *p, int ql, mp_t *q, mp_t *g, mp_t *y, mp_t *r, mp_t *s, int
   mp_t *tmp;
   mp_t *u1, *u2;
   mp_t *gu1, *yu2;
+  int res;
 #if 0
   mpdump(pl, p, "p = ");
   mpdump(ql, q, "q = ");
@@ -286,41 +346,38 @@ mpdsa(int pl, mp_t *p, int ql, mp_t *q, mp_t *g, mp_t *y, mp_t *r, mp_t *s, int
   mpdec(ql, tmp);                      /* tmp-- */
   mpdec(ql, tmp);                      /* tmp-- */
   w = mpnew(ql);
-  mppow(ql, w, s, ql, tmp, q);         /* w = s ^ tmp (s ^ -1) */
+  mppow(ql, w, s, ql, tmp, q);         /* w = s ^ tmp (s ^ -1) */
   u1 = mpnew(pl);                      /* note pl */
   /* order is important here: h can be >= q */
-  mpmult(ql, u1, w, hl, h, q);         /* u1 = w * h */
+  mpmul(ql, u1, w, hl, h, q);          /* u1 = w * h */
   u2 = mpnew(ql);                      /* u2 = 0 */
-  mpmult(ql, u2, w, ql, r, q);         /* u2 = w * r */
+  mpmul(ql, u2, w, ql, r, q);          /* u2 = w * r */
   free(w);
   gu1 = mpnew(pl);
   yu2 = mpnew(pl);
   mppow(pl, gu1, g, ql, u1, p);                /* gu1 = g ^ u1 */
   mppow(pl, yu2, y, ql, u2, p);                /* yu2 = y ^ u2 */
-  mpmult(pl, u1, gu1, pl, yu2, p);     /* u1 = gu1 * yu2 */
+  mpmul(pl, u1, gu1, pl, yu2, p);      /* u1 = gu1 * yu2 */
   free(gu1);
   free(yu2);
   mpzero(ql, u2);
   u2[0] = 1;                           /* u2 = 1 */
-  mpmult(ql, tmp, u2, pl, u1, q);      /* tmp = u2 * u1 */
+  mpmul(ql, tmp, u2, pl, u1, q);       /* tmp = u2 * u1 */
   free(u1);
   free(u2);
 #if 0
   mpdump(ql, tmp, "res = ");
 #endif
-  if (memcmp(tmp, r, ql * MP_T_BYTES) != 0)
-    {
-      free(tmp);
-      return 0;
-    }
+  res = mpisequal(ql, tmp, r);
   free(tmp);
-  return 1;
+  return res;
 }
 
 static int
 mprsa(int nl, mp_t *n, int el, mp_t *e, mp_t *m, mp_t *c)
 {
   mp_t *tmp;
+  int res;
 #if 0
   mpdump(nl, n, "n = ");
   mpdump(el, e, "e = ");
@@ -336,34 +393,24 @@ mprsa(int nl, mp_t *n, int el, mp_t *e, mp_t *m, mp_t *c)
 #if 0
   mpdump(nl, tmp, "res = ");
 #endif
-  if (memcmp(tmp, c, nl * MP_T_BYTES) != 0)
-    {
-      free(tmp);
-      return 0;
-    }
+  res = mpisequal(nl, tmp, c);
   free(tmp);
-  return 1;
+  return res;
 }
 
+#if ENABLE_PGPVRFY_ED25519
+# include "solv_ed25519.h"
+#endif
+
 /* create mp with size tbits from data with size dbits */
 static mp_t *
 mpbuild(const unsigned char *d, int dbits, int tbits, int *mplp)
 {
   int l = (tbits + MP_T_BITS - 1) / MP_T_BITS;
-  int dl, i;
-
   mp_t *out = mpnew(l ? l : 1);
   if (mplp)
     *mplp = l;
-  dl = (dbits + 7) / 8;
-  d += dl;
-  if (dbits > tbits)
-    dl = (tbits + 7) / 8;
-  for (i = 0; dl > 0; dl--, i++)
-    {
-      int x = *--d;
-      out[i / MP_T_BYTES] |= x << (8 * (i % MP_T_BYTES));
-    }
+  mpsetfrombe(l, out, d, (dbits + 7) / 8);
   return out;
 }
 
@@ -390,6 +437,8 @@ findmpi(const unsigned char **mpip, int *mpilp, int maxbits, int *outlen)
   return mpi + 2;
 }
 
+/* sig: 0:algo 1:hash 2-:mpidata */
+/* pub: 0:algo 1-:mpidata */
 int
 solv_pgpvrfy(const unsigned char *pub, int publ, const unsigned char *sig, int sigl)
 {
@@ -515,6 +564,36 @@ solv_pgpvrfy(const unsigned char *pub, int publ, const unsigned char *sig, int s
        free(hx);
        break;
       }
+#if ENABLE_PGPVRFY_ED25519
+    case 22:           /* EdDSA */
+      {
+       unsigned char sigdata[64];
+       const unsigned char *r, *s;
+       int rlen, slen;
+
+       /* check the curve */
+       if (publ < 11 || memcmp(pub + 1, "\011\053\006\001\004\001\332\107\017\001", 10) != 0)
+         return 0;     /* we only support the Ed25519 curve */
+       /* the pubkey always has 7 + 256 bits */
+       if (publ != 1 + 10 + 2 + 1 + 32 || pub[1 + 10 + 0] != 1 || pub[1 + 10 + 1] != 7 || pub[1 + 10 + 2] != 0x40)
+         return 0;
+       mpi = sig + 2 + hashl;
+       mpil = sigl - (2 + hashl);
+       r = findmpi(&mpi, &mpil, 256, &rlen);
+       s = findmpi(&mpi, &mpil, 256, &slen);
+       if (!r || !s)
+         return 0;
+       memset(sigdata, 0, 64);
+       rlen = (rlen + 7) / 8;
+       slen = (slen + 7) / 8;
+       if (rlen)
+         memcpy(sigdata + 32 - rlen, r, rlen);
+       if (slen)
+         memcpy(sigdata + 64 - slen, s, rlen);
+       res = mped25519(pub + 1 + 10 + 2 + 1, sigdata, sig + 2, hashl);
+       break;
+      }
+#endif
     default:
       return 0;                /* unsupported pubkey algo */
     }
index 5aec357..52ea164 100644 (file)
@@ -1,4 +1,13 @@
 -------------------------------------------------------------------
+Wed May 27 11:48:46 CEST 2020 - mls@suse.de
+
+- Support blacklisted packages in solver_findproblemrule()
+  [bnc#1172135]
+- Support rules with multiple negative literals in choice rule
+  generation
+- bump version to 0.7.14
+
+-------------------------------------------------------------------
 Fri Apr 24 12:00:30 CEST 2020 - mls@suse.de
 
 - Fix solvable swapping messing up idarrays
index fe8d55e..6551cbf 100644 (file)
@@ -833,6 +833,7 @@ move_installed_to_front(Pool *pool, Queue *plist)
     }
 }
 
+#ifdef ENABLE_CONDA
 static int
 pool_buildversioncmp(Pool *pool, Solvable *s1, Solvable *s2)
 {
@@ -858,6 +859,7 @@ pool_buildflavorcmp(Pool *pool, Solvable *s1, Solvable *s2)
     return 0;
   return pool_evrcmp_str(pool, f1 ? f1 : "" , f2 ? f2 : "", EVRCMP_COMPARE);
 }
+#endif
 
 /*
  * prune_to_best_version
@@ -906,10 +908,17 @@ prune_to_best_version(Pool *pool, Queue *plist)
       if (r == 0 && has_package_link(pool, s))
         r = pool_link_evrcmp(pool, best, s);
 #endif
-      if (r == 0 && pool->disttype == DISTTYPE_CONDA)
-       r = pool_buildversioncmp(pool, best, s);
-      if (r == 0 && pool->disttype == DISTTYPE_CONDA)
-       r = pool_buildflavorcmp(pool, best, s);
+#ifdef ENABLE_CONDA
+      if (pool->disttype == DISTTYPE_CONDA)
+       {
+         if (r == 0)
+           r = (best->repo ? best->repo->subpriority : 0) - (s->repo ? s->repo->subpriority : 0);
+         if (r == 0)
+           r = pool_buildversioncmp(pool, best, s);
+         if (r == 0)
+           r = pool_buildflavorcmp(pool, best, s);
+       }
+#endif
       if (r < 0)
        best = s;
     }
index 63165f3..a6b9394 100644 (file)
@@ -1068,10 +1068,10 @@ solver_take_solution(Solver *solv, Id problem, Id solution, Queue *job)
  */
 
 static void
-findproblemrule_internal(Solver *solv, Id idx, Id *reqrp, Id *conrp, Id *sysrp, Id *jobrp, Map *rseen)
+findproblemrule_internal(Solver *solv, Id idx, Id *reqrp, Id *conrp, Id *sysrp, Id *jobrp, Id *blkrp, Map *rseen)
 {
   Id rid, d;
-  Id lreqr, lconr, lsysr, ljobr;
+  Id lreqr, lconr, lsysr, ljobr, lblkr;
   Rule *r;
   Id jobassert = 0;
   int i, reqset = 0;   /* 0: unset, 1: installed, 2: jobassert, 3: assert */
@@ -1093,7 +1093,7 @@ findproblemrule_internal(Solver *solv, Id idx, Id *reqrp, Id *conrp, Id *sysrp,
 
   /* the problem rules are somewhat ordered from "near to the problem" to
    * "near to the job" */
-  lreqr = lconr = lsysr = ljobr = 0;
+  lreqr = lconr = lsysr = ljobr = lblkr = 0;
   while ((rid = solv->learnt_pool.elements[idx++]) != 0)
     {
       assert(rid > 0);
@@ -1102,9 +1102,9 @@ findproblemrule_internal(Solver *solv, Id idx, Id *reqrp, Id *conrp, Id *sysrp,
          if (MAPTST(rseen, rid - solv->learntrules))
            continue;
          MAPSET(rseen, rid - solv->learntrules);
-         findproblemrule_internal(solv, solv->learnt_why.elements[rid - solv->learntrules], &lreqr, &lconr, &lsysr, &ljobr, rseen);
+         findproblemrule_internal(solv, solv->learnt_why.elements[rid - solv->learntrules], &lreqr, &lconr, &lsysr, &ljobr, &lblkr, rseen);
        }
-      else if ((rid >= solv->jobrules && rid < solv->jobrules_end) || (rid >= solv->infarchrules && rid < solv->infarchrules_end) || (rid >= solv->duprules && rid < solv->duprules_end) || (rid >= solv->bestrules && rid < solv->bestrules_end) || (rid >= solv->yumobsrules && rid <= solv->yumobsrules_end))
+      else if ((rid >= solv->jobrules && rid < solv->jobrules_end) || (rid >= solv->infarchrules && rid < solv->infarchrules_end) || (rid >= solv->duprules && rid < solv->duprules_end) || (rid >= solv->bestrules && rid < solv->bestrules_end) || (rid >= solv->yumobsrules && rid < solv->yumobsrules_end))
        {
          if (!*jobrp)
            *jobrp = rid;
@@ -1114,6 +1114,11 @@ findproblemrule_internal(Solver *solv, Id idx, Id *reqrp, Id *conrp, Id *sysrp,
          if (!*sysrp)
            *sysrp = rid;
        }
+      else if (rid >= solv->blackrules && rid < solv->blackrules_end)
+       {
+         if (!*blkrp)
+           *blkrp = rid;
+       }
       else
        {
          assert(rid < solv->pkgrules_end);
@@ -1176,6 +1181,8 @@ findproblemrule_internal(Solver *solv, Id idx, Id *reqrp, Id *conrp, Id *sysrp,
     *jobrp = ljobr;
   if (!*sysrp && lsysr)
     *sysrp = lsysr;
+  if (!*blkrp && lblkr)
+    *blkrp = lblkr;
 }
 
 /*
@@ -1190,12 +1197,12 @@ findproblemrule_internal(Solver *solv, Id idx, Id *reqrp, Id *conrp, Id *sysrp,
 Id
 solver_findproblemrule(Solver *solv, Id problem)
 {
-  Id reqr, conr, sysr, jobr;
+  Id reqr, conr, sysr, jobr, blkr;
   Id idx = solv->problems.elements[2 * problem - 2];
   Map rseen;
-  reqr = conr = sysr = jobr = 0;
+  reqr = conr = sysr = jobr = blkr = 0;
   map_init(&rseen, solv->learntrules ? solv->nrules - solv->learntrules : 0);
-  findproblemrule_internal(solv, idx, &reqr, &conr, &sysr, &jobr, &rseen);
+  findproblemrule_internal(solv, idx, &reqr, &conr, &sysr, &jobr, &blkr, &rseen);
   map_free(&rseen);
   /* check if the request is about a not-installed package requiring a installed
    * package conflicting with the non-installed package. In that case return the conflict */
@@ -1223,6 +1230,8 @@ solver_findproblemrule(Solver *solv, Id problem)
     return reqr;       /* some requires */
   if (conr)
     return conr;       /* some conflict */
+  if (blkr)
+    return blkr;       /* a blacklisted package */
   if (sysr)
     return sysr;       /* an update rule */
   if (jobr)
index 6b1432f..ffa2988 100644 (file)
@@ -3210,7 +3210,7 @@ solver_addchoicerules(Solver *solv)
   Map m, mneg;
   Rule *r;
   Queue q, qi, qcheck, infoq;
-  int i, j, rid, havechoice;
+  int i, j, rid, havechoice, negcnt;
   Id p, d, pp;
   Id p2, pp2;
   Solvable *s, *s2;
@@ -3389,9 +3389,12 @@ solver_addchoicerules(Solver *solv)
              qi.elements[j] = 0;
        }
       /* empty map again */
+      negcnt = 0;
       FOR_RULELITERALS(p, pp, r)
         if (p > 0)
          MAPCLR(&m, p);
+       else
+         negcnt++;
       if (i == qi.count)
        {
 #if 0
@@ -3400,7 +3403,14 @@ solver_addchoicerules(Solver *solv)
 #endif
          continue;
        }
-
+      /* add neg elements to the front */
+      if (negcnt > 1)
+       {
+         i = 0;
+         FOR_RULELITERALS(p, pp, r)
+          if (p < 0 && p != r->p)
+            queue_insert(&q, i++, p);
+       }
       /* don't add identical rules */
       if (lastaddedp == r->p && lastaddedcnt == q.count)
        {