summaryrefslogtreecommitdiff
path: root/board/cr50/dcrypto/hmacsha2.h
diff options
context:
space:
mode:
Diffstat (limited to 'board/cr50/dcrypto/hmacsha2.h')
-rw-r--r--board/cr50/dcrypto/hmacsha2.h490
1 files changed, 490 insertions, 0 deletions
diff --git a/board/cr50/dcrypto/hmacsha2.h b/board/cr50/dcrypto/hmacsha2.h
new file mode 100644
index 0000000000..6d9c842c1e
--- /dev/null
+++ b/board/cr50/dcrypto/hmacsha2.h
@@ -0,0 +1,490 @@
+/* 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.
+ */
+#pragma once
+#include "common.h"
+
+#define SHA1_DIGEST_SIZE 20
+#define SHA_DIGEST_SIZE SHA1_DIGEST_SIZE
+
+#define SHA224_DIGEST_SIZE 28
+#define SHA256_DIGEST_SIZE 32
+#define SHA1_BLOCK_SIZE 64
+#define SHA1_BLOCK_WORDS (SHA1_BLOCK_SIZE / sizeof(uint32_t))
+#define SHA1_BLOCK_DWORDS (SHA1_BLOCK_SIZE / sizeof(uint64_t))
+#define SHA1_DIGEST_WORDS (SHA1_DIGEST_SIZE / sizeof(uint32_t))
+#define SHA224_BLOCK_SIZE 64
+#define SHA224_BLOCK_WORDS (SHA224_BLOCK_SIZE / sizeof(uint32_t))
+#define SHA224_BLOCK_DWORDS (SHA224_BLOCK_SIZE / sizeof(uint64_t))
+#define SHA224_DIGEST_WORDS (SHA224_DIGEST_SIZE / sizeof(uint32_t))
+#define SHA256_BLOCK_SIZE 64
+#define SHA256_BLOCK_WORDS (SHA256_BLOCK_SIZE / sizeof(uint32_t))
+#define SHA256_BLOCK_DWORDS (SHA256_BLOCK_SIZE / sizeof(uint64_t))
+#define SHA256_DIGEST_WORDS (SHA256_DIGEST_SIZE / sizeof(uint32_t))
+
+/**
+ * Hash contexts. Each context starts with pointer to vtable containing
+ * functions to perform implementation specific operations.
+ * It is designed to support both software and hardware implementations.
+ * Contexts for different digest types can overlap, but vtable stores
+ * actual size of context which enables stack-efficient implementation of
+ * HMAC - say HMAC SHA2-256 shouldn't reserve space as for HMAC SHA2-512.
+ */
+union hash_ctx; /* forward declaration of generic hash context type */
+union hmac_ctx; /* forward declaration of generic HMAC context type */
+
+union sha_digests; /* forward declaration of generic digest type */
+
+/* Combined HASH & HMAC vtable to support SW & HW implementations. */
+struct hash_vtable {
+ /* SHA init function, used primarily by SW HMAC implementation. */
+ void (*const init)(union hash_ctx *const);
+ /* Update function for SHA & HMAC, assuming it's the same. */
+ void (*const update)(union hash_ctx *const, const void *, size_t);
+ /* SHA final function, digest specific. */
+ const union sha_digests *(*const final)(union hash_ctx *const);
+
+ /* HW HMAC support may require special ending. */
+ const union sha_digests *(*const hmac_final)(union hmac_ctx *const);
+
+ /* Digest size of in bytes. */
+ size_t digest_size;
+
+ /* Digest block size in bytes. */
+ size_t block_size;
+
+ /* Offset of first byte after context, used for HMAC */
+ size_t context_size;
+};
+
+struct sha256_digest {
+ union {
+ uint8_t b8[SHA256_DIGEST_SIZE];
+ uint32_t b32[SHA256_DIGEST_WORDS];
+ };
+};
+BUILD_ASSERT(sizeof(struct sha256_digest) == SHA256_DIGEST_SIZE);
+
+struct sha224_digest {
+ union {
+ uint8_t b8[SHA224_DIGEST_SIZE];
+ uint32_t b32[SHA224_DIGEST_WORDS];
+ };
+};
+BUILD_ASSERT(sizeof(struct sha224_digest) == SHA224_DIGEST_SIZE);
+
+struct sha1_digest {
+ union {
+ uint8_t b8[SHA1_DIGEST_SIZE];
+ uint32_t b32[SHA1_DIGEST_WORDS];
+ };
+};
+BUILD_ASSERT(sizeof(struct sha1_digest) == SHA1_DIGEST_SIZE);
+
+
+/* SHA256 specific type to allocate just enough memory. */
+struct sha256_ctx {
+ const struct hash_vtable *f; /* metadata & vtable */
+ size_t count; /* number of bytes processed */
+ uint32_t state[SHA256_DIGEST_WORDS]; /* up to SHA2-256 */
+ union {
+ uint8_t b8[SHA256_BLOCK_SIZE];
+ uint32_t b32[SHA256_BLOCK_WORDS];
+ uint64_t b64[SHA256_BLOCK_DWORDS];
+ struct sha256_digest digest;
+ };
+};
+
+#define sha224_ctx sha256_ctx
+
+struct sha1_ctx {
+ const struct hash_vtable *f; /* metadata & vtable. */
+ size_t count; /* number of bytes processed. */
+ uint32_t state[SHA1_DIGEST_WORDS];
+ union {
+ uint8_t b8[SHA1_BLOCK_SIZE];
+ uint32_t b32[SHA1_BLOCK_WORDS];
+ uint64_t b64[SHA1_BLOCK_DWORDS];
+ struct sha1_digest digest;
+ };
+};
+
+#ifdef CONFIG_UPTO_SHA512
+#define SHA384_DIGEST_SIZE 48
+#define SHA512_DIGEST_SIZE 64
+
+#define SHA384_BLOCK_SIZE 128
+#define SHA512_BLOCK_SIZE 128
+
+#define SHA384_BLOCK_WORDS (SHA384_BLOCK_SIZE / sizeof(uint32_t))
+#define SHA384_BLOCK_DWORDS (SHA384_BLOCK_SIZE / sizeof(uint64_t))
+#define SHA384_DIGEST_WORDS (SHA384_DIGEST_SIZE / sizeof(uint32_t))
+#define SHA384_DIGEST_DWORDS (SHA384_DIGEST_SIZE / sizeof(uint64_t))
+
+#define SHA512_BLOCK_WORDS (SHA512_BLOCK_SIZE / sizeof(uint32_t))
+#define SHA512_BLOCK_DWORDS (SHA512_BLOCK_SIZE / sizeof(uint64_t))
+#define SHA512_DIGEST_WORDS (SHA512_DIGEST_SIZE / sizeof(uint32_t))
+#define SHA512_DIGEST_DWORDS (SHA512_DIGEST_SIZE / sizeof(uint64_t))
+
+struct sha384_digest {
+ union {
+ uint8_t b8[SHA384_DIGEST_SIZE];
+ uint32_t b32[SHA384_DIGEST_WORDS];
+ };
+};
+BUILD_ASSERT(sizeof(struct sha384_digest) == SHA384_DIGEST_SIZE);
+
+struct sha512_digest {
+ union {
+ uint8_t b8[SHA512_DIGEST_SIZE];
+ uint32_t b32[SHA512_DIGEST_WORDS];
+ };
+};
+BUILD_ASSERT(sizeof(struct sha512_digest) == SHA512_DIGEST_SIZE);
+
+struct sha512_ctx {
+ const struct hash_vtable *f; /* metadata & vtable. */
+ size_t count; /* number of bytes processed. */
+ uint64_t state[SHA512_DIGEST_DWORDS]; /* up to SHA2-512. */
+ union {
+ uint8_t b8[SHA512_BLOCK_SIZE];
+ uint32_t b32[SHA512_BLOCK_WORDS];
+ uint64_t b64[SHA512_BLOCK_DWORDS];
+ struct sha512_digest digest;
+ };
+};
+
+#define sha384_ctx sha512_ctx
+#endif
+
+/**
+ * Generic hash type, allocating memory for any supported hash context
+ * Each context should have header at known location.
+ */
+union hash_ctx {
+ const struct hash_vtable *f; /* common metadata & vtable */
+ struct sha1_ctx sha1;
+ struct sha256_ctx sha256;
+ struct sha224_ctx sha224;
+#ifdef CONFIG_UPTO_SHA512
+ struct sha384_ctx sha384;
+ struct sha512_ctx sha512;
+#endif
+};
+
+union sha_digests {
+ struct sha1_digest sha1;
+ struct sha224_digest sha224;
+ struct sha256_digest sha256;
+#ifdef CONFIG_UPTO_SHA512
+ struct sha384_digest sha384;
+ struct sha512_digest sha512;
+#endif
+ /* Convenience accessor to bytes. */
+ uint8_t b8[SHA256_DIGEST_SIZE];
+};
+
+/* Header should be at constant offset to safely cast types to smaller size */
+BUILD_ASSERT(offsetof(union hash_ctx, f) == offsetof(struct sha1_ctx, f));
+BUILD_ASSERT(offsetof(union hash_ctx, f) == offsetof(struct sha256_ctx, f));
+BUILD_ASSERT(offsetof(union hash_ctx, f) == offsetof(struct sha224_ctx, f));
+
+#ifdef CONFIG_UPTO_SHA512
+BUILD_ASSERT(offsetof(union hash_ctx, f) == offsetof(struct sha384_ctx, f));
+BUILD_ASSERT(offsetof(union hash_ctx, f) == offsetof(struct sha512_ctx, f));
+#endif
+
+struct hmac_sha1_ctx {
+ struct sha1_ctx hash;
+ uint32_t opad[SHA1_BLOCK_WORDS];
+};
+
+struct hmac_sha224_ctx {
+ struct sha224_ctx hash;
+ uint32_t opad[SHA224_BLOCK_WORDS];
+};
+
+struct hmac_sha256_ctx {
+ struct sha256_ctx hash;
+ uint32_t opad[SHA256_BLOCK_WORDS];
+};
+
+#ifdef CONFIG_UPTO_SHA512
+struct hmac_sha384_ctx {
+ struct sha384_ctx hash;
+ uint32_t opad[SHA384_BLOCK_WORDS];
+};
+
+struct hmac_sha512_ctx {
+ struct sha512_ctx hash;
+ uint32_t opad[SHA512_BLOCK_WORDS];
+};
+#endif
+
+/**
+ * HMAC context reserving memory for any supported hash type.
+ * It's SHA context following storage for ipad/opad
+ */
+union hmac_ctx {
+ const struct hash_vtable *f; /* common metadata & vtable */
+ union hash_ctx hash; /* access as hash */
+ /* hmac contexts */
+ struct hmac_sha1_ctx hmac_sha1;
+ struct hmac_sha256_ctx hmac_sha256;
+ struct hmac_sha224_ctx hmac_sha224;
+#ifdef CONFIG_UPTO_SHA512
+ struct hmac_sha384_ctx hmac_sha384;
+ struct hmac_sha512_ctx hmac_sha512;
+#endif
+};
+
+/* Header should be at constant offset to safely cast types to smaller size */
+BUILD_ASSERT(offsetof(union hmac_ctx, f) == offsetof(struct sha1_ctx, f));
+BUILD_ASSERT(offsetof(union hmac_ctx, f) == offsetof(struct sha256_ctx, f));
+BUILD_ASSERT(offsetof(union hmac_ctx, f) == offsetof(struct sha224_ctx, f));
+
+#ifdef CONFIG_UPTO_SHA512
+BUILD_ASSERT(offsetof(union hmac_ctx, f) == offsetof(struct sha384_ctx, f));
+BUILD_ASSERT(offsetof(union hmac_ctx, f) == offsetof(struct sha512_ctx, f));
+#endif
+
+/**
+ * Reset hash context with the same hash function as configured.
+ * Will crash if previously not configured! Used for HMAC.
+ */
+static inline void HASH_reinit(union hash_ctx *const ctx)
+{
+ ctx->f->init(ctx);
+}
+
+#ifndef CONFIG_DCRYPTO_MOCK
+/**
+ * Add data to message, call configured transform function when block
+ * is full.
+ */
+static inline void HASH_update(union hash_ctx *const ctx, const void *data,
+ size_t len)
+{
+ ctx->f->update(ctx, data, len);
+}
+#else
+void HASH_update(union hash_ctx *const ctx, const void *data, size_t len);
+#endif
+
+static inline void SHA1_update(struct sha1_ctx *const ctx, const void *data,
+ size_t len)
+{
+ ctx->f->update((union hash_ctx *)ctx, data, len);
+}
+
+static inline void SHA256_update(struct sha256_ctx *const ctx, const void *data,
+ size_t len)
+{
+ ctx->f->update((union hash_ctx *)ctx, data, len);
+}
+
+/**
+ * Finalize hash computation by adding padding, message length.
+ * Returns pointer to computed digest stored inside provided context.
+ */
+#ifndef CONFIG_DCRYPTO_MOCK
+static inline const union sha_digests *HASH_final(union hash_ctx *const ctx)
+{
+ return ctx->f->final(ctx);
+}
+#else
+const union sha_digests *HASH_final(union hash_ctx *const ctx);
+#endif
+
+static inline const struct sha1_digest *SHA1_final(struct sha1_ctx *const ctx)
+{
+ return &ctx->f->final((union hash_ctx *)ctx)->sha1;
+}
+
+static inline const struct sha256_digest *
+SHA256_final(struct sha256_ctx *const ctx)
+{
+ return &ctx->f->final((union hash_ctx *)ctx)->sha256;
+}
+
+/**
+ * Returns digest size for configured hash.
+ */
+static inline size_t HASH_size(union hash_ctx *const ctx)
+{
+ return ctx->f->digest_size;
+}
+
+/**
+ * Return block size for configured hash.
+ */
+static inline size_t HASH_block_size(union hash_ctx *const ctx)
+{
+ return ctx->f->block_size;
+}
+
+/* Software implementations of hash functions. */
+void SHA1_sw_init(struct sha1_ctx *const ctx);
+void SHA1_sw_update(struct sha1_ctx *const ctx, const void *data, size_t len);
+const struct sha1_digest *SHA1_sw_final(struct sha1_ctx *const ctx);
+const struct sha1_digest *SHA1_sw_hash(const void *data, size_t len,
+ struct sha1_digest *digest);
+void SHA256_sw_init(struct sha256_ctx *const ctx);
+void SHA256_sw_update(struct sha256_ctx *const ctx, const void *data,
+ size_t len);
+const struct sha256_digest *SHA256_sw_final(struct sha256_ctx *const ctx);
+const struct sha256_digest *SHA256_sw_hash(const void *data, size_t len,
+ struct sha256_digest *digest);
+void SHA224_sw_init(struct sha224_ctx *const ctx);
+void SHA224_sw_update(struct sha224_ctx *const ctx, const void *data,
+ size_t len);
+const struct sha224_digest *SHA224_sw_final(struct sha224_ctx *const ctx);
+const struct sha224_digest *SHA224_sw_hash(const void *data, size_t len,
+ struct sha224_digest *digest);
+
+/**
+ * Initialize HMAC for pre-configured hash.
+ * This is generic function which can initialize HMAC with any supported
+ * hash function.
+ */
+void HMAC_sw_init(union hmac_ctx *const ctx, const void *key, size_t len);
+const union sha_digests *HMAC_sw_final(union hmac_ctx *const ctx);
+
+/* HMAC update is same as SHA update. */
+static inline void HMAC_update(union hmac_ctx *const ctx, const void *data,
+ size_t len)
+{
+ ctx->f->update(&ctx->hash, data, len);
+}
+
+static inline size_t HMAC_size(union hmac_ctx *const ctx)
+{
+ return ctx->f->digest_size;
+}
+
+static inline const union sha_digests *HMAC_final(union hmac_ctx *const ctx)
+{
+ return ctx->f->hmac_final(ctx);
+}
+
+/**
+ * HMAC SHA1 initialization.
+ */
+static inline void HMAC_SHA1_sw_init(struct hmac_sha1_ctx *const ctx,
+ const void *key, size_t len)
+{
+ SHA1_sw_init(&ctx->hash);
+ HMAC_sw_init((union hmac_ctx *)ctx, key, len);
+}
+
+static inline void HMAC_SHA1_update(struct hmac_sha1_ctx *const ctx,
+ const void *data, size_t len)
+{
+ ctx->hash.f->update((union hash_ctx *)&ctx->hash, data, len);
+}
+
+static inline const struct sha1_digest *
+HMAC_SHA1_final(struct hmac_sha1_ctx *const ctx)
+{
+ return &ctx->hash.f->hmac_final((union hmac_ctx *)ctx)->sha1;
+}
+
+/**
+ * HMAC SHA2-224 initialization.
+ */
+static inline void HMAC_SHA224_sw_init(struct hmac_sha224_ctx *const ctx,
+ const void *key, size_t len)
+{
+ SHA224_sw_init(&ctx->hash);
+ HMAC_sw_init((union hmac_ctx *)ctx, key, len);
+}
+
+static inline void HMAC_SHA224_update(struct hmac_sha224_ctx *const ctx,
+ const void *data, size_t len)
+{
+ ctx->hash.f->update((union hash_ctx *)&ctx->hash, data, len);
+}
+
+static inline const struct sha224_digest *
+HMAC_SHA224_final(struct hmac_sha224_ctx *const ctx)
+{
+ return &ctx->hash.f->hmac_final((union hmac_ctx *)ctx)->sha224;
+}
+
+/**
+ * HMAC SHA2-256 initialization.
+ */
+static inline void HMAC_SHA256_sw_init(struct hmac_sha256_ctx *const ctx,
+ const void *key, size_t len)
+{
+ SHA256_sw_init(&ctx->hash);
+ HMAC_sw_init((union hmac_ctx *)ctx, key, len);
+}
+
+static inline void HMAC_SHA256_update(struct hmac_sha256_ctx *const ctx,
+ const void *data, size_t len)
+{
+ ctx->hash.f->update((union hash_ctx *)&ctx->hash, data, len);
+}
+
+static inline const struct sha256_digest *
+HMAC_SHA256_final(struct hmac_sha256_ctx *ctx)
+{
+ return &ctx->hash.f->hmac_final((union hmac_ctx *)ctx)->sha256;
+}
+
+#ifdef CONFIG_UPTO_SHA512
+void SHA384_sw_init(struct sha384_ctx *const ctx);
+void SHA384_sw_update(struct sha384_ctx *const ctx, const void *data,
+ size_t len);
+const struct sha384_digest *SHA384_sw_final(struct sha384_ctx *const ctx);
+const struct sha384_digest *SHA384_sw_hash(const void *data, size_t len,
+ struct sha384_digest *digest);
+void SHA512_sw_init(struct sha512_ctx *const ctx);
+void SHA512_sw_update(struct sha512_ctx *const ctx, const void *data,
+ size_t len);
+const struct sha512_digest *SHA512_sw_final(struct sha512_ctx *ctx);
+const struct sha512_digest *SHA512_sw_hash(const void *data, size_t len,
+ struct sha512_digest *digest);
+
+/**
+ * HMAC SHA2-384 initialization.
+ */
+static inline void HMAC_SHA384_sw_init(struct hmac_sha384_ctx *ctx,
+ const void *key, size_t len)
+{
+ SHA384_sw_init(&ctx->hash);
+ HMAC_sw_init((union hmac_ctx *)ctx, key, len);
+}
+
+static inline void HMAC_SHA384_update(struct hmac_sha384_ctx *ctx,
+ const void *data, size_t len)
+{
+ ctx->hash.f->update((union hash_ctx *)&ctx->hash, data, len);
+}
+static inline const struct sha384_digest *
+HMAC_SHA384_final(struct hmac_sha384_ctx *ctx)
+{
+ return &ctx->hash.f->hmac_final((union hmac_ctx *)ctx)->sha384;
+}
+/**
+ * HMAC SHA2-512 initialization.
+ */
+static inline void HMAC_SHA512_sw_init(struct hmac_sha512_ctx *ctx,
+ const void *key, size_t len)
+{
+ SHA512_sw_init(&ctx->hash);
+ HMAC_sw_init((union hmac_ctx *)ctx, key, len);
+}
+static inline void HMAC_SHA512_update(struct hmac_sha512_ctx *ctx,
+ const void *data, size_t len)
+{
+ ctx->hash.f->update((union hash_ctx *)&ctx->hash, data, len);
+}
+static inline const struct sha512_digest *
+HMAC_SHA512_final(struct hmac_sha512_ctx *ctx)
+{
+ return &ctx->hash.f->hmac_final((union hmac_ctx *)ctx)->sha512;
+}
+#endif