diff mbox series

crypto: testmgr - add NIAP FPT_TST_EXT.1 subset of tests

Message ID 20210108173849.333780-1-lenaptr@google.com
State New
Headers show
Series crypto: testmgr - add NIAP FPT_TST_EXT.1 subset of tests | expand

Commit Message

Elena Petrova Jan. 8, 2021, 5:38 p.m. UTC
NIAP FPT_TST_EXT.1 [1] specification requires testing of a small set of
cryptographic modules on boot for devices that need to be NIAP
compliant. This is also a requirement for FIPS CMVP 140-2/140-3
certification.

Currently testmgr adds significant boot time overhead when enabled; we
measured 3-5 seconds for Android.

This change adds a CONFIG_ option that allows testmgr to run a
smaller subset of tests required by NIAP FPT_TST_EXT.1.

[1] https://www.niap-ccevs.org/MMO/PP/-417-/#FPT_TST_EXT.1.1

Signed-off-by: Elena Petrova <lenaptr@google.com>
---
 crypto/Kconfig   | 19 +++++++++++++++++++
 crypto/testmgr.c | 38 +++++++++++++++++++++++++++++++++++++-
 2 files changed, 56 insertions(+), 1 deletion(-)

Comments

Stephan Mueller Jan. 8, 2021, 6:53 p.m. UTC | #1
Am Freitag, dem 08.01.2021 um 17:38 +0000 schrieb Elena Petrova:
> NIAP FPT_TST_EXT.1 [1] specification requires testing of a small set of
> cryptographic modules on boot for devices that need to be NIAP
> compliant. This is also a requirement for FIPS CMVP 140-2/140-3
> certification.
> 
> Currently testmgr adds significant boot time overhead when enabled; we
> measured 3-5 seconds for Android.

I am not sure whether this is necessary. If you build the ciphers as modules,
you can insmod them during boot time before general user space is made
available. Once you insmoded all needed KOs, you load tcrypt to invoke them
which implies that they are verified. This approach allows user space to
determine which KOs are self-tested during boot.

This is the approach all Linux validations took in the past.

Besides, for FIPS 140-3, it is now allowed to have "lazy" self testing which
allows the self-tests to be executed before first use (just like what the
kernel testmgr already does).

Can you please help us understand why the mentioned approach is not
sufficient?

Thanks
Stephan
Elena Petrova Feb. 9, 2021, 1:35 p.m. UTC | #2
Hi Stephan,

On Fri, 8 Jan 2021 at 18:57, Stephan Mueller <smueller@chronox.de> wrote:
>

> Am Freitag, dem 08.01.2021 um 17:38 +0000 schrieb Elena Petrova:

> > NIAP FPT_TST_EXT.1 [1] specification requires testing of a small set of

> > cryptographic modules on boot for devices that need to be NIAP

> > compliant. This is also a requirement for FIPS CMVP 140-2/140-3

> > certification.

> >

> > Currently testmgr adds significant boot time overhead when enabled; we

> > measured 3-5 seconds for Android.

>

> I am not sure whether this is necessary. If you build the ciphers as modules,

> you can insmod them during boot time before general user space is made

> available. Once you insmoded all needed KOs, you load tcrypt to invoke them

> which implies that they are verified. This approach allows user space to

> determine which KOs are self-tested during boot.


We've asked our certification lab whether they'd approve the tcrypt
testing, but they say they are concerned that the test would run too
late and it won't exactly match the NIAP requirements.

> This is the approach all Linux validations took in the past.


If you could provide an example of some validation that folks from the
ecosystem did successfully with tcrypt, then I might be able to point
the lab to their CMVP certificate (like
https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/3753),
and maybe that'd make them happy with Android using tcrypt...

> Besides, for FIPS 140-3, it is now allowed to have "lazy" self testing which

> allows the self-tests to be executed before first use (just like what the

> kernel testmgr already does).


Yeah, that's what I was intending to utilize in my patch: I just
reduced the number of crypto modules to which the self-tests should
apply, to avoid testing ones that aren't essential to certification.

> Can you please help us understand why the mentioned approach is not

> sufficient?


Well, as I mentioned above, the certification lab is concerned about
invoking tcrypt for testing because user-space controls it and "it's
too late". And the testmgr, when fully enabled, introduces a big
enough boot time increase for our Android team to shout at me angrily
:) So I decided to go with "testmgr but partial".


Cheers,
Elena
Stephan Mueller Feb. 9, 2021, 2:02 p.m. UTC | #3
Am Dienstag, dem 09.02.2021 um 13:35 +0000 schrieb Elena Petrova:
> Hi Stephan,

> 

> On Fri, 8 Jan 2021 at 18:57, Stephan Mueller <smueller@chronox.de> wrote:

> > 

> > Am Freitag, dem 08.01.2021 um 17:38 +0000 schrieb Elena Petrova:

> > > NIAP FPT_TST_EXT.1 [1] specification requires testing of a small set of

> > > cryptographic modules on boot for devices that need to be NIAP

> > > compliant. This is also a requirement for FIPS CMVP 140-2/140-3

> > > certification.

> > > 

> > > Currently testmgr adds significant boot time overhead when enabled; we

> > > measured 3-5 seconds for Android.

> > 

> > I am not sure whether this is necessary. If you build the ciphers as

> > modules,

> > you can insmod them during boot time before general user space is made

> > available. Once you insmoded all needed KOs, you load tcrypt to invoke

> > them

> > which implies that they are verified. This approach allows user space to

> > determine which KOs are self-tested during boot.

> 

> We've asked our certification lab whether they'd approve the tcrypt

> testing, but they say they are concerned that the test would run too

> late and it won't exactly match the NIAP requirements.


Tcrypt does not do any testing, it simply allocates the ciphers to ensure that
the self tests defined in testmgr are executed.

If tcrypt is loaded as one of the first steps in user space boot, the self
tests are executed before any algo is put to use.

> 

> > This is the approach all Linux validations took in the past.

> 

> If you could provide an example of some validation that folks from the

> ecosystem did successfully with tcrypt, then I might be able to point

> the lab to their CMVP certificate (like

>  

> https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/3753

> ),

> and maybe that'd make them happy with Android using tcrypt...


Search for all RHEL/SLES/Ubuntu CMVP kernel validations.

The key is in the dracut component:

https://github.com/dracutdevs/dracut/tree/master/modules.d/01fips
> 

> > Besides, for FIPS 140-3, it is now allowed to have "lazy" self testing

> > which

> > allows the self-tests to be executed before first use (just like what the

> > kernel testmgr already does).

> 

> Yeah, that's what I was intending to utilize in my patch: I just

> reduced the number of crypto modules to which the self-tests should

> apply, to avoid testing ones that aren't essential to certification.


What I mean is that with 140-3 the current kernel behavior of invoking the
testmgr during the first-time allocation of an algorithm is sufficient without
any changes to the current code.
> 

> > Can you please help us understand why the mentioned approach is not

> > sufficient?

> 

> Well, as I mentioned above, the certification lab is concerned about

> invoking tcrypt for testing because user-space controls it


Yes, user space controls it, but not the user. It is hard-wired into the boot
process.

>  and "it's

> too late".


Not sure how it can be too late if it is one of the first steps in the user
space boot.

>  And the testmgr, when fully enabled, introduces a big

> enough boot time increase for our Android team to shout at me angrily

> :) So I decided to go with "testmgr but partial".


Check the dracut approach - there you have your selection ability.

Ciao
Stephan
> 

> 

> Cheers,

> Elena
diff mbox series

Patch

diff --git a/crypto/Kconfig b/crypto/Kconfig
index a367fcfeb5d4..4985406f1342 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -32,6 +32,17 @@  config CRYPTO_FIPS
 	  certification.  You should say no unless you know what
 	  this is.
 
+config CRYPTO_NIAP_FPT_TST_EXT_11
+	bool "NIAP FPT_TST_EXT.1.1 compliance"
+	depends on CRYPTO_MANAGER
+	depends on CRYPTO_SHA512 && CRYPTO_HMAC
+	depends on CRYPTO_SHA256
+	depends on CRYPTO_AES && CRYPTO_CBC
+	help
+	  This option enables a set of self-tests to demonstrate
+	  the correct operation of cryptographic functionality, as
+	  required in NIAP FPT_TST_EXT.1.1.
+
 config CRYPTO_ALGAPI
 	tristate
 	select CRYPTO_ALGAPI2
@@ -153,6 +164,14 @@  config CRYPTO_MANAGER_EXTRA_TESTS
 	  This is intended for developer use only, as these tests take much
 	  longer to run than the normal self tests.
 
+config CRYPTO_MANAGER_NIAP_TESTS_ONLY
+	bool "Enable only NIAP FPT_TST_EXT.1 run-time self tests"
+	depends on !CRYPTO_MANAGER_DISABLE_TESTS && CRYPTO_NIAP_FPT_TST_EXT_11
+	default y
+	help
+	  Disable run-time self tests except for those required by
+	  NIAP FPT_TST_EXT.1.
+
 config CRYPTO_GF128MUL
 	tristate
 
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 321e38eef51b..2abe140f265a 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -1919,6 +1919,7 @@  static int alg_test_hash(const struct alg_test_desc *desc, const char *driver,
 	return err;
 }
 
+#ifndef CONFIG_CRYPTO_MANAGER_NIAP_TESTS_ONLY
 static int test_aead_vec_cfg(int enc, const struct aead_testvec *vec,
 			     const char *vec_name,
 			     const struct testvec_config *cfg,
@@ -2597,6 +2598,7 @@  static int alg_test_aead(const struct alg_test_desc *desc, const char *driver,
 	crypto_free_aead(tfm);
 	return err;
 }
+#endif /* !CONFIG_CRYPTO_MANAGER_NIAP_TESTS_ONLY */
 
 static int test_cipher(struct crypto_cipher *tfm, int enc,
 		       const struct cipher_testvec *template,
@@ -3166,6 +3168,7 @@  static int alg_test_skcipher(const struct alg_test_desc *desc,
 	return err;
 }
 
+#ifndef CONFIG_CRYPTO_MANAGER_NIAP_TESTS_ONLY
 static int test_comp(struct crypto_comp *tfm,
 		     const struct comp_testvec *ctemplate,
 		     const struct comp_testvec *dtemplate,
@@ -3502,6 +3505,7 @@  static int test_cprng(struct crypto_rng *tfm,
 	kfree(seed);
 	return err;
 }
+#endif /* !CONFIG_CRYPTO_MANAGER_NIAP_TESTS_ONLY */
 
 static int alg_test_cipher(const struct alg_test_desc *desc,
 			   const char *driver, u32 type, u32 mask)
@@ -3525,6 +3529,7 @@  static int alg_test_cipher(const struct alg_test_desc *desc,
 	return err;
 }
 
+#ifndef CONFIG_CRYPTO_MANAGER_NIAP_TESTS_ONLY
 static int alg_test_comp(const struct alg_test_desc *desc, const char *driver,
 			 u32 type, u32 mask)
 {
@@ -4141,12 +4146,38 @@  static int alg_test_null(const struct alg_test_desc *desc,
 {
 	return 0;
 }
+#endif /* !CONFIG_CRYPTO_MANAGER_NIAP_TESTS_ONLY */
 
 #define ____VECS(tv)	.vecs = tv, .count = ARRAY_SIZE(tv)
 #define __VECS(tv)	{ ____VECS(tv) }
 
 /* Please keep this list sorted by algorithm name. */
 static const struct alg_test_desc alg_test_descs[] = {
+#ifdef CONFIG_CRYPTO_MANAGER_NIAP_TESTS_ONLY
+	/* Reduced list of algorithms for NIAP FPT_TST_EXT.1 */
+	{
+		.alg = "cbc(aes)",
+		.test = alg_test_skcipher,
+		.fips_allowed = 1,
+		.suite = {
+			.cipher = __VECS(aes_cbc_tv_template)
+		},
+	}, {
+		.alg = "hmac(sha512)",
+		.test = alg_test_hash,
+		.fips_allowed = 1,
+		.suite = {
+			.hash = __VECS(hmac_sha512_tv_template)
+		}
+	}, {
+		.alg = "sha256",
+		.test = alg_test_hash,
+		.fips_allowed = 1,
+		.suite = {
+			.hash = __VECS(sha256_tv_template)
+		}
+	}
+#else /* !CONFIG_CRYPTO_MANAGER_NIAP_TESTS_ONLY */
 	{
 		.alg = "adiantum(xchacha12,aes)",
 		.generic_driver = "adiantum(xchacha12-generic,aes-generic,nhpoly1305-generic)",
@@ -5544,6 +5575,7 @@  static const struct alg_test_desc alg_test_descs[] = {
 			}
 		}
 	}
+#endif /* !CONFIG_CRYPTO_MANAGER_NIAP_TESTS_ONLY */
 };
 
 static void alg_check_test_descs_order(void)
@@ -5671,10 +5703,14 @@  int alg_test(const char *driver, const char *alg, u32 type, u32 mask)
 			      driver, alg,
 			      fips_enabled ? "fips" : "panic_on_fail");
 		}
+		if (IS_ENABLED(CONFIG_CRYPTO_NIAP_FPT_TST_EXT_11))
+			panic("alg: self-tests for %s (%s) failed in NIAP mode!\n",
+			      driver, alg);
+
 		WARN(1, "alg: self-tests for %s (%s) failed (rc=%d)",
 		     driver, alg, rc);
 	} else {
-		if (fips_enabled)
+		if (fips_enabled || IS_ENABLED(CONFIG_CRYPTO_NIAP_FPT_TST_EXT_11))
 			pr_info("alg: self-tests for %s (%s) passed\n",
 				driver, alg);
 	}