- p0i = br_i15_ninv15(mp[1]);
- br_i15_decode_reduce(s1, x, xlen, mp);
- br_i15_modpow(s1, sk->dp, sk->dplen, mp, p0i, t1, t2);
+ mq = tmp;
+ if (((uintptr_t)mq & 2) == 0) {
+ mq ++;
+ }
+
+ /*
+ * Decode q.
+ */
+ br_i15_decode(mq, q, qlen);
+
+ /*
+ * Decode p.
+ */
+ t1 = mq + fwlen;
+ br_i15_decode(t1, p, plen);
+
+ /*
+ * Compute the modulus (product of the two factors), to compare
+ * it with the source value. We use br_i15_mulacc(), since it's
+ * already used later on.
+ */
+ t2 = mq + 2 * fwlen;
+ br_i15_zero(t2, mq[0]);
+ br_i15_mulacc(t2, mq, t1);
+
+ /*
+ * We encode the modulus into bytes, to perform the comparison
+ * with bytes. We know that the product length, in bytes, is
+ * exactly xlen.
+ * The comparison actually computes the carry when subtracting
+ * the modulus from the source value; that carry must be 1 for
+ * a value in the correct range. We keep it in r, which is our
+ * accumulator for the error code.
+ */
+ t3 = mq + 4 * fwlen;
+ br_i15_encode(t3, xlen, t2);
+ u = xlen;
+ r = 0;
+ while (u > 0) {
+ uint32_t wn, wx;
+
+ u --;
+ wn = ((unsigned char *)t3)[u];
+ wx = x[u];
+ r = ((wx - (wn + r)) >> 8) & 1;
+ }
+
+ /*
+ * Move the decoded p to another temporary buffer.
+ */
+ mp = mq + 2 * fwlen;
+ memmove(mp, t1, fwlen * sizeof *t1);