diff options
-rw-r--r-- | include/constrainedcrypto/hash-internal.h | 6 | ||||
-rw-r--r-- | include/constrainedcrypto/sha.h | 4 | ||||
-rw-r--r-- | include/constrainedcrypto/sha256.h | 4 | ||||
-rw-r--r-- | p256.c | 78 | ||||
-rw-r--r-- | p256_ec.c | 17 | ||||
-rw-r--r-- | p256_ecdsa.c | 1 | ||||
-rw-r--r-- | sha.c | 14 | ||||
-rw-r--r-- | sha256.c | 13 |
8 files changed, 115 insertions, 22 deletions
diff --git a/include/constrainedcrypto/hash-internal.h b/include/constrainedcrypto/hash-internal.h index f0a00f9..add1c90 100644 --- a/include/constrainedcrypto/hash-internal.h +++ b/include/constrainedcrypto/hash-internal.h @@ -37,10 +37,10 @@ struct HASH_CTX; // forward decl typedef struct HASH_VTAB { void (* const init)(struct HASH_CTX*); - void (* const update)(struct HASH_CTX*, const void*, int); + void (* const update)(struct HASH_CTX*, const void*, unsigned int); const uint8_t* (* const final)(struct HASH_CTX*); - const uint8_t* (* const hash)(const void*, int, uint8_t*); - int size; + const uint8_t* (* const hash)(const void*, unsigned int, uint8_t*); + unsigned int size; } HASH_VTAB; typedef struct HASH_CTX { diff --git a/include/constrainedcrypto/sha.h b/include/constrainedcrypto/sha.h index 94dcdb4..e07b125 100644 --- a/include/constrainedcrypto/sha.h +++ b/include/constrainedcrypto/sha.h @@ -36,12 +36,12 @@ extern "C" { typedef HASH_CTX SHA_CTX; void SHA_init(SHA_CTX* ctx); -void SHA_update(SHA_CTX* ctx, const void* data, int len); +void SHA_update(SHA_CTX* ctx, const void* data, unsigned int len); const uint8_t* SHA_final(SHA_CTX* ctx); // Convenience method. Returns digest address. // NOTE: *digest needs to hold SHA_DIGEST_SIZE bytes. -const uint8_t* SHA_hash(const void* data, int len, uint8_t* digest); +const uint8_t* SHA_hash(const void* data, unsigned int len, uint8_t* digest); #define SHA_DIGEST_SIZE 20 diff --git a/include/constrainedcrypto/sha256.h b/include/constrainedcrypto/sha256.h index eb2917c..5feab38 100644 --- a/include/constrainedcrypto/sha256.h +++ b/include/constrainedcrypto/sha256.h @@ -37,11 +37,11 @@ extern "C" { typedef HASH_CTX SHA256_CTX; void SHA256_init(SHA256_CTX* ctx); -void SHA256_update(SHA256_CTX* ctx, const void* data, int len); +void SHA256_update(SHA256_CTX* ctx, const void* data, unsigned int len); const uint8_t* SHA256_final(SHA256_CTX* ctx); // Convenience method. Returns digest address. -const uint8_t* SHA256_hash(const void* data, int len, uint8_t* digest); +const uint8_t* SHA256_hash(const void* data, unsigned int len, uint8_t* digest); #define SHA256_DIGEST_SIZE 32 @@ -42,6 +42,9 @@ const p256_int SECP256r1_n = // curve order {{0xfc632551, 0xf3b9cac2, 0xa7179e84, 0xbce6faad, -1, -1, 0, -1}}; +static const p256_int SECP256r1_nMin2 = // curve order - 2 + {{0xfc632551 - 2, 0xf3b9cac2, 0xa7179e84, 0xbce6faad, -1, -1, 0, -1}}; + const p256_int SECP256r1_p = // curve field size {{-1, -1, -1, 0, 0, 0, 1, -1 }}; @@ -49,6 +52,9 @@ const p256_int SECP256r1_b = // curve b {{0x27d2604b, 0x3bce3c3e, 0xcc53b0f6, 0x651d06b0, 0x769886bc, 0xb3ebbd55, 0xaa3a93e7, 0x5ac635d8}}; +static const p256_int p256_one = P256_ONE; + + void p256_init(p256_int* a) { memset(a, 0, sizeof(*a)); } @@ -188,6 +194,7 @@ void p256_modmul(const p256_int* MOD, memcpy(c, tmp, P256_NBYTES); } + int p256_is_odd(const p256_int* a) { return P256_DIGIT(a, 0) & 1; } int p256_is_even(const p256_int* a) { return !(P256_DIGIT(a, 0) & 1); } @@ -287,6 +294,61 @@ int p256_add_d(const p256_int* a, p256_digit d, p256_int* b) { return (int)carry; } +// if (mask) dst = src, fixed-timing style. +static void copyConditional(const p256_int* src, + p256_int* dst, + int mask) { + int i; + for (i = 0; i < P256_NDIGITS; ++i) { + p256_digit b = P256_DIGIT(src, i) & mask; // 0 or src[i] + b |= P256_DIGIT(dst, i) & ~mask; // dst[i] or 0 + P256_DIGIT(dst, i) = b; + } +} + +// -1 iff (x&15) == 0, 0 otherwise. +// Relies on arithmetic shift right behavior. +#define ZEROtoONES(x) (((int32_t)(((x)&15)-1))>>31) + +// tbl[0] = tbl[idx], fixed-timing style. +static void set0ToIdx(p256_int tbl[16], int idx) { + int32_t i; + tbl[0] = p256_one; + for (i = 1; i < 16; ++i) { + copyConditional(&tbl[i], &tbl[0], ZEROtoONES(i-idx)); + } +} + +// b = 1/a mod MOD, fixed timing, Fermat's little theorem. +void p256_modinv(const p256_int* MOD, + const p256_int* a, + p256_int* b) { + p256_int tbl[16]; + int i; + + // tbl[i] = a**i, tbl[0] unused. + tbl[1] = *a; + for (i = 2; i < 16; ++i) { + p256_modmul(MOD, &tbl[i-1], 0, a, &tbl[i]); + } + + *b = p256_one; + for (i = 256; i > 0; i -= 4) { + int32_t idx = 0; + p256_modmul(MOD, b, 0, b, b); + p256_modmul(MOD, b, 0, b, b); + p256_modmul(MOD, b, 0, b, b); + p256_modmul(MOD, b, 0, b, b); + idx |= p256_get_bit(&SECP256r1_nMin2, i - 1) << 3; + idx |= p256_get_bit(&SECP256r1_nMin2, i - 2) << 2; + idx |= p256_get_bit(&SECP256r1_nMin2, i - 3) << 1; + idx |= p256_get_bit(&SECP256r1_nMin2, i - 4) << 0; + set0ToIdx(tbl, idx); // tbl[0] = tbl[idx] + p256_modmul(MOD, b, 0, &tbl[0], &tbl[0]); + copyConditional(&tbl[0], b, ~ZEROtoONES(idx)); + } +} + // b = 1/a mod MOD, binary euclid. void p256_modinv_vartime(const p256_int* MOD, const p256_int* a, @@ -354,6 +416,8 @@ int p256_is_valid_point(const p256_int* x, const p256_int* y) { if (p256_sub(&x3, x, &x3)) p256_add(&x3, &SECP256r1_p, &x3); // x^3 - 3x if (p256_add(&x3, &SECP256r1_b, &x3)) // x^3 - 3x + b p256_sub(&x3, &SECP256r1_p, &x3); + if (p256_sub(&x3, &SECP256r1_p, &x3)) // make sure 0 <= x3 < p + p256_add(&x3, &SECP256r1_p, &x3); return p256_cmp(&y2, &x3) == 0; } @@ -371,3 +435,17 @@ void p256_from_bin(const uint8_t src[P256_NBYTES], p256_int* dst) { p += 4; } } + +void p256_to_bin(const p256_int* src, uint8_t dst[P256_NBYTES]) { + int i; + uint8_t* p = &dst[0]; + + for (i = P256_NDIGITS - 1; i >= 0; --i) { + p256_digit digit = P256_DIGIT(src, i); + p[0] = (uint8_t)(digit >> 24); + p[1] = (uint8_t)(digit >> 16); + p[2] = (uint8_t)(digit >> 8); + p[3] = (uint8_t)(digit); + p += 4; + } +} @@ -791,7 +791,6 @@ static char felem_is_zero_vartime(const felem in) { memcmp(tmp, k2P, sizeof(tmp)) == 0; } - /* Group operations: * * Elements of the elliptic curve group are represented in Jacobian @@ -1236,6 +1235,22 @@ void p256_base_point_mul(const p256_int* n, p256_int* out_x, p256_int* out_y) { } } +/* p256_point_mul sets {out_x,out_y} = n*{in_x,in_y}, where n is < + * the order of the group. */ +void p256_point_mul(const p256_int* n, const p256_int* in_x, + const p256_int* in_y, p256_int* out_x, p256_int* out_y) { + felem x, y, z, px, py; + + to_montgomery(px, in_x); + to_montgomery(py, in_y); + + scalar_mult(x, y, z, px, py, n); + + point_to_affine(px, py, x, y, z); + from_montgomery(out_x, px); + from_montgomery(out_y, py); +} + /* p256_points_mul_vartime sets {out_x,out_y} = n1*G + n2*{in_x,in_y}, where * n1 and n2 are < the order of the group. * diff --git a/p256_ecdsa.c b/p256_ecdsa.c index 47dcd7b..c104aac 100644 --- a/p256_ecdsa.c +++ b/p256_ecdsa.c @@ -53,4 +53,3 @@ int p256_ecdsa_verify(const p256_int* key_x, const p256_int* key_y, p256_mod(&SECP256r1_n, &u, &u); // (x coord % p) % n return p256_cmp(r, &u) == 0; } - @@ -104,8 +104,8 @@ void SHA_init(SHA_CTX* ctx) { } -void SHA_update(SHA_CTX* ctx, const void* data, int len) { - int i = (int) (ctx->count & 63); +void SHA_update(SHA_CTX* ctx, const void* data, unsigned int len) { + unsigned int i = (unsigned int)(ctx->count & 63); const uint8_t* p = (const uint8_t*)data; ctx->count += len; @@ -136,17 +136,17 @@ const uint8_t* SHA_final(SHA_CTX* ctx) { for (i = 0; i < 5; i++) { uint32_t tmp = ctx->state[i]; - *p++ = tmp >> 24; - *p++ = tmp >> 16; - *p++ = tmp >> 8; - *p++ = tmp >> 0; + *p++ = (uint8_t)(tmp >> 24); + *p++ = (uint8_t)(tmp >> 16); + *p++ = (uint8_t)(tmp >> 8); + *p++ = (uint8_t)(tmp >> 0); } return ctx->buf; } /* Convenience function */ -const uint8_t* SHA_hash(const void* data, int len, uint8_t* digest) { +const uint8_t* SHA_hash(const void* data, unsigned int len, uint8_t* digest) { SHA_CTX ctx; SHA_init(&ctx); SHA_update(&ctx, data, len); @@ -133,7 +133,7 @@ void SHA256_init(SHA256_CTX* ctx) { } -void SHA256_update(SHA256_CTX* ctx, const void* data, int len) { +void SHA256_update(SHA256_CTX* ctx, const void* data, unsigned int len) { int i = (int) (ctx->count & 63); const uint8_t* p = (const uint8_t*)data; @@ -165,17 +165,18 @@ const uint8_t* SHA256_final(SHA256_CTX* ctx) { for (i = 0; i < 8; i++) { uint32_t tmp = ctx->state[i]; - *p++ = tmp >> 24; - *p++ = tmp >> 16; - *p++ = tmp >> 8; - *p++ = tmp >> 0; + *p++ = (uint8_t)(tmp >> 24); + *p++ = (uint8_t)(tmp >> 16); + *p++ = (uint8_t)(tmp >> 8); + *p++ = (uint8_t)(tmp >> 0); } return ctx->buf; } /* Convenience function */ -const uint8_t* SHA256_hash(const void* data, int len, uint8_t* digest) { +const uint8_t* SHA256_hash(const void* data, unsigned int len, + uint8_t* digest) { SHA256_CTX ctx; SHA256_init(&ctx); SHA256_update(&ctx, data, len); |