1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-23 06:48:16 +00:00

Merge pull request #7 from hiviah/ecdsa_arithmetic_fix

Handling of special cases in ECDSA point arithmetic
This commit is contained in:
Pavol Rusnak 2014-07-06 22:34:15 +02:00
commit d3505ecb46
2 changed files with 79 additions and 12 deletions

86
ecdsa.c
View File

@ -33,12 +33,36 @@
#include "ecdsa.h" #include "ecdsa.h"
#include "base58.h" #include "base58.h"
// Set cp2 = cp1
void point_copy(const curve_point *cp1, curve_point *cp2)
{
memcpy(&(cp2->x), &(cp1->x), sizeof(bignum256));
memcpy(&(cp2->y), &(cp1->y), sizeof(bignum256));
}
// cp2 = cp1 + cp2 // cp2 = cp1 + cp2
void point_add(const curve_point *cp1, curve_point *cp2) void point_add(const curve_point *cp1, curve_point *cp2)
{ {
int i; int i;
uint32_t temp; uint32_t temp;
bignum256 lambda, inv, xr, yr; bignum256 lambda, inv, xr, yr;
if (point_is_infinity(cp1)) {
return;
}
if (point_is_infinity(cp2)) {
point_copy(cp1, cp2);
return;
}
if (point_is_equal(cp1, cp2)) {
point_double(cp2);
return;
}
if (point_is_negative_of(cp1, cp2)) {
point_set_infinity(cp2);
return;
}
bn_substract(&(cp2->x), &(cp1->x), &inv); bn_substract(&(cp2->x), &(cp1->x), &inv);
bn_inverse(&inv, &prime256k1); bn_inverse(&inv, &prime256k1);
bn_substract(&(cp2->y), &(cp1->y), &lambda); bn_substract(&(cp2->y), &(cp1->y), &lambda);
@ -60,6 +84,8 @@ void point_add(const curve_point *cp1, curve_point *cp2)
bn_fast_mod(&yr, &prime256k1); bn_fast_mod(&yr, &prime256k1);
memcpy(&(cp2->x), &xr, sizeof(bignum256)); memcpy(&(cp2->x), &xr, sizeof(bignum256));
memcpy(&(cp2->y), &yr, sizeof(bignum256)); memcpy(&(cp2->y), &yr, sizeof(bignum256));
bn_mod(&(cp2->x), &prime256k1);
bn_mod(&(cp2->y), &prime256k1);
} }
// cp = cp + cp // cp = cp + cp
@ -68,6 +94,15 @@ void point_double(curve_point *cp)
int i; int i;
uint32_t temp; uint32_t temp;
bignum256 lambda, inverse_y, xr, yr; bignum256 lambda, inverse_y, xr, yr;
if (point_is_infinity(cp)) {
return;
}
if (bn_is_zero(&(cp->y))) {
point_set_infinity(cp);
return;
}
memcpy(&inverse_y, &(cp->y), sizeof(bignum256)); memcpy(&inverse_y, &(cp->y), sizeof(bignum256));
bn_inverse(&inverse_y, &prime256k1); bn_inverse(&inverse_y, &prime256k1);
memcpy(&lambda, &three_over_two256k1, sizeof(bignum256)); memcpy(&lambda, &three_over_two256k1, sizeof(bignum256));
@ -91,6 +126,8 @@ void point_double(curve_point *cp)
bn_fast_mod(&yr, &prime256k1); bn_fast_mod(&yr, &prime256k1);
memcpy(&(cp->x), &xr, sizeof(bignum256)); memcpy(&(cp->x), &xr, sizeof(bignum256));
memcpy(&(cp->y), &yr, sizeof(bignum256)); memcpy(&(cp->y), &yr, sizeof(bignum256));
bn_mod(&(cp->x), &prime256k1);
bn_mod(&(cp->y), &prime256k1);
} }
// res = k * p // res = k * p
@ -116,8 +153,43 @@ void point_multiply(const bignum256 *k, const curve_point *p, curve_point *res)
point_double(&curr); point_double(&curr);
} }
} }
bn_mod(&(res->x), &prime256k1); }
bn_mod(&(res->y), &prime256k1);
// set point to internal representation of point at infinity
void point_set_infinity(curve_point *p)
{
bn_zero(&(p->x));
bn_zero(&(p->y));
}
// return true iff p represent point at infinity
// both coords are zero in internal representation
int point_is_infinity(const curve_point *p)
{
return bn_is_zero(&(p->x)) && bn_is_zero(&(p->y));
}
// return true iff both points are equal
int point_is_equal(const curve_point *p, const curve_point *q)
{
return bn_is_equal(&(p->x), &(q->x)) && bn_is_equal(&(p->y), &(q->y));
}
// returns true iff p == -q
// expects p and q be valid points on curve other than point at infinity
int point_is_negative_of(const curve_point *p, const curve_point *q)
{
// if P == (x, y), then -P would be (x, -y) on this curve
if (!bn_is_equal(&(p->x), &(q->x))) {
return 0;
}
// we shouldn't hit this for a valid point
if (bn_is_zero(&(p->y))) {
return 0;
}
return !bn_is_equal(&(p->y), &(q->y));
} }
// res = k * G // res = k * G
@ -160,8 +232,6 @@ void scalar_multiply(const bignum256 *k, curve_point *res)
point_double(&curr); point_double(&curr);
#endif #endif
} }
bn_mod(&(res->x), &prime256k1);
bn_mod(&(res->y), &prime256k1);
} }
// generate random K for signing // generate random K for signing
@ -460,20 +530,12 @@ int ecdsa_verify_digest(const uint8_t *pub_key, const uint8_t *sig, const uint8_
for (j = 0; j < 30; j++) { for (j = 0; j < 30; j++) {
if (i == 8 && (s.val[i] >> j) == 0) break; if (i == 8 && (s.val[i] >> j) == 0) break;
if (s.val[i] & (1u << j)) { if (s.val[i] & (1u << j)) {
bn_mod(&(pub.x), &prime256k1);
bn_mod(&(res.x), &prime256k1);
if (bn_is_equal(&(pub.x), &(res.x))) {
// this is not a failure, but a very inprobable case
// that we don't handle because of its inprobability
return 4;
}
point_add(&pub, &res); point_add(&pub, &res);
} }
point_double(&pub); point_double(&pub);
} }
} }
bn_mod(&(res.x), &prime256k1);
bn_mod(&(res.x), &order256k1); bn_mod(&(res.x), &order256k1);
// signature does not match // signature does not match

View File

@ -32,9 +32,14 @@
#define USE_RFC6979 1 #define USE_RFC6979 1
#endif #endif
void point_copy(const curve_point *cp1, curve_point *cp2);
void point_add(const curve_point *cp1, curve_point *cp2); void point_add(const curve_point *cp1, curve_point *cp2);
void point_double(curve_point *cp); void point_double(curve_point *cp);
void point_multiply(const bignum256 *k, const curve_point *p, curve_point *res); void point_multiply(const bignum256 *k, const curve_point *p, curve_point *res);
void point_set_infinity(curve_point *p);
int point_is_infinity(const curve_point *p);
int point_is_equal(const curve_point *p, const curve_point *q);
int point_is_negative_of(const curve_point *p, const curve_point *q);
void scalar_multiply(const bignum256 *k, curve_point *res); void scalar_multiply(const bignum256 *k, curve_point *res);
void uncompress_coords(uint8_t odd, const bignum256 *x, bignum256 *y); void uncompress_coords(uint8_t odd, const bignum256 *x, bignum256 *y);