Added stricter rule on input for RSA private key operation (mathematically correct but out-of-range values are now rejected).

This commit is contained in:
Thomas Pornin 2018-05-23 18:48:19 +02:00
parent 932fb89081
commit f81a282878
5 changed files with 652 additions and 64 deletions

View file

@ -27,24 +27,6 @@
#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)
@ -53,7 +35,7 @@ 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;
size_t xlen, u;
uint16_t tmp[1 + TLEN];
long z;
uint16_t *mp, *mq, *s1, *s2, *t1, *t2, *t3;
@ -116,20 +98,57 @@ br_rsa_i15_private(unsigned char *x, const br_rsa_private_key *sk)
*/
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);
/*
* 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 + 2 * fwlen, TLEN - 2 * fwlen);
/*
* Decode p.
*/
mp = mq + 2 * fwlen;
br_i15_decode(mp, p, plen);
r &= br_i15_modpow_opt(s2, sk->dq, sk->dqlen, mq, q0i,
mq + 3 * fwlen, TLEN - 3 * fwlen);
/*
* Compute s1 = x^dq mod q.

View file

@ -35,7 +35,7 @@ br_rsa_i31_private(unsigned char *x, const br_rsa_private_key *sk)
size_t plen, qlen;
size_t fwlen;
uint32_t p0i, q0i;
size_t xlen;
size_t xlen, u;
uint32_t tmp[1 + TLEN];
long z;
uint32_t *mp, *mq, *s1, *s2, *t1, *t2, *t3;
@ -82,7 +82,7 @@ br_rsa_i31_private(unsigned char *x, const br_rsa_private_key *sk)
}
/*
* Compute signature length (in bytes).
* Compute modulus length (in bytes).
*/
xlen = (sk->n_bitlen + 7) >> 3;
@ -92,20 +92,57 @@ br_rsa_i31_private(unsigned char *x, const br_rsa_private_key *sk)
mq = tmp;
br_i31_decode(mq, q, qlen);
/*
* Decode p.
*/
t1 = mq + fwlen;
br_i31_decode(t1, p, plen);
/*
* Compute the modulus (product of the two factors), to compare
* it with the source value. We use br_i31_mulacc(), since it's
* already used later on.
*/
t2 = mq + 2 * fwlen;
br_i31_zero(t2, mq[0]);
br_i31_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_i31_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_i31_ninv31(mq[1]);
s2 = mq + fwlen;
br_i31_decode_reduce(s2, x, xlen, mq);
r = br_i31_modpow_opt(s2, sk->dq, sk->dqlen, mq, q0i,
mq + 2 * fwlen, TLEN - 2 * fwlen);
/*
* Decode p.
*/
mp = mq + 2 * fwlen;
br_i31_decode(mp, p, plen);
r &= br_i31_modpow_opt(s2, sk->dq, sk->dqlen, mq, q0i,
mq + 3 * fwlen, TLEN - 3 * fwlen);
/*
* Compute s1 = x^dp mod p.

View file

@ -35,7 +35,8 @@ br_rsa_i32_private(unsigned char *x, const br_rsa_private_key *sk)
uint32_t tmp[6 * U];
uint32_t *mp, *mq, *s1, *s2, *t1, *t2, *t3;
uint32_t p0i, q0i;
size_t xlen;
size_t xlen, u;
uint32_t r;
/*
* All our temporary buffers are from the tmp[] array.
@ -82,16 +83,22 @@ br_rsa_i32_private(unsigned char *x, const br_rsa_private_key *sk)
br_i32_decode(mq, q, qlen);
/*
* obsolete -- we do not compute the length of n, it is now
* an input parameter.
br_i32_zero(t3, mp[0]);
br_i32_mulacc(t3, mp, mq);
n_bitlen = br_i32_bit_length(t3 + 1, (t3[0] + 31) >> 5);
if (xlen != ((n_bitlen + 7) >> 3)) {
return 0;
}
* Recompute modulus, to compare with the source value.
*/
br_i32_zero(t2, mp[0]);
br_i32_mulacc(t2, mp, mq);
xlen = (sk->n_bitlen + 7) >> 3;
br_i32_encode(t2 + 2 * U, xlen, t2);
u = xlen;
r = 0;
while (u > 0) {
uint32_t wn, wx;
u --;
wn = ((unsigned char *)(t2 + 2 * U))[u];
wx = x[u];
r = ((wx - (wn + r)) >> 8) & 1;
}
/*
* Compute s1 = x^dp mod p.
@ -149,5 +156,5 @@ br_rsa_i32_private(unsigned char *x, const br_rsa_private_key *sk)
* The only error conditions remaining at that point are invalid
* values for p and q (even integers).
*/
return p0i & q0i & 1;
return p0i & q0i & r;
}

View file

@ -37,7 +37,7 @@ br_rsa_i62_private(unsigned char *x, const br_rsa_private_key *sk)
size_t plen, qlen;
size_t fwlen;
uint32_t p0i, q0i;
size_t xlen;
size_t xlen, u;
uint64_t tmp[TLEN];
long z;
uint32_t *mp, *mq, *s1, *s2, *t1, *t2, *t3;
@ -94,20 +94,57 @@ br_rsa_i62_private(unsigned char *x, const br_rsa_private_key *sk)
mq = (uint32_t *)tmp;
br_i31_decode(mq, q, qlen);
/*
* Decode p.
*/
t1 = (uint32_t *)(tmp + fwlen);
br_i31_decode(t1, p, plen);
/*
* Compute the modulus (product of the two factors), to compare
* it with the source value. We use br_i31_mulacc(), since it's
* already used later on.
*/
t2 = (uint32_t *)(tmp + 2 * fwlen);
br_i31_zero(t2, mq[0]);
br_i31_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 = (uint32_t *)(tmp + 4 * fwlen);
br_i31_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 = (uint32_t *)(tmp + 2 * fwlen);
memmove(mp, t1, 2 * fwlen * sizeof *t1);
/*
* Compute s2 = x^dq mod q.
*/
q0i = br_i31_ninv31(mq[1]);
s2 = (uint32_t *)(tmp + fwlen);
br_i31_decode_reduce(s2, x, xlen, mq);
r = br_i62_modpow_opt(s2, sk->dq, sk->dqlen, mq, q0i,
tmp + 2 * fwlen, TLEN - 2 * fwlen);
/*
* Decode p.
*/
mp = (uint32_t *)(tmp + 2 * fwlen);
br_i31_decode(mp, p, plen);
r &= br_i62_modpow_opt(s2, sk->dq, sk->dqlen, mq, q0i,
tmp + 3 * fwlen, TLEN - 3 * fwlen);
/*
* Compute s1 = x^dp mod p.