Merge "cryptoc: sync with upstream sources"
diff --git a/Makefile b/Makefile
index 3a5b54b..863a53b 100644
--- a/Makefile
+++ b/Makefile
@@ -8,11 +8,13 @@
AR ?= $(CROSS_COMPILE)ar
SOURCES = hmac.c
+SOURCES += md5.c
SOURCES += p256.c
SOURCES += p256_ec.c
SOURCES += p256_ecdsa.c
SOURCES += p256_prng.c
SOURCES += sha.c
+SOURCES += sha224.c
SOURCES += sha256.c
ifeq ($(CONFIG_UPTO_SHA512),y)
SOURCES += sha384.c
diff --git a/hmac.c b/hmac.c
index ef6ad82..9fa569d 100644
--- a/hmac.c
+++ b/hmac.c
@@ -17,13 +17,16 @@
#include <string.h>
#include "cryptoc/sha.h"
#include "cryptoc/md5.h"
+#include "cryptoc/sha224.h"
#include "cryptoc/sha256.h"
+#include "cryptoc/sha384.h"
+#include "cryptoc/sha512.h"
static void HMAC_init(LITE_HMAC_CTX* ctx, const void* key, unsigned int len) {
unsigned int i;
memset(&ctx->opad[0], 0, sizeof(ctx->opad));
- if (len > sizeof(ctx->opad)) {
+ if (len > HASH_block_size(&ctx->hash)) {
HASH_init(&ctx->hash);
HASH_update(&ctx->hash, key, len);
memcpy(&ctx->opad[0], HASH_final(&ctx->hash), HASH_size(&ctx->hash));
@@ -31,14 +34,14 @@
memcpy(&ctx->opad[0], key, len);
}
- for (i = 0; i < sizeof(ctx->opad); ++i) {
+ for (i = 0; i < HASH_block_size(&ctx->hash); ++i) {
ctx->opad[i] ^= 0x36;
}
HASH_init(&ctx->hash);
- HASH_update(&ctx->hash, ctx->opad, sizeof(ctx->opad)); // hash ipad
+ HASH_update(&ctx->hash, ctx->opad, HASH_block_size(&ctx->hash)); // hash ipad
- for (i = 0; i < sizeof(ctx->opad); ++i) {
+ for (i = 0; i < HASH_block_size(&ctx->hash); ++i) {
ctx->opad[i] ^= (0x36 ^ 0x5c);
}
}
@@ -53,18 +56,39 @@
HMAC_init(ctx, key, len);
}
+void HMAC_SHA224_init(LITE_HMAC_CTX* ctx, const void* key, unsigned int len) {
+ SHA224_init(&ctx->hash);
+ HMAC_init(ctx, key, len);
+}
+
void HMAC_SHA256_init(LITE_HMAC_CTX* ctx, const void* key, unsigned int len) {
SHA256_init(&ctx->hash);
HMAC_init(ctx, key, len);
}
+#ifdef SHA512_SUPPORT
+void HMAC_SHA384_init(LITE_HMAC_CTX* ctx, const void* key, unsigned int len) {
+ SHA384_init(&ctx->hash);
+ HMAC_init(ctx, key, len);
+}
+
+void HMAC_SHA512_init(LITE_HMAC_CTX* ctx, const void* key, unsigned int len) {
+ SHA512_init(&ctx->hash);
+ HMAC_init(ctx, key, len);
+}
+#endif
+
const uint8_t* HMAC_final(LITE_HMAC_CTX* ctx) {
- uint8_t digest[32]; // upto SHA2
+#ifndef SHA512_SUPPORT
+ uint8_t digest[32]; // upto SHA2-256
+#else
+ uint8_t digest[64]; // upto SHA2-512
+#endif
memcpy(digest, HASH_final(&ctx->hash),
(HASH_size(&ctx->hash) <= sizeof(digest) ?
HASH_size(&ctx->hash) : sizeof(digest)));
HASH_init(&ctx->hash);
- HASH_update(&ctx->hash, ctx->opad, sizeof(ctx->opad));
+ HASH_update(&ctx->hash, ctx->opad, HASH_block_size(&ctx->hash));
HASH_update(&ctx->hash, digest, HASH_size(&ctx->hash));
always_memset(&ctx->opad[0], 0, sizeof(ctx->opad)); // wipe key
return HASH_final(&ctx->hash);
diff --git a/include/cryptoc/hash-internal.h b/include/cryptoc/hash-internal.h
index 668cafc..e6ebcef 100644
--- a/include/cryptoc/hash-internal.h
+++ b/include/cryptoc/hash-internal.h
@@ -14,8 +14,16 @@
#ifndef SECURITY_UTIL_LITE_HASH_INTERNAL_H__
#define SECURITY_UTIL_LITE_HASH_INTERNAL_H__
-#include <stdint.h>
#include <stddef.h>
+#include <stdint.h>
+
+#ifdef LITE_EMULATED_64BIT_OPS
+#define LITE_LShiftU64(a, b) LShiftU64((a), (b))
+#define LITE_RShiftU64(a, b) RShiftU64((a), (b))
+#else
+#define LITE_LShiftU64(a, b) ((a) << (b))
+#define LITE_RShiftU64(a, b) ((a) >> (b))
+#endif // LITE_EMULATED_64BIT_OPS
#ifdef __cplusplus
extern "C" {
@@ -29,6 +37,9 @@
const uint8_t* (* const final)(struct HASH_CTX*);
const uint8_t* (* const hash)(const void*, size_t, uint8_t*);
unsigned int size;
+#ifdef SHA512_SUPPORT
+ unsigned int block_size;
+#endif
} HASH_VTAB;
typedef struct HASH_CTX {
@@ -48,6 +59,11 @@
#define HASH_final(ctx) (ctx)->f->final(ctx)
#define HASH_hash(data, len, digest) (ctx)->f->hash(data, len, digest)
#define HASH_size(ctx) (ctx)->f->size
+#ifdef SHA512_SUPPORT
+#define HASH_block_size(ctx) (ctx)->f->block_size
+#else
+#define HASH_block_size(ctx) sizeof((ctx)->buf)
+#endif
#ifdef __cplusplus
}
diff --git a/include/cryptoc/hmac.h b/include/cryptoc/hmac.h
index 4e86dec..15f6563 100644
--- a/include/cryptoc/hmac.h
+++ b/include/cryptoc/hmac.h
@@ -23,12 +23,19 @@
typedef struct LITE_HMAC_CTX {
HASH_CTX hash;
+#ifndef SHA512_SUPPORT
uint8_t opad[64];
+#else
+ uint8_t opad[128];
+#endif
} LITE_HMAC_CTX;
void HMAC_MD5_init(LITE_HMAC_CTX* ctx, const void* key, unsigned int len);
void HMAC_SHA_init(LITE_HMAC_CTX* ctx, const void* key, unsigned int len);
+void HMAC_SHA224_init(LITE_HMAC_CTX* ctx, const void* key, unsigned int len);
void HMAC_SHA256_init(LITE_HMAC_CTX* ctx, const void* key, unsigned int len);
+void HMAC_SHA384_init(LITE_HMAC_CTX* ctx, const void* key, unsigned int len);
+void HMAC_SHA512_init(LITE_HMAC_CTX* ctx, const void* key, unsigned int len);
const uint8_t* HMAC_final(LITE_HMAC_CTX* ctx);
#define HMAC_update(ctx, data, len) HASH_update(&(ctx)->hash, data, len)
diff --git a/include/cryptoc/md5.h b/include/cryptoc/md5.h
index f335568..a86f0e8 100644
--- a/include/cryptoc/md5.h
+++ b/include/cryptoc/md5.h
@@ -14,8 +14,8 @@
#ifndef SECURITY_UTIL_LITE_MD5_H__
#define SECURITY_UTIL_LITE_MD5_H__
-#include <stdint.h>
#include <stddef.h>
+#include <stdint.h>
#include "cryptoc/hash-internal.h"
#ifdef __cplusplus
@@ -33,6 +33,7 @@
const uint8_t* MD5_hash(const void* data, size_t len, uint8_t* digest);
#define MD5_DIGEST_SIZE 16
+#define MD5_BLOCK_SIZE 64
#ifdef __cplusplus
}
diff --git a/include/cryptoc/p256.h b/include/cryptoc/p256.h
index fc482ce..e63badc 100644
--- a/include/cryptoc/p256.h
+++ b/include/cryptoc/p256.h
@@ -140,10 +140,16 @@
// Outputs big-endian binary form. No leading zero skips.
void p256_to_bin(const p256_int* src, uint8_t dst[P256_NBYTES]);
+// Outputs little-endian binary form. No leading zero skips.
+void p256_to_le_bin(const p256_int* src, uint8_t dst[P256_NBYTES]);
+
// Reads from big-endian binary form,
// thus pre-pad with leading zeros if short.
void p256_from_bin(const uint8_t src[P256_NBYTES], p256_int* dst);
+// Reads from little-endian binary form.
+void p256_from_le_bin(const uint8_t src[P256_NBYTES], p256_int* dst);
+
#define P256_DIGITS(x) ((x)->a)
#define P256_DIGIT(x,y) ((x)->a[y])
diff --git a/include/cryptoc/p256_prng.h b/include/cryptoc/p256_prng.h
index c459f19..d0a6dc0 100644
--- a/include/cryptoc/p256_prng.h
+++ b/include/cryptoc/p256_prng.h
@@ -34,8 +34,8 @@
#define P256_PRNG_SIZE 32
typedef struct P256_PRNG_CTX {
- uint32_t Key[P256_PRNG_SIZE];
- uint32_t V[P256_PRNG_SIZE];
+ uint8_t Key[P256_PRNG_SIZE];
+ uint8_t V[P256_PRNG_SIZE];
uint64_t instance_count;
uint64_t call_count;
} P256_PRNG_CTX;
diff --git a/include/cryptoc/sha.h b/include/cryptoc/sha.h
index d760ac2..ca402a9 100644
--- a/include/cryptoc/sha.h
+++ b/include/cryptoc/sha.h
@@ -34,6 +34,7 @@
#ifndef SHA_DIGEST_SIZE
#define SHA_DIGEST_SIZE 20
#endif
+#define SHA_BLOCK_SIZE 64
#ifdef __cplusplus
}
diff --git a/include/cryptoc/sha224.h b/include/cryptoc/sha224.h
new file mode 100644
index 0000000..2a1074a
--- /dev/null
+++ b/include/cryptoc/sha224.h
@@ -0,0 +1,42 @@
+// Copyright 2016 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#ifndef SECURITY_UTIL_LITE_SHA224_H__
+#define SECURITY_UTIL_LITE_SHA224_H__
+
+#include <stddef.h>
+#include <stdint.h>
+#include "cryptoc/hash-internal.h"
+#include "cryptoc/sha256.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+typedef HASH_CTX LITE_SHA224_CTX;
+
+void SHA224_init(LITE_SHA224_CTX* ctx);
+#define SHA224_update(ctx, data, len) SHA256_update((ctx), (data), (len));
+#define SHA224_final(ctx) SHA256_final((ctx))
+
+// Convenience method. Returns digest address.
+const uint8_t* SHA224_hash(const void* data, size_t len, uint8_t* digest);
+
+#define SHA224_DIGEST_SIZE 28
+#define SHA224_BLOCK_SIZE 64
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // SECURITY_UTIL_LITE_SHA224_H__
diff --git a/include/cryptoc/sha256.h b/include/cryptoc/sha256.h
index 6b86c8e..8797d97 100644
--- a/include/cryptoc/sha256.h
+++ b/include/cryptoc/sha256.h
@@ -32,6 +32,7 @@
const uint8_t* SHA256_hash(const void* data, size_t len, uint8_t* digest);
#define SHA256_DIGEST_SIZE 32
+#define SHA256_BLOCK_SIZE 64
#ifdef __cplusplus
}
diff --git a/include/cryptoc/sha384.h b/include/cryptoc/sha384.h
index 3cd848b..29c538d 100644
--- a/include/cryptoc/sha384.h
+++ b/include/cryptoc/sha384.h
@@ -32,6 +32,7 @@
const uint8_t* SHA384_hash(const void* data, size_t len, uint8_t* digest);
#define SHA384_DIGEST_SIZE 48
+#define SHA384_BLOCK_SIZE 128
#ifdef __cplusplus
}
diff --git a/include/cryptoc/sha512.h b/include/cryptoc/sha512.h
index e882b3e..d6002c9 100644
--- a/include/cryptoc/sha512.h
+++ b/include/cryptoc/sha512.h
@@ -32,6 +32,7 @@
const uint8_t* SHA512_hash(const void* data, size_t len, uint8_t* digest);
#define SHA512_DIGEST_SIZE 64
+#define SHA512_BLOCK_SIZE 128
#ifdef __cplusplus
}
diff --git a/include/cryptoc/util.h b/include/cryptoc/util.h
index 4ba7b21..6c65c45 100644
--- a/include/cryptoc/util.h
+++ b/include/cryptoc/util.h
@@ -15,9 +15,22 @@
#define SECURITY_UTIL_LITE_UTIL_H_
#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
/* An implementation of memset that ought not to be optimized away;
* useful for scrubbing security sensitive buffers. */
void *always_memset(void *s, int c, size_t n);
+/* Constant-time memory equality test. Returns 0 to indicate equivalence to
+ * behave in a memcmp()-compatible way. */
+int ct_memeq(const void* s1, const void* s2, uint32_t n);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
#endif // SECURITY_UTIL_LITE_UTIL_H_
diff --git a/md5.c b/md5.c
new file mode 100644
index 0000000..ab4af66
--- /dev/null
+++ b/md5.c
@@ -0,0 +1,174 @@
+// Copyright 2016 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "cryptoc/md5.h"
+
+#include <string.h>
+#include <stdint.h>
+
+#define rol(bits, value) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+static const char Kr[64] =
+{
+ 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
+ 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
+ 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
+ 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21
+};
+
+static const uint32_t KK[64] =
+{
+ 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
+ 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
+ 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
+ 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
+ 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
+ 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
+ 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
+ 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
+ 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
+ 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
+ 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
+ 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
+ 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
+ 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
+ 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
+ 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
+};
+
+static void MD5_Transform(LITE_MD5_CTX* ctx) {
+ uint32_t W[64];
+ uint32_t A, B, C, D;
+ uint8_t* p = ctx->buf;
+ int t;
+
+ for(t = 0; t < 16; ++t) {
+ uint32_t tmp = *p++;
+ tmp |= (uint32_t)*p++ << 8u;
+ tmp |= (uint32_t)*p++ << 16u;
+ tmp |= (uint32_t)*p++ << 24u;
+ W[t] = tmp;
+ }
+
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+
+ for(t = 0; t < 64; t++) {
+ uint32_t f, tmp;
+ int g;
+
+ if (t < 16) {
+ f = (D^(B&(C^D)));
+ g = t;
+ } else if ( t < 32) {
+ f = (C^(D&(B^C)));
+ g = (5*t + 1) & 15;
+ } else if ( t < 48) {
+ f = (B^C^D);
+ g = (3*t + 5) & 15;
+ } else {
+ f = (C^(B|(~D)));
+ g = (7*t) & 15;
+ }
+
+ tmp = D;
+ D = C;
+ C = B;
+ B = B + rol(Kr[t], (A+f+KK[t]+W[g]));
+ A = tmp;
+ }
+
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+}
+
+static const HASH_VTAB MD5_VTAB = {
+ MD5_init,
+ MD5_update,
+ MD5_final,
+ MD5_hash,
+ MD5_DIGEST_SIZE,
+#ifdef SHA512_SUPPORT
+ MD5_BLOCK_SIZE,
+#endif
+};
+
+void MD5_init(LITE_MD5_CTX* ctx) {
+ ctx->f = &MD5_VTAB;
+ ctx->state[0] = 0x67452301;
+ ctx->state[1] = 0xEFCDAB89;
+ ctx->state[2] = 0x98BADCFE;
+ ctx->state[3] = 0x10325476;
+ ctx->count = 0;
+}
+
+
+void MD5_update(LITE_MD5_CTX* ctx, const void* data, size_t len) {
+ unsigned int i = (unsigned int)(ctx->count & 63);
+ const uint8_t* p = (const uint8_t*)data;
+
+ ctx->count += len;
+
+ while (len--) {
+ ctx->buf[i++] = *p++;
+ if (i == 64) {
+ MD5_Transform(ctx);
+ i = 0;
+ }
+ }
+}
+
+
+const uint8_t* MD5_final(LITE_MD5_CTX* ctx) {
+ uint8_t* p = ctx->buf;
+ uint64_t cnt = ctx->count * 8;
+ int i;
+
+ MD5_update(ctx, (uint8_t*)"\x80", 1);
+ while ((ctx->count & 63) != 56) {
+ MD5_update(ctx, (uint8_t*)"\0", 1);
+ }
+ for (i = 0; i < 4; ++i) {
+ uint8_t tmp = (uint8_t)(((uint32_t)cnt) >> (i * 8));
+ MD5_update(ctx, &tmp, 1);
+ }
+ cnt >>= 32;
+ for (i = 0; i < 4; ++i) {
+ uint8_t tmp = (uint8_t)(((uint32_t)cnt) >> (i * 8));
+ MD5_update(ctx, &tmp, 1);
+ }
+
+ for (i = 0; i < 4; i++) {
+ uint32_t tmp = ctx->state[i];
+ *p++ = tmp;
+ *p++ = tmp >> 8;
+ *p++ = tmp >> 16;
+ *p++ = tmp >> 24;
+ }
+
+ return ctx->buf;
+}
+
+
+/* Convenience function */
+const uint8_t* MD5_hash(const void* data, size_t len, uint8_t* digest) {
+ LITE_MD5_CTX ctx;
+ MD5_init(&ctx);
+ MD5_update(&ctx, data, len);
+ memcpy(digest, MD5_final(&ctx), MD5_DIGEST_SIZE);
+ return digest;
+}
diff --git a/p256.c b/p256.c
index d31c4fc..0fdd35c 100644
--- a/p256.c
+++ b/p256.c
@@ -400,6 +400,34 @@
return p256_cmp(&y2, &x3) == 0;
}
+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;
+ }
+}
+
+void p256_to_le_bin(const p256_int* src, uint8_t dst[P256_NBYTES]) {
+ int i;
+ uint8_t* p = &dst[0];
+
+ for (i = 0; i < P256_NDIGITS; ++i) {
+ p256_digit digit = P256_DIGIT(src, i);
+ p[0] = (uint8_t)(digit);
+ p[1] = (uint8_t)(digit >> 8);
+ p[2] = (uint8_t)(digit >> 16);
+ p[3] = (uint8_t)(digit >> 24);
+ p += 4;
+ }
+}
+
void p256_from_bin(const uint8_t src[P256_NBYTES], p256_int* dst) {
int i;
const uint8_t* p = &src[0];
@@ -414,16 +442,16 @@
}
}
-void p256_to_bin(const p256_int* src, uint8_t dst[P256_NBYTES]) {
+void p256_from_le_bin(const uint8_t src[P256_NBYTES], p256_int* dst) {
int i;
- uint8_t* p = &dst[0];
+ const uint8_t* p = &src[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);
+ for (i = 0; i < P256_NDIGITS; ++i) {
+ P256_DIGIT(dst, i) =
+ (uint32_t)p[0] |
+ ((uint32_t)p[1] << 8) |
+ ((uint32_t)p[2] << 16) |
+ ((uint32_t)p[3] << 24);
p += 4;
}
}
diff --git a/p256_unittest.c b/p256_unittest.c
index 03954eb..fb0b87a 100644
--- a/p256_unittest.c
+++ b/p256_unittest.c
@@ -14,6 +14,7 @@
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
+#include <string.h>
#include "cryptoc/p256.h"
@@ -139,11 +140,43 @@
CHECK(p256_is_valid_point(&x, &y) == 1);
}
+void test_bin() {
+ p256_int a = {{1}};
+ p256_int b;
+ uint8_t a_bytes_be[P256_NBYTES];
+ uint8_t a_bytes_le[P256_NBYTES];
+ int i;
+
+ p256_to_bin(&a, a_bytes_be);
+ p256_to_le_bin(&a, a_bytes_le);
+
+ // Check big-endian serialization.
+ for (i = 0; i < P256_NBYTES - 1; ++i) {
+ CHECK(a_bytes_be[i] == 0);
+ }
+ CHECK(a_bytes_be[P256_NBYTES - 1] == 1);
+
+ // Check little-endian serialization.
+ CHECK(a_bytes_le[0] == 1);
+ for (i = 1; i < P256_NBYTES; ++i) {
+ CHECK(a_bytes_le[i] == 0);
+ }
+
+ // Check big-endian parsing.
+ p256_from_bin(a_bytes_be, &b);
+ CHECK(memcmp(&a, &b, sizeof(a)) == 0);
+
+ // Check little-endian parsing.
+ p256_from_le_bin(a_bytes_le, &b);
+ CHECK(memcmp(&a, &b, sizeof(a)) == 0);
+}
+
int main(int argc, char* argv[]) {
test_cpu_behavior();
test_shifts();
test_add_sub_cmp();
test_mul_inv();
test_valid_point();
+ test_bin();
return 0;
}
diff --git a/sha.c b/sha.c
index b0cd8f3..39fa8c9 100644
--- a/sha.c
+++ b/sha.c
@@ -25,10 +25,10 @@
int t;
for(t = 0; t < 16; ++t) {
- uint32_t tmp = *p++ << 24;
- tmp |= *p++ << 16;
- tmp |= *p++ << 8;
- tmp |= *p++;
+ uint32_t tmp = (uint32_t)(*p++) << 24;
+ tmp |= (uint32_t)(*p++) << 16;
+ tmp |= (uint32_t)(*p++) << 8;
+ tmp |= (uint32_t)(*p++);
W[t] = tmp;
}
@@ -73,7 +73,10 @@
SHA_update,
SHA_final,
SHA_hash,
- SHA_DIGEST_SIZE
+ SHA_DIGEST_SIZE,
+#ifdef SHA512_SUPPORT
+ SHA_BLOCK_SIZE,
+#endif
};
void SHA_init(SHA_CTX* ctx) {
@@ -105,7 +108,7 @@
const uint8_t* SHA_final(SHA_CTX* ctx) {
uint8_t *p = ctx->buf;
- uint64_t cnt = ctx->count * 8;
+ uint64_t cnt = LITE_LShiftU64(ctx->count, 3);
int i;
SHA_update(ctx, (uint8_t*)"\x80", 1);
@@ -113,8 +116,8 @@
SHA_update(ctx, (uint8_t*)"\0", 1);
}
for (i = 0; i < 8; ++i) {
- uint8_t tmp = (uint8_t) (cnt >> 56);
- cnt <<= 8;
+ uint8_t tmp = (uint8_t) LITE_RShiftU64(cnt, 56);
+ cnt = LITE_LShiftU64(cnt, 8);
SHA_update(ctx, &tmp, 1);
}
diff --git a/sha224.c b/sha224.c
new file mode 100644
index 0000000..bb4dca1
--- /dev/null
+++ b/sha224.c
@@ -0,0 +1,52 @@
+// Copyright 2016 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "cryptoc/sha224.h"
+#include "cryptoc/sha256.h"
+
+#include <string.h>
+#include <stdint.h>
+
+static const HASH_VTAB SHA224_VTAB = {
+ SHA224_init,
+ SHA256_update,
+ SHA256_final,
+ SHA224_hash,
+ SHA224_DIGEST_SIZE,
+#ifdef SHA512_SUPPORT
+ SHA224_BLOCK_SIZE,
+#endif
+};
+
+void SHA224_init(LITE_SHA224_CTX* ctx) {
+ ctx->f = &SHA224_VTAB;
+ ctx->state[0] = 0xc1059ed8;
+ ctx->state[1] = 0x367cd507;
+ ctx->state[2] = 0x3070dd17;
+ ctx->state[3] = 0xf70e5939;
+ ctx->state[4] = 0xffc00b31;
+ ctx->state[5] = 0x68581511;
+ ctx->state[6] = 0x64f98fa7;
+ ctx->state[7] = 0xbefa4fa4;
+ ctx->count = 0;
+}
+
+/* Convenience function */
+const uint8_t* SHA224_hash(const void* data, size_t len,
+ uint8_t* digest) {
+ LITE_SHA224_CTX ctx;
+ SHA224_init(&ctx);
+ SHA224_update(&ctx, data, len);
+ memcpy(digest, SHA224_final(&ctx), SHA224_DIGEST_SIZE);
+ return digest;
+}
diff --git a/sha256.c b/sha256.c
index ae074ac..44263a4 100644
--- a/sha256.c
+++ b/sha256.c
@@ -44,10 +44,10 @@
int t;
for(t = 0; t < 16; ++t) {
- uint32_t tmp = *p++ << 24;
- tmp |= *p++ << 16;
- tmp |= *p++ << 8;
- tmp |= *p++;
+ uint32_t tmp = (uint32_t)*p++ << 24;
+ tmp |= (uint32_t)*p++ << 16;
+ tmp |= (uint32_t)*p++ << 8;
+ tmp |= (uint32_t)*p++;
W[t] = tmp;
}
@@ -99,7 +99,10 @@
SHA256_update,
SHA256_final,
SHA256_hash,
- SHA256_DIGEST_SIZE
+ SHA256_DIGEST_SIZE,
+#ifdef SHA512_SUPPORT
+ SHA256_BLOCK_SIZE,
+#endif
};
void SHA256_init(LITE_SHA256_CTX* ctx) {
@@ -134,7 +137,7 @@
const uint8_t* SHA256_final(LITE_SHA256_CTX* ctx) {
uint8_t *p = ctx->buf;
- uint64_t cnt = ctx->count * 8;
+ uint64_t cnt = LITE_LShiftU64(ctx->count, 3);
int i;
SHA256_update(ctx, (uint8_t*)"\x80", 1);
@@ -142,8 +145,8 @@
SHA256_update(ctx, (uint8_t*)"\0", 1);
}
for (i = 0; i < 8; ++i) {
- uint8_t tmp = (uint8_t) (cnt >> 56);
- cnt <<= 8;
+ uint8_t tmp = (uint8_t)LITE_RShiftU64(cnt, 56);
+ cnt = LITE_LShiftU64(cnt, 8);
SHA256_update(ctx, &tmp, 1);
}
diff --git a/sha384.c b/sha384.c
index 3ce72d0..1485aad 100644
--- a/sha384.c
+++ b/sha384.c
@@ -27,7 +27,8 @@
SHA512_update,
SHA512_final,
SHA384_hash,
- SHA384_DIGEST_SIZE
+ SHA384_DIGEST_SIZE,
+ SHA384_BLOCK_SIZE
};
void SHA384_init(LITE_SHA384_CTX* ctx) {
diff --git a/sha512.c b/sha512.c
index eabff01..105d76c 100644
--- a/sha512.c
+++ b/sha512.c
@@ -125,7 +125,8 @@
SHA512_update,
SHA512_final,
SHA512_hash,
- SHA512_DIGEST_SIZE
+ SHA512_DIGEST_SIZE,
+ SHA512_BLOCK_SIZE
};
void SHA512_init(LITE_SHA512_CTX* ctx) {
diff --git a/util.c b/util.c
index 6f40509..c027715 100644
--- a/util.c
+++ b/util.c
@@ -19,6 +19,22 @@
}
void *always_memset(void *s, int c, size_t n) {
- always_memset_impl(s, c, n);
+ always_memset_impl((char*) s, c, n);
return s;
}
+
+int ct_memeq(const void* s1, const void* s2, uint32_t n) {
+ uint8_t diff = 0;
+ const uint8_t* ps1 = s1;
+ const uint8_t* ps2 = s2;
+
+ while (n--) {
+ diff |= *ps1 ^ *ps2;
+ ps1++;
+ ps2++;
+ }
+
+ // Counter-intuitive, but we can't just return diff because we don't want to
+ // leak the xor of non-equal bytes
+ return 0 != diff;
+}