This PR adds the implementations for sha{256, 384, 512} and makes use of the hash implementation when extending the PCRs of the respective banks rather than always using the sha1 and zero-padding it for the PCR banks of a TPM 2.
Regards, Stefan
Stefan Berger (2): Add implementations for sha256, sha384, and sha512 tcgbios: Use The proper sha function for each PCR bank
Makefile | 2 +- src/sha.h | 11 +++ src/sha1.c | 8 +- src/sha1.h | 8 -- src/sha256.c | 211 +++++++++++++++++++++++++++++++++++++++++++ src/sha512.c | 244 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/tcgbios.c | 60 +++++++++---- src/x86.h | 7 ++ 8 files changed, 522 insertions(+), 29 deletions(-) create mode 100644 src/sha.h delete mode 100644 src/sha1.h create mode 100644 src/sha256.c create mode 100644 src/sha512.c
Signed-off-by: Stefan Berger stefanb@linux.ibm.com --- Makefile | 2 +- src/sha.h | 11 +++ src/sha1.c | 8 +- src/sha1.h | 8 -- src/sha256.c | 211 +++++++++++++++++++++++++++++++++++++++++++ src/sha512.c | 244 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/tcgbios.c | 2 +- src/x86.h | 7 ++ 8 files changed, 479 insertions(+), 14 deletions(-) create mode 100644 src/sha.h delete mode 100644 src/sha1.h create mode 100644 src/sha256.c create mode 100644 src/sha512.c
diff --git a/Makefile b/Makefile index 3d8943e..c108f87 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,7 @@ SRC32FLAT=$(SRCBOTH) post.c e820map.c malloc.c romfile.c x86.c \ fw/mtrr.c fw/xen.c fw/acpi.c fw/mptable.c fw/pirtable.c \ fw/smbios.c fw/romfile_loader.c fw/dsdt_parser.c hw/virtio-ring.c \ hw/virtio-pci.c hw/virtio-mmio.c hw/virtio-blk.c hw/virtio-scsi.c \ - hw/tpm_drivers.c hw/nvme.c + hw/tpm_drivers.c hw/nvme.c sha256.c sha512.c SRC32SEG=string.c output.c pcibios.c apm.c stacks.c hw/pci.c hw/serialio.c DIRS=src src/hw src/fw vgasrc
diff --git a/src/sha.h b/src/sha.h new file mode 100644 index 0000000..edc9437 --- /dev/null +++ b/src/sha.h @@ -0,0 +1,11 @@ +#ifndef __SHA_H +#define __SHA_H + +#include "types.h" // u32 + +void sha1(const u8 *data, u32 length, u8 *hash); +void sha256(const u8 *data, u32 length, u8 *hash); +void sha384(const u8 *data, u32 length, u8 *hash); +void sha512(const u8 *data, u32 length, u8 *hash); + +#endif // sha.h diff --git a/src/sha1.c b/src/sha1.c index 2ecb3cb..e6d80c8 100644 --- a/src/sha1.c +++ b/src/sha1.c @@ -13,7 +13,7 @@
#include "config.h" #include "byteorder.h" // cpu_to_*, __swab64 -#include "sha1.h" // sha1 +#include "sha.h" // sha1 #include "string.h" // memcpy #include "x86.h" // rol
@@ -126,11 +126,11 @@ sha1_do(sha1_ctx *ctx, const u8 *data32, u32 length) }
-u32 +void sha1(const u8 *data, u32 length, u8 *hash) { if (!CONFIG_TCGBIOS) - return 0; + return;
sha1_ctx ctx = { .h[0] = 0x67452301, @@ -143,5 +143,5 @@ sha1(const u8 *data, u32 length, u8 *hash) sha1_do(&ctx, data, length); memcpy(hash, &ctx.h[0], 20);
- return 0; + return; } diff --git a/src/sha1.h b/src/sha1.h deleted file mode 100644 index 07aabf3..0000000 --- a/src/sha1.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __SHA1_H -#define __SHA1_H - -#include "types.h" // u32 - -u32 sha1(const u8 *data, u32 length, u8 *hash); - -#endif // sha1.h diff --git a/src/sha256.c b/src/sha256.c new file mode 100644 index 0000000..72c3df8 --- /dev/null +++ b/src/sha256.c @@ -0,0 +1,211 @@ +/***************************************************************************** + * Copyright (c) 2015-2020 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +/* + * See: NIST standard for SHA-256 in FIPS PUB 180-4 + */ + +#include "config.h" +#include "byteorder.h" +#include "sha.h" +#include "string.h" +#include "x86.h" + +typedef struct _sha256_ctx { + u32 h[8]; +} sha256_ctx; + +static inline u32 Ch(u32 x, u32 y, u32 z) +{ + return (x & y) | ((x ^ 0xffffffff) & z); +} + +static inline u32 Maj(u32 x, u32 y, u32 z) +{ + return (x & y) | (x & z) | (y & z); +} + +static inline u32 sum0(u32 x) +{ + return ror(x, 2) ^ ror(x, 13) ^ ror(x, 22); +} + +static inline u32 sum1(u32 x) +{ + return ror(x, 6) ^ ror(x, 11) ^ ror(x, 25); +} + +static inline u32 sigma0(u32 x) +{ + return ror(x, 7) ^ ror(x, 18) ^ (x >> 3); +} + +static inline u32 sigma1(u32 x) +{ + return ror(x, 17) ^ ror(x, 19) ^ (x >> 10); +} + +static void sha256_block(u32 *w, sha256_ctx *ctx) +{ + u32 t; + u32 a, b, c, d, e, f, g, h; + u32 T1, T2; + + /* + * FIPS 180-4 4.2.2: SHA256 Constants + */ + static const u32 sha_ko[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 + }; + + /* + * FIPS 180-4 6.2.2: step 1 + * + * 0 <= i <= 15: + * W(t) = M(t) + * 16 <= i <= 63: + * W(t) = sigma1(W(t-2)) + W(t-7) + sigma0(W(t-15)) + W(t-16) + */ + + /* w(0)..w(15) are in big endian format */ + for (t = 0; t <= 15; t++) + w[t] = be32_to_cpu(w[t]); + + for (t = 16; t <= 63; t++) + w[t] = sigma1(w[t-2]) + w[t-7] + sigma0(w[t-15]) + w[t-16]; + + /* + * step 2: a = H0, b = H1, c = H2, d = H3, e = H4, f = H5, g = H6, h = H7 + */ + a = ctx->h[0]; + b = ctx->h[1]; + c = ctx->h[2]; + d = ctx->h[3]; + e = ctx->h[4]; + f = ctx->h[5]; + g = ctx->h[6]; + h = ctx->h[7]; + + /* + * step 3: For i = 0 to 63: + * T1 = h + sum1(e) + Ch(e,f,g) + K(t) + W(t); + * T2 = sum0(a) + Maj(a,b,c) + * h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a + T1 + T2 + */ + for (t = 0; t <= 63; t++) { + T1 = h + sum1(e) + Ch(e, f, g) + sha_ko[t] + w[t]; + T2 = sum0(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + } + + /* + * step 4: + * H0 = a + H0, H1 = b + H1, H2 = c + H2, H3 = d + H3, H4 = e + H4 + */ + ctx->h[0] += a; + ctx->h[1] += b; + ctx->h[2] += c; + ctx->h[3] += d; + ctx->h[4] += e; + ctx->h[5] += f; + ctx->h[6] += g; + ctx->h[7] += h; +} + +static void sha256_do(sha256_ctx *ctx, const u8 *data32, u32 length) +{ + u32 offset; + u16 num; + u32 bits = 0; + u32 w[64]; + u64 tmp; + + /* treat data in 64-byte chunks */ + for (offset = 0; length - offset >= 64; offset += 64) { + memcpy(w, data32 + offset, 64); + sha256_block((u32 *)w, ctx); + bits += (64 * 8); + } + + /* last block with less than 64 bytes */ + num = length - offset; + bits += (num << 3); + + memcpy(w, data32 + offset, num); + /* + * FIPS 180-4 5.1: Padding the Message + */ + ((u8 *)w)[num] = 0x80; + if (64 - (num + 1) > 0) + memset( &((u8 *)w)[num + 1], 0, 64 - (num + 1)); + + if (num >= 56) { + /* cannot append number of bits here */ + sha256_block((u32 *)w, ctx); + memset(w, 0, 60); + } + + /* write number of bits to end of block */ + tmp = cpu_to_be64(bits); + memcpy(&w[14], &tmp, 8); + + sha256_block(w, ctx); + + /* need to switch result's endianness */ + for (num = 0; num < 8; num++) + ctx->h[num] = cpu_to_be32(ctx->h[num]); +} + +void sha256(const u8 *data, u32 length, u8 *hash) +{ + sha256_ctx ctx = { + .h = { + /* + * FIPS 180-4: 6.2.1 + * -> 5.3.3: initial hash value + */ + 0x6a09e667, + 0xbb67ae85, + 0x3c6ef372, + 0xa54ff53a, + 0x510e527f, + 0x9b05688c, + 0x1f83d9ab, + 0x5be0cd19 + } + }; + + sha256_do(&ctx, data, length); + memcpy(hash, ctx.h, sizeof(ctx.h)); +} diff --git a/src/sha512.c b/src/sha512.c new file mode 100644 index 0000000..fddd9fa --- /dev/null +++ b/src/sha512.c @@ -0,0 +1,244 @@ +/***************************************************************************** + * Copyright (c) 2021 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +/* + * See: NIST standard for SHA-512 and SHA-384 in FIPS PUB 180-4 & RFC 6234 + */ + +#include "config.h" +#include "byteorder.h" +#include "sha.h" +#include "string.h" + +typedef struct _sha512_ctx { + u64 h[8]; +} sha512_ctx; + +static inline u64 ror64(u64 x, u8 n) +{ + return (x >> n) | (x << (64 - n)); +} + +static inline u64 Ch64(u64 x, u64 y, u64 z) +{ + return (x & y) ^ ((x ^ 0xffffffffffffffffULL) & z); +} + +static inline u64 Maj64(u64 x, u64 y, u64 z) +{ + return (x & y) ^ (x & z) ^ (y & z); +} + +static inline u64 sum0_64(u64 x) +{ + return ror64(x, 28) ^ ror64(x, 34) ^ ror64(x, 39); +} + +static inline u64 sum1_64(u64 x) +{ + return ror64(x, 14) ^ ror64(x, 18) ^ ror64(x, 41); +} + +static inline u64 sigma0_64(u64 x) +{ + return ror64(x, 1) ^ ror64(x, 8) ^ (x >> 7); +} + +static inline u64 sigma1_64(u64 x) +{ + return ror64(x, 19) ^ ror64(x, 61) ^ (x >> 6); +} + +static void sha512_block(u64 *w, sha512_ctx *ctx) +{ + u32 t; + u64 a, b, c, d, e, f, g, h; + u64 T1, T2; + + /* + * FIPS 180-4 4.2.2: SHA512 Constants + */ + static const u64 sha_ko[80] = { + 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, + 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, + 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, + 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694, + 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, + 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, + 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, + 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70, + 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, + 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b, + 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, + 0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, + 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, + 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, + 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec, + 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, + 0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, + 0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b, + 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c, + 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817 + }; + + /* + * FIPS 180-4 6.4.2: step 1 + * + * 0 <= i <= 15: + * W(t) = M(t) + * 16 <= i <= 79: + * W(t) = sigma1(W(t-2)) + W(t-7) + sigma0(W(t-15)) + W(t-16) + */ + + /* w(0)..w(15) are in big endian format */ + for (t = 0; t <= 15; t++) + w[t] = be64_to_cpu(w[t]); + + for (t = 16; t <= 79; t++) + w[t] = sigma1_64(w[t-2]) + w[t-7] + sigma0_64(w[t-15]) + w[t-16]; + + /* + * step 2: a = H0, b = H1, c = H2, d = H3, e = H4, f = H5, g = H6, h = H7 + */ + a = ctx->h[0]; + b = ctx->h[1]; + c = ctx->h[2]; + d = ctx->h[3]; + e = ctx->h[4]; + f = ctx->h[5]; + g = ctx->h[6]; + h = ctx->h[7]; + + /* + * step 3: For i = 0 to 79: + * T1 = h + sum1(e) + Ch(e,f,g) + K(t) + W(t); + * T2 = sum0(a) + Maj(a,b,c) + * h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a + T1 + T2 + */ + for (t = 0; t <= 79; t++) { + T1 = h + sum1_64(e) + Ch64(e, f, g) + sha_ko[t] + w[t]; + T2 = sum0_64(a) + Maj64(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + } + + /* + * step 4: + * H0 = a + H0, H1 = b + H1, H2 = c + H2, H3 = d + H3, H4 = e + H4 + */ + ctx->h[0] += a; + ctx->h[1] += b; + ctx->h[2] += c; + ctx->h[3] += d; + ctx->h[4] += e; + ctx->h[5] += f; + ctx->h[6] += g; + ctx->h[7] += h; +} + +static void sha512_do(sha512_ctx *ctx, const u8 *data32, u32 length) +{ + u32 offset; + u16 num; + u64 bits = 0; + u64 w[80]; + u64 tmp; + + /* treat data in 128-byte/1024 bit chunks */ + for (offset = 0; length - offset >= 128; offset += 128) { + memcpy(w, data32 + offset, 128); + sha512_block(w, ctx); + bits += (128 * 8); + } + + /* last block with less than 128 bytes */ + num = length - offset; + bits += (num << 3); + + memcpy(w, data32 + offset, num); + /* + * FIPS 180-4 5.1: Padding the Message + */ + ((u8 *)w)[num] = 0x80; + if (128 - (num + 1) > 0) + memset( &((u8 *)w)[num + 1], 0, 128 - (num + 1)); + + if (num >= 112) { + /* cannot append number of bits here; + * need space for 128 bits (16 bytes) + */ + sha512_block((u64 *)w, ctx); + memset(w, 0, 128); + } + + /* write number of bits to end of the block; we write 64 bits */ + tmp = cpu_to_be64(bits); + memcpy(&w[15], &tmp, 8); + + sha512_block(w, ctx); + + /* need to switch result's endianness */ + for (num = 0; num < 8; num++) + ctx->h[num] = cpu_to_be64(ctx->h[num]); +} + +void sha384(const u8 *data, u32 length, u8 *hash) +{ + sha512_ctx ctx = { + .h = { + /* + * FIPS 180-4: 6.2.1 + * -> 5.3.4: initial hash value + */ + 0xcbbb9d5dc1059ed8, + 0x629a292a367cd507, + 0x9159015a3070dd17, + 0x152fecd8f70e5939, + 0x67332667ffc00b31, + 0x8eb44a8768581511, + 0xdb0c2e0d64f98fa7, + 0x47b5481dbefa4fa4 + } + }; + + sha512_do(&ctx, data, length); + memcpy(hash, ctx.h, 384/8); +} + +void sha512(const u8 *data, u32 length, u8 *hash) +{ + sha512_ctx ctx = { + .h = { + /* + * FIPS 180-4: 6.2.1 + * -> 5.3.5: initial hash value + */ + 0x6a09e667f3bcc908, + 0xbb67ae8584caa73b, + 0x3c6ef372fe94f82b, + 0xa54ff53a5f1d36f1, + 0x510e527fade682d1, + 0x9b05688c2b3e6c1f, + 0x1f83d9abfb41bd6b, + 0x5be0cd19137e2179 + } + }; + + sha512_do(&ctx, data, length); + memcpy(hash, ctx.h, sizeof(ctx.h)); +} diff --git a/src/tcgbios.c b/src/tcgbios.c index 4150aa0..a9d62c8 100644 --- a/src/tcgbios.c +++ b/src/tcgbios.c @@ -16,7 +16,7 @@ #include "fw/paravirt.h" // runningOnXen #include "hw/tpm_drivers.h" // tpm_drivers[] #include "output.h" // dprintf -#include "sha1.h" // sha1 +#include "sha.h" // sha1, sha256, ... #include "std/acpi.h" // RSDP_SIGNATURE, rsdt_descriptor #include "std/smbios.h" // struct smbios_entry_point #include "std/tcg.h" // TCG_PC_LOGOVERFLOW diff --git a/src/x86.h b/src/x86.h index c7bb60d..43a9e6d 100644 --- a/src/x86.h +++ b/src/x86.h @@ -140,6 +140,13 @@ static inline u32 rol(u32 val, u16 rol) { return res; }
+static inline u32 ror(u32 val, u16 ror) { + u32 res; + asm volatile("rorl %%cl, %%eax" + : "=a" (res) : "a" (val), "c" (ror)); + return res; +} + static inline void outb(u8 value, u16 port) { __asm__ __volatile__("outb %b0, %w1" : : "a"(value), "Nd"(port)); }
Dear Stefan,
Am 14.06.21 um 19:35 schrieb Stefan Berger:
Signed-off-by: Stefan Berger stefanb@linux.ibm.com
Makefile | 2 +- src/sha.h | 11 +++ src/sha1.c | 8 +- src/sha1.h | 8 -- src/sha256.c | 211 +++++++++++++++++++++++++++++++++++++++++++ src/sha512.c | 244 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/tcgbios.c | 2 +- src/x86.h | 7 ++ 8 files changed, 479 insertions(+), 14 deletions(-) create mode 100644 src/sha.h delete mode 100644 src/sha1.h create mode 100644 src/sha256.c create mode 100644 src/sha512.c
Thank you for the patch. As the diffstatt is quite big, I am wondering how the correctness can be verified? Did you run some tests? Can I reproduce this in QEMU somehow?
Did you copy the code from somewhere?
Kind regards,
Paul
diff --git a/Makefile b/Makefile index 3d8943e..c108f87 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,7 @@ SRC32FLAT=$(SRCBOTH) post.c e820map.c malloc.c romfile.c x86.c \ fw/mtrr.c fw/xen.c fw/acpi.c fw/mptable.c fw/pirtable.c \ fw/smbios.c fw/romfile_loader.c fw/dsdt_parser.c hw/virtio-ring.c \ hw/virtio-pci.c hw/virtio-mmio.c hw/virtio-blk.c hw/virtio-scsi.c \
- hw/tpm_drivers.c hw/nvme.c
- hw/tpm_drivers.c hw/nvme.c sha256.c sha512.c SRC32SEG=string.c output.c pcibios.c apm.c stacks.c hw/pci.c hw/serialio.c DIRS=src src/hw src/fw vgasrc
diff --git a/src/sha.h b/src/sha.h new file mode 100644 index 0000000..edc9437 --- /dev/null +++ b/src/sha.h @@ -0,0 +1,11 @@ +#ifndef __SHA_H +#define __SHA_H
+#include "types.h" // u32
+void sha1(const u8 *data, u32 length, u8 *hash); +void sha256(const u8 *data, u32 length, u8 *hash); +void sha384(const u8 *data, u32 length, u8 *hash); +void sha512(const u8 *data, u32 length, u8 *hash);
+#endif // sha.h diff --git a/src/sha1.c b/src/sha1.c index 2ecb3cb..e6d80c8 100644 --- a/src/sha1.c +++ b/src/sha1.c @@ -13,7 +13,7 @@
#include "config.h" #include "byteorder.h" // cpu_to_*, __swab64 -#include "sha1.h" // sha1 +#include "sha.h" // sha1 #include "string.h" // memcpy #include "x86.h" // rol
@@ -126,11 +126,11 @@ sha1_do(sha1_ctx *ctx, const u8 *data32, u32 length) }
-u32 +void sha1(const u8 *data, u32 length, u8 *hash) { if (!CONFIG_TCGBIOS)
return 0;
return; sha1_ctx ctx = { .h[0] = 0x67452301,
@@ -143,5 +143,5 @@ sha1(const u8 *data, u32 length, u8 *hash) sha1_do(&ctx, data, length); memcpy(hash, &ctx.h[0], 20);
- return 0;
- return; }
diff --git a/src/sha1.h b/src/sha1.h deleted file mode 100644 index 07aabf3..0000000 --- a/src/sha1.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __SHA1_H -#define __SHA1_H
-#include "types.h" // u32
-u32 sha1(const u8 *data, u32 length, u8 *hash);
-#endif // sha1.h diff --git a/src/sha256.c b/src/sha256.c new file mode 100644 index 0000000..72c3df8 --- /dev/null +++ b/src/sha256.c @@ -0,0 +1,211 @@ +/*****************************************************************************
- Copyright (c) 2015-2020 IBM Corporation
- All rights reserved.
- This program and the accompanying materials
- are made available under the terms of the BSD License
- which accompanies this distribution, and is available at
- Contributors:
IBM Corporation - initial implementation
- *****************************************************************************/
+/*
- See: NIST standard for SHA-256 in FIPS PUB 180-4
- */
+#include "config.h" +#include "byteorder.h" +#include "sha.h" +#include "string.h" +#include "x86.h"
+typedef struct _sha256_ctx {
- u32 h[8];
+} sha256_ctx;
+static inline u32 Ch(u32 x, u32 y, u32 z) +{
- return (x & y) | ((x ^ 0xffffffff) & z);
+}
+static inline u32 Maj(u32 x, u32 y, u32 z) +{
- return (x & y) | (x & z) | (y & z);
+}
+static inline u32 sum0(u32 x) +{
- return ror(x, 2) ^ ror(x, 13) ^ ror(x, 22);
+}
+static inline u32 sum1(u32 x) +{
- return ror(x, 6) ^ ror(x, 11) ^ ror(x, 25);
+}
+static inline u32 sigma0(u32 x) +{
- return ror(x, 7) ^ ror(x, 18) ^ (x >> 3);
+}
+static inline u32 sigma1(u32 x) +{
- return ror(x, 17) ^ ror(x, 19) ^ (x >> 10);
+}
+static void sha256_block(u32 *w, sha256_ctx *ctx) +{
- u32 t;
- u32 a, b, c, d, e, f, g, h;
- u32 T1, T2;
- /*
* FIPS 180-4 4.2.2: SHA256 Constants
*/
- static const u32 sha_ko[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
- };
- /*
* FIPS 180-4 6.2.2: step 1
*
* 0 <= i <= 15:
* W(t) = M(t)
* 16 <= i <= 63:
* W(t) = sigma1(W(t-2)) + W(t-7) + sigma0(W(t-15)) + W(t-16)
*/
- /* w(0)..w(15) are in big endian format */
- for (t = 0; t <= 15; t++)
w[t] = be32_to_cpu(w[t]);
- for (t = 16; t <= 63; t++)
w[t] = sigma1(w[t-2]) + w[t-7] + sigma0(w[t-15]) + w[t-16];
- /*
* step 2: a = H0, b = H1, c = H2, d = H3, e = H4, f = H5, g = H6, h = H7
*/
- a = ctx->h[0];
- b = ctx->h[1];
- c = ctx->h[2];
- d = ctx->h[3];
- e = ctx->h[4];
- f = ctx->h[5];
- g = ctx->h[6];
- h = ctx->h[7];
- /*
* step 3: For i = 0 to 63:
* T1 = h + sum1(e) + Ch(e,f,g) + K(t) + W(t);
* T2 = sum0(a) + Maj(a,b,c)
* h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a + T1 + T2
*/
- for (t = 0; t <= 63; t++) {
T1 = h + sum1(e) + Ch(e, f, g) + sha_ko[t] + w[t];
T2 = sum0(a) + Maj(a, b, c);
h = g;
g = f;
f = e;
e = d + T1;
d = c;
c = b;
b = a;
a = T1 + T2;
- }
- /*
* step 4:
* H0 = a + H0, H1 = b + H1, H2 = c + H2, H3 = d + H3, H4 = e + H4
*/
- ctx->h[0] += a;
- ctx->h[1] += b;
- ctx->h[2] += c;
- ctx->h[3] += d;
- ctx->h[4] += e;
- ctx->h[5] += f;
- ctx->h[6] += g;
- ctx->h[7] += h;
+}
+static void sha256_do(sha256_ctx *ctx, const u8 *data32, u32 length) +{
- u32 offset;
- u16 num;
- u32 bits = 0;
- u32 w[64];
- u64 tmp;
- /* treat data in 64-byte chunks */
- for (offset = 0; length - offset >= 64; offset += 64) {
memcpy(w, data32 + offset, 64);
sha256_block((u32 *)w, ctx);
bits += (64 * 8);
- }
- /* last block with less than 64 bytes */
- num = length - offset;
- bits += (num << 3);
- memcpy(w, data32 + offset, num);
- /*
* FIPS 180-4 5.1: Padding the Message
*/
- ((u8 *)w)[num] = 0x80;
- if (64 - (num + 1) > 0)
memset( &((u8 *)w)[num + 1], 0, 64 - (num + 1));
- if (num >= 56) {
/* cannot append number of bits here */
sha256_block((u32 *)w, ctx);
memset(w, 0, 60);
- }
- /* write number of bits to end of block */
- tmp = cpu_to_be64(bits);
- memcpy(&w[14], &tmp, 8);
- sha256_block(w, ctx);
- /* need to switch result's endianness */
- for (num = 0; num < 8; num++)
ctx->h[num] = cpu_to_be32(ctx->h[num]);
+}
+void sha256(const u8 *data, u32 length, u8 *hash) +{
- sha256_ctx ctx = {
.h = {
/*
* FIPS 180-4: 6.2.1
* -> 5.3.3: initial hash value
*/
0x6a09e667,
0xbb67ae85,
0x3c6ef372,
0xa54ff53a,
0x510e527f,
0x9b05688c,
0x1f83d9ab,
0x5be0cd19
}
- };
- sha256_do(&ctx, data, length);
- memcpy(hash, ctx.h, sizeof(ctx.h));
+} diff --git a/src/sha512.c b/src/sha512.c new file mode 100644 index 0000000..fddd9fa --- /dev/null +++ b/src/sha512.c @@ -0,0 +1,244 @@ +/*****************************************************************************
- Copyright (c) 2021 IBM Corporation
- All rights reserved.
- This program and the accompanying materials
- are made available under the terms of the BSD License
- which accompanies this distribution, and is available at
- Contributors:
IBM Corporation - initial implementation
- *****************************************************************************/
+/*
- See: NIST standard for SHA-512 and SHA-384 in FIPS PUB 180-4 & RFC 6234
- */
+#include "config.h" +#include "byteorder.h" +#include "sha.h" +#include "string.h"
+typedef struct _sha512_ctx {
- u64 h[8];
+} sha512_ctx;
+static inline u64 ror64(u64 x, u8 n) +{
- return (x >> n) | (x << (64 - n));
+}
+static inline u64 Ch64(u64 x, u64 y, u64 z) +{
- return (x & y) ^ ((x ^ 0xffffffffffffffffULL) & z);
+}
+static inline u64 Maj64(u64 x, u64 y, u64 z) +{
- return (x & y) ^ (x & z) ^ (y & z);
+}
+static inline u64 sum0_64(u64 x) +{
- return ror64(x, 28) ^ ror64(x, 34) ^ ror64(x, 39);
+}
+static inline u64 sum1_64(u64 x) +{
- return ror64(x, 14) ^ ror64(x, 18) ^ ror64(x, 41);
+}
+static inline u64 sigma0_64(u64 x) +{
- return ror64(x, 1) ^ ror64(x, 8) ^ (x >> 7);
+}
+static inline u64 sigma1_64(u64 x) +{
- return ror64(x, 19) ^ ror64(x, 61) ^ (x >> 6);
+}
+static void sha512_block(u64 *w, sha512_ctx *ctx) +{
- u32 t;
- u64 a, b, c, d, e, f, g, h;
- u64 T1, T2;
- /*
* FIPS 180-4 4.2.2: SHA512 Constants
*/
- static const u64 sha_ko[80] = {
0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694,
0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4,
0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70,
0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30,
0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8,
0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3,
0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b,
0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817
- };
- /*
* FIPS 180-4 6.4.2: step 1
*
* 0 <= i <= 15:
* W(t) = M(t)
* 16 <= i <= 79:
* W(t) = sigma1(W(t-2)) + W(t-7) + sigma0(W(t-15)) + W(t-16)
*/
- /* w(0)..w(15) are in big endian format */
- for (t = 0; t <= 15; t++)
w[t] = be64_to_cpu(w[t]);
- for (t = 16; t <= 79; t++)
w[t] = sigma1_64(w[t-2]) + w[t-7] + sigma0_64(w[t-15]) + w[t-16];
- /*
* step 2: a = H0, b = H1, c = H2, d = H3, e = H4, f = H5, g = H6, h = H7
*/
- a = ctx->h[0];
- b = ctx->h[1];
- c = ctx->h[2];
- d = ctx->h[3];
- e = ctx->h[4];
- f = ctx->h[5];
- g = ctx->h[6];
- h = ctx->h[7];
- /*
* step 3: For i = 0 to 79:
* T1 = h + sum1(e) + Ch(e,f,g) + K(t) + W(t);
* T2 = sum0(a) + Maj(a,b,c)
* h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a + T1 + T2
*/
- for (t = 0; t <= 79; t++) {
T1 = h + sum1_64(e) + Ch64(e, f, g) + sha_ko[t] + w[t];
T2 = sum0_64(a) + Maj64(a, b, c);
h = g;
g = f;
f = e;
e = d + T1;
d = c;
c = b;
b = a;
a = T1 + T2;
- }
- /*
* step 4:
* H0 = a + H0, H1 = b + H1, H2 = c + H2, H3 = d + H3, H4 = e + H4
*/
- ctx->h[0] += a;
- ctx->h[1] += b;
- ctx->h[2] += c;
- ctx->h[3] += d;
- ctx->h[4] += e;
- ctx->h[5] += f;
- ctx->h[6] += g;
- ctx->h[7] += h;
+}
+static void sha512_do(sha512_ctx *ctx, const u8 *data32, u32 length) +{
- u32 offset;
- u16 num;
- u64 bits = 0;
- u64 w[80];
- u64 tmp;
- /* treat data in 128-byte/1024 bit chunks */
- for (offset = 0; length - offset >= 128; offset += 128) {
memcpy(w, data32 + offset, 128);
sha512_block(w, ctx);
bits += (128 * 8);
- }
- /* last block with less than 128 bytes */
- num = length - offset;
- bits += (num << 3);
- memcpy(w, data32 + offset, num);
- /*
* FIPS 180-4 5.1: Padding the Message
*/
- ((u8 *)w)[num] = 0x80;
- if (128 - (num + 1) > 0)
memset( &((u8 *)w)[num + 1], 0, 128 - (num + 1));
- if (num >= 112) {
/* cannot append number of bits here;
* need space for 128 bits (16 bytes)
*/
sha512_block((u64 *)w, ctx);
memset(w, 0, 128);
- }
- /* write number of bits to end of the block; we write 64 bits */
- tmp = cpu_to_be64(bits);
- memcpy(&w[15], &tmp, 8);
- sha512_block(w, ctx);
- /* need to switch result's endianness */
- for (num = 0; num < 8; num++)
ctx->h[num] = cpu_to_be64(ctx->h[num]);
+}
+void sha384(const u8 *data, u32 length, u8 *hash) +{
- sha512_ctx ctx = {
.h = {
/*
* FIPS 180-4: 6.2.1
* -> 5.3.4: initial hash value
*/
0xcbbb9d5dc1059ed8,
0x629a292a367cd507,
0x9159015a3070dd17,
0x152fecd8f70e5939,
0x67332667ffc00b31,
0x8eb44a8768581511,
0xdb0c2e0d64f98fa7,
0x47b5481dbefa4fa4
}
- };
- sha512_do(&ctx, data, length);
- memcpy(hash, ctx.h, 384/8);
+}
+void sha512(const u8 *data, u32 length, u8 *hash) +{
- sha512_ctx ctx = {
.h = {
/*
* FIPS 180-4: 6.2.1
* -> 5.3.5: initial hash value
*/
0x6a09e667f3bcc908,
0xbb67ae8584caa73b,
0x3c6ef372fe94f82b,
0xa54ff53a5f1d36f1,
0x510e527fade682d1,
0x9b05688c2b3e6c1f,
0x1f83d9abfb41bd6b,
0x5be0cd19137e2179
}
- };
- sha512_do(&ctx, data, length);
- memcpy(hash, ctx.h, sizeof(ctx.h));
+} diff --git a/src/tcgbios.c b/src/tcgbios.c index 4150aa0..a9d62c8 100644 --- a/src/tcgbios.c +++ b/src/tcgbios.c @@ -16,7 +16,7 @@ #include "fw/paravirt.h" // runningOnXen #include "hw/tpm_drivers.h" // tpm_drivers[] #include "output.h" // dprintf -#include "sha1.h" // sha1 +#include "sha.h" // sha1, sha256, ... #include "std/acpi.h" // RSDP_SIGNATURE, rsdt_descriptor #include "std/smbios.h" // struct smbios_entry_point #include "std/tcg.h" // TCG_PC_LOGOVERFLOW diff --git a/src/x86.h b/src/x86.h index c7bb60d..43a9e6d 100644 --- a/src/x86.h +++ b/src/x86.h @@ -140,6 +140,13 @@ static inline u32 rol(u32 val, u16 rol) { return res; }
+static inline u32 ror(u32 val, u16 ror) {
- u32 res;
- asm volatile("rorl %%cl, %%eax"
: "=a" (res) : "a" (val), "c" (ror));
- return res;
+}
- static inline void outb(u8 value, u16 port) { __asm__ __volatile__("outb %b0, %w1" : : "a"(value), "Nd"(port)); }
On 6/15/21 4:36 AM, Paul Menzel wrote:
Dear Stefan,
Am 14.06.21 um 19:35 schrieb Stefan Berger:
Signed-off-by: Stefan Berger stefanb@linux.ibm.com
Makefile | 2 +- src/sha.h | 11 +++ src/sha1.c | 8 +- src/sha1.h | 8 -- src/sha256.c | 211 +++++++++++++++++++++++++++++++++++++++++++ src/sha512.c | 244 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/tcgbios.c | 2 +- src/x86.h | 7 ++ 8 files changed, 479 insertions(+), 14 deletions(-) create mode 100644 src/sha.h delete mode 100644 src/sha1.h create mode 100644 src/sha256.c create mode 100644 src/sha512.c
Thank you for the patch. As the diffstatt is quite big, I am wondering how the correctness can be verified? Did you run some tests? Can I reproduce this in QEMU somehow?
I had tested the sha implementations with the first 3 of these vectors here and some other test data measured by trusted grub (on SLOF):
https://www.di-mgt.com.au/sha_testvectors.html
I ran tests inside QEMU with Fedora 34 using the tss2-1.6.0 package for example:
cp /sys/kernel/security/tpm/binary_bios_measurements ./
tsseventextend -if ./binary_bios_measurements -v -sim | less
Did you copy the code from somewhere?
No, it's not copied. SLOF has had the sha256 implementation for quite a while (I contributed it) and sha512 and sha384 are 64 bit derivatives more or less of the sha256 implementation.
Stefan
Kind regards,
Paul
diff --git a/Makefile b/Makefile index 3d8943e..c108f87 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,7 @@ SRC32FLAT=$(SRCBOTH) post.c e820map.c malloc.c romfile.c x86.c \ fw/mtrr.c fw/xen.c fw/acpi.c fw/mptable.c fw/pirtable.c \ fw/smbios.c fw/romfile_loader.c fw/dsdt_parser.c hw/virtio-ring.c \ hw/virtio-pci.c hw/virtio-mmio.c hw/virtio-blk.c hw/virtio-scsi.c \ - hw/tpm_drivers.c hw/nvme.c + hw/tpm_drivers.c hw/nvme.c sha256.c sha512.c SRC32SEG=string.c output.c pcibios.c apm.c stacks.c hw/pci.c hw/serialio.c DIRS=src src/hw src/fw vgasrc diff --git a/src/sha.h b/src/sha.h new file mode 100644 index 0000000..edc9437 --- /dev/null +++ b/src/sha.h @@ -0,0 +1,11 @@ +#ifndef __SHA_H +#define __SHA_H
+#include "types.h" // u32
+void sha1(const u8 *data, u32 length, u8 *hash); +void sha256(const u8 *data, u32 length, u8 *hash); +void sha384(const u8 *data, u32 length, u8 *hash); +void sha512(const u8 *data, u32 length, u8 *hash);
+#endif // sha.h diff --git a/src/sha1.c b/src/sha1.c index 2ecb3cb..e6d80c8 100644 --- a/src/sha1.c +++ b/src/sha1.c @@ -13,7 +13,7 @@ #include "config.h" #include "byteorder.h" // cpu_to_*, __swab64 -#include "sha1.h" // sha1 +#include "sha.h" // sha1 #include "string.h" // memcpy #include "x86.h" // rol @@ -126,11 +126,11 @@ sha1_do(sha1_ctx *ctx, const u8 *data32, u32 length) } -u32 +void sha1(const u8 *data, u32 length, u8 *hash) { if (!CONFIG_TCGBIOS) - return 0; + return; sha1_ctx ctx = { .h[0] = 0x67452301, @@ -143,5 +143,5 @@ sha1(const u8 *data, u32 length, u8 *hash) sha1_do(&ctx, data, length); memcpy(hash, &ctx.h[0], 20); - return 0; + return; } diff --git a/src/sha1.h b/src/sha1.h deleted file mode 100644 index 07aabf3..0000000 --- a/src/sha1.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __SHA1_H -#define __SHA1_H
-#include "types.h" // u32
-u32 sha1(const u8 *data, u32 length, u8 *hash);
-#endif // sha1.h diff --git a/src/sha256.c b/src/sha256.c new file mode 100644 index 0000000..72c3df8 --- /dev/null +++ b/src/sha256.c @@ -0,0 +1,211 @@ +/*****************************************************************************
- Copyright (c) 2015-2020 IBM Corporation
- All rights reserved.
- This program and the accompanying materials
- are made available under the terms of the BSD License
- which accompanies this distribution, and is available at
- Contributors:
- * IBM Corporation - initial implementation
*****************************************************************************/
+/*
- * See: NIST standard for SHA-256 in FIPS PUB 180-4
- */
+#include "config.h" +#include "byteorder.h" +#include "sha.h" +#include "string.h" +#include "x86.h"
+typedef struct _sha256_ctx { + u32 h[8]; +} sha256_ctx;
+static inline u32 Ch(u32 x, u32 y, u32 z) +{ + return (x & y) | ((x ^ 0xffffffff) & z); +}
+static inline u32 Maj(u32 x, u32 y, u32 z) +{ + return (x & y) | (x & z) | (y & z); +}
+static inline u32 sum0(u32 x) +{ + return ror(x, 2) ^ ror(x, 13) ^ ror(x, 22); +}
+static inline u32 sum1(u32 x) +{ + return ror(x, 6) ^ ror(x, 11) ^ ror(x, 25); +}
+static inline u32 sigma0(u32 x) +{ + return ror(x, 7) ^ ror(x, 18) ^ (x >> 3); +}
+static inline u32 sigma1(u32 x) +{ + return ror(x, 17) ^ ror(x, 19) ^ (x >> 10); +}
+static void sha256_block(u32 *w, sha256_ctx *ctx) +{ + u32 t; + u32 a, b, c, d, e, f, g, h; + u32 T1, T2;
+ /* + * FIPS 180-4 4.2.2: SHA256 Constants + */ + static const u32 sha_ko[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 + };
+ /* + * FIPS 180-4 6.2.2: step 1 + * + * 0 <= i <= 15: + * W(t) = M(t) + * 16 <= i <= 63: + * W(t) = sigma1(W(t-2)) + W(t-7) + sigma0(W(t-15)) + W(t-16) + */
+ /* w(0)..w(15) are in big endian format */ + for (t = 0; t <= 15; t++) + w[t] = be32_to_cpu(w[t]);
+ for (t = 16; t <= 63; t++) + w[t] = sigma1(w[t-2]) + w[t-7] + sigma0(w[t-15]) + w[t-16];
+ /* + * step 2: a = H0, b = H1, c = H2, d = H3, e = H4, f = H5, g = H6, h = H7 + */ + a = ctx->h[0]; + b = ctx->h[1]; + c = ctx->h[2]; + d = ctx->h[3]; + e = ctx->h[4]; + f = ctx->h[5]; + g = ctx->h[6]; + h = ctx->h[7];
+ /* + * step 3: For i = 0 to 63: + * T1 = h + sum1(e) + Ch(e,f,g) + K(t) + W(t); + * T2 = sum0(a) + Maj(a,b,c) + * h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a + T1 + T2 + */ + for (t = 0; t <= 63; t++) { + T1 = h + sum1(e) + Ch(e, f, g) + sha_ko[t] + w[t]; + T2 = sum0(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + }
+ /* + * step 4: + * H0 = a + H0, H1 = b + H1, H2 = c + H2, H3 = d + H3, H4 = e
- H4
+ */ + ctx->h[0] += a; + ctx->h[1] += b; + ctx->h[2] += c; + ctx->h[3] += d; + ctx->h[4] += e; + ctx->h[5] += f; + ctx->h[6] += g; + ctx->h[7] += h; +}
+static void sha256_do(sha256_ctx *ctx, const u8 *data32, u32 length) +{ + u32 offset; + u16 num; + u32 bits = 0; + u32 w[64]; + u64 tmp;
+ /* treat data in 64-byte chunks */ + for (offset = 0; length - offset >= 64; offset += 64) { + memcpy(w, data32 + offset, 64); + sha256_block((u32 *)w, ctx); + bits += (64 * 8); + }
+ /* last block with less than 64 bytes */ + num = length - offset; + bits += (num << 3);
+ memcpy(w, data32 + offset, num); + /* + * FIPS 180-4 5.1: Padding the Message + */ + ((u8 *)w)[num] = 0x80; + if (64 - (num + 1) > 0) + memset( &((u8 *)w)[num + 1], 0, 64 - (num + 1));
+ if (num >= 56) { + /* cannot append number of bits here */ + sha256_block((u32 *)w, ctx); + memset(w, 0, 60); + }
+ /* write number of bits to end of block */ + tmp = cpu_to_be64(bits); + memcpy(&w[14], &tmp, 8);
+ sha256_block(w, ctx);
+ /* need to switch result's endianness */ + for (num = 0; num < 8; num++) + ctx->h[num] = cpu_to_be32(ctx->h[num]); +}
+void sha256(const u8 *data, u32 length, u8 *hash) +{ + sha256_ctx ctx = { + .h = { + /* + * FIPS 180-4: 6.2.1 + * -> 5.3.3: initial hash value + */ + 0x6a09e667, + 0xbb67ae85, + 0x3c6ef372, + 0xa54ff53a, + 0x510e527f, + 0x9b05688c, + 0x1f83d9ab, + 0x5be0cd19 + } + };
+ sha256_do(&ctx, data, length); + memcpy(hash, ctx.h, sizeof(ctx.h)); +} diff --git a/src/sha512.c b/src/sha512.c new file mode 100644 index 0000000..fddd9fa --- /dev/null +++ b/src/sha512.c @@ -0,0 +1,244 @@ +/*****************************************************************************
- Copyright (c) 2021 IBM Corporation
- All rights reserved.
- This program and the accompanying materials
- are made available under the terms of the BSD License
- which accompanies this distribution, and is available at
- Contributors:
- * IBM Corporation - initial implementation
*****************************************************************************/
+/*
- * See: NIST standard for SHA-512 and SHA-384 in FIPS PUB 180-4 &
RFC 6234
- */
+#include "config.h" +#include "byteorder.h" +#include "sha.h" +#include "string.h"
+typedef struct _sha512_ctx { + u64 h[8]; +} sha512_ctx;
+static inline u64 ror64(u64 x, u8 n) +{ + return (x >> n) | (x << (64 - n)); +}
+static inline u64 Ch64(u64 x, u64 y, u64 z) +{ + return (x & y) ^ ((x ^ 0xffffffffffffffffULL) & z); +}
+static inline u64 Maj64(u64 x, u64 y, u64 z) +{ + return (x & y) ^ (x & z) ^ (y & z); +}
+static inline u64 sum0_64(u64 x) +{ + return ror64(x, 28) ^ ror64(x, 34) ^ ror64(x, 39); +}
+static inline u64 sum1_64(u64 x) +{ + return ror64(x, 14) ^ ror64(x, 18) ^ ror64(x, 41); +}
+static inline u64 sigma0_64(u64 x) +{ + return ror64(x, 1) ^ ror64(x, 8) ^ (x >> 7); +}
+static inline u64 sigma1_64(u64 x) +{ + return ror64(x, 19) ^ ror64(x, 61) ^ (x >> 6); +}
+static void sha512_block(u64 *w, sha512_ctx *ctx) +{ + u32 t; + u64 a, b, c, d, e, f, g, h; + u64 T1, T2;
+ /* + * FIPS 180-4 4.2.2: SHA512 Constants + */ + static const u64 sha_ko[80] = { + 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, + 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, + 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, + 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694, + 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, + 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, + 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, + 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70, + 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, + 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b, + 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, + 0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, + 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, + 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, + 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec, + 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, + 0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, + 0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b, + 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c, + 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817 + };
+ /* + * FIPS 180-4 6.4.2: step 1 + * + * 0 <= i <= 15: + * W(t) = M(t) + * 16 <= i <= 79: + * W(t) = sigma1(W(t-2)) + W(t-7) + sigma0(W(t-15)) + W(t-16) + */
+ /* w(0)..w(15) are in big endian format */ + for (t = 0; t <= 15; t++) + w[t] = be64_to_cpu(w[t]);
+ for (t = 16; t <= 79; t++) + w[t] = sigma1_64(w[t-2]) + w[t-7] + sigma0_64(w[t-15]) + w[t-16];
+ /* + * step 2: a = H0, b = H1, c = H2, d = H3, e = H4, f = H5, g = H6, h = H7 + */ + a = ctx->h[0]; + b = ctx->h[1]; + c = ctx->h[2]; + d = ctx->h[3]; + e = ctx->h[4]; + f = ctx->h[5]; + g = ctx->h[6]; + h = ctx->h[7];
+ /* + * step 3: For i = 0 to 79: + * T1 = h + sum1(e) + Ch(e,f,g) + K(t) + W(t); + * T2 = sum0(a) + Maj(a,b,c) + * h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a + T1 + T2 + */ + for (t = 0; t <= 79; t++) { + T1 = h + sum1_64(e) + Ch64(e, f, g) + sha_ko[t] + w[t]; + T2 = sum0_64(a) + Maj64(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + }
+ /* + * step 4: + * H0 = a + H0, H1 = b + H1, H2 = c + H2, H3 = d + H3, H4 = e
- H4
+ */ + ctx->h[0] += a; + ctx->h[1] += b; + ctx->h[2] += c; + ctx->h[3] += d; + ctx->h[4] += e; + ctx->h[5] += f; + ctx->h[6] += g; + ctx->h[7] += h; +}
+static void sha512_do(sha512_ctx *ctx, const u8 *data32, u32 length) +{ + u32 offset; + u16 num; + u64 bits = 0; + u64 w[80]; + u64 tmp;
+ /* treat data in 128-byte/1024 bit chunks */ + for (offset = 0; length - offset >= 128; offset += 128) { + memcpy(w, data32 + offset, 128); + sha512_block(w, ctx); + bits += (128 * 8); + }
+ /* last block with less than 128 bytes */ + num = length - offset; + bits += (num << 3);
+ memcpy(w, data32 + offset, num); + /* + * FIPS 180-4 5.1: Padding the Message + */ + ((u8 *)w)[num] = 0x80; + if (128 - (num + 1) > 0) + memset( &((u8 *)w)[num + 1], 0, 128 - (num + 1));
+ if (num >= 112) { + /* cannot append number of bits here; + * need space for 128 bits (16 bytes) + */ + sha512_block((u64 *)w, ctx); + memset(w, 0, 128); + }
+ /* write number of bits to end of the block; we write 64 bits */ + tmp = cpu_to_be64(bits); + memcpy(&w[15], &tmp, 8);
+ sha512_block(w, ctx);
+ /* need to switch result's endianness */ + for (num = 0; num < 8; num++) + ctx->h[num] = cpu_to_be64(ctx->h[num]); +}
+void sha384(const u8 *data, u32 length, u8 *hash) +{ + sha512_ctx ctx = { + .h = { + /* + * FIPS 180-4: 6.2.1 + * -> 5.3.4: initial hash value + */ + 0xcbbb9d5dc1059ed8, + 0x629a292a367cd507, + 0x9159015a3070dd17, + 0x152fecd8f70e5939, + 0x67332667ffc00b31, + 0x8eb44a8768581511, + 0xdb0c2e0d64f98fa7, + 0x47b5481dbefa4fa4 + } + };
+ sha512_do(&ctx, data, length); + memcpy(hash, ctx.h, 384/8); +}
+void sha512(const u8 *data, u32 length, u8 *hash) +{ + sha512_ctx ctx = { + .h = { + /* + * FIPS 180-4: 6.2.1 + * -> 5.3.5: initial hash value + */ + 0x6a09e667f3bcc908, + 0xbb67ae8584caa73b, + 0x3c6ef372fe94f82b, + 0xa54ff53a5f1d36f1, + 0x510e527fade682d1, + 0x9b05688c2b3e6c1f, + 0x1f83d9abfb41bd6b, + 0x5be0cd19137e2179 + } + };
+ sha512_do(&ctx, data, length); + memcpy(hash, ctx.h, sizeof(ctx.h)); +} diff --git a/src/tcgbios.c b/src/tcgbios.c index 4150aa0..a9d62c8 100644 --- a/src/tcgbios.c +++ b/src/tcgbios.c @@ -16,7 +16,7 @@ #include "fw/paravirt.h" // runningOnXen #include "hw/tpm_drivers.h" // tpm_drivers[] #include "output.h" // dprintf -#include "sha1.h" // sha1 +#include "sha.h" // sha1, sha256, ... #include "std/acpi.h" // RSDP_SIGNATURE, rsdt_descriptor #include "std/smbios.h" // struct smbios_entry_point #include "std/tcg.h" // TCG_PC_LOGOVERFLOW diff --git a/src/x86.h b/src/x86.h index c7bb60d..43a9e6d 100644 --- a/src/x86.h +++ b/src/x86.h @@ -140,6 +140,13 @@ static inline u32 rol(u32 val, u16 rol) { return res; } +static inline u32 ror(u32 val, u16 ror) { + u32 res; + asm volatile("rorl %%cl, %%eax" + : "=a" (res) : "a" (val), "c" (ror)); + return res; +}
static inline void outb(u8 value, u16 port) { __asm__ __volatile__("outb %b0, %w1" : : "a"(value), "Nd"(port)); }
On 6/15/21 7:53 AM, Stefan Berger wrote:
On 6/15/21 4:36 AM, Paul Menzel wrote:
Dear Stefan,
Am 14.06.21 um 19:35 schrieb Stefan Berger:
Signed-off-by: Stefan Berger stefanb@linux.ibm.com
Makefile | 2 +- src/sha.h | 11 +++ src/sha1.c | 8 +- src/sha1.h | 8 -- src/sha256.c | 211 +++++++++++++++++++++++++++++++++++++++++++ src/sha512.c | 244 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/tcgbios.c | 2 +- src/x86.h | 7 ++ 8 files changed, 479 insertions(+), 14 deletions(-) create mode 100644 src/sha.h delete mode 100644 src/sha1.h create mode 100644 src/sha256.c create mode 100644 src/sha512.c
Thank you for the patch. As the diffstatt is quite big, I am wondering how the correctness can be verified? Did you run some tests? Can I reproduce this in QEMU somehow?
I had tested the sha implementations with the first 3 of these vectors here and some other test data measured by trusted grub (on SLOF):
A critical input case for sha512 is at 112 and 113 bytes for example. This is where the input block contains too many bytes to append the 1024 bit length indicator. This is tested for here and I verify it via shell 'echo -en "${i}" | sha512sum':
https://github.com/stefanberger/SLOF-tpm/commit/bdddbb16a0d8215552d8b6a4447b...
Stefan
Instead of just using sha1 for all PCR banks (and truncating the value or zero-padding it) use the proper hash function for each one of the banks. For unimplemented hashes, fill the buffer with 0xff.
Signed-off-by: Stefan Berger stefanb@linux.ibm.com --- src/tcgbios.c | 58 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 15 deletions(-)
diff --git a/src/tcgbios.c b/src/tcgbios.c index a9d62c8..02921d8 100644 --- a/src/tcgbios.c +++ b/src/tcgbios.c @@ -167,27 +167,32 @@ static const struct hash_parameters { u8 hashalg_flag; u8 hash_buffersize; const char *name; + void (*hashfunc)(const u8 *data, u32 length, u8 *hash); } hash_parameters[] = { { .hashalg = TPM2_ALG_SHA1, .hashalg_flag = TPM2_ALG_SHA1_FLAG, .hash_buffersize = SHA1_BUFSIZE, .name = "SHA1", + .hashfunc = sha1, }, { .hashalg = TPM2_ALG_SHA256, .hashalg_flag = TPM2_ALG_SHA256_FLAG, .hash_buffersize = SHA256_BUFSIZE, .name = "SHA256", + .hashfunc = sha256, }, { .hashalg = TPM2_ALG_SHA384, .hashalg_flag = TPM2_ALG_SHA384_FLAG, .hash_buffersize = SHA384_BUFSIZE, .name = "SHA384", + .hashfunc = sha384, }, { .hashalg = TPM2_ALG_SHA512, .hashalg_flag = TPM2_ALG_SHA512_FLAG, .hash_buffersize = SHA512_BUFSIZE, .name = "SHA512", + .hashfunc = sha512, }, { .hashalg = TPM2_ALG_SM3_256, .hashalg_flag = TPM2_ALG_SM3_256_FLAG, @@ -259,6 +264,21 @@ tpm20_hashalg_flag_to_name(u8 hashalg_flag) return NULL; }
+static void tpm2_hash_data(u16 hashAlg, const u8 *data, u32 data_len, u8 *hash) +{ + unsigned i; + + for (i = 0; i < ARRAY_SIZE(hash_parameters); i++) { + if (hash_parameters[i].hashalg == hashAlg) { + if (hash_parameters[i].hashfunc) { + hash_parameters[i].hashfunc(data, data_len, hash); + } else { + memset(hash, 0xff, hash_parameters[i].hash_buffersize); + } + } + } +} + // Add an entry at the start of the log describing digest formats static int tpm20_write_EfiSpecIdEventStruct(void) @@ -342,14 +362,16 @@ tpm20_write_EfiSpecIdEventStruct(void) * hash when writing it in the area of the sha1 hash. * * le: the log entry to build the digest in - * sha1: the sha1 hash value to use + * hashdata: the data to hash + * hashdata_len: the length of the hashdata * bigEndian: whether to build in big endian format for the TPM or * little endian for the log * * Returns the digest size; -1 on fatal error */ static int -tpm20_build_digest(struct tpm_log_entry *le, const u8 *sha1, int bigEndian) +tpm20_build_digest(struct tpm_log_entry *le, + const u8 *hashdata, u32 hashdata_len, int bigEndian) { if (!tpm20_pcr_selection) return -1; @@ -391,8 +413,8 @@ tpm20_build_digest(struct tpm_log_entry *le, const u8 *sha1, int bigEndian) else v->hashAlg = be16_to_cpu(sel->hashAlg);
- memset(v->hash, 0, hsize); - memcpy(v->hash, sha1, hsize > SHA1_BUFSIZE ? SHA1_BUFSIZE : hsize); + tpm2_hash_data(be16_to_cpu(sel->hashAlg), hashdata, hashdata_len, + v->hash);
dest += sizeof(*v) + hsize; sel = nsel; @@ -415,7 +437,15 @@ tpm20_build_digest(struct tpm_log_entry *le, const u8 *sha1, int bigEndian) }
static int -tpm12_build_digest(struct tpm_log_entry *le, const u8 *sha1) +tpm12_build_digest(struct tpm_log_entry *le, + const u8 *hashdata, u32 hashdata_len) +{ + sha1(hashdata, hashdata_len, le->hdr.digest); + return SHA1_BUFSIZE; +} + +static int +tpm12_build_digest_direct(struct tpm_log_entry *le, const u8 *sha1) { // On TPM 1.2 the digest contains just the SHA1 hash memcpy(le->hdr.digest, sha1, SHA1_BUFSIZE); @@ -423,13 +453,14 @@ tpm12_build_digest(struct tpm_log_entry *le, const u8 *sha1) }
static int -tpm_build_digest(struct tpm_log_entry *le, const u8 *sha1, int bigEndian) +tpm_build_digest(struct tpm_log_entry *le, const u8 *hashdata, u32 hashdata_len + , int bigEndian) { switch (TPM_version) { case TPM_VERSION_1_2: - return tpm12_build_digest(le, sha1); + return tpm12_build_digest(le, hashdata, hashdata_len); case TPM_VERSION_2: - return tpm20_build_digest(le, sha1, bigEndian); + return tpm20_build_digest(le, hashdata, hashdata_len, bigEndian); } return -1; } @@ -978,14 +1009,11 @@ tpm_add_measurement_to_log(u32 pcrindex, u32 event_type, if (!tpm_is_working()) return;
- u8 hash[SHA1_BUFSIZE]; - sha1(hashdata, hashdata_length, hash); - struct tpm_log_entry le = { .hdr.pcrindex = pcrindex, .hdr.eventtype = event_type, }; - int digest_len = tpm_build_digest(&le, hash, 1); + int digest_len = tpm_build_digest(&le, hashdata, hashdata_length, 1); if (digest_len < 0) return; int ret = tpm_extend(&le, digest_len); @@ -993,7 +1021,7 @@ tpm_add_measurement_to_log(u32 pcrindex, u32 event_type, tpm_set_failure(); return; } - tpm_build_digest(&le, hash, 0); + tpm_build_digest(&le, hashdata, hashdata_length, 0); tpm_log_event(&le.hdr, digest_len, event, event_length); }
@@ -1407,7 +1435,7 @@ hash_log_extend(struct pcpes *pcpes, const void *hashdata, u32 hashdata_length .hdr.pcrindex = pcpes->pcrindex, .hdr.eventtype = pcpes->eventtype, }; - int digest_len = tpm_build_digest(&le, pcpes->digest, 1); + int digest_len = tpm12_build_digest_direct(&le, pcpes->digest); if (digest_len < 0) return TCG_GENERAL_ERROR; if (extend) { @@ -1415,7 +1443,7 @@ hash_log_extend(struct pcpes *pcpes, const void *hashdata, u32 hashdata_length if (ret) return TCG_TCG_COMMAND_ERROR; } - tpm_build_digest(&le, pcpes->digest, 0); + tpm12_build_digest_direct(&le, pcpes->digest); int ret = tpm_log_event(&le.hdr, digest_len , pcpes->event, pcpes->eventdatasize); if (ret)
On Mon, Jun 14, 2021 at 01:35:47PM -0400, Stefan Berger wrote:
This PR adds the implementations for sha{256, 384, 512} and makes use of the hash implementation when extending the PCRs of the respective banks rather than always using the sha1 and zero-padding it for the PCR banks of a TPM 2.
Okay, thanks. Looks fine to me. If there are no further comments I'll look to commit this (and the previous tcgbios fix) in a few days.
-Kevin
On 6/14/21 7:20 PM, Kevin O'Connor wrote:
On Mon, Jun 14, 2021 at 01:35:47PM -0400, Stefan Berger wrote:
This PR adds the implementations for sha{256, 384, 512} and makes use of the hash implementation when extending the PCRs of the respective banks rather than always using the sha1 and zero-padding it for the PCR banks of a TPM 2.
Okay, thanks. Looks fine to me. If there are no further comments I'll look to commit this (and the previous tcgbios fix) in a few days.
Thanks. Similar patches will go out to SLOF tomorrow.
Stefan
-Kevin
On Mon, Jun 14, 2021 at 01:35:47PM -0400, Stefan Berger wrote:
This PR adds the implementations for sha{256, 384, 512} and makes use of the hash implementation when extending the PCRs of the respective banks rather than always using the sha1 and zero-padding it for the PCR banks of a TPM 2.
Thanks. I committed this change.
-Kevin