CR50: port dcrypto/cr50 code to depend on third_party/cryptoc

Port SHA and P256 code to depend on third_party/cryptoc.
Remove config options CONFIG_SHA1, and CONFIG_SHA256 as
these are provided by third_party/cryptoc.

Also remove unused config options CONFIG_SHA384, CONFIG_SHA512.

Crypto functions prefixed by dcrypto_ (declared in internal.h ),
DCRYPTO_ (declared in dcrypto.h)  are implemented under
chip/g/dcrypto, and otherwise are implemented under third_party/cryptoc.

BRANCH=none
BUG=chrome-os-partner:43025,chrome-os-partner:47524,chrome-os-partner:53782
TEST=all tests in test/tpm_test/tpmtest.py pass

Change-Id: If7da02849aba9703573559370af5fae721d594fc
Signed-off-by: nagendra modadugu <ngm@google.com>
Reviewed-on: https://chromium-review.googlesource.com/340853
Commit-Ready: Nagendra Modadugu <ngm@google.com>
Tested-by: Nagendra Modadugu <ngm@google.com>
Reviewed-by: Nagendra Modadugu <ngm@google.com>
Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
This commit is contained in:
nagendra modadugu
2016-04-27 00:07:11 -07:00
committed by chrome-bot
parent abe2a55191
commit aca616c551
19 changed files with 231 additions and 2221 deletions

View File

@@ -25,6 +25,8 @@
/* Define interrupt and gpio structs */
#include "gpio_list.h"
#include "cryptoc/sha.h"
/*
* TODO: NV_MEMORY_SIZE is defined in 2 places. Here and in
* /src/third_party/tmp2/Implementation.h. This needs to be
@@ -209,7 +211,7 @@ void sys_rst_asserted(enum gpio_signal signal)
void nvmem_compute_sha(uint8_t *p_buf, int num_bytes,
uint8_t *p_sha, int sha_len)
{
uint8_t sha1_digest[SHA1_DIGEST_SIZE];
uint8_t sha1_digest[SHA_DIGEST_SIZE];
/*
* Taking advantage of the built in dcrypto engine to generate
* a CRC-like value that can be used to validate contents of an

View File

@@ -80,8 +80,6 @@
/* Include crypto stuff, both software and hardware. */
#define CONFIG_DCRYPTO
#define CONFIG_SHA1
#define CONFIG_SHA256
#ifndef __ASSEMBLER__

View File

@@ -60,9 +60,11 @@ CPPFLAGS += -I$(abspath ./test)
# Make sure the context of the software sha256 implementation fits. If it ever
# increases, a compile time assert will fire in tpm2/hash.c.
CFLAGS += -DUSER_MIN_HASH_STATE_SIZE=210
CFLAGS += -DUSER_MIN_HASH_STATE_SIZE=112
# Configure TPM2 headers accordingly.
CFLAGS += -DEMBEDDED_MODE=1
# Configure cryptoc headers to handle unaligned accesses.
CFLAGS += -DSUPPORT_UNALIGNED=1
# Add dependencies on that library
$(out)/RW/ec.RW.elf $(out)/RW/ec.RW_B.elf: LDFLAGS_EXTRA += -L$(out)/tpm2 -ltpm2

View File

@@ -10,8 +10,12 @@
#include "TPMB.h"
#include "trng.h"
#include "util.h"
#include "dcrypto.h"
#include "cryptoc/p256.h"
#include "cryptoc/p256_ecdsa.h"
static void reverse_tpm2b(TPM2B *b)
{
reverse(b->buffer, b->size);
@@ -42,8 +46,8 @@ BOOL _cpri__EccIsPointOnCurve(TPM_ECC_CURVE curve_id, TPMS_ECC_POINT *q)
reverse_tpm2b(&q->x.b);
reverse_tpm2b(&q->y.b);
result = DCRYPTO_p256_valid_point((p256_int *) q->x.b.buffer,
(p256_int *) q->y.b.buffer);
result = p256_is_valid_point((p256_int *) q->x.b.buffer,
(p256_int *) q->y.b.buffer);
reverse_tpm2b(&q->x.b);
reverse_tpm2b(&q->y.b);
@@ -198,10 +202,10 @@ CRYPT_RESULT _cpri__SignEcc(
reverse_tpm2b(&d->b);
DCRYPTO_p256_ecdsa_sign((p256_int *) d->b.buffer,
&p256_digest,
(p256_int *) r->b.buffer,
(p256_int *) s->b.buffer);
p256_ecdsa_sign((p256_int *) d->b.buffer,
&p256_digest,
(p256_int *) r->b.buffer,
(p256_int *) s->b.buffer);
reverse_tpm2b(&d->b);
r->b.size = sizeof(p256_int);
@@ -242,7 +246,7 @@ CRYPT_RESULT _cpri__ValidateSignatureEcc(
reverse_tpm2b(&r->b);
reverse_tpm2b(&s->b);
result = DCRYPTO_p256_ecdsa_verify(
result = p256_ecdsa_verify(
(p256_int *) q->x.b.buffer,
(p256_int *) q->y.b.buffer,
&p256_digest,

View File

@@ -42,6 +42,7 @@ uint16_t _cpri__GetHashBlockSize(TPM_ALG_ID alg)
return lookup_hash_info(alg)->blockSize;
}
BUILD_ASSERT(sizeof(LITE_SHA256_CTX) == USER_MIN_HASH_STATE_SIZE);
BUILD_ASSERT(sizeof(CPRI_HASH_STATE) == sizeof(EXPORT_HASH_STATE));
void _cpri__ImportExportHashState(CPRI_HASH_STATE *osslFmt,
EXPORT_HASH_STATE *externalFmt,
@@ -99,11 +100,11 @@ uint16_t _cpri__StartHash(TPM_ALG_ID alg, BOOL sequence,
switch (alg) {
case TPM_ALG_SHA1:
DCRYPTO_SHA1_init(ctx, sequence);
result = DCRYPTO_HASH_size(ctx);
result = HASH_size(ctx);
break;
case TPM_ALG_SHA256:
DCRYPTO_SHA256_init(ctx, sequence);
result = DCRYPTO_HASH_size(ctx);
result = HASH_size(ctx);
break;
/* TODO: add support for SHA384 and SHA512
* case TPM_ALG_SHA384:
@@ -128,7 +129,7 @@ void _cpri__UpdateHash(CPRI_HASH_STATE *state, uint32_t in_len,
{
struct HASH_CTX *ctx = (struct HASH_CTX *) state->state;
DCRYPTO_HASH_update(ctx, in, in_len);
HASH_update(ctx, in, in_len);
}
uint16_t _cpri__CompleteHash(CPRI_HASH_STATE *state,
@@ -136,8 +137,8 @@ uint16_t _cpri__CompleteHash(CPRI_HASH_STATE *state,
{
struct HASH_CTX *ctx = (struct HASH_CTX *) state->state;
out_len = MIN(DCRYPTO_HASH_size(ctx), out_len);
memcpy(out, DCRYPTO_HASH_final(ctx), out_len);
out_len = MIN(HASH_size(ctx), out_len);
memcpy(out, HASH_final(ctx), out_len);
return out_len;
}

View File

@@ -17,6 +17,16 @@ ver_params := $(shell echo "$(ver_defs) $(bld_defs)" | $(CPP) $(CPPFLAGS) -P \
ver_str := $(shell printf "%s%s %d_%d" $(ver_params))
CPPFLAGS+= -DGC_REVISION="$(ver_str)"
ifeq ($(CONFIG_DCRYPTO),y)
INCLUDE_ROOT := $(abspath ./include)
CRYPTOCLIB := $(realpath ../../third_party/cryptoc)
CPPFLAGS += -I$(abspath .)
CPPFLAGS += -I$(abspath ./builtin)
CPPFLAGS += -I$(abspath ./chip/$(CHIP))
CPPFLAGS += -I$(INCLUDE_ROOT)
CPPFLAGS += -I$(CRYPTOCLIB)/include
endif
# Required chip modules
chip-y=clock.o gpio.o hwtimer.o jtag.o system.o
ifeq ($(CONFIG_POLLING_UART),y)
@@ -32,7 +42,6 @@ chip-$(CONFIG_DCRYPTO)+= dcrypto/hmac.o
chip-$(CONFIG_DCRYPTO)+= dcrypto/hkdf.o
chip-$(CONFIG_DCRYPTO)+= dcrypto/p256.o
chip-$(CONFIG_DCRYPTO)+= dcrypto/p256_ec.o
chip-$(CONFIG_DCRYPTO)+= dcrypto/p256_ecdsa.o
chip-$(CONFIG_DCRYPTO)+= dcrypto/p256_ecies.o
chip-$(CONFIG_DCRYPTO)+= dcrypto/rsa.o
chip-$(CONFIG_DCRYPTO)+= dcrypto/sha1.o
@@ -96,3 +105,25 @@ $(out)/RW/ec.RW_B.flat: $(out)/util/signer
endif
CR50_RO_KEY ?= rom-testkey-A.pem
# This file is included twice by the Makefile, once to determine the CHIP info
# # and then again after defining all the CONFIG_ and HAS_TASK variables. We use
# # a guard so that recipe definitions and variable extensions only happen the
# # second time.
ifeq ($(CHIP_MK_INCLUDED_ONCE),)
CHIP_MK_INCLUDED_ONCE=1
else
ifeq ($(CONFIG_DCRYPTO),y)
$(out)/RW/ec.RW.elf $(out)/RW/ec.RW_B.elf: LDFLAGS_EXTRA += -L$(out)/cryptoc \
-lcryptoc
$(out)/RW/ec.RW.elf $(out)/RW/ec.RW_B.elf: $(out)/cryptoc/libcryptoc.a
# Force the external build each time, so it can look for changed sources.
.PHONY: $(out)/cryptoc/libcryptoc.a
$(out)/cryptoc/libcryptoc.a:
$(MAKE) obj=$(realpath $(out))/cryptoc SUPPORT_UNALIGNED=1 \
-C $(CRYPTOCLIB)
endif # end CONFIG_DCRYPTO
endif # CHIP_MK_INCLUDED_ONCE is nonempty

View File

@@ -14,6 +14,10 @@
#include "internal.h"
#include <stddef.h>
#include "cryptoc/hmac.h"
enum cipher_mode {
CIPHER_MODE_ECB = 0,
CIPHER_MODE_CTR = 1,
@@ -26,27 +30,11 @@ enum encrypt_mode {
ENCRYPT_MODE = 1
};
struct HASH_CTX; /* Forward declaration. */
typedef struct HASH_CTX SHA1_CTX;
typedef struct HASH_CTX SHA256_CTX;
enum hashing_mode {
HASH_SHA1 = 0,
HASH_SHA256 = 1
};
#define DCRYPTO_HASH_update(ctx, data, len) \
((ctx)->vtab->update((ctx), (data), (len)))
#define DCRYPTO_HASH_final(ctx) \
((ctx)->vtab->final((ctx)))
#define DCRYPTO_HASH_size(ctx) \
((ctx)->vtab->size)
#define DCRYPTO_SHA1_update(ctx, data, n) \
DCRYPTO_HASH_update((ctx), (data), (n))
#define DCRYPTO_SHA1_final(ctx) DCRYPTO_HASH_final((ctx))
/*
* AES implementation, based on a hardware AES block.
*/
@@ -68,16 +56,19 @@ int DCRYPTO_aes_ctr(uint8_t *out, const uint8_t *key, uint32_t key_bits,
* is TRUE, in which case there will be no attempt to use the hardware for
* this particular hashing session.
*/
void DCRYPTO_SHA1_init(SHA1_CTX *ctx, uint32_t sw_required);
void DCRYPTO_SHA256_init(SHA256_CTX *ctx, uint32_t sw_required);
const uint8_t *DCRYPTO_SHA1_hash(const uint8_t *data, uint32_t n,
void DCRYPTO_SHA1_init(SHA_CTX *ctx, uint32_t sw_required);
void DCRYPTO_SHA256_init(LITE_SHA256_CTX *ctx, uint32_t sw_required);
const uint8_t *DCRYPTO_SHA1_hash(const void *data, uint32_t n,
uint8_t *digest);
const uint8_t *DCRYPTO_SHA256_hash(const void *data, uint32_t n,
uint8_t *digest);
#define DCRYPTO_SHA256_update(ctx, data, n) \
DCRYPTO_HASH_update((ctx), (data), (n))
#define DCRYPTO_SHA256_final(ctx) DCRYPTO_HASH_final((ctx))
const uint8_t *DCRYPTO_SHA256_hash(const uint8_t *data, uint32_t n,
uint8_t *digest);
/*
* HMAC.
*/
void DCRYPTO_HMAC_SHA256_init(LITE_HMAC_CTX *ctx, const void *key,
unsigned int len);
const uint8_t *DCRYPTO_HMAC_final(LITE_HMAC_CTX *ctx);
/*
* BIGNUM utility methods.
@@ -137,7 +128,6 @@ int DCRYPTO_rsa_key_compute(struct BIGNUM *N, struct BIGNUM *d,
/*
* EC.
*/
int DCRYPTO_p256_valid_point(const p256_int *x, const p256_int *y);
int DCRYPTO_p256_base_point_mul(p256_int *out_x, p256_int *out_y,
const p256_int *n);
int DCRYPTO_p256_point_mul(p256_int *out_x, p256_int *out_y,
@@ -145,12 +135,6 @@ int DCRYPTO_p256_point_mul(p256_int *out_x, p256_int *out_y,
const p256_int *in_y);
int DCRYPTO_p256_key_from_bytes(p256_int *x, p256_int *y, p256_int *d,
const uint8_t key_bytes[P256_NBYTES]);
void DCRYPTO_p256_ecdsa_sign(const p256_int *d, const p256_int *digest,
p256_int *r, p256_int *s);
int DCRYPTO_p256_ecdsa_verify(const p256_int *key_x, const p256_int *key_y,
const p256_int *digest, const p256_int *r,
const p256_int *s);
/* P256 based integration encryption (DH+AES128+SHA256). */
/* Authenticated data may be provided, where the first auth_data_len
* bytes of in will be authenticated but not encrypted. */

View File

@@ -7,10 +7,12 @@
#include "dcrypto.h"
#include "internal.h"
#include "cryptoc/sha256.h"
static int hkdf_extract(uint8_t *PRK, const uint8_t *salt, size_t salt_len,
const uint8_t *IKM, size_t IKM_len)
{
struct HMAC_CTX ctx;
LITE_HMAC_CTX ctx;
if (PRK == NULL)
return 0;
@@ -19,9 +21,9 @@ static int hkdf_extract(uint8_t *PRK, const uint8_t *salt, size_t salt_len,
if (IKM == NULL && IKM_len > 0)
return 0;
dcrypto_HMAC_SHA256_init(&ctx, salt, salt_len);
dcrypto_HMAC_update(&ctx, IKM, IKM_len);
memcpy(PRK, dcrypto_HMAC_final(&ctx), SHA256_DIGEST_BYTES);
DCRYPTO_HMAC_SHA256_init(&ctx, salt, salt_len);
HASH_update(&ctx.hash, IKM, IKM_len);
memcpy(PRK, DCRYPTO_HMAC_final(&ctx), SHA256_DIGEST_SIZE);
return 1;
}
@@ -31,8 +33,8 @@ static int hkdf_expand(uint8_t *OKM, size_t OKM_len, const uint8_t *PRK,
uint8_t count = 1;
const uint8_t *T = OKM;
size_t T_len = 0;
uint32_t num_blocks = (OKM_len / SHA256_DIGEST_BYTES) +
(OKM_len % SHA256_DIGEST_BYTES ? 1 : 0);
uint32_t num_blocks = (OKM_len / SHA256_DIGEST_SIZE) +
(OKM_len % SHA256_DIGEST_SIZE ? 1 : 0);
if (OKM == NULL || OKM_len == 0)
return 0;
@@ -44,17 +46,18 @@ static int hkdf_expand(uint8_t *OKM, size_t OKM_len, const uint8_t *PRK,
return 0;
while (OKM_len > 0) {
struct HMAC_CTX ctx;
const size_t block_size = MIN(OKM_len, SHA256_DIGEST_BYTES);
LITE_HMAC_CTX ctx;
const size_t block_size = OKM_len < SHA256_DIGEST_SIZE ?
OKM_len : SHA256_DIGEST_SIZE;
dcrypto_HMAC_SHA256_init(&ctx, PRK, SHA256_DIGEST_BYTES);
dcrypto_HMAC_update(&ctx, T, T_len);
dcrypto_HMAC_update(&ctx, info, info_len);
dcrypto_HMAC_update(&ctx, &count, sizeof(count));
memcpy(OKM, dcrypto_HMAC_final(&ctx), block_size);
DCRYPTO_HMAC_SHA256_init(&ctx, PRK, SHA256_DIGEST_SIZE);
HASH_update(&ctx.hash, T, T_len);
HASH_update(&ctx.hash, info, info_len);
HASH_update(&ctx.hash, &count, sizeof(count));
memcpy(OKM, DCRYPTO_HMAC_final(&ctx), block_size);
T += T_len;
T_len = SHA256_DIGEST_BYTES;
T_len = SHA256_DIGEST_SIZE;
count += 1;
OKM += block_size;
OKM_len -= block_size;
@@ -68,7 +71,7 @@ int DCRYPTO_hkdf(uint8_t *OKM, size_t OKM_len,
const uint8_t *info, size_t info_len)
{
int result;
uint8_t PRK[SHA256_DIGEST_BYTES];
uint8_t PRK[SHA256_DIGEST_SIZE];
if (!hkdf_extract(PRK, salt, salt_len, IKM, IKM_len))
return 0;

View File

@@ -3,12 +3,15 @@
* found in the LICENSE file.
*/
#include <stdint.h>
#include "internal.h"
#include "dcrypto.h"
static void HMAC_init(struct HMAC_CTX *ctx, const void *key, unsigned int len)
#include <stdint.h>
#include "cryptoc/sha256.h"
/* TODO(ngm): add support for hardware hmac. */
static void HMAC_init(LITE_HMAC_CTX *ctx, const void *key, unsigned int len)
{
unsigned int i;
@@ -16,9 +19,9 @@ static void HMAC_init(struct HMAC_CTX *ctx, const void *key, unsigned int len)
if (len > sizeof(ctx->opad)) {
DCRYPTO_SHA256_init(&ctx->hash, 0);
DCRYPTO_HASH_update(&ctx->hash, key, len);
memcpy(&ctx->opad[0], DCRYPTO_HASH_final(&ctx->hash),
DCRYPTO_HASH_size(&ctx->hash));
HASH_update(&ctx->hash, key, len);
memcpy(&ctx->opad[0], HASH_final(&ctx->hash),
HASH_size(&ctx->hash));
} else {
memcpy(&ctx->opad[0], key, len);
}
@@ -28,29 +31,29 @@ static void HMAC_init(struct HMAC_CTX *ctx, const void *key, unsigned int len)
DCRYPTO_SHA256_init(&ctx->hash, 0);
/* hash ipad */
DCRYPTO_HASH_update(&ctx->hash, ctx->opad, sizeof(ctx->opad));
HASH_update(&ctx->hash, ctx->opad, sizeof(ctx->opad));
for (i = 0; i < sizeof(ctx->opad); ++i)
ctx->opad[i] ^= (0x36 ^ 0x5c);
}
void dcrypto_HMAC_SHA256_init(struct HMAC_CTX *ctx, const void *key,
void DCRYPTO_HMAC_SHA256_init(LITE_HMAC_CTX *ctx, const void *key,
unsigned int len)
{
DCRYPTO_SHA256_init(&ctx->hash, 0);
HMAC_init(ctx, key, len);
}
const uint8_t *dcrypto_HMAC_final(struct HMAC_CTX *ctx)
const uint8_t *DCRYPTO_HMAC_final(LITE_HMAC_CTX *ctx)
{
uint8_t digest[SHA_DIGEST_MAX_BYTES]; /* upto SHA2 */
memcpy(digest, DCRYPTO_HASH_final(&ctx->hash),
(DCRYPTO_HASH_size(&ctx->hash) <= sizeof(digest) ?
DCRYPTO_HASH_size(&ctx->hash) : sizeof(digest)));
memcpy(digest, HASH_final(&ctx->hash),
(HASH_size(&ctx->hash) <= sizeof(digest) ?
HASH_size(&ctx->hash) : sizeof(digest)));
DCRYPTO_SHA256_init(&ctx->hash, 0);
DCRYPTO_HASH_update(&ctx->hash, ctx->opad, sizeof(ctx->opad));
DCRYPTO_HASH_update(&ctx->hash, digest, DCRYPTO_HASH_size(&ctx->hash));
HASH_update(&ctx->hash, ctx->opad, sizeof(ctx->opad));
HASH_update(&ctx->hash, digest, HASH_size(&ctx->hash));
memset(&ctx->opad[0], 0, sizeof(ctx->opad)); /* wipe key */
return DCRYPTO_HASH_final(&ctx->hash);
return HASH_final(&ctx->hash);
}

View File

@@ -6,11 +6,15 @@
#ifndef __EC_CHIP_G_DCRYPTO_INTERNAL_H
#define __EC_CHIP_G_DCRYPTO_INTERNAL_H
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include "common.h"
#include "sha1.h"
#include "sha256.h"
#include "util.h"
#include "cryptoc/p256.h"
#include "cryptoc/sha.h"
#include "cryptoc/sha256.h"
/*
* SHA.
@@ -20,43 +24,10 @@
#define CTRL_ENCRYPT 1
#define CTRL_NO_SOFT_RESET 0
struct HASH_CTX; /* Forward declaration. */
#define SHA_DIGEST_WORDS (SHA_DIGEST_SIZE / sizeof(uint32_t))
#define SHA256_DIGEST_WORDS (SHA256_DIGEST_SIZE / sizeof(uint32_t))
struct HASH_VTAB {
void (* const update)(struct HASH_CTX *, const uint8_t *, uint32_t);
const uint8_t *(* const final)(struct HASH_CTX *);
const uint8_t *(* const hash)(const uint8_t *, uint32_t, uint8_t *);
uint32_t size;
};
#define SHA1_DIGEST_BYTES 20
#define SHA256_DIGEST_BYTES 32
#define SHA384_DIGEST_BYTES 48
#define SHA512_DIGEST_BYTES 64
#define SHA1_DIGEST_WORDS (SHA1_DIGEST_BYTES / sizeof(uint32_t))
#define SHA256_DIGEST_WORDS (SHA256_DIGEST_BYTES / sizeof(uint32_t))
#define SHA384_DIGEST_WORDS (SHA384_DIGEST_BYTES / sizeof(uint32_t))
#define SHA512_DIGEST_WORDS (SHA512_DIGEST_BYTES / sizeof(uint32_t))
#if defined(CONFIG_SHA512)
#define SHA_DIGEST_MAX_BYTES SHA512_DIGEST_BYTES
#elif defined(CONFIG_SHA384)
#define SHA_DIGEST_MAX_BYTES SHA384_DIGEST_BYTES
#elif defined(CONFIG_SHA256)
#define SHA_DIGEST_MAX_BYTES SHA256_DIGEST_BYTES
#elif defined CONFIG_SHA1
#define SHA_DIGEST_MAX_BYTES SHA1_DIGEST_BYTES
#endif
struct HASH_CTX {
const struct HASH_VTAB *vtab;
union {
uint8_t buf[SHA_DIGEST_MAX_BYTES];
struct sha1_ctx sw_sha1;
struct sha256_ctx sw_sha256;
} u;
};
#define SHA_DIGEST_MAX_BYTES SHA256_DIGEST_SIZE
enum sha_mode {
SHA1_MODE = 0,
@@ -79,24 +50,9 @@ void dcrypto_sha_hash(enum sha_mode mode, const uint8_t *data,
uint32_t n, uint8_t *digest);
void dcrypto_sha_init(enum sha_mode mode);
void dcrypto_sha_update(struct HASH_CTX *unused,
const uint8_t *data, uint32_t n);
const void *data, uint32_t n);
void dcrypto_sha_wait(enum sha_mode mode, uint32_t *digest);
/*
* HMAC.
*/
struct HMAC_CTX {
struct HASH_CTX hash;
uint8_t opad[64];
};
#define HASH_update(ctx, data, len) \
((ctx)->vtab->update((ctx), (data), (len)))
void dcrypto_HMAC_SHA256_init(struct HMAC_CTX *ctx, const void *key,
unsigned int len);
#define dcrypto_HMAC_update(ctx, data, len) HASH_update(&(ctx)->hash, data, len)
const uint8_t *dcrypto_HMAC_final(struct HMAC_CTX *ctx);
/*
* BIGNUM.
*/
@@ -122,54 +78,6 @@ void bn_mul(struct BIGNUM *c, const struct BIGNUM *a, const struct BIGNUM *b);
int bn_modinv_vartime(struct BIGNUM *r, const struct BIGNUM *e,
const struct BIGNUM *MOD);
/*
* EC.
*/
#define P256_BITSPERDIGIT 32
#define P256_NDIGITS 8
#define P256_NBYTES 32
typedef uint32_t p256_digit;
typedef int32_t p256_sdigit;
typedef uint64_t p256_ddigit;
typedef int64_t p256_sddigit;
/* Define p256_int as a struct to leverage struct assignment. */
typedef struct {
p256_digit a[P256_NDIGITS] __packed;
} p256_int;
#define P256_DIGITS(x) ((x)->a)
#define P256_DIGIT(x, y) ((x)->a[y])
#define P256_ZERO { {0} }
#define P256_ONE { {1} }
/* Curve constants. */
extern const p256_int SECP256r1_n;
extern const p256_int SECP256r1_p;
extern const p256_int SECP256r1_b;
void p256_init(p256_int *a);
void p256_from_bin(const uint8_t src[P256_NBYTES], p256_int *dst);
void p256_to_bin(const p256_int *src, uint8_t dst[P256_NBYTES]);
#define p256_clear(a) p256_init((a))
int p256_is_zero(const p256_int *a);
int p256_cmp(const p256_int *a, const p256_int *b);
int p256_get_bit(const p256_int *scalar, int bit);
p256_digit p256_shl(const p256_int *a, int n, p256_int *b);
void p256_shr(const p256_int *a, int n, p256_int *b);
int p256_add(const p256_int *a, const p256_int *b, p256_int *c);
int p256_add_d(const p256_int *a, p256_digit d, p256_int *b);
void p256_points_mul_vartime(
const p256_int *n1, const p256_int *n2, const p256_int *in_x,
const p256_int *in_y, p256_int *out_x, p256_int *out_y);
void p256_mod(const p256_int *MOD, const p256_int *in, p256_int *out);
void p256_modmul(const p256_int *MOD, const p256_int *a,
const p256_digit top_b, const p256_int *b, p256_int *c);
void p256_modinv(const p256_int *MOD, const p256_int *a, p256_int *b);
void p256_modinv_vartime(const p256_int *MOD, const p256_int *a, p256_int *b);
/*
* Utility functions.
*/

View File

@@ -4,442 +4,11 @@
*/
#include "dcrypto.h"
#include "internal.h"
#include <assert.h>
#include "cryptoc/p256.h"
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 } };
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));
}
int p256_get_bit(const p256_int *scalar, int bit)
{
return (P256_DIGIT(scalar, bit / P256_BITSPERDIGIT)
>> (bit & (P256_BITSPERDIGIT - 1))) & 1;
}
p256_digit p256_shl(const p256_int *a, int n, p256_int *b)
{
int i;
p256_digit top = P256_DIGIT(a, P256_NDIGITS - 1);
n %= P256_BITSPERDIGIT;
for (i = P256_NDIGITS - 1; i > 0; --i) {
p256_digit accu = (P256_DIGIT(a, i) << n);
accu |= (P256_DIGIT(a, i - 1) >> (P256_BITSPERDIGIT - n));
P256_DIGIT(b, i) = accu;
}
P256_DIGIT(b, i) = (P256_DIGIT(a, i) << n);
top >>= (P256_BITSPERDIGIT - n);
return top;
}
void p256_shr(const p256_int *a, int n, p256_int *b)
{
int i;
n %= P256_BITSPERDIGIT;
for (i = 0; i < P256_NDIGITS - 1; ++i) {
p256_digit accu = (P256_DIGIT(a, i) >> n);
accu |= (P256_DIGIT(a, i + 1) << (P256_BITSPERDIGIT - n));
P256_DIGIT(b, i) = accu;
}
P256_DIGIT(b, i) = (P256_DIGIT(a, i) >> n);
}
int p256_is_zero(const p256_int *a)
{
int i, result = 0;
for (i = 0; i < P256_NDIGITS; ++i)
result |= P256_DIGIT(a, i);
return !result;
}
int p256_cmp(const p256_int *a, const p256_int *b)
{
int i;
p256_sddigit borrow = 0;
p256_digit notzero = 0;
for (i = 0; i < P256_NDIGITS; ++i) {
borrow += (p256_sddigit) P256_DIGIT(a, i) - P256_DIGIT(b, i);
/* Track whether any result digit is ever not zero.
* Relies on !!(non-zero) evaluating to 1, e.g., !!(-1)
* evaluating to 1. */
notzero |= !!((p256_digit) borrow);
borrow >>= P256_BITSPERDIGIT;
}
return (int) borrow | notzero;
}
/* c = a - b. Returns borrow: 0 or -1. */
int p256_sub(const p256_int *a, const p256_int *b, p256_int *c)
{
int i;
p256_sddigit borrow = 0;
for (i = 0; i < P256_NDIGITS; ++i) {
borrow += (p256_sddigit) P256_DIGIT(a, i) - P256_DIGIT(b, i);
if (c)
P256_DIGIT(c, i) = (p256_digit) borrow;
borrow >>= P256_BITSPERDIGIT;
}
return (int) borrow;
}
/* c = a + b. Returns carry: 0 or 1. */
int p256_add(const p256_int *a, const p256_int *b, p256_int *c)
{
int i;
p256_ddigit carry = 0;
for (i = 0; i < P256_NDIGITS; ++i) {
carry += (p256_ddigit) P256_DIGIT(a, i) + P256_DIGIT(b, i);
if (c)
P256_DIGIT(c, i) = (p256_digit) carry;
carry >>= P256_BITSPERDIGIT;
}
return (int) carry;
}
/* b = a + d. Returns carry, 0 or 1. */
int p256_add_d(const p256_int *a, p256_digit d, p256_int *b)
{
int i;
p256_ddigit carry = d;
for (i = 0; i < P256_NDIGITS; ++i) {
carry += (p256_ddigit) P256_DIGIT(a, i);
if (b)
P256_DIGIT(b, i) = (p256_digit) carry;
carry >>= P256_BITSPERDIGIT;
}
return (int) carry;
}
/* top, c[] += a[] * b */
/* Returns new top. */
static p256_digit p256_muladd(const p256_int *a, p256_digit b,
p256_digit top, p256_digit *c)
{
int i;
p256_ddigit carry = 0;
for (i = 0; i < P256_NDIGITS; ++i) {
carry += *c;
carry += (p256_ddigit) P256_DIGIT(a, i) * b;
*c++ = (p256_digit) carry;
carry >>= P256_BITSPERDIGIT;
}
return top + (p256_digit) carry;
}
/* top, c[] -= top_a, a[] */
static p256_digit p256_subtop(p256_digit top_a, const p256_digit *a,
p256_digit top_c, p256_digit *c)
{
int i;
p256_sddigit borrow = 0;
for (i = 0; i < P256_NDIGITS; ++i) {
borrow += *c;
borrow -= *a++;
*c++ = (p256_digit) borrow;
borrow >>= P256_BITSPERDIGIT;
}
borrow += top_c;
borrow -= top_a;
top_c = (p256_digit) borrow;
assert((borrow >> P256_BITSPERDIGIT) == 0);
return top_c;
}
/* top, c[] += MOD[] & mask (0 or -1) */
/* returns new top. */
static p256_digit p256_addM(const p256_int *MOD, p256_digit top,
p256_digit *c, p256_digit mask)
{
int i;
p256_ddigit carry = 0;
for (i = 0; i < P256_NDIGITS; ++i) {
carry += *c;
carry += P256_DIGIT(MOD, i) & mask;
*c++ = (p256_digit) carry;
carry >>= P256_BITSPERDIGIT;
}
return top + (p256_digit) carry;
}
/* top, c[] -= MOD[] & mask (0 or -1) */
/* returns new top. */
static p256_digit p256_subM(const p256_int *MOD, p256_digit top,
p256_digit *c, p256_digit mask)
{
int i;
p256_sddigit borrow = 0;
for (i = 0; i < P256_NDIGITS; ++i) {
borrow += *c;
borrow -= P256_DIGIT(MOD, i) & mask;
*c++ = (p256_digit) borrow;
borrow >>= P256_BITSPERDIGIT;
}
return top + (p256_digit) borrow;
}
/* Convert in. */
void p256_from_bin(const uint8_t src[P256_NBYTES], p256_int *dst)
{
int i;
const uint8_t *p = &src[0];
for (i = P256_NDIGITS - 1; i >= 0; --i) {
P256_DIGIT(dst, i) =
(p[0] << 24) |
(p[1] << 16) |
(p[2] << 8) |
p[3];
p += 4;
}
}
/* Convert out. */
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 d = P256_DIGIT(src, i);
p[0] = (d >> 24) & 0xFF;
p[1] = (d >> 16) & 0xFF;
p[2] = (d >> 8) & 0xFF;
p[3] = d & 0xFF;
p += 4;
}
}
void p256_mod(const p256_int *MOD, const p256_int *in, p256_int *out)
{
if (out != in)
*out = *in;
p256_addM(MOD, 0, P256_DIGITS(out),
p256_subM(MOD, 0, P256_DIGITS(out), -1));
}
void p256_modmul(const p256_int *MOD, const p256_int *a,
const p256_digit top_b, const p256_int *b, p256_int *c)
{
p256_digit tmp[P256_NDIGITS * 2 + 1] = { 0 };
p256_digit top = 0;
int i;
/* Multiply/add into tmp. */
for (i = 0; i < P256_NDIGITS; ++i) {
if (i)
tmp[i + P256_NDIGITS - 1] = top;
top = p256_muladd(a, P256_DIGIT(b, i), 0, tmp + i);
}
/* Multiply/add top digit. */
tmp[i + P256_NDIGITS - 1] = top;
top = p256_muladd(a, top_b, 0, tmp + i);
/* Reduce tmp, digit by digit. */
for (; i >= 0; --i) {
p256_digit reducer[P256_NDIGITS] = { 0 };
p256_digit top_reducer;
/* top can be any value at this point.
* Guestimate reducer as top * MOD, since msw of MOD is -1. */
top_reducer = p256_muladd(MOD, top, 0, reducer);
/* Subtract reducer from top | tmp. */
top = p256_subtop(top_reducer, reducer, top, tmp + i);
/* top is now either 0 or 1. Make it 0, fixed-timing. */
assert(top <= 1);
top = p256_subM(MOD, top, tmp + i, ~(top - 1));
assert(top == 0);
/* We have now reduced the top digit off tmp. Fetch
* new top digit. */
top = tmp[i + P256_NDIGITS - 1];
}
/* tmp might still be larger than MOD, yet same bit length.
* Make sure it is less, fixed-timing. */
p256_addM(MOD, 0, tmp, p256_subM(MOD, 0, tmp, -1));
memcpy(c, tmp, P256_NBYTES);
}
/* if (mask) dst = src, fixed-timing style. */
static void conditional_copy(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)
conditional_copy(&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)
{
int i;
p256_int tbl[16];
/* 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]);
conditional_copy(&tbl[0], b, ~ZEROtoONES(idx));
}
}
static int p256_is_even(const p256_int *a)
{
return !(P256_DIGIT(a, 0) & 1);
}
static void p256_shr1(const p256_int *a, int highbit, p256_int *b)
{
int i;
for (i = 0; i < P256_NDIGITS - 1; ++i) {
p256_digit accu = (P256_DIGIT(a, i) >> 1);
accu |= (P256_DIGIT(a, i + 1) << (P256_BITSPERDIGIT - 1));
P256_DIGIT(b, i) = accu;
}
P256_DIGIT(b, i) = (P256_DIGIT(a, i) >> 1) |
(highbit << (P256_BITSPERDIGIT - 1));
}
/* b = 1/a mod MOD, binary euclid. */
void p256_modinv_vartime(const p256_int *MOD, const p256_int *a, p256_int *b)
{
p256_int R = P256_ZERO;
p256_int S = P256_ONE;
p256_int U = *MOD;
p256_int V = *a;
for (;;) {
if (p256_is_even(&U)) {
p256_shr1(&U, 0, &U);
if (p256_is_even(&R)) {
p256_shr1(&R, 0, &R);
} else {
/* R = (R + MOD)/2 */
p256_shr1(&R, p256_add(&R, MOD, &R), &R);
}
} else if (p256_is_even(&V)) {
p256_shr1(&V, 0, &V);
if (p256_is_even(&S)) {
p256_shr1(&S, 0, &S);
} else {
/* S = (S + MOD)/2 */
p256_shr1(&S, p256_add(&S, MOD, &S) , &S);
}
} else { /* U, V both odd. */
if (!p256_sub(&V, &U, NULL)) {
p256_sub(&V, &U, &V);
if (p256_sub(&S, &R, &S))
p256_add(&S, MOD, &S);
if (p256_is_zero(&V))
break; /* done. */
} else {
p256_sub(&U, &V, &U);
if (p256_sub(&R, &S, &R))
p256_add(&R, MOD, &R);
}
}
}
p256_mod(MOD, &R, b);
}
int DCRYPTO_p256_valid_point(const p256_int *x, const p256_int *y)
{
p256_int y2, x3;
if (p256_cmp(&SECP256r1_p, x) <= 0 || p256_cmp(&SECP256r1_p, y) <= 0 ||
p256_is_zero(x) || p256_is_zero(y))
return 0;
p256_modmul(&SECP256r1_p, y, 0, y, &y2); /* y^2 */
p256_modmul(&SECP256r1_p, x, 0, x, &x3); /* x^2 */
p256_modmul(&SECP256r1_p, x, 0, &x3, &x3); /* x^3 */
if (p256_sub(&x3, x, &x3))
p256_add(&x3, &SECP256r1_p, &x3); /* x^3 - x */
if (p256_sub(&x3, x, &x3))
p256_add(&x3, &SECP256r1_p, &x3); /* x^3 - 2x */
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;
}
/*
* Key selection based on FIPS-186-4, section B.4.2 (Key Pair
* Generation by Testing Candidates).
@@ -447,15 +16,13 @@ int DCRYPTO_p256_valid_point(const p256_int *x, const p256_int *y)
int DCRYPTO_p256_key_from_bytes(p256_int *x, p256_int *y, p256_int *d,
const uint8_t key_bytes[P256_NBYTES])
{
int valid;
p256_int key;
p256_from_bin(key_bytes, &key);
if (p256_cmp(&SECP256r1_nMin2, &key) < 0)
return 0;
p256_add(&key, &p256_one, &key);
valid = DCRYPTO_p256_base_point_mul(x, y, &key);
if (valid)
*d = key;
return valid;
p256_add(&key, &p256_one, d);
p256_base_point_mul(d, x, y);
dcrypto_memset(&key, 0, sizeof(key));
return 1;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,103 +0,0 @@
/* Copyright 2015 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <stdint.h>
#include "dcrypto.h"
/* Compute k based on a given {key, digest} pair, 0 < k < n. */
static void determine_k(const p256_int *key, const p256_int *digest,
char *tweak, p256_int *k)
{
do {
p256_int p1, p2;
struct HMAC_CTX hmac;
/* NOTE: taking the p256_int in-memory representation
* is not endian neutral. Signatures with an
* identical key on identical digests will differ per
* host endianness. This however does not jeopardize
* the key bits. */
dcrypto_HMAC_SHA256_init(&hmac, key, P256_NBYTES);
dcrypto_HMAC_update(&hmac, tweak, 1);
dcrypto_HMAC_update(&hmac, (uint8_t *) digest, P256_NBYTES);
++(*tweak);
p256_from_bin(dcrypto_HMAC_final(&hmac), &p1);
dcrypto_HMAC_SHA256_init(&hmac, key, P256_NBYTES);
dcrypto_HMAC_update(&hmac, tweak, 1);
dcrypto_HMAC_update(&hmac, (uint8_t *) digest, P256_NBYTES);
++(*tweak);
p256_from_bin(dcrypto_HMAC_final(&hmac), &p2);
/* Combine p1 and p2 into well distributed k. */
p256_modmul(&SECP256r1_n, &p1, 0, &p2, k);
/* (Attempt to) clear stack state. */
p256_clear(&p1);
p256_clear(&p2);
} while (p256_is_zero(k));
}
void DCRYPTO_p256_ecdsa_sign(const p256_int *key, const p256_int *digest,
p256_int *r, p256_int *s)
{
char tweak = 'A';
p256_digit top;
for (;;) {
p256_int k, kinv;
determine_k(key, digest, &tweak, &k);
DCRYPTO_p256_base_point_mul(r, s, &k);
p256_mod(&SECP256r1_n, r, r);
/* Make sure r != 0. */
if (p256_is_zero(r))
continue;
p256_modmul(&SECP256r1_n, r, 0, key, s);
top = p256_add(s, digest, s);
p256_modinv(&SECP256r1_n, &k, &kinv);
p256_modmul(&SECP256r1_n, &kinv, top, s, s);
/* (Attempt to) clear stack state. */
p256_clear(&k);
p256_clear(&kinv);
/* Make sure s != 0. */
if (p256_is_zero(s))
continue;
break;
}
}
int DCRYPTO_p256_ecdsa_verify(const p256_int *key_x, const p256_int *key_y,
const p256_int *digest,
const p256_int *r, const p256_int *s)
{
p256_int u, v;
/* Check public key. */
if (!DCRYPTO_p256_valid_point(key_x, key_y))
return 0;
/* Check r and s are != 0 % n. */
p256_mod(&SECP256r1_n, r, &u);
p256_mod(&SECP256r1_n, s, &v);
if (p256_is_zero(&u) || p256_is_zero(&v))
return 0;
p256_modinv_vartime(&SECP256r1_n, s, &v);
p256_modmul(&SECP256r1_n, digest, 0, &v, &u); /* digest / s % n */
p256_modmul(&SECP256r1_n, r, 0, &v, &v); /* r / s % n */
p256_points_mul_vartime(&u, &v, key_x, key_y, &u, &v);
p256_mod(&SECP256r1_n, &u, &u); /* (x coord % p) % n */
return p256_cmp(r, &u) == 0;
}

View File

@@ -7,6 +7,10 @@
#include "dcrypto.h"
#include "trng.h"
#include "util.h"
#include "cryptoc/p256.h"
#include "cryptoc/sha256.h"
#define AES_KEY_BYTES 16
#define HMAC_KEY_BYTES 32
@@ -35,14 +39,14 @@ size_t DCRYPTO_ecies_encrypt(
uint8_t key[AES_KEY_BYTES + HMAC_KEY_BYTES];
const uint8_t *aes_key;
const uint8_t *hmac_key;
struct HMAC_CTX ctx;
LITE_HMAC_CTX ctx;
uint8_t *outp = out;
uint8_t *ciphertext;
if (auth_data_len > in_len)
return 0;
if (out_len < 1 + P256_NBYTES + P256_NBYTES +
in_len + SHA256_DIGEST_BYTES)
in_len + SHA256_DIGEST_SIZE)
return 0;
/* Generate emphemeral EC key. */
@@ -54,7 +58,7 @@ size_t DCRYPTO_ecies_encrypt(
&eph_d, pub_x, pub_y))
return 0;
/* Check for computational errors. */
if (!DCRYPTO_p256_valid_point(&secret_x, &secret_y))
if (!p256_is_valid_point(&secret_x, &secret_y))
return 0;
/* Convert secret to big-endian. */
reverse(&secret_x, sizeof(secret_x));
@@ -94,11 +98,11 @@ size_t DCRYPTO_ecies_encrypt(
outp += P256_NBYTES;
/* Calculate HMAC(auth_data || ciphertext). */
dcrypto_HMAC_SHA256_init(&ctx, hmac_key, HMAC_KEY_BYTES);
dcrypto_HMAC_update(&ctx, outp, in_len);
DCRYPTO_HMAC_SHA256_init(&ctx, hmac_key, HMAC_KEY_BYTES);
HASH_update(&ctx.hash, outp, in_len);
outp += in_len;
memcpy(outp, dcrypto_HMAC_final(&ctx), SHA256_DIGEST_BYTES);
outp += SHA256_DIGEST_BYTES;
memcpy(outp, DCRYPTO_HMAC_final(&ctx), SHA256_DIGEST_SIZE);
outp += SHA256_DIGEST_SIZE;
return outp - (uint8_t *) out;
}
@@ -117,17 +121,17 @@ size_t DCRYPTO_ecies_decrypt(
uint8_t key[AES_KEY_BYTES + HMAC_KEY_BYTES];
const uint8_t *aes_key;
const uint8_t *hmac_key;
struct HMAC_CTX ctx;
LITE_HMAC_CTX ctx;
const uint8_t *inp = in;
uint8_t *outp = out;
if (in_len < 1 + P256_NBYTES + P256_NBYTES + auth_data_len +
SHA256_DIGEST_BYTES)
SHA256_DIGEST_SIZE)
return 0;
if (inp[0] != 0x04)
return 0;
in_len -= 1 + P256_NBYTES + P256_NBYTES + SHA256_DIGEST_BYTES;
in_len -= 1 + P256_NBYTES + P256_NBYTES + SHA256_DIGEST_SIZE;
inp++;
p256_from_bin(inp, &eph_x);
@@ -136,14 +140,14 @@ size_t DCRYPTO_ecies_decrypt(
inp += P256_NBYTES;
/* Verify that the public point is on the curve. */
if (!DCRYPTO_p256_valid_point(&eph_x, &eph_y))
if (!p256_is_valid_point(&eph_x, &eph_y))
return 0;
/* Compute the DH point. */
if (!DCRYPTO_p256_point_mul(&secret_x, &secret_y,
d, &eph_x, &eph_y))
return 0;
/* Check for computational errors. */
if (!DCRYPTO_p256_valid_point(&secret_x, &secret_y))
if (!p256_is_valid_point(&secret_x, &secret_y))
return 0;
/* Convert secret to big-endian. */
reverse(&secret_x, sizeof(secret_x));
@@ -155,11 +159,11 @@ size_t DCRYPTO_ecies_decrypt(
aes_key = &key[0];
hmac_key = &key[AES_KEY_BYTES];
dcrypto_HMAC_SHA256_init(&ctx, hmac_key, HMAC_KEY_BYTES);
dcrypto_HMAC_update(&ctx, inp, in_len);
DCRYPTO_HMAC_SHA256_init(&ctx, hmac_key, HMAC_KEY_BYTES);
HASH_update(&ctx.hash, inp, in_len);
/* TODO(ngm): replace with constant time verify. */
if (memcmp(inp + in_len, dcrypto_HMAC_final(&ctx),
SHA256_DIGEST_BYTES) != 0)
if (memcmp(inp + in_len, DCRYPTO_HMAC_final(&ctx),
SHA256_DIGEST_SIZE) != 0)
return 0;
memmove(outp, inp, auth_data_len);

View File

@@ -11,11 +11,14 @@
#include <assert.h>
#include "cryptoc/sha.h"
#include "cryptoc/sha256.h"
static void MGF1_xor(uint8_t *dst, uint32_t dst_len,
const uint8_t *seed, uint32_t seed_len,
enum hashing_mode hashing)
{
struct HASH_CTX ctx;
HASH_CTX ctx;
struct {
uint8_t b3;
uint8_t b2;
@@ -23,8 +26,8 @@ static void MGF1_xor(uint8_t *dst, uint32_t dst_len,
uint8_t b0;
} cnt;
const uint8_t *digest;
const size_t hash_size = (hashing == HASH_SHA1) ? SHA1_DIGEST_BYTES
: SHA256_DIGEST_BYTES;
const size_t hash_size = (hashing == HASH_SHA1) ? SHA_DIGEST_SIZE
: SHA256_DIGEST_SIZE;
cnt.b0 = cnt.b1 = cnt.b2 = cnt.b3 = 0;
while (dst_len) {
@@ -35,9 +38,9 @@ static void MGF1_xor(uint8_t *dst, uint32_t dst_len,
else
DCRYPTO_SHA256_init(&ctx, 0);
DCRYPTO_HASH_update(&ctx, seed, seed_len);
DCRYPTO_HASH_update(&ctx, (uint8_t *) &cnt, sizeof(cnt));
digest = DCRYPTO_HASH_final(&ctx);
HASH_update(&ctx, seed, seed_len);
HASH_update(&ctx, (uint8_t *) &cnt, sizeof(cnt));
digest = HASH_final(&ctx);
for (i = 0; i < dst_len && i < hash_size; ++i)
*dst++ ^= *digest++;
dst_len -= i;
@@ -62,8 +65,8 @@ static int oaep_pad(uint8_t *output, uint32_t output_len,
enum hashing_mode hashing, const char *label)
{
int i;
const size_t hash_size = (hashing == HASH_SHA1) ? SHA1_DIGEST_BYTES
: SHA256_DIGEST_BYTES;
const size_t hash_size = (hashing == HASH_SHA1) ? SHA_DIGEST_SIZE
: SHA256_DIGEST_SIZE;
uint8_t *const seed = output + 1;
uint8_t *const phash = seed + hash_size;
uint8_t *const PS = phash + hash_size;
@@ -92,8 +95,8 @@ static int oaep_pad(uint8_t *output, uint32_t output_len,
else
DCRYPTO_SHA256_init(&ctx, 0);
DCRYPTO_HASH_update(&ctx, label, label ? strlen(label) + 1 : 0);
memcpy(phash, DCRYPTO_HASH_final(&ctx), hash_size);
HASH_update(&ctx, label, label ? strlen(label) + 1 : 0);
memcpy(phash, HASH_final(&ctx), hash_size);
*one = 1;
memcpy(one + 1, msg, msg_len);
MGF1_xor(phash, hash_size + 1 + max_msg_len,
@@ -109,8 +112,8 @@ static int check_oaep_pad(uint8_t *out, uint32_t *out_len,
uint8_t *padded, uint32_t padded_len,
enum hashing_mode hashing, const char *label)
{
const size_t hash_size = (hashing == HASH_SHA1) ? SHA1_DIGEST_BYTES
: SHA256_DIGEST_BYTES;
const size_t hash_size = (hashing == HASH_SHA1) ? SHA_DIGEST_SIZE
: SHA256_DIGEST_SIZE;
uint8_t *seed = padded + 1;
uint8_t *phash = seed + hash_size;
uint8_t *PS = phash + hash_size;
@@ -132,9 +135,9 @@ static int check_oaep_pad(uint8_t *out, uint32_t *out_len,
DCRYPTO_SHA1_init(&ctx, 0);
else
DCRYPTO_SHA256_init(&ctx, 0);
DCRYPTO_HASH_update(&ctx, label, label ? strlen(label) + 1 : 0);
HASH_update(&ctx, label, label ? strlen(label) + 1 : 0);
bad = memcmp(phash, DCRYPTO_HASH_final(&ctx), hash_size);
bad = memcmp(phash, HASH_final(&ctx), hash_size);
bad |= padded[0];
for (i = PS - padded; i < padded_len; i++) {
@@ -239,8 +242,8 @@ static int pkcs1_type1_pad(uint8_t *padded, uint32_t padded_len,
: &SHA256_DER[0];
const uint32_t der_size = (hashing == HASH_SHA1) ? sizeof(SHA1_DER)
: sizeof(SHA256_DER);
const uint32_t hash_size = (hashing == HASH_SHA1) ? SHA1_DIGEST_BYTES
: SHA256_DIGEST_BYTES;
const uint32_t hash_size = (hashing == HASH_SHA1) ? SHA_DIGEST_SIZE
: SHA256_DIGEST_SIZE;
uint32_t ps_len;
if (padded_len < RSA_PKCS1_PADDING_SIZE + der_size)
@@ -273,8 +276,8 @@ static int check_pkcs1_type1_pad(const uint8_t *msg, uint32_t msg_len,
: &SHA256_DER[0];
const uint32_t der_size = (hashing == HASH_SHA1) ? sizeof(SHA1_DER)
: sizeof(SHA256_DER);
const uint32_t hash_size = (hashing == HASH_SHA1) ? SHA1_DIGEST_BYTES
: SHA256_DIGEST_BYTES;
const uint32_t hash_size = (hashing == HASH_SHA1) ? SHA_DIGEST_SIZE
: SHA256_DIGEST_SIZE;
uint32_t ps_len;
if (msg_len != hash_size)
@@ -303,8 +306,8 @@ static int pkcs1_pss_pad(uint8_t *padded, uint32_t padded_len,
const uint8_t *in, uint32_t in_len,
enum hashing_mode hashing)
{
const uint32_t hash_size = (hashing == HASH_SHA1) ? SHA1_DIGEST_BYTES
: SHA256_DIGEST_BYTES;
const uint32_t hash_size = (hashing == HASH_SHA1) ? SHA_DIGEST_SIZE
: SHA256_DIGEST_SIZE;
const uint32_t salt_len = MIN(padded_len - hash_size - 2, hash_size);
uint32_t db_len;
uint32_t ps_len;
@@ -323,14 +326,14 @@ static int pkcs1_pss_pad(uint8_t *padded, uint32_t padded_len,
/* Pilfer bits of output for temporary use. */
memset(padded, 0, 8);
DCRYPTO_HASH_update(&ctx, padded, 8);
DCRYPTO_HASH_update(&ctx, in, in_len);
HASH_update(&ctx, padded, 8);
HASH_update(&ctx, in, in_len);
/* Pilfer bits of output for temporary use. */
rand_bytes(padded, salt_len);
DCRYPTO_HASH_update(&ctx, padded, salt_len);
HASH_update(&ctx, padded, salt_len);
/* Output hash. */
memcpy(padded + db_len, DCRYPTO_HASH_final(&ctx), hash_size);
memcpy(padded + db_len, HASH_final(&ctx), hash_size);
/* Prepare DB. */
ps_len = db_len - salt_len - 1;
@@ -351,13 +354,13 @@ static int check_pkcs1_pss_pad(const uint8_t *in, uint32_t in_len,
uint8_t *padded, uint32_t padded_len,
enum hashing_mode hashing)
{
const uint32_t hash_size = (hashing == HASH_SHA1) ? SHA1_DIGEST_BYTES
: SHA256_DIGEST_BYTES;
const uint32_t hash_size = (hashing == HASH_SHA1) ? SHA_DIGEST_SIZE
: SHA256_DIGEST_SIZE;
const uint8_t zeros[8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint32_t db_len;
uint32_t max_ps_len;
uint32_t salt_len;
struct HASH_CTX ctx;
HASH_CTX ctx;
int bad = 0;
int i;
@@ -392,10 +395,10 @@ static int check_pkcs1_pss_pad(const uint8_t *in, uint32_t in_len,
DCRYPTO_SHA1_init(&ctx, 0);
else
DCRYPTO_SHA256_init(&ctx, 0);
DCRYPTO_HASH_update(&ctx, zeros, sizeof(zeros));
DCRYPTO_HASH_update(&ctx, in, in_len);
DCRYPTO_HASH_update(&ctx, padded + db_len - salt_len, salt_len);
bad |= memcmp(padded + db_len, DCRYPTO_HASH_final(&ctx), hash_size);
HASH_update(&ctx, zeros, sizeof(zeros));
HASH_update(&ctx, in, in_len);
HASH_update(&ctx, padded + db_len - salt_len, salt_len);
bad |= memcmp(padded + db_len, HASH_final(&ctx), hash_size);
return !bad;
}

View File

@@ -7,59 +7,29 @@
#include "internal.h"
#include "registers.h"
static void sw_sha1_init(SHA1_CTX *ctx);
static void sw_sha1_update(SHA1_CTX *ctx, const uint8_t *data, uint32_t len);
static const uint8_t *sw_sha1_final(SHA1_CTX *ctx);
static const uint8_t *sha1_hash(const uint8_t *data, uint32_t len,
uint8_t *digest);
static const uint8_t *dcrypto_sha1_final(SHA1_CTX *unused);
/* Software SHA1 implementation. */
static const struct HASH_VTAB SW_SHA1_VTAB = {
sw_sha1_update,
sw_sha1_final,
sha1_hash,
SHA1_DIGEST_BYTES
};
static void sw_sha1_init(SHA1_CTX *ctx)
{
ctx->vtab = &SW_SHA1_VTAB;
sha1_init(&ctx->u.sw_sha1);
}
static void sw_sha1_update(SHA1_CTX *ctx, const uint8_t *data, uint32_t len)
{
sha1_update(&ctx->u.sw_sha1, data, len);
}
static const uint8_t *sw_sha1_final(SHA1_CTX *ctx)
{
return sha1_final(&ctx->u.sw_sha1);
}
static const uint8_t *sha1_hash(const uint8_t *data, uint32_t len,
uint8_t *digest)
{
SHA1_CTX ctx;
sw_sha1_init(&ctx);
sw_sha1_update(&ctx, data, len);
memcpy(digest, sw_sha1_final(&ctx), SHA1_DIGEST_BYTES);
return digest;
}
#include "cryptoc/sha.h"
static void dcrypto_sha1_init(SHA_CTX *ctx);
static const uint8_t *dcrypto_sha1_final(SHA_CTX *unused);
/*
* Hardware SHA implementation.
*/
static const struct HASH_VTAB HW_SHA1_VTAB = {
static const HASH_VTAB HW_SHA1_VTAB = {
dcrypto_sha1_init,
dcrypto_sha_update,
dcrypto_sha1_final,
DCRYPTO_SHA1_hash,
SHA1_DIGEST_BYTES
SHA_DIGEST_SIZE
};
/* Requires dcrypto_grab_sha_hw() to be called first. */
static void dcrypto_sha1_init(SHA_CTX *ctx)
{
ctx->f = &HW_SHA1_VTAB;
dcrypto_sha_init(SHA1_MODE);
}
/* Select and initialize either the software or hardware
* implementation. If "multi-threaded" behaviour is required, then
* callers must set sw_required to 1. This is because SHA1 state
@@ -69,30 +39,27 @@ static const struct HASH_VTAB HW_SHA1_VTAB = {
* If the caller has no preference as to implementation, then hardware
* is preferred based on availability. Hardware is considered to be
* in use between init() and finished() calls. */
void DCRYPTO_SHA1_init(SHA1_CTX *ctx, uint32_t sw_required)
void DCRYPTO_SHA1_init(SHA_CTX *ctx, uint32_t sw_required)
{
if (!sw_required && dcrypto_grab_sha_hw()) {
ctx->vtab = &HW_SHA1_VTAB;
dcrypto_sha_init(SHA1_MODE);
} else {
sw_sha1_init(ctx);
}
if (!sw_required && dcrypto_grab_sha_hw())
dcrypto_sha1_init(ctx);
else
SHA_init(ctx);
}
static const uint8_t *dcrypto_sha1_final(SHA1_CTX *ctx)
static const uint8_t *dcrypto_sha1_final(SHA_CTX *ctx)
{
dcrypto_sha_wait(SHA1_MODE, (uint32_t *) ctx->u.buf);
return ctx->u.buf;
dcrypto_sha_wait(SHA1_MODE, (uint32_t *) ctx->buf);
return ctx->buf;
}
const uint8_t *DCRYPTO_SHA1_hash(const uint8_t *data, uint32_t n,
const uint8_t *DCRYPTO_SHA1_hash(const void *data, uint32_t n,
uint8_t *digest)
{
if (dcrypto_grab_sha_hw())
/* dcrypto_sha_wait() will release the hw. */
dcrypto_sha_hash(SHA1_MODE, data, n, digest);
else
sha1_hash(data, n, digest);
SHA_hash(data, n, digest);
return digest;
}

View File

@@ -8,7 +8,10 @@
#include "registers.h"
#include "util.h"
static const uint8_t *dcrypto_sha256_final(SHA256_CTX *ctx);
#include "cryptoc/sha256.h"
static void dcrypto_sha256_init(LITE_SHA256_CTX *ctx);
static const uint8_t *dcrypto_sha256_final(LITE_SHA256_CTX *ctx);
#ifdef SECTION_IS_RO
/* RO is single threaded. */
@@ -25,46 +28,6 @@ static inline void dcrypto_release_sha_hw(void)
#include "task.h"
static struct mutex hw_busy_mutex;
static void sha256_init(SHA256_CTX *ctx);
static void sha256_update(SHA256_CTX *ctx, const uint8_t *data, uint32_t len);
static const uint8_t *sha256_final(SHA256_CTX *ctx);
static const uint8_t *sha256_hash(const uint8_t *data, uint32_t len,
uint8_t *digest);
static const struct HASH_VTAB SW_SHA256_VTAB = {
sha256_update,
sha256_final,
sha256_hash,
SHA256_DIGEST_BYTES
};
static void sha256_init(SHA256_CTX *ctx)
{
ctx->vtab = &SW_SHA256_VTAB;
SHA256_init(&ctx->u.sw_sha256);
}
static void sha256_update(SHA256_CTX *ctx, const uint8_t *data, uint32_t len)
{
SHA256_update(&ctx->u.sw_sha256, data, len);
}
static const uint8_t *sha256_final(SHA256_CTX *ctx)
{
return SHA256_final(&ctx->u.sw_sha256);
}
static const uint8_t *sha256_hash(const uint8_t *data, uint32_t len,
uint8_t *digest)
{
SHA256_CTX ctx;
sha256_init(&ctx);
sha256_update(&ctx, data, len);
memcpy(digest, sha256_final(&ctx), SHA256_DIGEST_BYTES);
return digest;
}
static int hw_busy;
int dcrypto_grab_sha_hw(void)
@@ -94,8 +57,8 @@ void dcrypto_sha_wait(enum sha_mode mode, uint32_t *digest)
{
int i;
const int digest_len = (mode == SHA1_MODE) ?
SHA1_DIGEST_BYTES :
SHA256_DIGEST_BYTES;
SHA_DIGEST_SIZE :
SHA256_DIGEST_SIZE;
/* Stop LIVESTREAM mode. */
GWRITE_FIELD(KEYMGR, SHA_TRIG, TRIG_STOP, 1);
@@ -110,11 +73,12 @@ void dcrypto_sha_wait(enum sha_mode mode, uint32_t *digest)
}
/* Hardware SHA implementation. */
static const struct HASH_VTAB HW_SHA256_VTAB = {
static const HASH_VTAB HW_SHA256_VTAB = {
dcrypto_sha256_init,
dcrypto_sha_update,
dcrypto_sha256_final,
DCRYPTO_SHA256_hash,
SHA256_DIGEST_BYTES
SHA256_DIGEST_SIZE
};
void dcrypto_sha_hash(enum sha_mode mode, const uint8_t *data, uint32_t n,
@@ -126,7 +90,7 @@ void dcrypto_sha_hash(enum sha_mode mode, const uint8_t *data, uint32_t n,
}
void dcrypto_sha_update(struct HASH_CTX *unused,
const uint8_t *data, uint32_t n)
const void *data, uint32_t n)
{
const uint8_t *bp = (const uint8_t *) data;
const uint32_t *wp;
@@ -180,25 +144,30 @@ void dcrypto_sha_init(enum sha_mode mode)
GWRITE_FIELD(KEYMGR, SHA_TRIG, TRIG_GO, 1);
}
void DCRYPTO_SHA256_init(SHA256_CTX *ctx, uint32_t sw_required)
static void dcrypto_sha256_init(LITE_SHA256_CTX *ctx)
{
if (!sw_required && dcrypto_grab_sha_hw()) {
ctx->vtab = &HW_SHA256_VTAB;
dcrypto_sha_init(SHA256_MODE);
}
ctx->f = &HW_SHA256_VTAB;
dcrypto_sha_init(SHA256_MODE);
}
/* Requires dcrypto_grab_sha_hw() to be called first. */
void DCRYPTO_SHA256_init(LITE_SHA256_CTX *ctx, uint32_t sw_required)
{
if (!sw_required && dcrypto_grab_sha_hw())
dcrypto_sha256_init(ctx);
#ifndef SECTION_IS_RO
else
sha256_init(ctx);
SHA256_init(ctx);
#endif
}
static const uint8_t *dcrypto_sha256_final(SHA256_CTX *ctx)
static const uint8_t *dcrypto_sha256_final(LITE_SHA256_CTX *ctx)
{
dcrypto_sha_wait(SHA256_MODE, (uint32_t *) ctx->u.buf);
return ctx->u.buf;
dcrypto_sha_wait(SHA256_MODE, (uint32_t *) ctx->buf);
return ctx->buf;
}
const uint8_t *DCRYPTO_SHA256_hash(const uint8_t *data, uint32_t n,
const uint8_t *DCRYPTO_SHA256_hash(const void *data, uint32_t n,
uint8_t *digest)
{
if (dcrypto_grab_sha_hw())
@@ -206,7 +175,7 @@ const uint8_t *DCRYPTO_SHA256_hash(const uint8_t *data, uint32_t n,
dcrypto_sha_hash(SHA256_MODE, data, n, digest);
#ifndef SECTION_IS_RO
else
sha256_hash(data, n, digest);
SHA256_hash(data, n, digest);
#endif
return digest;
}

View File

@@ -11,9 +11,10 @@
#include "hooks.h"
#include "include/compile_time_macros.h"
#include "memory.h"
#include "sha1.h"
#include "uart.h"
#include "cryptoc/sha.h"
#define CPRINTF(format, args...) cprintf(CC_EXTENSION, format, ## args)
/* Various upgrade extension command return values. */
@@ -91,7 +92,7 @@ void fw_upgrade_command_handler(void *body,
{
struct upgrade_command *cmd_body = body;
uint8_t *rv = body;
uint8_t sha1_digest[SHA1_DIGEST_SIZE];
uint8_t sha1_digest[SHA_DIGEST_SIZE];
size_t body_size;
uint32_t block_offset;

View File

@@ -1566,8 +1566,6 @@
/* Support computing of other hash sizes (without the VBOOT code) */
#undef CONFIG_SHA256
#undef CONFIG_SHA384
#undef CONFIG_SHA512
/* Emulate the CLZ (Count Leading Zeros) in software for CPU lacking support */
#undef CONFIG_SOFTWARE_CLZ