Fix equality predicates.

The count we passed to memcmp() in mpi_eq() and mpi_eq_abs() was actually the number of significant words in the MPI, rather than the number of bytes we wanted to compare.  Multiply by 4 to get the correct value.

To make the intent of the code more apparent, introduce a private MPI_MSW() macro which evaluates to the number of significant words (or 1-based index of the most significant word).  This also comes in handy in mpi_{add,sub,mul}_abs().

Add a couple of test cases which not only demonstrate the bug we fixed here but also demonstrate why we must compare whole words: on a big-endian machine, we would be comparing the unused upper bytes of the first and only word instead of the lower bytes which actually hold a value...
This commit is contained in:
Dag-Erling Smørgrav 2017-04-22 05:32:25 +02:00
parent c556bc0aa8
commit a09cdc6318
7 changed files with 13 additions and 6 deletions

View File

@ -92,7 +92,7 @@ mpi_add_abs(cryb_mpi *X, const cryb_mpi *A, const cryb_mpi *B)
*/
/* add B into X word by word until we run out of B */
for (c = i = 0; i < (B->msb + 31) / 32; ++i) {
for (c = i = 0; i < MPI_MSW(B); ++i) {
X->words[i] += c;
c = (X->words[i] < c);
X->words[i] += B->words[i];

View File

@ -47,5 +47,5 @@ mpi_eq(const cryb_mpi *A, const cryb_mpi *B)
return (1);
if (A->neg != B->neg || A->msb != B->msb)
return (0);
return (memcmp(A->words, B->words, (A->msb + 31) / 32) == 0);
return (memcmp(A->words, B->words, MPI_MSW(A) * 4) == 0);
}

View File

@ -47,5 +47,5 @@ mpi_eq_abs(const cryb_mpi *A, const cryb_mpi *B)
return (1);
if (A->msb != B->msb)
return (0);
return (memcmp(A->words, B->words, (A->msb + 31) / 32) == 0);
return (memcmp(A->words, B->words, MPI_MSW(A) * 4) == 0);
}

View File

@ -30,6 +30,9 @@
/* n rounded up to nearest multiple of p */
#define RUP(n, p) ((((n) + (p) - 1) / (p)) * (p))
/* one-based index of the most significant word of an mpi */
#define MPI_MSW(n) (((n)->msb + 31) / 32)
/*
* Initialize an all-zeroes mpi.
*/

View File

@ -72,8 +72,8 @@ mpi_mul_abs(cryb_mpi *X, const cryb_mpi *A, const cryb_mpi *B)
*/
P = (X == A || X == B) ? &T : X;
mpi_zero(P);
a = (A->msb + 31) / 32;
b = (B->msb + 31) / 32;
a = MPI_MSW(A);
b = MPI_MSW(B);
if (mpi_grow(P, (a + b) * 32) != 0)
return (-1);

View File

@ -81,7 +81,7 @@ mpi_sub_abs(cryb_mpi *X, const cryb_mpi *A, const cryb_mpi *B)
return (-1);
/* subtract L from G word by word until we run out of L */
for (c = i = 0; i < (L->msb + 31) / 32; ++i) {
for (c = i = 0; i < MPI_MSW(L); ++i) {
cn = G->words[i] < c ||
G->words[i] - c < L->words[i];
X->words[i] = G->words[i] - L->words[i] - c;

View File

@ -107,6 +107,10 @@ static struct t_cmp_case {
{ "3 > 1", 3, 1, 1 },
{ "3 > 2", 3, 2, 1 },
{ "3 == 3", 3, 3, 0 },
/* 0x200 and 0x300: same msb, identical lowest byte */
{ "512 < 768", 512, 768, -1 },
{ "768 > 512", 768, 512, 1 },
};
/*