Fix sign bug in special cases in mpi_{add,sub}_abs().

We failed to clear the negative flag when handling trivial cases, so if one of the terms was 0 and the other was negative, the result would be an exact copy of the non-zero term instead of its absolute value.
This commit is contained in:
Dag-Erling Smørgrav 2017-03-14 00:32:32 +01:00
parent fc99e7973b
commit 9ee45d4e34
3 changed files with 77 additions and 22 deletions

View file

@ -52,12 +52,23 @@ mpi_add_abs(cryb_mpi *X, cryb_mpi *A, cryb_mpi *B)
if (A == B || mpi_eq_abs(A, B)) {
if (X != A && X != B && mpi_copy(X, A) != 0)
return (-1);
return (mpi_lshift(X, 1));
if (mpi_lshift(X, 1) != 0)
return (-1);
X->neg = 0;
return (0);
}
if (A->msb == 0) {
if (X != B && mpi_copy(X, B) != 0)
return (-1);
X->neg = 0;
return (0);
}
if (B->msb == 0) {
if (X != A && mpi_copy(X, A) != 0)
return (-1);
X->neg = 0;
return (0);
}
if (A->msb == 0)
return (X == B ? 0 : mpi_copy(X, B));
if (B->msb == 0)
return (X == A ? 0 : mpi_copy(X, A));
/*
* Normalize our operands: if X is identical to either A or B, we

View file

@ -54,10 +54,18 @@ mpi_sub_abs(cryb_mpi *X, cryb_mpi *A, cryb_mpi *B)
mpi_zero(X);
return (0);
}
if (A->msb == 0)
return (X == B ? 0 : mpi_copy(X, B));
if (B->msb == 0)
return (X == A ? 0 : mpi_copy(X, A));
if (A->msb == 0) {
if (X != B && mpi_copy(X, B) != 0)
return (-1);
X->neg = 0;
return (0);
}
if (B->msb == 0) {
if (X != A && mpi_copy(X, A) != 0)
return (-1);
X->neg = 0;
return (0);
}
/* we want to subtract the smaller number from the larger */
if (mpi_cmp_abs(A, B) < 0)

View file

@ -60,28 +60,46 @@ static struct t_add_case {
int eneg:1;
} t_add_cases[] = {
{
"0 + 0 == 0",
"|0| + |0| == 0",
{ }, 0, 0,
{ }, 0, 0,
{ }, 0, 0,
},
{
"0 + 1 == 1",
"|0| + |1| == 1",
{ }, 0, 0,
{ 0x01, }, 1, 0,
{ 0x01, }, 1, 0,
},
{
"1 + 0 == 1",
"|1| + |0| == 1",
{ 0x01, }, 1, 0,
{ }, 0, 0,
{ 0x01, }, 1, 0,
},
{
"2 + 2 == 4",
"|1| + |1| == 2",
{ 0x01, }, 1, 0,
{ 0x01 }, 1, 0,
{ 0x02, }, 2, 0,
},
{
"|0| + |-1| == 1",
{ }, 0, 0,
{ 0x01, }, 1, 1,
{ 0x01, }, 1, 0,
},
{
"|-1| + |0| == 1",
{ 0x01, }, 1, 1,
{ }, 0, 0,
{ 0x01, }, 1, 0,
},
{
"|-1| + |-1| == 2",
{ 0x01, }, 1, 1,
{ 0x01 }, 1, 1,
{ 0x02, }, 2, 0,
{ 0x04, }, 3, 0,
},
{
"|0x20140901| + |0x19700101| == 0x39840a02",
@ -109,14 +127,14 @@ static struct t_add_case {
},
{
"simple carry, "
"0xffffffff + 0x01 == 0x0100000000",
"|0xffffffff| + |0x01| == 0x0100000000",
{ 0xff, 0xff, 0xff, 0xff, }, 32, 0,
{ 0x01, }, 1, 0,
{ 0x01, 0x00, 0x00, 0x00, 0x00, }, 33, 0,
},
{
"complex carry, "
"0x0100000000ffffffff + 0x01 == 0x010000000100000000",
"|0x0100000000ffffffff| + |0x01| == 0x010000000100000000",
{ 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, }, 64, 0,
{ 0x01, }, 1, 0,
{ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, }, 64, 0,
@ -478,37 +496,55 @@ static struct t_sub_case {
int eneg:1;
} t_sub_cases[] = {
{
"0 - 0 == 0",
"| |0| - |0| | == 0",
{ }, 0, 0,
{ }, 0, 0,
{ }, 0, 0,
},
{
"0 - 1 == 1",
"| |0| - |1| | == 1",
{ }, 0, 0,
{ 0x01, }, 1, 0,
{ 0x01, }, 1, 0,
},
{
"1 - 0 == 1",
"| |1| - |0| | == 1",
{ 0x01, }, 1, 0,
{ }, 0, 0,
{ 0x01, }, 1, 0,
},
{
"1 - 1 == 0",
"| |1| - |1| | == 0",
{ 0x01, }, 1, 0,
{ 0x01 }, 1, 0,
{ 0x02, }, 0, 0,
},
{
"| |0| - |-1| | == 1",
{ }, 0, 0,
{ 0x01, }, 1, 1,
{ 0x01, }, 1, 0,
},
{
"| |-1| - |0| | == 1",
{ 0x01, }, 1, 1,
{ }, 0, 0,
{ 0x01, }, 1, 0,
},
{
"| |-1| - |-1| | == 0",
{ 0x01, }, 1, 1,
{ 0x01 }, 1, 1,
{ }, 0, 0,
},
{
"4 - 2 == 2",
"| |4| - |2| | == 2",
{ 0x04, }, 3, 0,
{ 0x02, }, 2, 0,
{ 0x02, }, 2, 0,
},
{
"2 - 4 == 2",
"| |2| - |4| | == 2",
{ 0x02, }, 2, 0,
{ 0x04, }, 3, 0,
{ 0x02, }, 2, 0,