/* Copyright 2021 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 "dcrypto.h"
#include "fips.h"
#include "internal.h"
#include "dcrypto_regs.h"

/**
 * Define KEYMGR SHA/HMAC access structure.
 */
static volatile struct keymgr_sha *reg_keymgr_sha =
	(void *)(GC_KEYMGR_BASE_ADDR + GC_KEYMGR_SHA_CFG_MSGLEN_LO_OFFSET);

#ifdef SECTION_IS_RO
/* RO is single threaded. */
#define mutex_lock(x)
#define mutex_unlock(x)
static inline int dcrypto_grab_sha_hw(void)
{
	return 1;
}
static inline void dcrypto_release_sha_hw(void)
{
}
#else
#include "task.h"
static struct mutex hw_busy_mutex;

static bool hw_busy;

int dcrypto_grab_sha_hw(void)
{
	int rv = 0;

	fips_vtable->mutex_lock(&hw_busy_mutex);
	if (!hw_busy) {
		rv = 1;
		hw_busy = true;
	}
	fips_vtable->mutex_unlock(&hw_busy_mutex);

	return rv;
}

void dcrypto_release_sha_hw(void)
{
	fips_vtable->mutex_lock(&hw_busy_mutex);
	hw_busy = false;
	fips_vtable->mutex_unlock(&hw_busy_mutex);
}

#endif /* ! SECTION_IS_RO */

/* Stall frequency for SHA/HMAC engine. */
enum keymgr_stall_freq {
	KEYMGR_STALL_FREQ_50 = 0,
	KEYMGR_STALL_FREQ_25 = 1,
	KEYMGR_STALL_FREQ_12 = 2,
	KEYMGR_STALL_FREQ_6 = 3,
};

#define KEYMGR_STALL(freq)                            \
	(GC_KEYMGR_SHA_RAND_STALL_CTL_STALL_EN_MASK | \
	 (freq << GC_KEYMGR_SHA_RAND_STALL_CTL_FREQ_LSB))

/* Ready to use settings for SHA_RAND_STALL_CTL register. */
enum keymgr_stall_cfg {
	KEYMGR_STALL_DISABLED = 0,
	KEYMGR_STALL_50 = KEYMGR_STALL(KEYMGR_STALL_FREQ_50),
	KEYMGR_STALL_25 = KEYMGR_STALL(KEYMGR_STALL_FREQ_25),
	KEYMGR_STALL_12 = KEYMGR_STALL(KEYMGR_STALL_FREQ_12),
	KEYMGR_STALL_6 = KEYMGR_STALL(KEYMGR_STALL_FREQ_6)
};

/* Ready to use configuration of KEYMGR SHA engine. */
enum sha_cfg {
	MODE_SHA256_LIVESTREAM = (GC_KEYMGR_SHA_CFG_EN_LIVESTREAM_MASK |
				  GC_KEYMGR_SHA_CFG_EN_INT_EN_DONE_MASK),

	MODE_SHA1_LIVESTREAM = (GC_KEYMGR_SHA_CFG_EN_LIVESTREAM_MASK |
				GC_KEYMGR_SHA_CFG_EN_INT_EN_DONE_MASK |
				GC_KEYMGR_SHA_CFG_EN_SHA1_MASK),

	MODE_SHA256_ONESHOT = (GC_KEYMGR_SHA_CFG_EN_INT_EN_DONE_MASK),

	MODE_SHA1_ONESHOT = (GC_KEYMGR_SHA_CFG_EN_INT_EN_DONE_MASK |
			     GC_KEYMGR_SHA_CFG_EN_SHA1_MASK),

	MODE_HMAC_SHA256_LIVESTREAM = (GC_KEYMGR_SHA_CFG_EN_LIVESTREAM_MASK |
				       GC_KEYMGR_SHA_CFG_EN_INT_EN_DONE_MASK |
				       GC_KEYMGR_SHA_CFG_EN_HMAC_MASK)
};

static void dcrypto_sha_wait(uint32_t *digest, size_t digest_words)
{
	/* Stop LIVESTREAM mode (if active). */
	reg_keymgr_sha->trig = GC_KEYMGR_SHA_TRIG_TRIG_STOP_MASK;

	/* Wait for SHA DONE interrupt. */
	while (!reg_keymgr_sha->itop)
		;

	/**
	 * Read out final digest. Note, we unroll loop for
	 * 2 cases - SHA1 and SHA256, defaulting to SHA1 to remove
	 * extra check. This function is only called with
	 * SHA256_DIGEST_WORDS or SHA1_DIGEST_WORDS. Such unrolling
	 * is cheap, as each read/write instruction is just 2 bytes.
	 */
	switch (digest_words) {
	case SHA256_DIGEST_WORDS:
		digest[5] = reg_keymgr_sha->h[5];
		digest[6] = reg_keymgr_sha->h[6];
		digest[7] = reg_keymgr_sha->h[7];
		/* Fall through */
	default: /* SHA1_DIGEST_WORDS */
		digest[0] = reg_keymgr_sha->h[0];
		digest[1] = reg_keymgr_sha->h[1];
		digest[2] = reg_keymgr_sha->h[2];
		digest[3] = reg_keymgr_sha->h[3];
		digest[4] = reg_keymgr_sha->h[4];
	}

	/* Clear interrupt status. */
	reg_keymgr_sha->itop = 0;

	/* Destroy any leftovers in SHA engine. */
	reg_keymgr_sha->trig = GC_KEYMGR_SHA_TRIG_TRIG_RESET_MASK;
}

/* Wrapper for HW SHA/HMAC to match vtable function signature. */
static void dcrypto_sha_update(union hash_ctx *unused, const void *data,
			       size_t n)
{
	dcrypto_sha_fifo_load(data, n);
}

void dcrypto_sha_fifo_load(const void *data, size_t n)
{
	const uint8_t *bp = (const uint8_t *)data;
	const uint8_t *bp_end = bp + n;
	const uint32_t *wp_end = (uint32_t *)((uintptr_t)bp_end & ~WORD_MASK);
	const uint32_t *wp;

	/* Feed unaligned start bytes. */
	while (is_not_aligned(bp) && bp < bp_end)
		reg_keymgr_sha->fifo_u8 = *bp++;

	wp = (uint32_t *)bp;

	/* Feed groups of aligned words. */
	while (wp + 4 < wp_end) {
		reg_keymgr_sha->fifo_u32 = *wp++;
		reg_keymgr_sha->fifo_u32 = *wp++;
		reg_keymgr_sha->fifo_u32 = *wp++;
		reg_keymgr_sha->fifo_u32 = *wp++;
	}

	/* Feed individual aligned words. */
	while (wp < wp_end)
		reg_keymgr_sha->fifo_u32 = *wp++;

	/* Feed remaining bytes. */
	bp = (uint8_t *)wp;
	while (bp < bp_end)
		reg_keymgr_sha->fifo_u8 = *bp++;
}

static void dcrypto_load_hmac_key(uint32_t *hmac_key)
{
	volatile uint32_t *reg_key = reg_keymgr_sha->key;

	/* Set that we want key from KEY_W0..W7. */
	reg_keymgr_sha->use_hidden_key = 0;
	reg_keymgr_sha->use_cert = 0;

	/* Only SHA2-256 is supported for HMAC. */
	for (size_t i = 0; i < SHA256_DIGEST_WORDS; ++i)
		*reg_key++ = *hmac_key++;
}

/**
 * Program SHA/HMAC in specified mode and set random stalls to
 * harden against side-channel attacks.
 *
 * @param mode SHA/HMAC operation mode
 * @param stall configured random stalls
 * @param len length of message for one-shot mode (ignored in livestream)
 */
static void dcrypto_sha_init(enum sha_cfg mode, enum keymgr_stall_cfg stall,
			     size_t len)
{
	/* Clear interrupt status. */
	reg_keymgr_sha->itop = 0;

	/* Reset logic. */
	reg_keymgr_sha->trig = GC_KEYMGR_SHA_TRIG_TRIG_RESET_MASK;

	/* Load data length, ignored in livestream mode. */
	reg_keymgr_sha->msglen_lo = len;
	reg_keymgr_sha->msglen_hi = 0;

	/* Turn off random nops (which are enabled by default) to reprogram. */
	reg_keymgr_sha->rand_stall = 0;

	/* Configure and enable random nop percentage. */
	reg_keymgr_sha->rand_stall = stall;

	reg_keymgr_sha->cfg_en = mode;

	/* Start SHA engine. */
	reg_keymgr_sha->trig = GC_KEYMGR_SHA_TRIG_TRIG_GO_MASK;
}

static const struct sha1_digest *dcrypto_sha1_final(union hash_ctx *ctx)
{
	dcrypto_sha_wait(ctx->sha1.digest.b32, SHA1_DIGEST_WORDS);
	dcrypto_release_sha_hw();
	return &ctx->sha1.digest;
}

static const struct sha256_digest *dcrypto_sha256_final(union hash_ctx *ctx)
{
	dcrypto_sha_wait(ctx->sha256.digest.b32, SHA256_DIGEST_WORDS);
	dcrypto_release_sha_hw();
	return &ctx->sha256.digest;
}

static const union sha_digests *dcrypto_sha256_final_as_hash(
	union hash_ctx *const ctx) __alias(dcrypto_sha256_final);

static const union sha_digests *dcrypto_sha1_final_as_hash(
	union hash_ctx *const ctx) __alias(dcrypto_sha1_final);

static const union sha_digests *dcrypto_hmac_final(union hmac_ctx *const ctx)
{
	size_t i;

	dcrypto_sha_wait(ctx->hmac_sha256.hash.digest.b32, SHA256_DIGEST_WORDS);
	/* Destroy loaded key after use. */
	for (i = 0; i < SHA256_DIGEST_WORDS; ++i)
		reg_keymgr_sha->key[i] = 0;
	dcrypto_release_sha_hw();
	return (union sha_digests *)&ctx->hmac_sha256.hash.digest;
}

/* Requires dcrypto_grab_sha_hw() to be called first. */
static void dcrypto_sha1_init(union hash_ctx *ctx)
{
	static const struct hash_vtable hw_sha1_vtab = {
		dcrypto_sha1_init,	    dcrypto_sha_update,
		dcrypto_sha1_final_as_hash, HMAC_sw_final,
		SHA1_DIGEST_SIZE,	    SHA1_BLOCK_SIZE,
		sizeof(struct sha1_ctx)
	};

	ctx->f = &hw_sha1_vtab;
	dcrypto_sha_init(MODE_SHA1_LIVESTREAM, KEYMGR_STALL_6, 0);
}

static void dcrypto_sha256_init(union hash_ctx *ctx)
{
	/* Hardware SHA implementation. */
	static const struct hash_vtable HW_SHA256_VTAB = {
		dcrypto_sha256_init,	      dcrypto_sha_update,
		dcrypto_sha256_final_as_hash, HMAC_sw_final,
		SHA256_DIGEST_SIZE,	      SHA256_BLOCK_SIZE,
		sizeof(struct sha256_ctx)
	};

	ctx->f = &HW_SHA256_VTAB;
	dcrypto_sha_init(MODE_SHA256_LIVESTREAM, KEYMGR_STALL_6, 0);
}

/**
 * Select and initialize either the software or hardware
 * implementation.  If "multi-threaded" behaviour is required, then
 * callers must specifically use software version SHA1_sw_init(). This
 * is because SHA1 state internal to the hardware cannot be extracted, so
 * it is not possible to suspend and resume a hardware based SHA operation.
 *
 * Hardware implementation is selected based on availability. Hardware is
 * considered to be in use between init() and finished() calls. If hardware
 * is not available, fall back to software implementation.
 */
void SHA1_hw_init(struct sha1_ctx *ctx)
{
	if (dcrypto_grab_sha_hw())
		dcrypto_sha1_init((union hash_ctx *)ctx);
	else
		SHA1_sw_init(ctx);
}

/**
 * Select and initialize either the software or hardware
 * implementation.  If "multi-threaded" behaviour is required, then
 * callers must specifically use software version SHA256_sw_init(). This
 * is because SHA256 state internal to the hardware cannot be extracted, so
 * it is not possible to suspend and resume a hardware based SHA operation.
 *
 * Hardware implementation is selected based on availability. Hardware is
 * considered to be in use between init() and finished() calls. If hardware
 * is not available, fall back to software implementation.
 */
void SHA256_hw_init(struct sha256_ctx *ctx)
{
	if (dcrypto_grab_sha_hw())
		dcrypto_sha256_init((union hash_ctx *)ctx);
	else
		SHA256_sw_init(ctx);
}

/* SHA1/256/HMAC SHA256 one-shot mode primitive. */
static void dcrypto_sha_oneshot(enum sha_cfg mode, const void *data, size_t n,
				uint32_t *digest, size_t digest_words)
{
	/**
	 * Load message length in one-shot mode. This way engine can start
	 * processing data blocks earlier than in livestream mode.
	 */
	if (n != 0) { /* One-shot only works for non-empty data. */
		dcrypto_sha_init(mode, KEYMGR_STALL_6, n);

		dcrypto_sha_fifo_load(data, n);
	} else /* Due to bug in SHA engine, force livestream for this case. */
		dcrypto_sha_init(mode | GC_KEYMGR_SHA_CFG_EN_LIVESTREAM_MASK,
				 KEYMGR_STALL_6, 0);
	dcrypto_sha_wait(digest, digest_words);
}

const struct sha1_digest *SHA1_hw_hash(const void *data, size_t n,
				       struct sha1_digest *digest)
{
	if (dcrypto_grab_sha_hw()) {
		dcrypto_sha_oneshot(MODE_SHA1_ONESHOT, data, n, digest->b32,
				    SHA1_DIGEST_WORDS);
		dcrypto_release_sha_hw();
	} else
		SHA1_sw_hash(data, n, digest);
	return digest;
}

const struct sha256_digest *SHA256_hw_hash(const void *data, size_t n,
					   struct sha256_digest *digest)
{
	if (dcrypto_grab_sha_hw()) {
		dcrypto_sha_oneshot(MODE_SHA256_ONESHOT, data, n, digest->b32,
				    SHA256_DIGEST_WORDS);
		dcrypto_release_sha_hw();
	} else
		SHA256_sw_hash(data, n, digest);
	return digest;
}

const struct sha256_digest *HMAC_SHA256_hw_final(struct hmac_sha256_ctx *ctx)
{
	return HMAC_SHA256_final(ctx);
}

void HMAC_SHA256_hw_init(struct hmac_sha256_ctx *ctx, const void *key,
			 size_t len)
{
	/* VTable for Hardware HMAC implementation. */
	static const struct hash_vtable HW_HMAC_SHA256_VTAB = {
		dcrypto_sha256_init,	      dcrypto_sha_update,
		dcrypto_sha256_final_as_hash, dcrypto_hmac_final,
		SHA256_DIGEST_SIZE,	      SHA256_BLOCK_SIZE,
		sizeof(struct sha256_ctx)
	};

	struct sha256_digest padded_key;

	/**
	 * HW HMAC only supports key length <= 256 bits. However,
	 * large keys are hashed back to 256 bits.
	 */
	if ((len > SHA256_DIGEST_SIZE) && (len <= SHA256_BLOCK_SIZE)) {
		/* Try a hybrid path with HW SHA2 and software HMAC. */
		SHA256_hw_init(&ctx->hash);
		HMAC_sw_init((union hmac_ctx *)ctx, key, len);
		return;
	}

	if (!dcrypto_grab_sha_hw()) {
		/* Fallback to software path. */
		SHA256_sw_init(&ctx->hash);
		HMAC_sw_init((union hmac_ctx *)ctx, key, len);
		return;
	}

	if (len > SHA256_BLOCK_SIZE) {
		/* For long keys make key 256 bit. */
		dcrypto_sha_oneshot(MODE_SHA256_ONESHOT, key, len,
				    padded_key.b32, SHA256_DIGEST_WORDS);
	} else {
		/**
		 * len <= SHA256_DIGEST_SIZE, so zero pad HMAC key
		 * before sending to HW.
		 */
		memset(padded_key.b32, 0, sizeof(padded_key));
		memcpy(padded_key.b32, key, len);
	}

	ctx->hash.f = &HW_HMAC_SHA256_VTAB;

	dcrypto_load_hmac_key(padded_key.b32);
	dcrypto_sha_init(MODE_HMAC_SHA256_LIVESTREAM, KEYMGR_STALL_25, 0);

	always_memset(padded_key.b32, 0, sizeof(padded_key));
}

#ifdef CRYPTO_TEST_SETUP
/**
 * To use hmac command for testing, set one or many configuration variables:
 * SHA1_TEST - SHA1 test vectors
 * SHA256_TEST - SHA2 test vectors
 * HMAC_SHA256_TEST - HMAC SHA256 test vectors.
 *
 * It will test all software and hardware implementations available.
 */
#include "console.h"
#include "common.h"
#include "endian.h"

#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args)

struct hash_test {
	size_t len;
	uint8_t *c;
	uint8_t *d;
};

struct hmac_test {
	size_t klen;
	uint8_t *k;
	size_t len;
	uint8_t *c;
	uint8_t *d;
};

union kdata32 {
	uint8_t bytes[32];
	uint32_t words[8];
};

#ifndef SHA1_TEST
#define SHA1_TEST 0
#endif

#ifndef SHA256_TEST
#define SHA256_TEST 0
#endif

#ifndef HMAC_SHA256_TEST
#define HMAC_SHA256_TEST 0
#endif

#if SHA1_TEST || SHA256_TEST || HMAC_SHA256_TEST
static const char *smemcmp(const void *a, const void *b, size_t len)
{
	return (memcmp(a, b, len) == 0) ? "passed" : "NOT passed!";
}
#endif

#if SHA1_TEST
static int cmd_sha1_test(int argc, char *argv[])
{
	/**
	 * Test vectors for SHA1, SHA256 from
	 * https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/secure-hashing
	 */
	const struct hash_test sha1_v[] = {
		{ .len = 0,
		  .c = (uint8_t[]){},
		  .d = (uint8_t[]){ 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b,
				    0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60,
				    0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09 } },
		{ .len = 1,
		  .c = (uint8_t[]){ 0x36 },
		  .d = (uint8_t[]){ 0xc1, 0xdf, 0xd9, 0x6e, 0xea, 0x8c, 0xc2,
				    0xb6, 0x27, 0x85, 0x27, 0x5b, 0xca, 0x38,
				    0xac, 0x26, 0x12, 0x56, 0xe2, 0x78 } },
		{ .len = 12,
		  .c = (uint8_t[]){ 0x09, 0x38, 0xf2, 0xe2, 0xeb, 0xb6, 0x4f,
				    0x8a, 0xf8, 0xbb, 0xfc, 0x91 },
		  .d = (uint8_t[]){ 0x9f, 0x4e, 0x66, 0xb6, 0xce, 0xea, 0x40,
				    0xdc, 0xf4, 0xb9, 0x16, 0x6c, 0x28, 0xf1,
				    0xc8, 0x84, 0x74, 0x14, 0x1d, 0xa9 } },
		{ .len = 20,
		  .c = (uint8_t[]){ 0x63, 0xa3, 0xcc, 0x83, 0xfd, 0x1e, 0xc1,
				    0xb6, 0x68, 0x0e, 0x99, 0x74, 0xa0, 0x51,
				    0x4e, 0x1a, 0x9e, 0xce, 0xbb, 0x6a },
		  .d = (uint8_t[]){ 0x8b, 0xb8, 0xc0, 0xd8, 0x15, 0xa9, 0xc6,
				    0x8a, 0x1d, 0x29, 0x10, 0xf3, 0x9d, 0x94,
				    0x26, 0x03, 0xd8, 0x07, 0xfb, 0xcc } },
		{ .len = 32,
		  .c = (uint8_t[]){ 0x03, 0x21, 0x79, 0x4b, 0x73, 0x94, 0x18,
				    0xc2, 0x4e, 0x7c, 0x2e, 0x56, 0x52, 0x74,
				    0x79, 0x1c, 0x4b, 0xe7, 0x49, 0x75, 0x2a,
				    0xd2, 0x34, 0xed, 0x56, 0xcb, 0x0a, 0x63,
				    0x47, 0x43, 0x0c, 0x6b },
		  .d = (uint8_t[]){ 0xb8, 0x99, 0x62, 0xc9, 0x4d, 0x60, 0xf6,
				    0xa3, 0x32, 0xfd, 0x60, 0xf6, 0xf0, 0x7d,
				    0x4f, 0x03, 0x2a, 0x58, 0x6b, 0x76 } },
		{ .len = 48,
		  .c = (uint8_t[]){ 0x57, 0xe8, 0x96, 0x59, 0xd8, 0x78, 0xf3,
				    0x60, 0xaf, 0x6d, 0xe4, 0x5a, 0x9a, 0x5e,
				    0x37, 0x2e, 0xf4, 0x0c, 0x38, 0x49, 0x88,
				    0xe8, 0x26, 0x40, 0xa3, 0xd5, 0xe4, 0xb7,
				    0x6d, 0x2e, 0xf1, 0x81, 0x78, 0x0b, 0x9a,
				    0x09, 0x9a, 0xc0, 0x6e, 0xf0, 0xf8, 0xa7,
				    0xf3, 0xf7, 0x64, 0x20, 0x97, 0x20 },
		  .d = (uint8_t[]){ 0xf6, 0x52, 0xf3, 0xb1, 0x54, 0x9f, 0x16,
				    0x71, 0x0c, 0x74, 0x02, 0x89, 0x59, 0x11,
				    0xe2, 0xb8, 0x6a, 0x9b, 0x2a, 0xee } },
		{ .len = 55,
		  .c = (uint8_t[]){ 0xec, 0x6b, 0x4a, 0x88, 0x71, 0x3d, 0xf2,
				    0x7c, 0x0f, 0x2d, 0x02, 0xe7, 0x38, 0xb6,
				    0x9d, 0xb4, 0x3a, 0xbd, 0xa3, 0x92, 0x13,
				    0x17, 0x25, 0x9c, 0x86, 0x4c, 0x1c, 0x38,
				    0x6e, 0x9a, 0x5a, 0x3f, 0x53, 0x3d, 0xc0,
				    0x5f, 0x3b, 0xee, 0xb2, 0xbe, 0xc2, 0xaa,
				    0xc8, 0xe0, 0x6d, 0xb4, 0xc6, 0xcb, 0x3c,
				    0xdd, 0xcf, 0x69, 0x7e, 0x03, 0xd5 },
		  .d = (uint8_t[]){ 0xa7, 0x27, 0x2e, 0x23, 0x08, 0x62, 0x2f,
				    0xf7, 0xa3, 0x39, 0x46, 0x0a, 0xdc, 0x61,
				    0xef, 0xd0, 0xea, 0x8d, 0xab, 0xdc } },
		{ .len = 56,
		  .c = (uint8_t[]){ 0x03, 0x21, 0x73, 0x6b, 0xeb, 0xa5, 0x78,
				    0xe9, 0x0a, 0xbc, 0x1a, 0x90, 0xaa, 0x56,
				    0x15, 0x7d, 0x87, 0x16, 0x18, 0xf6, 0xde,
				    0x0d, 0x76, 0x4c, 0xc8, 0xc9, 0x1e, 0x06,
				    0xc6, 0x8e, 0xcd, 0x3b, 0x9d, 0xe3, 0x82,
				    0x40, 0x64, 0x50, 0x33, 0x84, 0xdb, 0x67,
				    0xbe, 0xb7, 0xfe, 0x01, 0x22, 0x32, 0xda,
				    0xca, 0xef, 0x93, 0xa0, 0x00, 0xfb, 0xa7 },
		  .d = (uint8_t[]){ 0xae, 0xf8, 0x43, 0xb8, 0x69, 0x16, 0xc1,
				    0x6f, 0x66, 0xc8, 0x4d, 0x83, 0xa6, 0x00,
				    0x5d, 0x23, 0xfd, 0x00, 0x5c, 0x9e } },
		{ .len = 163,
		  .c = (uint8_t[]){ 0x7c, 0x9c, 0x67, 0x32, 0x3a, 0x1d, 0xf1,
				    0xad, 0xbf, 0xe5, 0xce, 0xb4, 0x15, 0xea,
				    0xef, 0x01, 0x55, 0xec, 0xe2, 0x82, 0x0f,
				    0x4d, 0x50, 0xc1, 0xec, 0x22, 0xcb, 0xa4,
				    0x92, 0x8a, 0xc6, 0x56, 0xc8, 0x3f, 0xe5,
				    0x85, 0xdb, 0x6a, 0x78, 0xce, 0x40, 0xbc,
				    0x42, 0x75, 0x7a, 0xba, 0x7e, 0x5a, 0x3f,
				    0x58, 0x24, 0x28, 0xd6, 0xca, 0x68, 0xd0,
				    0xc3, 0x97, 0x83, 0x36, 0xa6, 0xef, 0xb7,
				    0x29, 0x61, 0x3e, 0x8d, 0x99, 0x79, 0x01,
				    0x62, 0x04, 0xbf, 0xd9, 0x21, 0x32, 0x2f,
				    0xdd, 0x52, 0x22, 0x18, 0x35, 0x54, 0x44,
				    0x7d, 0xe5, 0xe6, 0xe9, 0xbb, 0xe6, 0xed,
				    0xf7, 0x6d, 0x7b, 0x71, 0xe1, 0x8d, 0xc2,
				    0xe8, 0xd6, 0xdc, 0x89, 0xb7, 0x39, 0x83,
				    0x64, 0xf6, 0x52, 0xfa, 0xfc, 0x73, 0x43,
				    0x29, 0xaa, 0xfa, 0x3d, 0xcd, 0x45, 0xd4,
				    0xf3, 0x1e, 0x38, 0x8e, 0x4f, 0xaf, 0xd7,
				    0xfc, 0x64, 0x95, 0xf3, 0x7c, 0xa5, 0xcb,
				    0xab, 0x7f, 0x54, 0xd5, 0x86, 0x46, 0x3d,
				    0xa4, 0xbf, 0xea, 0xa3, 0xba, 0xe0, 0x9f,
				    0x7b, 0x8e, 0x92, 0x39, 0xd8, 0x32, 0xb4,
				    0xf0, 0xa7, 0x33, 0xaa, 0x60, 0x9c, 0xc1,
				    0xf8, 0xd4 },
		  .d = (uint8_t[]){ 0xd8, 0xfd, 0x6a, 0x91, 0xef, 0x3b, 0x6c,
				    0xed, 0x05, 0xb9, 0x83, 0x58, 0xa9, 0x91,
				    0x07, 0xc1, 0xfa, 0xc8, 0xc8, 0x07 } }
	};
	for (size_t i = 0; i < ARRAY_SIZE(sha1_v); i++) {
		struct sha1_digest sha1;
		struct sha1_ctx ctx;

		memset(&sha1, 0, sizeof(sha1));
		SHA1_sw_hash(sha1_v[i].c, sha1_v[i].len, &sha1);

		CPRINTS("SHA1_sw_hash test %zu, len=%zu, %s", i, sha1_v[i].len,
			smemcmp(sha1.b8, sha1_v[i].d, SHA1_DIGEST_SIZE));

		memset(&sha1, 0, sizeof(sha1));
		SHA1_hw_hash(sha1_v[i].c, sha1_v[i].len, &sha1);
		CPRINTS("SHA1_hw_hash test %zu, len=%zu, %s", i, sha1_v[i].len,
			smemcmp(sha1.b8, sha1_v[i].d, SHA1_DIGEST_SIZE));

		SHA1_hw_init(&ctx);
		SHA1_update(&ctx, sha1_v[i].c, sha1_v[i].len);
		CPRINTS("SHA1_hw_init test %zu, len=%zu, %s", i, sha1_v[i].len,
			smemcmp(SHA1_final(&ctx)->b8, sha1_v[i].d,
				SHA1_DIGEST_SIZE));
		cflush();
	}
	return EC_SUCCESS;
}
DECLARE_SAFE_CONSOLE_COMMAND(sha1_test, cmd_sha1_test, NULL, NULL);
#endif

#if SHA256_TEST
static int cmd_sha256_test(int argc, char *argv[])
{
	/**
	 * Test vectors for SHA1, SHA256 from
	 * https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/secure-hashing
	 */

	const struct hash_test sha256_v[] = {
		{ .len = 0,
		  .c = (uint8_t[]){},
		  .d = (uint8_t[]){ 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c,
				    0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f,
				    0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64,
				    0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b,
				    0x78, 0x52, 0xb8, 0x55 } },
		{ .len = 1,
		  .c = (uint8_t[]){ 0xd3 },
		  .d = (uint8_t[]){ 0x28, 0x96, 0x9c, 0xdf, 0xa7, 0x4a, 0x12,
				    0xc8, 0x2f, 0x3b, 0xad, 0x96, 0x0b, 0x0b,
				    0x00, 0x0a, 0xca, 0x2a, 0xc3, 0x29, 0xde,
				    0xea, 0x5c, 0x23, 0x28, 0xeb, 0xc6, 0xf2,
				    0xba, 0x98, 0x02, 0xc1 } },
		{ .len = 5,
		  .c = (uint8_t[]){ 0xc2, 0x99, 0x20, 0x96, 0x82 },
		  .d = (uint8_t[]){ 0xf0, 0x88, 0x7f, 0xe9, 0x61, 0xc9, 0xcd,
				    0x3b, 0xea, 0xb9, 0x57, 0xe8, 0x22, 0x24,
				    0x94, 0xab, 0xb9, 0x69, 0xb1, 0xce, 0x4c,
				    0x65, 0x57, 0x97, 0x6d, 0xf8, 0xb0, 0xf6,
				    0xd2, 0x0e, 0x91, 0x66 } },
		{ .len = 10,
		  .c = (uint8_t[]){ 0x65, 0x74, 0x61, 0x6f, 0x6e, 0x72, 0x69,
				    0x73, 0x68, 0x64 },
		  .d = (uint8_t[]){ 0xf5, 0x53, 0xcd, 0xb8, 0xcf, 0x1,	0xee,
				    0x17, 0x9b, 0x93, 0xc9, 0x68, 0xc0, 0xea,
				    0x40, 0x91, 0x6,  0xec, 0x8e, 0x11, 0x96,
				    0xc8, 0x5d, 0x1c, 0xaf, 0x64, 0x22, 0xe6,
				    0x50, 0x4f, 0x47, 0x57 } },
		{ .len = 12,
		  .c = (uint8_t[]){ 0x9b, 0xaf, 0x69, 0xcb, 0xa3, 0x17, 0xf4,
				    0x22, 0xfe, 0x26, 0xa9, 0xa0 },
		  .d = (uint8_t[]){ 0xfe, 0x56, 0x28, 0x7c, 0xd6, 0x57, 0xe4,
				    0xaf, 0xc5, 0x0d, 0xba, 0x7a, 0x3a, 0x54,
				    0xc2, 0xa6, 0x32, 0x4b, 0x88, 0x6b, 0xec,
				    0xdc, 0xd1, 0xfa, 0xe4, 0x73, 0xb7, 0x69,
				    0xe5, 0x51, 0xa0, 0x9b } },
		{ .len = 20,
		  .c = (uint8_t[]){ 0xc1, 0xef, 0x39, 0xce, 0xe5, 0x8e, 0x78,
				    0xf6, 0xfc, 0xdc, 0x12, 0xe0, 0x58, 0xb7,
				    0xf9, 0x02, 0xac, 0xd1, 0xa9, 0x3b },
		  .d = (uint8_t[]){ 0x6d, 0xd5, 0x2b, 0x0d, 0x8b, 0x48, 0xcc,
				    0x81, 0x46, 0xce, 0xbd, 0x02, 0x16, 0xfb,
				    0xf5, 0xf6, 0xef, 0x7e, 0xea, 0xfc, 0x0f,
				    0xf2, 0xff, 0x9d, 0x14, 0x22, 0xd6, 0x34,
				    0x55, 0x55, 0xa1, 0x42 } },
		{ .len = 28,
		  .c = (uint8_t[]){ 0x07, 0x77, 0xfc, 0x1e, 0x1c, 0xa4, 0x73,
				    0x04, 0xc2, 0xe2, 0x65, 0x69, 0x28, 0x38,
				    0x10, 0x9e, 0x26, 0xaa, 0xb9, 0xe5, 0xc4,
				    0xae, 0x4e, 0x86, 0x00, 0xdf, 0x4b, 0x1f },
		  .d = (uint8_t[]){ 0xff, 0xb4, 0xfc, 0x03, 0xe0, 0x54, 0xf8,
				    0xec, 0xbc, 0x31, 0x47, 0x0f, 0xc0, 0x23,
				    0xbe, 0xdc, 0xd4, 0xa4, 0x06, 0xb9, 0xdd,
				    0x56, 0xc7, 0x1d, 0xa1, 0xb6, 0x60, 0xdc,
				    0xc4, 0x84, 0x2c, 0x65 } },
		{ .len = 32,
		  .c = (uint8_t[]){ 0x09, 0xfc, 0x1a, 0xcc, 0xc2, 0x30, 0xa2,
				    0x05, 0xe4, 0xa2, 0x08, 0xe6, 0x4a, 0x8f,
				    0x20, 0x42, 0x91, 0xf5, 0x81, 0xa1, 0x27,
				    0x56, 0x39, 0x2d, 0xa4, 0xb8, 0xc0, 0xcf,
				    0x5e, 0xf0, 0x2b, 0x95 },
		  .d = (uint8_t[]){ 0x4f, 0x44, 0xc1, 0xc7, 0xfb, 0xeb, 0xb6,
				    0xf9, 0x60, 0x18, 0x29, 0xf3, 0x89, 0x7b,
				    0xfd, 0x65, 0x0c, 0x56, 0xfa, 0x07, 0x84,
				    0x4b, 0xe7, 0x64, 0x89, 0x07, 0x63, 0x56,
				    0xac, 0x18, 0x86, 0xa4 } },
		{ .len = 48,
		  .c = (uint8_t[]){ 0x4e, 0xef, 0x51, 0x07, 0x45, 0x9b, 0xdd,
				    0xf8, 0xf2, 0x4f, 0xc7, 0x65, 0x6f, 0xd4,
				    0x89, 0x6d, 0xa8, 0x71, 0x1d, 0xb5, 0x04,
				    0x00, 0xc0, 0x16, 0x48, 0x47, 0xf6, 0x92,
				    0xb8, 0x86, 0xce, 0x8d, 0x7f, 0x4d, 0x67,
				    0x39, 0x50, 0x90, 0xb3, 0x53, 0x4e, 0xfd,
				    0x7b, 0x0d, 0x29, 0x8d, 0xa3, 0x4b },
		  .d = (uint8_t[]){ 0x7c, 0x5d, 0x14, 0xed, 0x83, 0xda, 0xb8,
				    0x75, 0xac, 0x25, 0xce, 0x7f, 0xee, 0xd6,
				    0xef, 0x83, 0x7d, 0x58, 0xe7, 0x9d, 0xc6,
				    0x01, 0xfb, 0x3c, 0x1f, 0xca, 0x48, 0xd4,
				    0x46, 0x4e, 0x8b, 0x83 } },
		{ .len = 55,
		  .c = (uint8_t[]){ 0x3e, 0xbf, 0xb0, 0x6d, 0xb8, 0xc3, 0x8d,
				    0x5b, 0xa0, 0x37, 0xf1, 0x36, 0x3e, 0x11,
				    0x85, 0x50, 0xaa, 0xd9, 0x46, 0x06, 0xe2,
				    0x68, 0x35, 0xa0, 0x1a, 0xf0, 0x50, 0x78,
				    0x53, 0x3c, 0xc2, 0x5f, 0x2f, 0x39, 0x57,
				    0x3c, 0x04, 0xb6, 0x32, 0xf6, 0x2f, 0x68,
				    0xc2, 0x94, 0xab, 0x31, 0xf2, 0xa3, 0xe2,
				    0xa1, 0xa0, 0xd8, 0xc2, 0xbe, 0x51 },
		  .d = (uint8_t[]){ 0x65, 0x95, 0xa2, 0xef, 0x53, 0x7a, 0x69,
				    0xba, 0x85, 0x83, 0xdf, 0xbf, 0x7f, 0x5b,
				    0xec, 0x0a, 0xb1, 0xf9, 0x3c, 0xe4, 0xc8,
				    0xee, 0x19, 0x16, 0xef, 0xf4, 0x4a, 0x93,
				    0xaf, 0x57, 0x49, 0xc4 } },
		{ .len = 56,
		  .c = (uint8_t[]){ 0x2d, 0x52, 0x44, 0x7d, 0x12, 0x44, 0xd2,
				    0xeb, 0xc2, 0x86, 0x50, 0xe7, 0xb0, 0x56,
				    0x54, 0xba, 0xd3, 0x5b, 0x3a, 0x68, 0xee,
				    0xdc, 0x7f, 0x85, 0x15, 0x30, 0x6b, 0x49,
				    0x6d, 0x75, 0xf3, 0xe7, 0x33, 0x85, 0xdd,
				    0x1b, 0x00, 0x26, 0x25, 0x02, 0x4b, 0x81,
				    0xa0, 0x2f, 0x2f, 0xd6, 0xdf, 0xfb, 0x6e,
				    0x6d, 0x56, 0x1c, 0xb7, 0xd0, 0xbd, 0x7a },
		  .d = (uint8_t[]){ 0xcf, 0xb8, 0x8d, 0x6f, 0xaf, 0x2d, 0xe3,
				    0xa6, 0x9d, 0x36, 0x19, 0x5a, 0xce, 0xc2,
				    0xe2, 0x55, 0xe2, 0xaf, 0x2b, 0x7d, 0x93,
				    0x39, 0x97, 0xf3, 0x48, 0xe0, 0x9f, 0x6c,
				    0xe5, 0x75, 0x83, 0x60 } },
		{ .len = 63,
		  .c = (uint8_t[]){ 0xe2, 0xf7, 0x6e, 0x97, 0x60, 0x6a, 0x87,
				    0x2e, 0x31, 0x74, 0x39, 0xf1, 0xa0, 0x3f,
				    0xcd, 0x92, 0xe6, 0x32, 0xe5, 0xbd, 0x4e,
				    0x7c, 0xbc, 0x4e, 0x97, 0xf1, 0xaf, 0xc1,
				    0x9a, 0x16, 0xfd, 0xe9, 0x2d, 0x77, 0xcb,
				    0xe5, 0x46, 0x41, 0x6b, 0x51, 0x64, 0x0c,
				    0xdd, 0xb9, 0x2a, 0xf9, 0x96, 0x53, 0x4d,
				    0xfd, 0x81, 0xed, 0xb1, 0x7c, 0x44, 0x24,
				    0xcf, 0x1a, 0xc4, 0xd7, 0x5a, 0xce, 0xeb },
		  .d = (uint8_t[]){ 0x18, 0x04, 0x1b, 0xd4, 0x66, 0x50, 0x83,
				    0x00, 0x1f, 0xba, 0x8c, 0x54, 0x11, 0xd2,
				    0xd7, 0x48, 0xe8, 0xab, 0xbf, 0xdc, 0xdf,
				    0xd9, 0x21, 0x8c, 0xb0, 0x2b, 0x68, 0xa7,
				    0x8e, 0x7d, 0x4c, 0x23 } },
		{ .len = 70,
		  .c = (uint8_t[]){ 0xbc, 0xe5, 0x0c, 0xdf, 0xff, 0x84, 0x38,
				    0x85, 0xd4, 0xf3, 0x64, 0xd6, 0x9f, 0x93,
				    0xbf, 0x58, 0xa2, 0x32, 0x2c, 0x70, 0x7b,
				    0x82, 0xe8, 0x78, 0xee, 0xc9, 0x6d, 0x11,
				    0xe5, 0xdb, 0x97, 0xbb, 0xb5, 0x46, 0x06,
				    0xa3, 0xa3, 0xcc, 0xc3, 0xbb, 0xa7, 0x16,
				    0x26, 0x10, 0x70, 0xa6, 0xf7, 0x59, 0xa7,
				    0x0e, 0xd3, 0xcb, 0x78, 0x5f, 0xd1, 0x35,
				    0x4f, 0xe5, 0x66, 0x48, 0xdf, 0x11, 0x86,
				    0x36, 0x69, 0xb7, 0x0c, 0x80, 0x3b, 0x7a },
		  .d = (uint8_t[]){ 0x8c, 0xb8, 0x7d, 0x8a, 0x8e, 0x48, 0x10,
				    0xcf, 0xa6, 0x07, 0x3f, 0xb2, 0x00, 0xde,
				    0xe5, 0x0e, 0xf1, 0xab, 0x90, 0x08, 0xfc,
				    0x9a, 0x18, 0x84, 0x25, 0x35, 0x0f, 0x00,
				    0x62, 0xd6, 0xd5, 0xf2 } },

		{ .len = 163,
		  .c = (uint8_t[]){ 0x45, 0x11, 0x01, 0x25, 0x0e, 0xc6, 0xf2,
				    0x66, 0x52, 0x24, 0x9d, 0x59, 0xdc, 0x97,
				    0x4b, 0x73, 0x61, 0xd5, 0x71, 0xa8, 0x10,
				    0x1c, 0xdf, 0xd3, 0x6a, 0xba, 0x3b, 0x58,
				    0x54, 0xd3, 0xae, 0x08, 0x6b, 0x5f, 0xdd,
				    0x45, 0x97, 0x72, 0x1b, 0x66, 0xe3, 0xc0,
				    0xdc, 0x5d, 0x8c, 0x60, 0x6d, 0x96, 0x57,
				    0xd0, 0xe3, 0x23, 0x28, 0x3a, 0x52, 0x17,
				    0xd1, 0xf5, 0x3f, 0x2f, 0x28, 0x4f, 0x57,
				    0xb8, 0x5c, 0x8a, 0x61, 0xac, 0x89, 0x24,
				    0x71, 0x1f, 0x89, 0x5c, 0x5e, 0xd9, 0x0e,
				    0xf1, 0x77, 0x45, 0xed, 0x2d, 0x72, 0x8a,
				    0xbd, 0x22, 0xa5, 0xf7, 0xa1, 0x34, 0x79,
				    0xa4, 0x62, 0xd7, 0x1b, 0x56, 0xc1, 0x9a,
				    0x74, 0xa4, 0x0b, 0x65, 0x5c, 0x58, 0xed,
				    0xfe, 0x0a, 0x18, 0x8a, 0xd2, 0xcf, 0x46,
				    0xcb, 0xf3, 0x05, 0x24, 0xf6, 0x5d, 0x42,
				    0x3c, 0x83, 0x7d, 0xd1, 0xff, 0x2b, 0xf4,
				    0x62, 0xac, 0x41, 0x98, 0x00, 0x73, 0x45,
				    0xbb, 0x44, 0xdb, 0xb7, 0xb1, 0xc8, 0x61,
				    0x29, 0x8c, 0xdf, 0x61, 0x98, 0x2a, 0x83,
				    0x3a, 0xfc, 0x72, 0x8f, 0xae, 0x1e, 0xda,
				    0x2f, 0x87, 0xaa, 0x2c, 0x94, 0x80, 0x85,
				    0x8b, 0xec },
		  .d = (uint8_t[]){ 0x3c, 0x59, 0x3a, 0xa5, 0x39, 0xfd, 0xcd,
				    0xae, 0x51, 0x6c, 0xdf, 0x2f, 0x15, 0x00,
				    0x0f, 0x66, 0x34, 0x18, 0x5c, 0x88, 0xf5,
				    0x05, 0xb3, 0x97, 0x75, 0xfb, 0x9a, 0xb1,
				    0x37, 0xa1, 0x0a, 0xa2 } }
	};
	for (size_t i = 0; i < ARRAY_SIZE(sha256_v); i++) {
		struct sha256_digest sha256;
		struct sha256_ctx ctx;

		memset(&sha256, 0, sizeof(sha256));
		SHA256_sw_hash(sha256_v[i].c, sha256_v[i].len, &sha256);

		CPRINTS("SHA256_sw_hash test %zu, len=%zu, %s", i,
			sha256_v[i].len,
			smemcmp(sha256.b8, sha256_v[i].d, SHA256_DIGEST_SIZE));

		memset(&sha256, 0, sizeof(sha256));
		SHA256_hw_hash(sha256_v[i].c, sha256_v[i].len, &sha256);
		CPRINTS("SHA256_hw_hash test %zu, len=%zu, %s", i,
			sha256_v[i].len,
			smemcmp(sha256.b8, sha256_v[i].d, SHA256_DIGEST_SIZE));

		SHA256_hw_init(&ctx);
		SHA256_update(&ctx, sha256_v[i].c, sha256_v[i].len);
		CPRINTS("SHA256_hw_init test %zu, len=%zu, %s", i,
			sha256_v[i].len,
			smemcmp(SHA256_final(&ctx)->b8, sha256_v[i].d,
				SHA256_DIGEST_SIZE));

		/* Test the path when sha hw is taken. */
		dcrypto_grab_sha_hw();
		memset(&sha256, 0, sizeof(sha256));
		SHA256_hw_hash(sha256_v[i].c, sha256_v[i].len, &sha256);
		CPRINTS("SHA256_hw_hash test (sw path) %zu, len=%zu, %s", i,
			sha256_v[i].len,
			smemcmp(sha256.b8, sha256_v[i].d, SHA256_DIGEST_SIZE));
		dcrypto_release_sha_hw();
		cflush();
	}
	return EC_SUCCESS;
}
DECLARE_SAFE_CONSOLE_COMMAND(sha256_test, cmd_sha256_test, NULL, NULL);
#endif

#if HMAC_SHA256_TEST
static int cmd_hmac_sha256(int argc, char *argv[])
{
	const struct hmac_test hmac_sha256_v[] = {
		{ .klen = 10,
		  .k = (uint8_t[]){ 0x65, 0x74, 0x61, 0x6f, 0x6e, 0x72, 0x69,
				    0x73, 0x68, 0x64 },
		  .len = 11,
		  .c = (uint8_t[]){ 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20,
				    0x74, 0x65, 0x78, 0x74 },
		  .d = (uint8_t[]){ 0xe9, 0x17, 0xc1, 0x7b, 0x4c, 0x6b, 0x77,
				    0xda, 0xd2, 0x30, 0x36, 0x02, 0xf5, 0x72,
				    0x33, 0x87, 0x9f, 0xc6, 0x6e, 0x7b, 0x7e,
				    0xa8, 0xea, 0xaa, 0x9f, 0xba, 0xee, 0x51,
				    0xff, 0xda, 0x24, 0xf4 } },
		{ .klen = 40,
		  .k = (uint8_t[]){ 0x97, 0x79, 0xd9, 0x12, 0x06, 0x42, 0x79,
				    0x7f, 0x17, 0x47, 0x02, 0x5d, 0x5b, 0x22,
				    0xb7, 0xac, 0x60, 0x7c, 0xab, 0x08, 0xe1,
				    0x75, 0x8f, 0x2f, 0x3a, 0x46, 0xc8, 0xbe,
				    0x1e, 0x25, 0xc5, 0x3b, 0x8c, 0x6a, 0x8f,
				    0x58, 0xff, 0xef, 0xa1, 0x76 },
		  .len = 128,
		  .c = (uint8_t[]){ 0xb1, 0x68, 0x9c, 0x25, 0x91, 0xea, 0xf3,
				    0xc9, 0xe6, 0x60, 0x70, 0xf8, 0xa7, 0x79,
				    0x54, 0xff, 0xb8, 0x17, 0x49, 0xf1, 0xb0,
				    0x03, 0x46, 0xf9, 0xdf, 0xe0, 0xb2, 0xee,
				    0x90, 0x5d, 0xcc, 0x28, 0x8b, 0xaf, 0x4a,
				    0x92, 0xde, 0x3f, 0x40, 0x01, 0xdd, 0x9f,
				    0x44, 0xc4, 0x68, 0xc3, 0xd0, 0x7d, 0x6c,
				    0x6e, 0xe8, 0x2f, 0xac, 0xea, 0xfc, 0x97,
				    0xc2, 0xfc, 0x0f, 0xc0, 0x60, 0x17, 0x19,
				    0xd2, 0xdc, 0xd0, 0xaa, 0x2a, 0xec, 0x92,
				    0xd1, 0xb0, 0xae, 0x93, 0x3c, 0x65, 0xeb,
				    0x06, 0xa0, 0x3c, 0x9c, 0x93, 0x5c, 0x2b,
				    0xad, 0x04, 0x59, 0x81, 0x02, 0x41, 0x34,
				    0x7a, 0xb8, 0x7e, 0x9f, 0x11, 0xad, 0xb3,
				    0x04, 0x15, 0x42, 0x4c, 0x6c, 0x7f, 0x5f,
				    0x22, 0xa0, 0x03, 0xb8, 0xab, 0x8d, 0xe5,
				    0x4f, 0x6d, 0xed, 0x0e, 0x3a, 0xb9, 0x24,
				    0x5f, 0xa7, 0x95, 0x68, 0x45, 0x1d, 0xfa,
				    0x25, 0x8e },
		  .d = (uint8_t[]){ 0x76, 0x9f, 0x00, 0xd3, 0xe6, 0xa6, 0xcc,
				    0x1f, 0xb4, 0x26, 0xa1, 0x4a, 0x4f, 0x76,
				    0xc6, 0x46, 0x2e, 0x61, 0x49, 0x72, 0x6e,
				    0x0d, 0xee, 0x0e, 0xc0, 0xcf, 0x97, 0xa1,
				    0x66, 0x05, 0xac, 0x8b } },
		{ .klen = 45,
		  .k = (uint8_t[]){ 0xb7, 0x63, 0x26, 0x3d, 0xc4, 0xfc, 0x62,
				    0xb2, 0x27, 0xcd, 0x3f, 0x6b, 0x4e, 0x9e,
				    0x35, 0x8c, 0x21, 0xca, 0x03, 0x6c, 0xe3,
				    0x96, 0xab, 0x92, 0x59, 0xc1, 0xbe, 0xdd,
				    0x2f, 0x5c, 0xd9, 0x02, 0x97, 0xdc, 0x70,
				    0x3c, 0x33, 0x6e, 0xca, 0x3e, 0x35, 0x8a,
				    0x4d, 0x6d, 0xc5 },
		  .len = 128,
		  .c = (uint8_t[]){ 0x53, 0xcb, 0x09, 0xd0, 0xa7, 0x88, 0xe4,
				    0x46, 0x6d, 0x01, 0x58, 0x8d, 0xf6, 0x94,
				    0x5d, 0x87, 0x28, 0xd9, 0x36, 0x3f, 0x76,
				    0xcd, 0x01, 0x2a, 0x10, 0x30, 0x8d, 0xad,
				    0x56, 0x2b, 0x6b, 0xe0, 0x93, 0x36, 0x48,
				    0x92, 0xe8, 0x39, 0x7a, 0x8d, 0x86, 0xf1,
				    0xd8, 0x1a, 0x20, 0x96, 0xcf, 0xc8, 0xa1,
				    0xbb, 0xb2, 0x6a, 0x1a, 0x75, 0x52, 0x5f,
				    0xfe, 0xbf, 0xcf, 0x16, 0x91, 0x1d, 0xad,
				    0xd0, 0x9e, 0x80, 0x2a, 0xa8, 0x68, 0x6a,
				    0xcf, 0xd1, 0xe4, 0x52, 0x46, 0x20, 0x25,
				    0x4a, 0x6b, 0xca, 0x18, 0xdf, 0xa5, 0x6e,
				    0x71, 0x41, 0x77, 0x56, 0xe5, 0xa4, 0x52,
				    0xfa, 0x9a, 0xe5, 0xae, 0xc5, 0xdc, 0x71,
				    0x59, 0x1c, 0x11, 0x63, 0x0e, 0x9d, 0xef,
				    0xec, 0x49, 0xa4, 0xec, 0xf8, 0x5a, 0x14,
				    0xf6, 0x0e, 0xb8, 0x54, 0x65, 0x78, 0x99,
				    0x97, 0x2e, 0xa5, 0xbf, 0x61, 0x59, 0xcb,
				    0x95, 0x47 },
		  .d = (uint8_t[]){ 0x73, 0x73, 0x01, 0xde, 0xa9, 0x3d, 0xb6,
				    0xbc, 0xba, 0xdd, 0x7b, 0xf7, 0x96, 0x69,
				    0x39, 0x61, 0x31, 0x7c, 0xa6, 0x80, 0xb3,
				    0x80, 0x41, 0x6f, 0x12, 0xf4, 0x66, 0xf0,
				    0x65, 0x26, 0xb3, 0x6b } },
		{ .klen = 64,
		  .k = (uint8_t[]){ 0x99, 0x28, 0x68, 0x50, 0x4d, 0x25, 0x64,
				    0xc4, 0xfb, 0x47, 0xbc, 0xbd, 0x4a, 0xe4,
				    0x82, 0xd8, 0xfb, 0x0e, 0x8e, 0x56, 0xd7,
				    0xb8, 0x18, 0x64, 0xe6, 0x19, 0x86, 0xa0,
				    0xe2, 0x56, 0x82, 0xda, 0xeb, 0x5b, 0x50,
				    0x17, 0x7c, 0x09, 0x5e, 0xdc, 0x9e, 0x97,
				    0x1d, 0xa9, 0x5c, 0x32, 0x10, 0xc3, 0x76,
				    0xe7, 0x23, 0x36, 0x5a, 0xc3, 0x3d, 0x1b,
				    0x4f, 0x39, 0x18, 0x17, 0xf4, 0xc3, 0x51,
				    0x24 },
		  .len = 128,
		  .c = (uint8_t[]){ 0xed, 0x4f, 0x26, 0x9a, 0x88, 0x51, 0xeb,
				    0x31, 0x54, 0x77, 0x15, 0x16, 0xb2, 0x72,
				    0x28, 0x15, 0x52, 0x00, 0x77, 0x80, 0x49,
				    0xb2, 0xdc, 0x19, 0x63, 0xf3, 0xac, 0x32,
				    0xba, 0x46, 0xea, 0x13, 0x87, 0xcf, 0xbb,
				    0x9c, 0x39, 0x15, 0x1a, 0x2c, 0xc4, 0x06,
				    0xcd, 0xc1, 0x3c, 0x3c, 0x98, 0x60, 0xa2,
				    0x7e, 0xb0, 0xb7, 0xfe, 0x8a, 0x72, 0x01,
				    0xad, 0x11, 0x55, 0x2a, 0xfd, 0x04, 0x1e,
				    0x33, 0xf7, 0x0e, 0x53, 0xd9, 0x7c, 0x62,
				    0xf1, 0x71, 0x94, 0xb6, 0x61, 0x17, 0x02,
				    0x8f, 0xa9, 0x07, 0x1c, 0xc0, 0xe0, 0x4b,
				    0xd9, 0x2d, 0xe4, 0x97, 0x2c, 0xd5, 0x4f,
				    0x71, 0x90, 0x10, 0xa6, 0x94, 0xe4, 0x14,
				    0xd4, 0x97, 0x7a, 0xbe, 0xd7, 0xca, 0x6b,
				    0x90, 0xba, 0x61, 0x2d, 0xf6, 0xc3, 0xd4,
				    0x67, 0xcd, 0xed, 0x85, 0x03, 0x25, 0x98,
				    0xa4, 0x85, 0x46, 0x80, 0x4f, 0x9c, 0xf2,
				    0xec, 0xfe },
		  .d = (uint8_t[]){ 0x2f, 0x83, 0x21, 0xf4, 0x16, 0xb9, 0xbb,
				    0x24, 0x9f, 0x11, 0x3b, 0x13, 0xfc, 0x12,
				    0xd7, 0x0e, 0x16, 0x68, 0xdc, 0x33, 0x28,
				    0x39, 0xc1, 0x0d, 0xaa, 0x57, 0x17, 0x89,
				    0x6c, 0xb7, 0x0d, 0xdf } },
		{ .klen = 70,
		  .k = (uint8_t[]){ 0xbc, 0xe5, 0x0c, 0xdf, 0xff, 0x84, 0x38,
				    0x85, 0xd4, 0xf3, 0x64, 0xd6, 0x9f, 0x93,
				    0xbf, 0x58, 0xa2, 0x32, 0x2c, 0x70, 0x7b,
				    0x82, 0xe8, 0x78, 0xee, 0xc9, 0x6d, 0x11,
				    0xe5, 0xdb, 0x97, 0xbb, 0xb5, 0x46, 0x06,
				    0xa3, 0xa3, 0xcc, 0xc3, 0xbb, 0xa7, 0x16,
				    0x26, 0x10, 0x70, 0xa6, 0xf7, 0x59, 0xa7,
				    0x0e, 0xd3, 0xcb, 0x78, 0x5f, 0xd1, 0x35,
				    0x4f, 0xe5, 0x66, 0x48, 0xdf, 0x11, 0x86,
				    0x36, 0x69, 0xb7, 0x0c, 0x80, 0x3b, 0x7a },
		  .len = 128,
		  .c = (uint8_t[]){ 0x93, 0xb7, 0xef, 0x0e, 0x47, 0x0d, 0xdf,
				    0xac, 0x6a, 0xef, 0x93, 0xc0, 0xdc, 0xd3,
				    0x7b, 0x8f, 0x1c, 0x4b, 0xaf, 0x5e, 0xad,
				    0xd9, 0x78, 0xe3, 0xbf, 0x05, 0x12, 0xfa,
				    0x0b, 0xae, 0xb0, 0x99, 0xff, 0x9e, 0xc1,
				    0x06, 0x1b, 0x61, 0x72, 0x47, 0x9b, 0x56,
				    0x74, 0xdb, 0x56, 0x06, 0xff, 0xa7, 0xe6,
				    0xb5, 0x17, 0x33, 0x09, 0x37, 0x0e, 0x16,
				    0x47, 0x05, 0x4a, 0xaf, 0xd5, 0x90, 0x48,
				    0x16, 0xba, 0xd5, 0xe1, 0x52, 0x30, 0x32,
				    0xcc, 0xcd, 0x4d, 0x78, 0x65, 0x05, 0xe2,
				    0x41, 0xac, 0x83, 0xa4, 0x84, 0x91, 0x11,
				    0x89, 0x66, 0x6f, 0x28, 0x75, 0x53, 0xd6,
				    0xa8, 0x16, 0x4e, 0x8d, 0xcb, 0x0c, 0x85,
				    0xd7, 0x5c, 0x4e, 0x29, 0xf6, 0x24, 0xc9,
				    0x7c, 0xee, 0xa6, 0x4a, 0x2c, 0x8b, 0x0c,
				    0x9d, 0xdf, 0xa5, 0x60, 0xf7, 0x0f, 0xa3,
				    0xff, 0x91, 0x18, 0x3e, 0x4b, 0x96, 0x8f,
				    0x88, 0xa1 },
		  .d = (uint8_t[]){ 0x37, 0xf9, 0xf3, 0x29, 0x18, 0x30, 0x82,
				    0x10, 0x84, 0x9d, 0xfe, 0xbf, 0x8d, 0xd4,
				    0x56, 0x80, 0x4b, 0xab, 0xd6, 0x84, 0x5a,
				    0xf0, 0x72, 0x18, 0xf9, 0xd9, 0xbe, 0x9d,
				    0xf9, 0x74, 0x3d, 0x55 } }
	};

	for (size_t i = 0; i < ARRAY_SIZE(hmac_sha256_v); i++) {
		struct hmac_sha256_ctx ctx;

		HMAC_SHA256_sw_init(&ctx, hmac_sha256_v[i].k,
				    hmac_sha256_v[i].klen);
		HMAC_SHA256_update(&ctx, hmac_sha256_v[i].c,
				   hmac_sha256_v[i].len);
		CPRINTS("HMAC SHA256_sw_init test %zu, klen=%zu, len=%zu, %s",
			i, hmac_sha256_v[i].klen, hmac_sha256_v[i].len,
			smemcmp(HMAC_SHA256_final(&ctx)->b8, hmac_sha256_v[i].d,
				SHA256_DIGEST_SIZE));

		HMAC_SHA256_hw_init(&ctx, hmac_sha256_v[i].k,
				    hmac_sha256_v[i].klen);
		HMAC_SHA256_update(&ctx, hmac_sha256_v[i].c,
				   hmac_sha256_v[i].len);
		CPRINTS("HMAC SHA256_hw_init test %zu, klen=%zu, len=%zu, %s",
			i, hmac_sha256_v[i].klen, hmac_sha256_v[i].len,
			smemcmp(HMAC_SHA256_final(&ctx)->b8, hmac_sha256_v[i].d,
				SHA256_DIGEST_SIZE));

		/* Test the path when sha hw is taken. */
		dcrypto_grab_sha_hw();
		HMAC_SHA256_hw_init(&ctx, hmac_sha256_v[i].k,
				    hmac_sha256_v[i].klen);
		HMAC_SHA256_update(&ctx, hmac_sha256_v[i].c,
				   hmac_sha256_v[i].len);
		CPRINTS("HMAC SHA256_hw_init(sw) test %zu, klen=%zu,"
			" len=%zu, %s",
			i, hmac_sha256_v[i].klen, hmac_sha256_v[i].len,
			smemcmp(HMAC_SHA256_final(&ctx)->b8, hmac_sha256_v[i].d,
				SHA256_DIGEST_SIZE));
		dcrypto_release_sha_hw();
		cflush();
	}
	return EC_SUCCESS;
}
DECLARE_SAFE_CONSOLE_COMMAND(hmac_sha256, cmd_hmac_sha256, NULL, NULL);
#endif

#endif
