#include "inner.h"
-#define U (1 + ((BR_MAX_RSA_FACTOR + 14) / 15))
+#define U (2 + ((BR_MAX_RSA_FACTOR + 14) / 15))
#define TLEN (8 * U)
-/* obsolete
-static void
-print_int(const char *name, const uint16_t *x)
-{
- extern int printf(const char *fmt, ...);
- unsigned char tmp[1000];
- size_t u, len;
-
- len = (x[0] - (x[0] >> 4) + 7) >> 3;
- br_i15_encode(tmp, len, x);
- printf("%s = ", name);
- for (u = 0; u < len; u ++) {
- printf("%02X", tmp[u]);
- }
- printf("\n");
-}
-*/
-
/* see bearssl_rsa.h */
uint32_t
br_rsa_i15_private(unsigned char *x, const br_rsa_private_key *sk)
size_t plen, qlen;
size_t fwlen;
uint16_t p0i, q0i;
- size_t xlen;
- uint16_t tmp[TLEN];
+ size_t xlen, u;
+ uint16_t tmp[1 + TLEN];
long z;
uint16_t *mp, *mq, *s1, *s2, *t1, *t2, *t3;
uint32_t r;
z -= 15;
fwlen ++;
}
+ /*
+ * Round up the word length to an even number.
+ */
+ fwlen += (fwlen & 1);
/*
* We need to fit at least 6 values in the stack buffer.
xlen = (sk->n_bitlen + 7) >> 3;
/*
- * Decode q.
+ * Ensure 32-bit alignment for value words.
*/
mq = tmp;
- br_i15_decode(mq, q, qlen);
+ if (((uintptr_t)mq & 2) == 0) {
+ mq ++;
+ }
/*
- * Compute s2 = x^dq mod q.
+ * Decode q.
*/
- q0i = br_i15_ninv15(mq[1]);
- s2 = tmp + fwlen;
- br_i15_decode_reduce(s2, x, xlen, mq);
- r = br_i15_modpow_opt(s2, sk->dq, sk->dqlen, mq, q0i,
- tmp + 2 * fwlen, TLEN - 2 * fwlen);
+ br_i15_decode(mq, q, qlen);
/*
* Decode p.
*/
- mp = tmp + 2 * fwlen;
- br_i15_decode(mp, p, plen);
+ 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);
+
+ /*
+ * Compute s2 = x^dq mod q.
+ */
+ q0i = br_i15_ninv15(mq[1]);
+ s2 = mq + fwlen;
+ br_i15_decode_reduce(s2, x, xlen, mq);
+ r &= br_i15_modpow_opt(s2, sk->dq, sk->dqlen, mq, q0i,
+ mq + 3 * fwlen, TLEN - 3 * fwlen);
/*
* Compute s1 = x^dq mod q.
*/
p0i = br_i15_ninv15(mp[1]);
- s1 = tmp + 3 * fwlen;
+ s1 = mq + 3 * fwlen;
br_i15_decode_reduce(s1, x, xlen, mp);
r &= br_i15_modpow_opt(s1, sk->dp, sk->dplen, mp, p0i,
- tmp + 4 * fwlen, TLEN - 4 * fwlen);
+ mq + 4 * fwlen, TLEN - 4 * fwlen);
/*
* Compute:
* inverse of q modulo p), we also tolerate improperly large
* values for this parameter.
*/
- t1 = tmp + 4 * fwlen;
- t2 = tmp + 5 * fwlen;
+ t1 = mq + 4 * fwlen;
+ t2 = mq + 5 * fwlen;
br_i15_reduce(t2, s2, mp);
br_i15_add(s1, mp, br_i15_sub(s1, t2, 1));
br_i15_to_monty(s1, mp);