SP int: fix rework of sp_invmod

Simplify code and check for m mod a == 0 which means there is no
inverse.
This commit is contained in:
Sean Parkinson
2022-01-20 10:27:50 +10:00
parent d668037541
commit b767857abb

View File

@ -8123,6 +8123,7 @@ int sp_invmod(sp_int* a, sp_int* m, sp_int* r)
sp_int* v = NULL;
sp_int* b = NULL;
sp_int* c = NULL;
sp_int* mm;
int used = ((m == NULL) || (a == NULL)) ? 1 :
((m->used >= a->used) ? m->used + 1 : a->used + 1);
int evenMod = 0;
@ -8182,19 +8183,19 @@ int sp_invmod(sp_int* a, sp_int* m, sp_int* r)
sp_init_size(c, m->used + 1);
if (sp_iseven(m)) {
sp_int* ts;
/* a^-1 mod m = m + (1 - m*(m^-1 % a)) / a
* = m - (m*(m^-1 % a) - 1) / a
*/
/* Reverse a and m and perform invmod. */
ts = a;
a = m;
m = ts;
sp_copy(m, u);
sp_mod(a, m, v);
/* a^-1 mod m = m + ((1 - m*(m^-1 % a)) / a) */
mm = a;
sp_copy(a, u);
sp_mod(m, a, v);
/* v == 0 when a divides m evenly - no inverse. */
if (sp_iszero(v)) {
/* Force u to no inverse answer. */
sp_set(u, 0);
}
evenMod = 1;
}
else {
mm = m;
sp_copy(m, u);
sp_copy(a, v);
}
@ -8205,28 +8206,28 @@ int sp_invmod(sp_int* a, sp_int* m, sp_int* r)
if (sp_iseven(u)) {
sp_div_2(u, u);
if (sp_isodd(b)) {
sp_add(b, m, b);
sp_add(b, mm, b);
}
sp_div_2(b, b);
}
else if (sp_iseven(v)) {
sp_div_2(v, v);
if (sp_isodd(c)) {
sp_add(c, m, c);
sp_add(c, mm, c);
}
sp_div_2(c, c);
}
else if (_sp_cmp(u, v) != MP_LT) {
sp_sub(u, v, u);
if (_sp_cmp(b, c) == MP_LT) {
sp_add(b, m, b);
sp_add(b, mm, b);
}
sp_sub(b, c, b);
}
else {
sp_sub(v, u, v);
if (_sp_cmp(c, b) == MP_LT) {
sp_add(c, m, c);
sp_add(c, mm, c);
}
sp_sub(c, b, c);
}
@ -8235,17 +8236,17 @@ int sp_invmod(sp_int* a, sp_int* m, sp_int* r)
err = MP_VAL;
}
else if (evenMod) {
/* a and m were reversed and now we need to finish operation.
* m - ((m*r - 1) / a) (reverse a and m)
* => a - ((a*r - 1) / m)
/* Finish operation.
* a^-1 mod m = m + ((1 - m*c) / a)
* => a^-1 mod m = m - ((m*c - 1) / a)
*/
err = sp_mul(c, a, v);
err = sp_mul(c, m, v);
if (err == MP_OKAY) {
_sp_sub_d(v, 1, v);
err = sp_div(v, m, v, NULL);
err = sp_div(v, a, v, NULL);
}
if (err == MP_OKAY) {
sp_sub(a, v, r);
sp_sub(m, v, r);
}
}
else {