aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/constrainedcrypto/hash-internal.h6
-rw-r--r--include/constrainedcrypto/sha.h4
-rw-r--r--include/constrainedcrypto/sha256.h4
-rw-r--r--p256.c78
-rw-r--r--p256_ec.c17
-rw-r--r--p256_ecdsa.c1
-rw-r--r--sha.c14
-rw-r--r--sha256.c13
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
diff --git a/p256.c b/p256.c
index 993cd4e..ddf0bac 100644
--- a/p256.c
+++ b/p256.c
@@ -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;
+ }
+}
diff --git a/p256_ec.c b/p256_ec.c
index 72e80e6..4dc02d4 100644
--- a/p256_ec.c
+++ b/p256_ec.c
@@ -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;
}
-
diff --git a/sha.c b/sha.c
index 43440a0..5b27152 100644
--- a/sha.c
+++ b/sha.c
@@ -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);
diff --git a/sha256.c b/sha256.c
index 2b5f073..5e91c8d 100644
--- a/sha256.c
+++ b/sha256.c
@@ -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);