[v7,06/13] x86: Add early SHA support for Secure Launch early measurements

Message ID 20231110222751.219836-7-ross.philipson@oracle.com
State New
Headers
Series x86: Trenchboot secure dynamic launch Linux kernel support |

Commit Message

Ross Philipson Nov. 10, 2023, 10:27 p.m. UTC
  From: "Daniel P. Smith" <dpsmith@apertussolutions.com>

The SHA algorithms are necessary to measure configuration information into
the TPM as early as possible before using the values. This implementation
uses the established approach of #including the SHA libraries directly in
the code since the compressed kernel is not uncompressed at this point.

The SHA code here has its origins in the code from the main kernel:

commit c4d5b9ffa31f ("crypto: sha1 - implement base layer for SHA-1")

A modified version of this code was introduced to the lib/crypto/sha1.c
to bring it in line with the sha256 code and allow it to be pulled into the
setup kernel in the same manner as sha256 is.

Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
---
 arch/x86/boot/compressed/Makefile       |  2 +
 arch/x86/boot/compressed/early_sha1.c   | 12 ++++
 arch/x86/boot/compressed/early_sha256.c |  6 ++
 include/crypto/sha1.h                   |  1 +
 lib/crypto/sha1.c                       | 81 +++++++++++++++++++++++++
 5 files changed, 102 insertions(+)
 create mode 100644 arch/x86/boot/compressed/early_sha1.c
 create mode 100644 arch/x86/boot/compressed/early_sha256.c
  

Comments

Eric Biggers Nov. 11, 2023, 5:44 p.m. UTC | #1
On Fri, Nov 10, 2023 at 05:27:44PM -0500, Ross Philipson wrote:
>  arch/x86/boot/compressed/early_sha1.c   | 12 ++++
>  lib/crypto/sha1.c                       | 81 +++++++++++++++++++++++++

It's surprising to still see this new use of SHA-1 after so many people objected
to it in the v6 patchset.  It's also frustrating that the SHA-1 support is still
being obfuscated by being combined in one patch with SHA-2 support, perhaps in
an attempt to conflate the two algorithms and avoid having to give a rationale
for the inclusion of SHA-1.  Finally, new functions should not be added to
lib/crypto/sha1.c unless those functions have multiple users.

- Eric
  
Andrew Cooper Nov. 11, 2023, 6:19 p.m. UTC | #2
On 11/11/2023 5:44 pm, Eric Biggers wrote:
> On Fri, Nov 10, 2023 at 05:27:44PM -0500, Ross Philipson wrote:
>>  arch/x86/boot/compressed/early_sha1.c   | 12 ++++
>>  lib/crypto/sha1.c                       | 81 +++++++++++++++++++++++++
> It's surprising to still see this new use of SHA-1 after so many people objected
> to it in the v6 patchset.  It's also frustrating that the SHA-1 support is still
> being obfuscated by being combined in one patch with SHA-2 support, perhaps in
> an attempt to conflate the two algorithms and avoid having to give a rationale
> for the inclusion of SHA-1.  Finally, new functions should not be added to
> lib/crypto/sha1.c unless those functions have multiple users.

The rational was given.  Let me reiterate it.

There are real TPMs in the world that can't use SHA-2.  The use of SHA-1
is necessary to support DRTM on such systems, and there are real users
of such configurations.

DRTM with SHA-1-only is a damnsight better than no DTRM, even if SHA-1
is getting a little long in the tooth.

So unless you have a credible plan to upgrade every non-SHA-2 TPM in the
world, you are deliberately breaking part of the usecase paying for the
effort of trying to upstream DRTM support into Linux.

~Andrew
  
James Bottomley Nov. 11, 2023, 8:36 p.m. UTC | #3
On Sat, 2023-11-11 at 18:19 +0000, Andrew Cooper wrote:
> On 11/11/2023 5:44 pm, Eric Biggers wrote:
> > On Fri, Nov 10, 2023 at 05:27:44PM -0500, Ross Philipson wrote:
> > >  arch/x86/boot/compressed/early_sha1.c   | 12 ++++
> > >  lib/crypto/sha1.c                       | 81
> > > +++++++++++++++++++++++++
> > It's surprising to still see this new use of SHA-1 after so many
> > people objected to it in the v6 patchset.  It's also frustrating
> > that the SHA-1 support is still being obfuscated by being combined
> > in one patch with SHA-2 support, perhaps in an attempt to conflate
> > the two algorithms and avoid having to give a rationale for the
> > inclusion of SHA-1.  Finally, new functions should not be added to
> > lib/crypto/sha1.c unless those functions have multiple users.
> 
> The rational was given.  Let me reiterate it.
> 
> There are real TPMs in the world that can't use SHA-2.  The use of
> SHA-1 is necessary to support DRTM on such systems, and there are
> real users of such configurations.

Given that TPM 2.0 has been shipping in bulk since Windows 10 (2015)
and is required for Windows 11 (2021), are there really such huge
numbers of TPM 1.2 systems involved in security functions?

> DRTM with SHA-1-only is a damnsight better than no DTRM, even if SHA-
> 1 is getting a little long in the tooth.

That's not the problem.  The problem is that sha1 is seen as a
compromised algorithm by NIST which began deprecating it in 2011 and is
now requiring it to be removed from all systems supplied to the US
government by 2030

https://www.nist.gov/news-events/news/2022/12/nist-retires-sha-1-cryptographic-algorithm

That means we have to control all uses of sha1 in the kernel and have
an option to build without it.  FIPS has an even tighter timetable: it
requires sha1 to be out by 2025.

> So unless you have a credible plan to upgrade every non-SHA-2 TPM in
> the world, you are deliberately breaking part of the usecase paying
> for the effort of trying to upstream DRTM support into Linux.

Given that most CSOs follow NIST and FIPS it seems a little strange
that there would be a huge demand for such an intricate security
protocol as Dynamic Launch on a system that can't be FIPS 140-3
certified.

James
  
Andrew Cooper Nov. 13, 2023, 11:21 p.m. UTC | #4
On 11/11/2023 8:36 pm, James Bottomley wrote:
> On Sat, 2023-11-11 at 18:19 +0000, Andrew Cooper wrote:
>> On 11/11/2023 5:44 pm, Eric Biggers wrote:
>>> On Fri, Nov 10, 2023 at 05:27:44PM -0500, Ross Philipson wrote:
>>>>  arch/x86/boot/compressed/early_sha1.c   | 12 ++++
>>>>  lib/crypto/sha1.c                       | 81
>>>> +++++++++++++++++++++++++
>>> It's surprising to still see this new use of SHA-1 after so many
>>> people objected to it in the v6 patchset.  It's also frustrating
>>> that the SHA-1 support is still being obfuscated by being combined
>>> in one patch with SHA-2 support, perhaps in an attempt to conflate
>>> the two algorithms and avoid having to give a rationale for the
>>> inclusion of SHA-1.  Finally, new functions should not be added to
>>> lib/crypto/sha1.c unless those functions have multiple users.
>> The rational was given.  Let me reiterate it.
>>
>> There are real TPMs in the world that can't use SHA-2.  The use of
>> SHA-1 is necessary to support DRTM on such systems, and there are
>> real users of such configurations.
> Given that TPM 2.0 has been shipping in bulk since Windows 10 (2015)
> and is required for Windows 11 (2021), are there really such huge
> numbers of TPM 1.2 systems involved in security functions?

Yes.

As ever, it's not as simple as a straight TPM version issue.

AMD's firmware-TPM2 isn't compatible with their DRTM implementation. 
Users are limited to whatever headers are available on the motherboard.

Furthermore, even with a TPM2, it is the firmware (Intel TXT ACM) or
hardware (AMD SKINIT) which chooses the hash algorithms to use, and in a
lot of cases the end user doesn't get a choice.

So yes - there really are modern systems which you can't use SHA-2-only
with.

>> DRTM with SHA-1-only is a damnsight better than no DTRM, even if SHA-
>> 1 is getting a little long in the tooth.
> That's not the problem.  The problem is that sha1 is seen as a
> compromised algorithm by NIST which began deprecating it in 2011 and is
> now requiring it to be removed from all systems supplied to the US
> government by 2030

This is a non-issue.

People who care about having no SHA-1 can not compile in DRTM support.

But there are people who will tolerate SHA-1 code to get DTRM support.

~Andrew
  

Patch

diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index 71fc531b95b4..07a2f56cd571 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -118,6 +118,8 @@  vmlinux-objs-$(CONFIG_EFI) += $(obj)/efi.o
 vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_mixed.o
 vmlinux-objs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
 
+vmlinux-objs-$(CONFIG_SECURE_LAUNCH) += $(obj)/early_sha1.o $(obj)/early_sha256.o
+
 $(obj)/vmlinux: $(vmlinux-objs-y) FORCE
 	$(call if_changed,ld)
 
diff --git a/arch/x86/boot/compressed/early_sha1.c b/arch/x86/boot/compressed/early_sha1.c
new file mode 100644
index 000000000000..0c7cf6f8157a
--- /dev/null
+++ b/arch/x86/boot/compressed/early_sha1.c
@@ -0,0 +1,12 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 Apertus Solutions, LLC.
+ */
+
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/string.h>
+#include <asm/boot.h>
+#include <asm/unaligned.h>
+
+#include "../../../../lib/crypto/sha1.c"
diff --git a/arch/x86/boot/compressed/early_sha256.c b/arch/x86/boot/compressed/early_sha256.c
new file mode 100644
index 000000000000..54930166ffee
--- /dev/null
+++ b/arch/x86/boot/compressed/early_sha256.c
@@ -0,0 +1,6 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 Apertus Solutions, LLC
+ */
+
+#include "../../../../lib/crypto/sha256.c"
diff --git a/include/crypto/sha1.h b/include/crypto/sha1.h
index 044ecea60ac8..d715dd5332e1 100644
--- a/include/crypto/sha1.h
+++ b/include/crypto/sha1.h
@@ -42,5 +42,6 @@  extern int crypto_sha1_finup(struct shash_desc *desc, const u8 *data,
 #define SHA1_WORKSPACE_WORDS	16
 void sha1_init(__u32 *buf);
 void sha1_transform(__u32 *digest, const char *data, __u32 *W);
+void sha1(const u8 *data, unsigned int len, u8 *out);
 
 #endif /* _CRYPTO_SHA1_H */
diff --git a/lib/crypto/sha1.c b/lib/crypto/sha1.c
index 1aebe7be9401..10152125b338 100644
--- a/lib/crypto/sha1.c
+++ b/lib/crypto/sha1.c
@@ -137,4 +137,85 @@  void sha1_init(__u32 *buf)
 }
 EXPORT_SYMBOL(sha1_init);
 
+static void __sha1_transform(u32 *digest, const char *data)
+{
+       u32 ws[SHA1_WORKSPACE_WORDS];
+
+       sha1_transform(digest, data, ws);
+
+       memzero_explicit(ws, sizeof(ws));
+}
+
+static void sha1_update(struct sha1_state *sctx, const u8 *data, unsigned int len)
+{
+	unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
+
+	sctx->count += len;
+
+	if (likely((partial + len) >= SHA1_BLOCK_SIZE)) {
+		int blocks;
+
+		if (partial) {
+			int p = SHA1_BLOCK_SIZE - partial;
+
+			memcpy(sctx->buffer + partial, data, p);
+			data += p;
+			len -= p;
+
+			__sha1_transform(sctx->state, sctx->buffer);
+		}
+
+		blocks = len / SHA1_BLOCK_SIZE;
+		len %= SHA1_BLOCK_SIZE;
+
+		if (blocks) {
+			while (blocks--) {
+				__sha1_transform(sctx->state, data);
+				data += SHA1_BLOCK_SIZE;
+			}
+		}
+		partial = 0;
+	}
+
+	if (len)
+		memcpy(sctx->buffer + partial, data, len);
+}
+
+static void sha1_final(struct sha1_state *sctx, u8 *out)
+{
+	const int bit_offset = SHA1_BLOCK_SIZE - sizeof(__be64);
+	unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
+	__be64 *bits = (__be64 *)(sctx->buffer + bit_offset);
+	__be32 *digest = (__be32 *)out;
+	int i;
+
+	sctx->buffer[partial++] = 0x80;
+	if (partial > bit_offset) {
+		memset(sctx->buffer + partial, 0x0, SHA1_BLOCK_SIZE - partial);
+		partial = 0;
+
+		__sha1_transform(sctx->state, sctx->buffer);
+	}
+
+	memset(sctx->buffer + partial, 0x0, bit_offset - partial);
+	*bits = cpu_to_be64(sctx->count << 3);
+	__sha1_transform(sctx->state, sctx->buffer);
+
+	for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(__be32); i++)
+		put_unaligned_be32(sctx->state[i], digest++);
+
+	*sctx = (struct sha1_state){};
+}
+
+void sha1(const u8 *data, unsigned int len, u8 *out)
+{
+	struct sha1_state sctx = {0};
+
+	sha1_init(sctx.state);
+	sctx.count = 0;
+	sha1_update(&sctx, data, len);
+	sha1_final(&sctx, out);
+}
+EXPORT_SYMBOL(sha1);
+
 MODULE_LICENSE("GPL");