Linux Modules
 help / color / mirror / Atom feed
* [PATCH 012/106] crypto: convert exported crypto symbol into pluggable interface for CONFIG_CRYPTO_RSA crypto
From: Jay Wang @ 2026-02-12  2:45 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
	Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
	linux-modules
In-Reply-To: <20260212024725.11264-1-wanjay@amazon.com>

Apply Crypto API wrappers to the exported crypto symbol in
CONFIG_CRYPTO_RSA-related crypto to convert them into pluggable
interface.

This patch is partially based on work by Vegard Nossum, with
modifications. Unlike the original, we do not include
DEFINE_CRYPTO_API since only one copy of the crypto symbols is
kept, either in the crypto module or in the main kernel, and we ensure
such wrapper do not have impact on crypto already chosen built as
module.

Co-developed-by: Vegard Nossum <vegard.nossum@oracle.com>
Signed-off-by: Jay Wang <wanjay@amazon.com>
---
 crypto/Makefile               |  2 +-
 crypto/fips140/fips140-api.c  | 12 ++++++++++++
 crypto/rsa.c                  |  4 ++--
 include/crypto/internal/rsa.h |  7 +++----
 4 files changed, 18 insertions(+), 7 deletions(-)

diff --git a/crypto/Makefile b/crypto/Makefile
index 21197857ad7d..3e12b556bfa7 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -52,7 +52,7 @@ rsa_generic-y += rsa.o
 rsa_generic-y += rsa_helper.o
 rsa_generic-y += rsa-pkcs1pad.o
 rsa_generic-y += rsassa-pkcs1.o
-obj-$(CONFIG_CRYPTO_RSA) += rsa_generic.o
+crypto-objs-$(CONFIG_CRYPTO_RSA) += rsa_generic.o
 
 $(obj)/ecdsasignature.asn1.o: $(obj)/ecdsasignature.asn1.c $(obj)/ecdsasignature.asn1.h
 $(obj)/ecdsa-x962.o: $(obj)/ecdsasignature.asn1.h
diff --git a/crypto/fips140/fips140-api.c b/crypto/fips140/fips140-api.c
index 50603e7a8bb0..d10eded6b61e 100644
--- a/crypto/fips140/fips140-api.c
+++ b/crypto/fips140/fips140-api.c
@@ -303,4 +303,16 @@ DEFINE_CRYPTO_API_STUB(crypto_register_kpp);
 DEFINE_CRYPTO_API_STUB(crypto_unregister_kpp);
 DEFINE_CRYPTO_API_STUB(kpp_register_instance);
 
+#endif
+
+/*
+ * crypto/rsa_helper.c
+ */
+#if IS_BUILTIN(CONFIG_CRYPTO_RSA)
+
+#include <crypto/internal/rsa.h>
+
+DEFINE_CRYPTO_API_STUB(rsa_parse_pub_key);
+DEFINE_CRYPTO_API_STUB(rsa_parse_priv_key);
+
 #endif
\ No newline at end of file
diff --git a/crypto/rsa.c b/crypto/rsa.c
index 6c7734083c98..44eef74ebad8 100644
--- a/crypto/rsa.c
+++ b/crypto/rsa.c
@@ -430,8 +430,8 @@ static void __exit rsa_exit(void)
 	crypto_unregister_akcipher(&rsa);
 }
 
-module_init(rsa_init);
-module_exit(rsa_exit);
+crypto_module_init(rsa_init);
+crypto_module_exit(rsa_exit);
 MODULE_ALIAS_CRYPTO("rsa");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("RSA generic algorithm");
diff --git a/include/crypto/internal/rsa.h b/include/crypto/internal/rsa.h
index 071a1951b992..3d8fe098eaae 100644
--- a/include/crypto/internal/rsa.h
+++ b/include/crypto/internal/rsa.h
@@ -7,6 +7,7 @@
  */
 #ifndef _RSA_HELPER_
 #define _RSA_HELPER_
+#include <crypto/api.h>
 #include <linux/types.h>
 #include <crypto/akcipher.h>
 
@@ -48,11 +49,9 @@ struct rsa_key {
 	size_t qinv_sz;
 };
 
-int rsa_parse_pub_key(struct rsa_key *rsa_key, const void *key,
-		      unsigned int key_len);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_RSA, rsa_parse_pub_key, int, (struct rsa_key *rsa_key, const void *key, unsigned int key_len), (rsa_key, key, key_len));
 
-int rsa_parse_priv_key(struct rsa_key *rsa_key, const void *key,
-		       unsigned int key_len);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_RSA, rsa_parse_priv_key, int, (struct rsa_key *rsa_key, const void *key, unsigned int key_len), (rsa_key, key, key_len));
 
 #define RSA_PUB (true)
 #define RSA_PRIV (false)
-- 
2.47.3


^ permalink raw reply related

* [PATCH 011/106] crypto: convert exported crypto symbol into pluggable interface for CONFIG_CRYPTO_KPP2 crypto
From: Jay Wang @ 2026-02-12  2:45 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
	Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
	linux-modules
In-Reply-To: <20260212024725.11264-1-wanjay@amazon.com>

Apply Crypto API wrappers to the exported crypto symbol in
CONFIG_CRYPTO_KPP2-related crypto to convert them into pluggable
interface.

This patch is partially based on work by Vegard Nossum, with
modifications. Unlike the original, we do not include
DEFINE_CRYPTO_API since only one copy of the crypto symbols is
kept, either in the crypto module or in the main kernel, and we ensure
such wrapper do not have impact on crypto already chosen built as
module.

Co-developed-by: Vegard Nossum <vegard.nossum@oracle.com>
Signed-off-by: Jay Wang <wanjay@amazon.com>
---
 crypto/Makefile               |  2 +-
 crypto/fips140/fips140-api.c  | 17 +++++++++++++++++
 include/crypto/internal/kpp.h | 12 +++++-------
 include/crypto/kpp.h          |  5 +++--
 4 files changed, 26 insertions(+), 10 deletions(-)

diff --git a/crypto/Makefile b/crypto/Makefile
index 2e722f7961d4..21197857ad7d 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -35,7 +35,7 @@ crypto-objs-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o
 
 crypto-objs-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o
 crypto-objs-$(CONFIG_CRYPTO_SIG2) += sig.o
-obj-$(CONFIG_CRYPTO_KPP2) += kpp.o
+crypto-objs-$(CONFIG_CRYPTO_KPP2) += kpp.o
 obj-$(CONFIG_CRYPTO_HKDF) += hkdf.o
 
 dh_generic-y := dh.o
diff --git a/crypto/fips140/fips140-api.c b/crypto/fips140/fips140-api.c
index c97806cfdd05..50603e7a8bb0 100644
--- a/crypto/fips140/fips140-api.c
+++ b/crypto/fips140/fips140-api.c
@@ -286,4 +286,21 @@ DEFINE_CRYPTO_API_STUB(crypto_unregister_sig);
 DEFINE_CRYPTO_API_STUB(sig_register_instance);
 DEFINE_CRYPTO_API_STUB(crypto_grab_sig);
 
+#endif
+
+/*
+ * crypto/kpp.c
+ */
+#if IS_BUILTIN(CONFIG_CRYPTO_KPP2)
+
+#include <crypto/kpp.h>
+#include <crypto/internal/kpp.h>
+
+DEFINE_CRYPTO_API_STUB(crypto_alloc_kpp);
+DEFINE_CRYPTO_API_STUB(crypto_grab_kpp);
+DEFINE_CRYPTO_API_STUB(crypto_has_kpp);
+DEFINE_CRYPTO_API_STUB(crypto_register_kpp);
+DEFINE_CRYPTO_API_STUB(crypto_unregister_kpp);
+DEFINE_CRYPTO_API_STUB(kpp_register_instance);
+
 #endif
\ No newline at end of file
diff --git a/include/crypto/internal/kpp.h b/include/crypto/internal/kpp.h
index 0a6db8c4a9a0..eff35727f700 100644
--- a/include/crypto/internal/kpp.h
+++ b/include/crypto/internal/kpp.h
@@ -7,6 +7,7 @@
  */
 #ifndef _CRYPTO_KPP_INT_H
 #define _CRYPTO_KPP_INT_H
+#include <crypto/api.h>
 #include <crypto/kpp.h>
 #include <crypto/algapi.h>
 
@@ -159,7 +160,7 @@ static inline void *kpp_instance_ctx(struct kpp_instance *inst)
  *
  * Return: zero on success; error code in case of error
  */
-int crypto_register_kpp(struct kpp_alg *alg);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_KPP2, crypto_register_kpp, int, (struct kpp_alg *alg), (alg));
 
 /**
  * crypto_unregister_kpp() -- Unregister key-agreement protocol primitive
@@ -170,7 +171,7 @@ int crypto_register_kpp(struct kpp_alg *alg);
  *
  * @alg:	algorithm definition
  */
-void crypto_unregister_kpp(struct kpp_alg *alg);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_KPP2, crypto_unregister_kpp, void, (struct kpp_alg *alg), (alg));
 
 /**
  * kpp_register_instance() - Register a KPP template instance.
@@ -178,8 +179,7 @@ void crypto_unregister_kpp(struct kpp_alg *alg);
  * @inst: The KPP template instance to be registered.
  * Return: %0 on success, negative error code otherwise.
  */
-int kpp_register_instance(struct crypto_template *tmpl,
-			  struct kpp_instance *inst);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_KPP2, kpp_register_instance, int, (struct crypto_template *tmpl, struct kpp_instance *inst), (tmpl, inst));
 
 /*
  * KPP spawn related functions.
@@ -193,9 +193,7 @@ int kpp_register_instance(struct crypto_template *tmpl,
  * @mask: The mask bismask to pass on to the lookup.
  * Return: %0 on success, a negative error code otherwise.
  */
-int crypto_grab_kpp(struct crypto_kpp_spawn *spawn,
-		    struct crypto_instance *inst,
-		    const char *name, u32 type, u32 mask);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_KPP2, crypto_grab_kpp, int, (struct crypto_kpp_spawn *spawn, struct crypto_instance *inst, const char *name, u32 type, u32 mask), (spawn, inst, name, type, mask));
 
 /**
  * crypto_drop_kpp() - Release a spawn previously bound via crypto_grab_kpp().
diff --git a/include/crypto/kpp.h b/include/crypto/kpp.h
index 2d9c4de57b69..068a6e218344 100644
--- a/include/crypto/kpp.h
+++ b/include/crypto/kpp.h
@@ -9,6 +9,7 @@
 #ifndef _CRYPTO_KPP_
 #define _CRYPTO_KPP_
 
+#include <crypto/api.h>
 #include <linux/atomic.h>
 #include <linux/container_of.h>
 #include <linux/crypto.h>
@@ -107,9 +108,9 @@ struct kpp_alg {
  * Return: allocated handle in case of success; IS_ERR() is true in case of
  *	   an error, PTR_ERR() returns the error code.
  */
-struct crypto_kpp *crypto_alloc_kpp(const char *alg_name, u32 type, u32 mask);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_KPP2, crypto_alloc_kpp, struct crypto_kpp *, (const char *alg_name, u32 type, u32 mask), (alg_name, type, mask));
 
-int crypto_has_kpp(const char *alg_name, u32 type, u32 mask);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_KPP2, crypto_has_kpp, int, (const char *alg_name, u32 type, u32 mask), (alg_name, type, mask));
 
 static inline struct crypto_tfm *crypto_kpp_tfm(struct crypto_kpp *tfm)
 {
-- 
2.47.3


^ permalink raw reply related

* [PATCH 010/106] crypto: convert exported crypto symbol into pluggable interface for CONFIG_CRYPTO_SIG2 crypto
From: Jay Wang @ 2026-02-12  2:45 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
	Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
	linux-modules
In-Reply-To: <20260212024725.11264-1-wanjay@amazon.com>

Apply Crypto API wrappers to the exported crypto symbol in
CONFIG_CRYPTO_SIG2-related crypto to convert them into pluggable
interface.

This patch is partially based on work by Vegard Nossum, with
modifications. Unlike the original, we do not include
DEFINE_CRYPTO_API since only one copy of the crypto symbols is
kept, either in the crypto module or in the main kernel, and we ensure
such wrapper do not have impact on crypto already chosen built as
module.

Co-developed-by: Vegard Nossum <vegard.nossum@oracle.com>
Signed-off-by: Jay Wang <wanjay@amazon.com>
---
 crypto/Makefile               |  2 +-
 crypto/fips140/fips140-api.c  | 16 ++++++++++++++++
 include/crypto/internal/sig.h | 12 +++++-------
 include/crypto/sig.h          |  3 ++-
 4 files changed, 24 insertions(+), 9 deletions(-)

diff --git a/crypto/Makefile b/crypto/Makefile
index 7d55be467108..2e722f7961d4 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -34,7 +34,7 @@ crypto_hash-y += shash.o
 crypto-objs-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o
 
 crypto-objs-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o
-obj-$(CONFIG_CRYPTO_SIG2) += sig.o
+crypto-objs-$(CONFIG_CRYPTO_SIG2) += sig.o
 obj-$(CONFIG_CRYPTO_KPP2) += kpp.o
 obj-$(CONFIG_CRYPTO_HKDF) += hkdf.o
 
diff --git a/crypto/fips140/fips140-api.c b/crypto/fips140/fips140-api.c
index 8d4d07060d86..c97806cfdd05 100644
--- a/crypto/fips140/fips140-api.c
+++ b/crypto/fips140/fips140-api.c
@@ -270,4 +270,20 @@ DEFINE_CRYPTO_API_STUB(akcipher_register_instance);
 DEFINE_CRYPTO_API_STUB(crypto_akcipher_sync_encrypt);
 DEFINE_CRYPTO_API_STUB(crypto_akcipher_sync_decrypt);
 
+#endif
+
+/*
+ * crypto/sig.c
+ */
+#if IS_BUILTIN(CONFIG_CRYPTO_SIG2)
+
+#include <crypto/sig.h>
+#include <crypto/internal/sig.h>
+
+DEFINE_CRYPTO_API_STUB(crypto_alloc_sig);
+DEFINE_CRYPTO_API_STUB(crypto_register_sig);
+DEFINE_CRYPTO_API_STUB(crypto_unregister_sig);
+DEFINE_CRYPTO_API_STUB(sig_register_instance);
+DEFINE_CRYPTO_API_STUB(crypto_grab_sig);
+
 #endif
\ No newline at end of file
diff --git a/include/crypto/internal/sig.h b/include/crypto/internal/sig.h
index b16648c1a986..51d3a617c00d 100644
--- a/include/crypto/internal/sig.h
+++ b/include/crypto/internal/sig.h
@@ -7,6 +7,7 @@
 #ifndef _CRYPTO_INTERNAL_SIG_H
 #define _CRYPTO_INTERNAL_SIG_H
 
+#include <crypto/api.h>
 #include <crypto/algapi.h>
 #include <crypto/sig.h>
 
@@ -39,7 +40,7 @@ static inline void *crypto_sig_ctx(struct crypto_sig *tfm)
  *
  * Return: zero on success; error code in case of error
  */
-int crypto_register_sig(struct sig_alg *alg);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SIG2, crypto_register_sig, int, (struct sig_alg *alg), (alg));
 
 /**
  * crypto_unregister_sig() -- Unregister public key signature algorithm
@@ -48,10 +49,9 @@ int crypto_register_sig(struct sig_alg *alg);
  *
  * @alg:	algorithm definition
  */
-void crypto_unregister_sig(struct sig_alg *alg);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SIG2, crypto_unregister_sig, void, (struct sig_alg *alg), (alg));
 
-int sig_register_instance(struct crypto_template *tmpl,
-			  struct sig_instance *inst);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SIG2, sig_register_instance, int, (struct crypto_template *tmpl, struct sig_instance *inst), (tmpl, inst));
 
 static inline struct sig_instance *sig_instance(struct crypto_instance *inst)
 {
@@ -74,9 +74,7 @@ static inline void *sig_instance_ctx(struct sig_instance *inst)
 	return crypto_instance_ctx(sig_crypto_instance(inst));
 }
 
-int crypto_grab_sig(struct crypto_sig_spawn *spawn,
-		    struct crypto_instance *inst,
-		    const char *name, u32 type, u32 mask);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SIG2, crypto_grab_sig, int, (struct crypto_sig_spawn *spawn, struct crypto_instance *inst, const char *name, u32 type, u32 mask), (spawn, inst, name, type, mask));
 
 static inline struct crypto_sig *crypto_spawn_sig(struct crypto_sig_spawn
 								   *spawn)
diff --git a/include/crypto/sig.h b/include/crypto/sig.h
index fa6dafafab3f..1b0595b3b245 100644
--- a/include/crypto/sig.h
+++ b/include/crypto/sig.h
@@ -7,6 +7,7 @@
 #ifndef _CRYPTO_SIG_H
 #define _CRYPTO_SIG_H
 
+#include <crypto/api.h>
 #include <linux/crypto.h>
 
 /**
@@ -91,7 +92,7 @@ struct sig_alg {
  * Return: allocated handle in case of success; IS_ERR() is true in case
  *	   of an error, PTR_ERR() returns the error code.
  */
-struct crypto_sig *crypto_alloc_sig(const char *alg_name, u32 type, u32 mask);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SIG2, crypto_alloc_sig, struct crypto_sig *, (const char *alg_name, u32 type, u32 mask), (alg_name, type, mask));
 
 static inline struct crypto_tfm *crypto_sig_tfm(struct crypto_sig *tfm)
 {
-- 
2.47.3


^ permalink raw reply related

* [PATCH 009/106] crypto: convert exported crypto symbol into pluggable interface for CONFIG_CRYPTO_AKCIPHER2 crypto
From: Jay Wang @ 2026-02-12  2:45 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
	Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
	linux-modules
In-Reply-To: <20260212024725.11264-1-wanjay@amazon.com>

Apply Crypto API wrappers to the exported crypto symbol in
CONFIG_CRYPTO_AKCIPHER2-related crypto to convert them into pluggable
interface.

This patch is partially based on work by Vegard Nossum, with
modifications. Unlike the original, we do not include
DEFINE_CRYPTO_API since only one copy of the crypto symbols is
kept, either in the crypto module or in the main kernel, and we ensure
such wrapper do not have impact on crypto already chosen built as
module.

Co-developed-by: Vegard Nossum <vegard.nossum@oracle.com>
Signed-off-by: Jay Wang <wanjay@amazon.com>
---
 crypto/Makefile                    |  2 +-
 crypto/fips140/fips140-api.c       | 18 ++++++++++++++++++
 include/crypto/akcipher.h          | 12 ++++--------
 include/crypto/internal/akcipher.h | 12 +++++-------
 4 files changed, 28 insertions(+), 16 deletions(-)

diff --git a/crypto/Makefile b/crypto/Makefile
index 210e4aa3dbac..7d55be467108 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -33,7 +33,7 @@ crypto_hash-y += ahash.o
 crypto_hash-y += shash.o
 crypto-objs-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o
 
-obj-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o
+crypto-objs-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o
 obj-$(CONFIG_CRYPTO_SIG2) += sig.o
 obj-$(CONFIG_CRYPTO_KPP2) += kpp.o
 obj-$(CONFIG_CRYPTO_HKDF) += hkdf.o
diff --git a/crypto/fips140/fips140-api.c b/crypto/fips140/fips140-api.c
index e1c2f709ad3b..8d4d07060d86 100644
--- a/crypto/fips140/fips140-api.c
+++ b/crypto/fips140/fips140-api.c
@@ -252,4 +252,22 @@ DEFINE_CRYPTO_API_STUB(crypto_unregister_shashes);
 DEFINE_CRYPTO_API_STUB(shash_register_instance);
 DEFINE_CRYPTO_API_STUB(shash_free_singlespawn_instance);
 
+#endif
+
+/*
+ * crypto/akcipher.c
+ */
+#if IS_BUILTIN(CONFIG_CRYPTO_AKCIPHER2)
+
+#include <crypto/akcipher.h>
+#include <crypto/internal/akcipher.h>
+
+DEFINE_CRYPTO_API_STUB(crypto_grab_akcipher);
+DEFINE_CRYPTO_API_STUB(crypto_alloc_akcipher);
+DEFINE_CRYPTO_API_STUB(crypto_register_akcipher);
+DEFINE_CRYPTO_API_STUB(crypto_unregister_akcipher);
+DEFINE_CRYPTO_API_STUB(akcipher_register_instance);
+DEFINE_CRYPTO_API_STUB(crypto_akcipher_sync_encrypt);
+DEFINE_CRYPTO_API_STUB(crypto_akcipher_sync_decrypt);
+
 #endif
\ No newline at end of file
diff --git a/include/crypto/akcipher.h b/include/crypto/akcipher.h
index cdf7da74bf2f..a48cf468521e 100644
--- a/include/crypto/akcipher.h
+++ b/include/crypto/akcipher.h
@@ -8,6 +8,7 @@
 #ifndef _CRYPTO_AKCIPHER_H
 #define _CRYPTO_AKCIPHER_H
 
+#include <crypto/api.h>
 #include <linux/atomic.h>
 #include <linux/crypto.h>
 
@@ -116,8 +117,7 @@ struct akcipher_alg {
  * Return: allocated handle in case of success; IS_ERR() is true in case
  *	   of an error, PTR_ERR() returns the error code.
  */
-struct crypto_akcipher *crypto_alloc_akcipher(const char *alg_name, u32 type,
-					      u32 mask);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_AKCIPHER2, crypto_alloc_akcipher, struct crypto_akcipher *, (const char *alg_name, u32 type, u32 mask), (alg_name, type, mask));
 
 static inline struct crypto_tfm *crypto_akcipher_tfm(
 	struct crypto_akcipher *tfm)
@@ -310,9 +310,7 @@ static inline int crypto_akcipher_decrypt(struct akcipher_request *req)
  *
  * Return: zero on success; error code in case of error
  */
-int crypto_akcipher_sync_encrypt(struct crypto_akcipher *tfm,
-				 const void *src, unsigned int slen,
-				 void *dst, unsigned int dlen);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_AKCIPHER2, crypto_akcipher_sync_encrypt, int, (struct crypto_akcipher *tfm, const void *src, unsigned int slen, void *dst, unsigned int dlen), (tfm, src, slen, dst, dlen));
 
 /**
  * crypto_akcipher_sync_decrypt() - Invoke public key decrypt operation
@@ -328,9 +326,7 @@ int crypto_akcipher_sync_encrypt(struct crypto_akcipher *tfm,
  *
  * Return: Output length on success; error code in case of error
  */
-int crypto_akcipher_sync_decrypt(struct crypto_akcipher *tfm,
-				 const void *src, unsigned int slen,
-				 void *dst, unsigned int dlen);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_AKCIPHER2, crypto_akcipher_sync_decrypt, int, (struct crypto_akcipher *tfm, const void *src, unsigned int slen, void *dst, unsigned int dlen), (tfm, src, slen, dst, dlen));
 
 /**
  * crypto_akcipher_set_pub_key() - Invoke set public key operation
diff --git a/include/crypto/internal/akcipher.h b/include/crypto/internal/akcipher.h
index 14ee62bc52b6..5b690a82d58e 100644
--- a/include/crypto/internal/akcipher.h
+++ b/include/crypto/internal/akcipher.h
@@ -7,6 +7,7 @@
  */
 #ifndef _CRYPTO_AKCIPHER_INT_H
 #define _CRYPTO_AKCIPHER_INT_H
+#include <crypto/api.h>
 #include <crypto/akcipher.h>
 #include <crypto/algapi.h>
 
@@ -100,9 +101,7 @@ static inline void *akcipher_instance_ctx(struct akcipher_instance *inst)
 	return crypto_instance_ctx(akcipher_crypto_instance(inst));
 }
 
-int crypto_grab_akcipher(struct crypto_akcipher_spawn *spawn,
-			 struct crypto_instance *inst,
-			 const char *name, u32 type, u32 mask);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_AKCIPHER2, crypto_grab_akcipher, int, (struct crypto_akcipher_spawn *spawn, struct crypto_instance *inst, const char *name, u32 type, u32 mask), (spawn, inst, name, type, mask));
 
 static inline struct crypto_akcipher *crypto_spawn_akcipher(
 		struct crypto_akcipher_spawn *spawn)
@@ -130,7 +129,7 @@ static inline struct akcipher_alg *crypto_spawn_akcipher_alg(
  *
  * Return: zero on success; error code in case of error
  */
-int crypto_register_akcipher(struct akcipher_alg *alg);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_AKCIPHER2, crypto_register_akcipher, int, (struct akcipher_alg *alg), (alg));
 
 /**
  * crypto_unregister_akcipher() -- Unregister public key algorithm
@@ -139,7 +138,7 @@ int crypto_register_akcipher(struct akcipher_alg *alg);
  *
  * @alg:	algorithm definition
  */
-void crypto_unregister_akcipher(struct akcipher_alg *alg);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_AKCIPHER2, crypto_unregister_akcipher, void, (struct akcipher_alg *alg), (alg));
 
 /**
  * akcipher_register_instance() -- Unregister public key template instance
@@ -150,6 +149,5 @@ void crypto_unregister_akcipher(struct akcipher_alg *alg);
  * @tmpl:	the template from which the algorithm was created
  * @inst:	the template instance
  */
-int akcipher_register_instance(struct crypto_template *tmpl,
-		struct akcipher_instance *inst);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_AKCIPHER2, akcipher_register_instance, int, (struct crypto_template *tmpl, struct akcipher_instance *inst), (tmpl, inst));
 #endif
-- 
2.47.3


^ permalink raw reply related

* [PATCH 008/106] crypto: convert exported crypto symbol into pluggable interface for CONFIG_CRYPTO_HASH2 crypto
From: Jay Wang @ 2026-02-12  2:45 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
	Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
	linux-modules
In-Reply-To: <20260212024725.11264-1-wanjay@amazon.com>

Apply Crypto API wrappers to the exported crypto symbol in
CONFIG_CRYPTO_HASH2-related crypto to convert them into pluggable
interface.

This patch is partially based on work by Vegard Nossum, with
modifications. Unlike the original, we do not include
DEFINE_CRYPTO_API since only one copy of the crypto symbols is
kept, either in the crypto module or in the main kernel, and we ensure
such wrapper do not have impact on crypto already chosen built as
module.

Co-developed-by: Vegard Nossum <vegard.nossum@oracle.com>
Signed-off-by: Jay Wang <wanjay@amazon.com>
---
 crypto/Makefile                |  2 +-
 crypto/fips140/fips140-api.c   | 63 ++++++++++++++++++++++++++++++++++
 include/crypto/hash.h          | 53 +++++++++++++---------------
 include/crypto/internal/hash.h | 59 ++++++++++++++-----------------
 4 files changed, 113 insertions(+), 64 deletions(-)

diff --git a/crypto/Makefile b/crypto/Makefile
index f14758177ee3..210e4aa3dbac 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -31,7 +31,7 @@ crypto-objs-$(CONFIG_CRYPTO_ECHAINIV) += echainiv.o
 
 crypto_hash-y += ahash.o
 crypto_hash-y += shash.o
-obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o
+crypto-objs-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o
 
 obj-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o
 obj-$(CONFIG_CRYPTO_SIG2) += sig.o
diff --git a/crypto/fips140/fips140-api.c b/crypto/fips140/fips140-api.c
index e256b0f3e4a6..e1c2f709ad3b 100644
--- a/crypto/fips140/fips140-api.c
+++ b/crypto/fips140/fips140-api.c
@@ -189,4 +189,67 @@ DEFINE_CRYPTO_API_STUB(skcipher_walk_aead_encrypt);
 DEFINE_CRYPTO_API_STUB(skcipher_walk_aead_decrypt);
 DEFINE_CRYPTO_API_STUB(skcipher_alloc_instance_simple);
 
+#endif
+
+/*
+ * crypto/ahash.c
+ */
+#if IS_BUILTIN(CONFIG_CRYPTO_HASH2)
+
+#include <crypto/hash.h>
+#include <crypto/internal/hash.h>
+
+DEFINE_CRYPTO_API_STUB(crypto_hash_walk_first);
+DEFINE_CRYPTO_API_STUB(crypto_hash_walk_done);
+DEFINE_CRYPTO_API_STUB(shash_ahash_update);
+DEFINE_CRYPTO_API_STUB(shash_ahash_finup);
+DEFINE_CRYPTO_API_STUB(shash_ahash_digest);
+DEFINE_CRYPTO_API_STUB(crypto_ahash_setkey);
+DEFINE_CRYPTO_API_STUB(crypto_ahash_init);
+DEFINE_CRYPTO_API_STUB(crypto_ahash_update);
+DEFINE_CRYPTO_API_STUB(crypto_ahash_finup);
+DEFINE_CRYPTO_API_STUB(crypto_ahash_digest);
+DEFINE_CRYPTO_API_STUB(crypto_ahash_export_core);
+DEFINE_CRYPTO_API_STUB(crypto_ahash_export);
+DEFINE_CRYPTO_API_STUB(crypto_ahash_import_core);
+DEFINE_CRYPTO_API_STUB(crypto_ahash_import);
+DEFINE_CRYPTO_API_STUB(crypto_grab_ahash);
+DEFINE_CRYPTO_API_STUB(crypto_alloc_ahash);
+DEFINE_CRYPTO_API_STUB(crypto_has_ahash);
+DEFINE_CRYPTO_API_STUB(crypto_hash_alg_has_setkey);
+DEFINE_CRYPTO_API_STUB(crypto_clone_ahash);
+DEFINE_CRYPTO_API_STUB(crypto_register_ahash);
+DEFINE_CRYPTO_API_STUB(crypto_unregister_ahash);
+DEFINE_CRYPTO_API_STUB(crypto_register_ahashes);
+DEFINE_CRYPTO_API_STUB(crypto_unregister_ahashes);
+DEFINE_CRYPTO_API_STUB(ahash_register_instance);
+DEFINE_CRYPTO_API_STUB(ahash_request_free);
+DEFINE_CRYPTO_API_STUB(crypto_hash_digest);
+DEFINE_CRYPTO_API_STUB(ahash_free_singlespawn_instance);
+
+/*
+ * crypto/shash.c
+ */
+
+DEFINE_CRYPTO_API_STUB(shash_no_setkey);
+DEFINE_CRYPTO_API_STUB(crypto_shash_setkey);
+DEFINE_CRYPTO_API_STUB(crypto_shash_init);
+DEFINE_CRYPTO_API_STUB(crypto_shash_finup);
+DEFINE_CRYPTO_API_STUB(crypto_shash_digest);
+DEFINE_CRYPTO_API_STUB(crypto_shash_tfm_digest);
+DEFINE_CRYPTO_API_STUB(crypto_shash_export_core);
+DEFINE_CRYPTO_API_STUB(crypto_shash_export);
+DEFINE_CRYPTO_API_STUB(crypto_shash_import_core);
+DEFINE_CRYPTO_API_STUB(crypto_shash_import);
+DEFINE_CRYPTO_API_STUB(crypto_grab_shash);
+DEFINE_CRYPTO_API_STUB(crypto_alloc_shash);
+DEFINE_CRYPTO_API_STUB(crypto_has_shash);
+DEFINE_CRYPTO_API_STUB(crypto_clone_shash);
+DEFINE_CRYPTO_API_STUB(crypto_register_shash);
+DEFINE_CRYPTO_API_STUB(crypto_unregister_shash);
+DEFINE_CRYPTO_API_STUB(crypto_register_shashes);
+DEFINE_CRYPTO_API_STUB(crypto_unregister_shashes);
+DEFINE_CRYPTO_API_STUB(shash_register_instance);
+DEFINE_CRYPTO_API_STUB(shash_free_singlespawn_instance);
+
 #endif
\ No newline at end of file
diff --git a/include/crypto/hash.h b/include/crypto/hash.h
index 586700332c73..10325879514a 100644
--- a/include/crypto/hash.h
+++ b/include/crypto/hash.h
@@ -8,6 +8,7 @@
 #ifndef _CRYPTO_HASH_H
 #define _CRYPTO_HASH_H
 
+#include <crypto/api.h>
 #include <linux/crypto.h>
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
@@ -319,10 +320,9 @@ static inline struct crypto_ahash *__crypto_ahash_cast(struct crypto_tfm *tfm)
  * Return: allocated cipher handle in case of success; IS_ERR() is true in case
  *	   of an error, PTR_ERR() returns the error code.
  */
-struct crypto_ahash *crypto_alloc_ahash(const char *alg_name, u32 type,
-					u32 mask);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_alloc_ahash, struct crypto_ahash *, (const char *alg_name, u32 type, u32 mask), (alg_name, type, mask));
 
-struct crypto_ahash *crypto_clone_ahash(struct crypto_ahash *tfm);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_clone_ahash, struct crypto_ahash *, (struct crypto_ahash *tfm), (tfm));
 
 static inline struct crypto_tfm *crypto_ahash_tfm(struct crypto_ahash *tfm)
 {
@@ -350,7 +350,7 @@ static inline void crypto_free_ahash(struct crypto_ahash *tfm)
  * Return: true when the ahash is known to the kernel crypto API; false
  *	   otherwise
  */
-int crypto_has_ahash(const char *alg_name, u32 type, u32 mask);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_has_ahash, int, (const char *alg_name, u32 type, u32 mask), (alg_name, type, mask));
 
 static inline const char *crypto_ahash_alg_name(struct crypto_ahash *tfm)
 {
@@ -476,8 +476,7 @@ static inline void *ahash_request_ctx(struct ahash_request *req)
  *
  * Return: 0 if the setting of the key was successful; < 0 if an error occurred
  */
-int crypto_ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
-			unsigned int keylen);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_ahash_setkey, int, (struct crypto_ahash *tfm, const u8 *key, unsigned int keylen), (tfm, key, keylen));
 
 /**
  * crypto_ahash_finup() - update and finalize message digest
@@ -490,7 +489,7 @@ int crypto_ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
  *
  * Return: see crypto_ahash_final()
  */
-int crypto_ahash_finup(struct ahash_request *req);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_ahash_finup, int, (struct ahash_request *req), (req));
 
 /**
  * crypto_ahash_final() - calculate message digest
@@ -524,7 +523,7 @@ static inline int crypto_ahash_final(struct ahash_request *req)
  *
  * Return: see crypto_ahash_final()
  */
-int crypto_ahash_digest(struct ahash_request *req);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_ahash_digest, int, (struct ahash_request *req), (req));
 
 /**
  * crypto_ahash_export() - extract current message digest state
@@ -537,7 +536,7 @@ int crypto_ahash_digest(struct ahash_request *req);
  *
  * Return: 0 if the export was successful; < 0 if an error occurred
  */
-int crypto_ahash_export(struct ahash_request *req, void *out);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_ahash_export, int, (struct ahash_request *req, void *out), (req, out));
 
 /**
  * crypto_ahash_import() - import message digest state
@@ -550,7 +549,7 @@ int crypto_ahash_export(struct ahash_request *req, void *out);
  *
  * Return: 0 if the import was successful; < 0 if an error occurred
  */
-int crypto_ahash_import(struct ahash_request *req, const void *in);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_ahash_import, int, (struct ahash_request *req, const void *in), (req, in));
 
 /**
  * crypto_ahash_init() - (re)initialize message digest handle
@@ -563,7 +562,7 @@ int crypto_ahash_import(struct ahash_request *req, const void *in);
  *
  * Return: see crypto_ahash_final()
  */
-int crypto_ahash_init(struct ahash_request *req);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_ahash_init, int, (struct ahash_request *req), (req));
 
 /**
  * crypto_ahash_update() - add data to message digest for processing
@@ -576,7 +575,7 @@ int crypto_ahash_init(struct ahash_request *req);
  *
  * Return: see crypto_ahash_final()
  */
-int crypto_ahash_update(struct ahash_request *req);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_ahash_update, int, (struct ahash_request *req), (req));
 
 /**
  * DOC: Asynchronous Hash Request Handle
@@ -634,7 +633,7 @@ static inline struct ahash_request *ahash_request_alloc_noprof(
  * ahash_request_free() - zeroize and free the request data structure
  * @req: request data structure cipher handle to be freed
  */
-void ahash_request_free(struct ahash_request *req);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, ahash_request_free, void, (struct ahash_request *req), (req));
 
 static inline void ahash_request_zero(struct ahash_request *req)
 {
@@ -756,12 +755,11 @@ static inline void ahash_request_set_virt(struct ahash_request *req,
  * Return: allocated cipher handle in case of success; IS_ERR() is true in case
  *	   of an error, PTR_ERR() returns the error code.
  */
-struct crypto_shash *crypto_alloc_shash(const char *alg_name, u32 type,
-					u32 mask);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_alloc_shash, struct crypto_shash *, (const char *alg_name, u32 type, u32 mask), (alg_name, type, mask));
 
-struct crypto_shash *crypto_clone_shash(struct crypto_shash *tfm);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_clone_shash, struct crypto_shash *, (struct crypto_shash *tfm), (tfm));
 
-int crypto_has_shash(const char *alg_name, u32 type, u32 mask);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_has_shash, int, (const char *alg_name, u32 type, u32 mask), (alg_name, type, mask));
 
 static inline struct crypto_tfm *crypto_shash_tfm(struct crypto_shash *tfm)
 {
@@ -885,8 +883,7 @@ static inline void *shash_desc_ctx(struct shash_desc *desc)
  * Context: Softirq or process context.
  * Return: 0 if the setting of the key was successful; < 0 if an error occurred
  */
-int crypto_shash_setkey(struct crypto_shash *tfm, const u8 *key,
-			unsigned int keylen);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_shash_setkey, int, (struct crypto_shash *tfm, const u8 *key, unsigned int keylen), (tfm, key, keylen));
 
 /**
  * crypto_shash_digest() - calculate message digest for buffer
@@ -903,8 +900,7 @@ int crypto_shash_setkey(struct crypto_shash *tfm, const u8 *key,
  * Return: 0 if the message digest creation was successful; < 0 if an error
  *	   occurred
  */
-int crypto_shash_digest(struct shash_desc *desc, const u8 *data,
-			unsigned int len, u8 *out);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_shash_digest, int, (struct shash_desc *desc, const u8 *data, unsigned int len, u8 *out), (desc, data, len, out));
 
 /**
  * crypto_shash_tfm_digest() - calculate message digest for buffer
@@ -922,11 +918,9 @@ int crypto_shash_digest(struct shash_desc *desc, const u8 *data,
  * Context: Softirq or process context.
  * Return: 0 on success; < 0 if an error occurred.
  */
-int crypto_shash_tfm_digest(struct crypto_shash *tfm, const u8 *data,
-			    unsigned int len, u8 *out);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_shash_tfm_digest, int, (struct crypto_shash *tfm, const u8 *data, unsigned int len, u8 *out), (tfm, data, len, out));
 
-int crypto_hash_digest(struct crypto_ahash *tfm, const u8 *data,
-		       unsigned int len, u8 *out);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_hash_digest, int, (struct crypto_ahash *tfm, const u8 *data, unsigned int len, u8 *out), (tfm, data, len, out));
 
 /**
  * crypto_shash_export() - extract operational state for message digest
@@ -940,7 +934,7 @@ int crypto_hash_digest(struct crypto_ahash *tfm, const u8 *data,
  * Context: Softirq or process context.
  * Return: 0 if the export creation was successful; < 0 if an error occurred
  */
-int crypto_shash_export(struct shash_desc *desc, void *out);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_shash_export, int, (struct shash_desc *desc, void *out), (desc, out));
 
 /**
  * crypto_shash_import() - import operational state
@@ -954,7 +948,7 @@ int crypto_shash_export(struct shash_desc *desc, void *out);
  * Context: Softirq or process context.
  * Return: 0 if the import was successful; < 0 if an error occurred
  */
-int crypto_shash_import(struct shash_desc *desc, const void *in);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_shash_import, int, (struct shash_desc *desc, const void *in), (desc, in));
 
 /**
  * crypto_shash_init() - (re)initialize message digest
@@ -968,7 +962,7 @@ int crypto_shash_import(struct shash_desc *desc, const void *in);
  * Return: 0 if the message digest initialization was successful; < 0 if an
  *	   error occurred
  */
-int crypto_shash_init(struct shash_desc *desc);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_shash_init, int, (struct shash_desc *desc), (desc));
 
 /**
  * crypto_shash_finup() - calculate message digest of buffer
@@ -985,8 +979,7 @@ int crypto_shash_init(struct shash_desc *desc);
  * Return: 0 if the message digest creation was successful; < 0 if an error
  *	   occurred
  */
-int crypto_shash_finup(struct shash_desc *desc, const u8 *data,
-		       unsigned int len, u8 *out);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_shash_finup, int, (struct shash_desc *desc, const u8 *data, unsigned int len, u8 *out), (desc, data, len, out));
 
 /**
  * crypto_shash_update() - add data to message digest for processing
diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h
index 6ec5f2f37ccb..7ab717d1fd9c 100644
--- a/include/crypto/internal/hash.h
+++ b/include/crypto/internal/hash.h
@@ -8,6 +8,7 @@
 #ifndef _CRYPTO_INTERNAL_HASH_H
 #define _CRYPTO_INTERNAL_HASH_H
 
+#include <crypto/api.h>
 #include <crypto/algapi.h>
 #include <crypto/hash.h>
 
@@ -75,32 +76,29 @@ struct crypto_shash_spawn {
 	struct crypto_spawn base;
 };
 
-int crypto_hash_walk_done(struct crypto_hash_walk *walk, int err);
-int crypto_hash_walk_first(struct ahash_request *req,
-			   struct crypto_hash_walk *walk);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_hash_walk_done, int, (struct crypto_hash_walk *walk, int err), (walk, err));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_hash_walk_first, int, (struct ahash_request *req, struct crypto_hash_walk *walk), (req, walk));
 
 static inline int crypto_hash_walk_last(struct crypto_hash_walk *walk)
 {
 	return !(walk->entrylen | walk->total);
 }
 
-int crypto_register_ahash(struct ahash_alg *alg);
-void crypto_unregister_ahash(struct ahash_alg *alg);
-int crypto_register_ahashes(struct ahash_alg *algs, int count);
-void crypto_unregister_ahashes(struct ahash_alg *algs, int count);
-int ahash_register_instance(struct crypto_template *tmpl,
-			    struct ahash_instance *inst);
-void ahash_free_singlespawn_instance(struct ahash_instance *inst);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_register_ahash, int, (struct ahash_alg *alg), (alg));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_unregister_ahash, void, (struct ahash_alg *alg), (alg));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_register_ahashes, int, (struct ahash_alg *algs, int count), (algs, count));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_unregister_ahashes, void, (struct ahash_alg *algs, int count), (algs, count));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, ahash_register_instance, int, (struct crypto_template *tmpl, struct ahash_instance *inst), (tmpl, inst));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, ahash_free_singlespawn_instance, void, (struct ahash_instance *inst), (inst));
 
-int shash_no_setkey(struct crypto_shash *tfm, const u8 *key,
-		    unsigned int keylen);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, shash_no_setkey, int, (struct crypto_shash *tfm, const u8 *key, unsigned int keylen), (tfm, key, keylen));
 
 static inline bool crypto_shash_alg_has_setkey(struct shash_alg *alg)
 {
 	return alg->setkey != shash_no_setkey;
 }
 
-bool crypto_hash_alg_has_setkey(struct hash_alg_common *halg);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_hash_alg_has_setkey, bool, (struct hash_alg_common *halg), (halg));
 
 static inline bool crypto_shash_alg_needs_key(struct shash_alg *alg)
 {
@@ -120,9 +118,7 @@ static inline bool crypto_hash_no_export_core(struct crypto_ahash *tfm)
 	       CRYPTO_AHASH_ALG_NO_EXPORT_CORE;
 }
 
-int crypto_grab_ahash(struct crypto_ahash_spawn *spawn,
-		      struct crypto_instance *inst,
-		      const char *name, u32 type, u32 mask);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_grab_ahash, int, (struct crypto_ahash_spawn *spawn, struct crypto_instance *inst, const char *name, u32 type, u32 mask), (spawn, inst, name, type, mask));
 
 static inline void crypto_drop_ahash(struct crypto_ahash_spawn *spawn)
 {
@@ -135,17 +131,14 @@ static inline struct hash_alg_common *crypto_spawn_ahash_alg(
 	return __crypto_hash_alg_common(spawn->base.alg);
 }
 
-int crypto_register_shash(struct shash_alg *alg);
-void crypto_unregister_shash(struct shash_alg *alg);
-int crypto_register_shashes(struct shash_alg *algs, int count);
-void crypto_unregister_shashes(struct shash_alg *algs, int count);
-int shash_register_instance(struct crypto_template *tmpl,
-			    struct shash_instance *inst);
-void shash_free_singlespawn_instance(struct shash_instance *inst);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_register_shash, int, (struct shash_alg *alg), (alg));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_unregister_shash, void, (struct shash_alg *alg), (alg));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_register_shashes, int, (struct shash_alg *algs, int count), (algs, count));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_unregister_shashes, void, (struct shash_alg *algs, int count), (algs, count));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, shash_register_instance, int, (struct crypto_template *tmpl, struct shash_instance *inst), (tmpl, inst));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, shash_free_singlespawn_instance, void, (struct shash_instance *inst), (inst));
 
-int crypto_grab_shash(struct crypto_shash_spawn *spawn,
-		      struct crypto_instance *inst,
-		      const char *name, u32 type, u32 mask);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_grab_shash, int, (struct crypto_shash_spawn *spawn, struct crypto_instance *inst, const char *name, u32 type, u32 mask), (spawn, inst, name, type, mask));
 
 static inline void crypto_drop_shash(struct crypto_shash_spawn *spawn)
 {
@@ -158,9 +151,9 @@ static inline struct shash_alg *crypto_spawn_shash_alg(
 	return __crypto_shash_alg(spawn->base.alg);
 }
 
-int shash_ahash_update(struct ahash_request *req, struct shash_desc *desc);
-int shash_ahash_finup(struct ahash_request *req, struct shash_desc *desc);
-int shash_ahash_digest(struct ahash_request *req, struct shash_desc *desc);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, shash_ahash_update, int, (struct ahash_request *req, struct shash_desc *desc), (req, desc));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, shash_ahash_finup, int, (struct ahash_request *req, struct shash_desc *desc), (req, desc));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, shash_ahash_digest, int, (struct ahash_request *req, struct shash_desc *desc), (req, desc));
 
 static inline void *crypto_ahash_ctx(struct crypto_ahash *tfm)
 {
@@ -363,7 +356,7 @@ static inline unsigned int crypto_shash_coresize(struct crypto_shash *tfm)
  * Context: Softirq or process context.
  * Return: 0 if the export creation was successful; < 0 if an error occurred
  */
-int crypto_ahash_export_core(struct ahash_request *req, void *out);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_ahash_export_core, int, (struct ahash_request *req, void *out), (req, out));
 
 /**
  * crypto_ahash_import_core() - import core state
@@ -375,7 +368,7 @@ int crypto_ahash_export_core(struct ahash_request *req, void *out);
  * Context: Softirq or process context.
  * Return: 0 if the import was successful; < 0 if an error occurred
  */
-int crypto_ahash_import_core(struct ahash_request *req, const void *in);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_ahash_import_core, int, (struct ahash_request *req, const void *in), (req, in));
 
 /**
  * crypto_shash_export_core() - extract core state for message digest
@@ -387,7 +380,7 @@ int crypto_ahash_import_core(struct ahash_request *req, const void *in);
  * Context: Softirq or process context.
  * Return: 0 if the export creation was successful; < 0 if an error occurred
  */
-int crypto_shash_export_core(struct shash_desc *desc, void *out);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_shash_export_core, int, (struct shash_desc *desc, void *out), (desc, out));
 
 /**
  * crypto_shash_import_core() - import core state
@@ -399,7 +392,7 @@ int crypto_shash_export_core(struct shash_desc *desc, void *out);
  * Context: Softirq or process context.
  * Return: 0 if the import was successful; < 0 if an error occurred
  */
-int crypto_shash_import_core(struct shash_desc *desc, const void *in);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_HASH2, crypto_shash_import_core, int, (struct shash_desc *desc, const void *in), (desc, in));
 
 #endif	/* _CRYPTO_INTERNAL_HASH_H */
 
-- 
2.47.3


^ permalink raw reply related

* [PATCH 007/106] crypto: convert exported crypto symbol into pluggable interface for CONFIG_CRYPTO_ECHAINIV crypto
From: Jay Wang @ 2026-02-12  2:45 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
	Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
	linux-modules
In-Reply-To: <20260212024725.11264-1-wanjay@amazon.com>

From: Vegard Nossum <vegard.nossum@oracle.com>

Apply Crypto API wrappers to the exported crypto symbol in
CONFIG_CRYPTO_ECHAINIV-related crypto to convert them into pluggable
interface.

Signed-off-by: Vegard Nossum <vegard.nossum@oracle.com>
[add echainiv.o into crypto-objs-y; revise commit message]
Signed-off-by: Jay Wang <wanjay@amazon.com>
---
 crypto/Makefile   | 2 +-
 crypto/echainiv.c | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/crypto/Makefile b/crypto/Makefile
index 4d6f1c927db4..f14758177ee3 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -27,7 +27,7 @@ crypto-objs-$(CONFIG_CRYPTO_SKCIPHER2) += bpf_crypto_skcipher.o
 endif
 
 crypto-objs-$(CONFIG_CRYPTO_SEQIV) += seqiv.o
-obj-$(CONFIG_CRYPTO_ECHAINIV) += echainiv.o
+crypto-objs-$(CONFIG_CRYPTO_ECHAINIV) += echainiv.o
 
 crypto_hash-y += ahash.o
 crypto_hash-y += shash.o
diff --git a/crypto/echainiv.c b/crypto/echainiv.c
index e0a2d3209938..d409b4169e83 100644
--- a/crypto/echainiv.c
+++ b/crypto/echainiv.c
@@ -145,8 +145,8 @@ static void __exit echainiv_module_exit(void)
 	crypto_unregister_template(&echainiv_tmpl);
 }
 
-module_init(echainiv_module_init);
-module_exit(echainiv_module_exit);
+crypto_module_init(echainiv_module_init);
+crypto_module_exit(echainiv_module_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Encrypted Chain IV Generator");
-- 
2.47.3


^ permalink raw reply related

* [PATCH 006/106] crypto: convert exported crypto symbol into pluggable interface for CONFIG_CRYPTO_SEQIV crypto
From: Jay Wang @ 2026-02-12  2:45 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
	Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
	linux-modules
In-Reply-To: <20260212024725.11264-1-wanjay@amazon.com>

From: Vegard Nossum <vegard.nossum@oracle.com>

Apply Crypto API wrappers to the exported crypto symbol in
CONFIG_CRYPTO_SEQIV-related crypto to convert them into pluggable
interface.

Signed-off-by: Vegard Nossum <vegard.nossum@oracle.com>
[add seqiv.o into crypto-objs-y; revise commit message]
Signed-off-by: Jay Wang <wanjay@amazon.com>
---
 crypto/Makefile | 2 +-
 crypto/seqiv.c  | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/crypto/Makefile b/crypto/Makefile
index 546f80e014e1..4d6f1c927db4 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -26,7 +26,7 @@ ifeq ($(CONFIG_BPF_SYSCALL),y)
 crypto-objs-$(CONFIG_CRYPTO_SKCIPHER2) += bpf_crypto_skcipher.o
 endif
 
-obj-$(CONFIG_CRYPTO_SEQIV) += seqiv.o
+crypto-objs-$(CONFIG_CRYPTO_SEQIV) += seqiv.o
 obj-$(CONFIG_CRYPTO_ECHAINIV) += echainiv.o
 
 crypto_hash-y += ahash.o
diff --git a/crypto/seqiv.c b/crypto/seqiv.c
index 678bb4145d78..5db32c596c40 100644
--- a/crypto/seqiv.c
+++ b/crypto/seqiv.c
@@ -170,8 +170,8 @@ static void __exit seqiv_module_exit(void)
 	crypto_unregister_template(&seqiv_tmpl);
 }
 
-module_init(seqiv_module_init);
-module_exit(seqiv_module_exit);
+crypto_module_init(seqiv_module_init);
+crypto_module_exit(seqiv_module_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Sequence Number IV Generator");
-- 
2.47.3


^ permalink raw reply related

* [PATCH 005/106] crypto: convert exported crypto symbol into pluggable interface for CONFIG_CRYPTO_SKCIPHER2 crypto
From: Jay Wang @ 2026-02-12  2:45 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
	Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
	linux-modules
In-Reply-To: <20260212024725.11264-1-wanjay@amazon.com>

Apply Crypto API wrappers to the exported crypto symbol in
CONFIG_CRYPTO_SKCIPHER2-related crypto to convert them into pluggable
interface.

This patch is partially based on work by Vegard Nossum, with
modifications. Unlike the original, we do not include
DEFINE_CRYPTO_API since only one copy of the crypto symbols is
kept, either in the crypto module or in the main kernel, and we ensure
such wrapper do not have impact on crypto already chosen built as
module.

Co-developed-by: Vegard Nossum <vegard.nossum@oracle.com>
Signed-off-by: Jay Wang <wanjay@amazon.com>
---
 crypto/Makefile                    |  4 +-
 crypto/bpf_crypto_skcipher.c       |  4 +-
 crypto/fips140/fips140-api.c       | 47 +++++++++++++++
 include/crypto/internal/skcipher.h | 91 +++++++++++++++++++-----------
 include/crypto/skcipher.h          | 56 +++++++++++-------
 5 files changed, 145 insertions(+), 57 deletions(-)

diff --git a/crypto/Makefile b/crypto/Makefile
index b05fdfacf170..546f80e014e1 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -21,9 +21,9 @@ crypto-objs-$(CONFIG_CRYPTO_GENIV) += geniv.o
 crypto_skcipher-y += lskcipher.o
 crypto_skcipher-y += skcipher.o
 
-obj-$(CONFIG_CRYPTO_SKCIPHER2) += crypto_skcipher.o
+crypto-objs-$(CONFIG_CRYPTO_SKCIPHER2) += crypto_skcipher.o
 ifeq ($(CONFIG_BPF_SYSCALL),y)
-obj-$(CONFIG_CRYPTO_SKCIPHER2) += bpf_crypto_skcipher.o
+crypto-objs-$(CONFIG_CRYPTO_SKCIPHER2) += bpf_crypto_skcipher.o
 endif
 
 obj-$(CONFIG_CRYPTO_SEQIV) += seqiv.o
diff --git a/crypto/bpf_crypto_skcipher.c b/crypto/bpf_crypto_skcipher.c
index a88798d3e8c8..764bfc27e477 100644
--- a/crypto/bpf_crypto_skcipher.c
+++ b/crypto/bpf_crypto_skcipher.c
@@ -77,7 +77,7 @@ static void __exit bpf_crypto_skcipher_exit(void)
 	WARN_ON_ONCE(err);
 }
 
-module_init(bpf_crypto_skcipher_init);
-module_exit(bpf_crypto_skcipher_exit);
+crypto_module_init(bpf_crypto_skcipher_init);
+crypto_module_exit(bpf_crypto_skcipher_exit);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Symmetric key cipher support for BPF");
diff --git a/crypto/fips140/fips140-api.c b/crypto/fips140/fips140-api.c
index 55129c62d813..e256b0f3e4a6 100644
--- a/crypto/fips140/fips140-api.c
+++ b/crypto/fips140/fips140-api.c
@@ -142,4 +142,51 @@ DEFINE_CRYPTO_API_STUB(aead_geniv_alloc);
 DEFINE_CRYPTO_API_STUB(aead_init_geniv);
 DEFINE_CRYPTO_API_STUB(aead_exit_geniv);
 
+#endif
+
+/*
+ * crypto/lskcipher.c
+ */
+#if IS_BUILTIN(CONFIG_CRYPTO_SKCIPHER2)
+
+#include <crypto/skcipher.h>
+
+DEFINE_CRYPTO_API_STUB(crypto_alloc_lskcipher);
+DEFINE_CRYPTO_API_STUB(crypto_lskcipher_setkey);
+DEFINE_CRYPTO_API_STUB(crypto_lskcipher_encrypt);
+DEFINE_CRYPTO_API_STUB(crypto_lskcipher_decrypt);
+
+#include <crypto/internal/skcipher.h>
+
+DEFINE_CRYPTO_API_STUB(crypto_grab_lskcipher);
+DEFINE_CRYPTO_API_STUB(crypto_register_lskcipher);
+DEFINE_CRYPTO_API_STUB(crypto_unregister_lskcipher);
+DEFINE_CRYPTO_API_STUB(crypto_register_lskciphers);
+DEFINE_CRYPTO_API_STUB(crypto_unregister_lskciphers);
+DEFINE_CRYPTO_API_STUB(lskcipher_register_instance);
+DEFINE_CRYPTO_API_STUB(lskcipher_alloc_instance_simple);
+
+/*
+ * crypto/skcipher.c
+ */
+DEFINE_CRYPTO_API_STUB(crypto_alloc_skcipher);
+DEFINE_CRYPTO_API_STUB(crypto_alloc_sync_skcipher);
+DEFINE_CRYPTO_API_STUB(crypto_has_skcipher);
+DEFINE_CRYPTO_API_STUB(crypto_skcipher_setkey);
+DEFINE_CRYPTO_API_STUB(crypto_skcipher_encrypt);
+DEFINE_CRYPTO_API_STUB(crypto_skcipher_decrypt);
+DEFINE_CRYPTO_API_STUB(crypto_skcipher_export);
+DEFINE_CRYPTO_API_STUB(crypto_skcipher_import);
+DEFINE_CRYPTO_API_STUB(crypto_grab_skcipher);
+DEFINE_CRYPTO_API_STUB(crypto_register_skcipher);
+DEFINE_CRYPTO_API_STUB(crypto_unregister_skcipher);
+DEFINE_CRYPTO_API_STUB(crypto_register_skciphers);
+DEFINE_CRYPTO_API_STUB(crypto_unregister_skciphers);
+DEFINE_CRYPTO_API_STUB(skcipher_register_instance);
+DEFINE_CRYPTO_API_STUB(skcipher_walk_done);
+DEFINE_CRYPTO_API_STUB(skcipher_walk_virt);
+DEFINE_CRYPTO_API_STUB(skcipher_walk_aead_encrypt);
+DEFINE_CRYPTO_API_STUB(skcipher_walk_aead_decrypt);
+DEFINE_CRYPTO_API_STUB(skcipher_alloc_instance_simple);
+
 #endif
\ No newline at end of file
diff --git a/include/crypto/internal/skcipher.h b/include/crypto/internal/skcipher.h
index a965b6aabf61..b571c58269bc 100644
--- a/include/crypto/internal/skcipher.h
+++ b/include/crypto/internal/skcipher.h
@@ -8,6 +8,7 @@
 #ifndef _CRYPTO_INTERNAL_SKCIPHER_H
 #define _CRYPTO_INTERNAL_SKCIPHER_H
 
+#include <crypto/api.h>
 #include <crypto/algapi.h>
 #include <crypto/internal/cipher.h>
 #include <crypto/skcipher.h>
@@ -136,13 +137,13 @@ static inline void skcipher_request_complete(struct skcipher_request *req, int e
 	crypto_request_complete(&req->base, err);
 }
 
-int crypto_grab_skcipher(struct crypto_skcipher_spawn *spawn,
-			 struct crypto_instance *inst,
-			 const char *name, u32 type, u32 mask);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SKCIPHER2, crypto_grab_skcipher, int,
+	(struct crypto_skcipher_spawn *spawn, struct crypto_instance *inst, const char *name, u32 type, u32 mask),
+	(spawn, inst, name, type, mask));
 
-int crypto_grab_lskcipher(struct crypto_lskcipher_spawn *spawn,
-			  struct crypto_instance *inst,
-			  const char *name, u32 type, u32 mask);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SKCIPHER2, crypto_grab_lskcipher, int,
+	(struct crypto_lskcipher_spawn *spawn, struct crypto_instance *inst, const char *name, u32 type, u32 mask),
+	(spawn, inst, name, type, mask));
 
 static inline void crypto_drop_skcipher(struct crypto_skcipher_spawn *spawn)
 {
@@ -197,30 +198,50 @@ static inline void crypto_skcipher_set_reqsize_dma(
 	skcipher->reqsize = reqsize;
 }
 
-int crypto_register_skcipher(struct skcipher_alg *alg);
-void crypto_unregister_skcipher(struct skcipher_alg *alg);
-int crypto_register_skciphers(struct skcipher_alg *algs, int count);
-void crypto_unregister_skciphers(struct skcipher_alg *algs, int count);
-int skcipher_register_instance(struct crypto_template *tmpl,
-			       struct skcipher_instance *inst);
-
-int crypto_register_lskcipher(struct lskcipher_alg *alg);
-void crypto_unregister_lskcipher(struct lskcipher_alg *alg);
-int crypto_register_lskciphers(struct lskcipher_alg *algs, int count);
-void crypto_unregister_lskciphers(struct lskcipher_alg *algs, int count);
-int lskcipher_register_instance(struct crypto_template *tmpl,
-				struct lskcipher_instance *inst);
-
-int skcipher_walk_done(struct skcipher_walk *walk, int res);
-int skcipher_walk_virt(struct skcipher_walk *__restrict walk,
-		       struct skcipher_request *__restrict req,
-		       bool atomic);
-int skcipher_walk_aead_encrypt(struct skcipher_walk *__restrict walk,
-			       struct aead_request *__restrict req,
-			       bool atomic);
-int skcipher_walk_aead_decrypt(struct skcipher_walk *__restrict walk,
-			       struct aead_request *__restrict req,
-			       bool atomic);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SKCIPHER2, crypto_register_skcipher, int,
+	(struct skcipher_alg *alg),
+	(alg));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SKCIPHER2, crypto_unregister_skcipher, void,
+	(struct skcipher_alg *alg),
+	(alg));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SKCIPHER2, crypto_register_skciphers, int,
+	(struct skcipher_alg *algs, int count),
+	(algs, count));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SKCIPHER2, crypto_unregister_skciphers, void,
+	(struct skcipher_alg *algs, int count),
+	(algs, count));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SKCIPHER2, skcipher_register_instance, int,
+	(struct crypto_template *tmpl, struct skcipher_instance *inst),
+	(tmpl, inst));
+
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SKCIPHER2, crypto_register_lskcipher, int,
+	(struct lskcipher_alg *alg),
+	(alg));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SKCIPHER2, crypto_unregister_lskcipher, void,
+	(struct lskcipher_alg *alg),
+	(alg));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SKCIPHER2, crypto_register_lskciphers, int,
+	(struct lskcipher_alg *algs, int count),
+	(algs, count));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SKCIPHER2, crypto_unregister_lskciphers, void,
+	(struct lskcipher_alg *algs, int count),
+	(algs, count));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SKCIPHER2, lskcipher_register_instance, int,
+	(struct crypto_template *tmpl, struct lskcipher_instance *inst),
+	(tmpl, inst));
+
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SKCIPHER2, skcipher_walk_done, int,
+	(struct skcipher_walk *walk, int res),
+	(walk, res));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SKCIPHER2, skcipher_walk_virt, int,
+	(struct skcipher_walk *__restrict walk, struct skcipher_request *__restrict req, bool atomic),
+	(walk, req, atomic));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SKCIPHER2, skcipher_walk_aead_encrypt, int,
+	(struct skcipher_walk *__restrict walk, struct aead_request *__restrict req, bool atomic),
+	(walk, req, atomic));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SKCIPHER2, skcipher_walk_aead_decrypt, int,
+	(struct skcipher_walk *__restrict walk, struct aead_request *__restrict req, bool atomic),
+	(walk, req, atomic));
 
 static inline void skcipher_walk_abort(struct skcipher_walk *walk)
 {
@@ -281,8 +302,9 @@ skcipher_cipher_simple(struct crypto_skcipher *tfm)
 	return ctx->cipher;
 }
 
-struct skcipher_instance *skcipher_alloc_instance_simple(
-	struct crypto_template *tmpl, struct rtattr **tb);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SKCIPHER2, skcipher_alloc_instance_simple, struct skcipher_instance *,
+	(struct crypto_template *tmpl, struct rtattr **tb),
+	(tmpl, tb));
 
 static inline struct crypto_alg *skcipher_ialg_simple(
 	struct skcipher_instance *inst)
@@ -300,8 +322,9 @@ static inline struct crypto_lskcipher *lskcipher_cipher_simple(
 	return *ctx;
 }
 
-struct lskcipher_instance *lskcipher_alloc_instance_simple(
-	struct crypto_template *tmpl, struct rtattr **tb);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SKCIPHER2, lskcipher_alloc_instance_simple, struct lskcipher_instance *,
+	(struct crypto_template *tmpl, struct rtattr **tb),
+	(tmpl, tb));
 
 static inline struct lskcipher_alg *lskcipher_ialg_simple(
 	struct lskcipher_instance *inst)
diff --git a/include/crypto/skcipher.h b/include/crypto/skcipher.h
index 9e5853464345..39282b83a280 100644
--- a/include/crypto/skcipher.h
+++ b/include/crypto/skcipher.h
@@ -8,6 +8,7 @@
 #ifndef _CRYPTO_SKCIPHER_H
 #define _CRYPTO_SKCIPHER_H
 
+#include <crypto/api.h>
 #include <linux/atomic.h>
 #include <linux/container_of.h>
 #include <linux/crypto.h>
@@ -276,11 +277,13 @@ static inline struct crypto_skcipher *__crypto_skcipher_cast(
  * Return: allocated cipher handle in case of success; IS_ERR() is true in case
  *	   of an error, PTR_ERR() returns the error code.
  */
-struct crypto_skcipher *crypto_alloc_skcipher(const char *alg_name,
-					      u32 type, u32 mask);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SKCIPHER2, crypto_alloc_skcipher, struct crypto_skcipher *,
+	(const char *alg_name, u32 type, u32 mask),
+	(alg_name, type, mask));
 
-struct crypto_sync_skcipher *crypto_alloc_sync_skcipher(const char *alg_name,
-					      u32 type, u32 mask);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SKCIPHER2, crypto_alloc_sync_skcipher, struct crypto_sync_skcipher *,
+	(const char *alg_name, u32 type, u32 mask),
+	(alg_name, type, mask));
 
 
 /**
@@ -297,8 +300,9 @@ struct crypto_sync_skcipher *crypto_alloc_sync_skcipher(const char *alg_name,
  * Return: allocated cipher handle in case of success; IS_ERR() is true in case
  *	   of an error, PTR_ERR() returns the error code.
  */
-struct crypto_lskcipher *crypto_alloc_lskcipher(const char *alg_name,
-						u32 type, u32 mask);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SKCIPHER2, crypto_alloc_lskcipher, struct crypto_lskcipher *,
+	(const char *alg_name, u32 type, u32 mask),
+	(alg_name, type, mask));
 
 static inline struct crypto_tfm *crypto_skcipher_tfm(
 	struct crypto_skcipher *tfm)
@@ -355,7 +359,9 @@ static inline void crypto_free_lskcipher(struct crypto_lskcipher *tfm)
  * Return: true when the skcipher is known to the kernel crypto API; false
  *	   otherwise
  */
-int crypto_has_skcipher(const char *alg_name, u32 type, u32 mask);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SKCIPHER2, crypto_has_skcipher, int,
+	(const char *alg_name, u32 type, u32 mask),
+	(alg_name, type, mask));
 
 static inline const char *crypto_skcipher_driver_name(
 	struct crypto_skcipher *tfm)
@@ -611,8 +617,9 @@ static inline void crypto_lskcipher_clear_flags(struct crypto_lskcipher *tfm,
  *
  * Return: 0 if the setting of the key was successful; < 0 if an error occurred
  */
-int crypto_skcipher_setkey(struct crypto_skcipher *tfm,
-			   const u8 *key, unsigned int keylen);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SKCIPHER2, crypto_skcipher_setkey, int,
+	(struct crypto_skcipher *tfm, const u8 *key, unsigned int keylen),
+	(tfm, key, keylen));
 
 static inline int crypto_sync_skcipher_setkey(struct crypto_sync_skcipher *tfm,
 					 const u8 *key, unsigned int keylen)
@@ -636,8 +643,9 @@ static inline int crypto_sync_skcipher_setkey(struct crypto_sync_skcipher *tfm,
  *
  * Return: 0 if the setting of the key was successful; < 0 if an error occurred
  */
-int crypto_lskcipher_setkey(struct crypto_lskcipher *tfm,
-			    const u8 *key, unsigned int keylen);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SKCIPHER2, crypto_lskcipher_setkey, int,
+	(struct crypto_lskcipher *tfm, const u8 *key, unsigned int keylen),
+	(tfm, key, keylen));
 
 static inline unsigned int crypto_skcipher_min_keysize(
 	struct crypto_skcipher *tfm)
@@ -697,7 +705,9 @@ static inline struct crypto_sync_skcipher *crypto_sync_skcipher_reqtfm(
  *
  * Return: 0 if the cipher operation was successful; < 0 if an error occurred
  */
-int crypto_skcipher_encrypt(struct skcipher_request *req);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SKCIPHER2, crypto_skcipher_encrypt, int,
+	(struct skcipher_request *req),
+	(req));
 
 /**
  * crypto_skcipher_decrypt() - decrypt ciphertext
@@ -710,7 +720,9 @@ int crypto_skcipher_encrypt(struct skcipher_request *req);
  *
  * Return: 0 if the cipher operation was successful; < 0 if an error occurred
  */
-int crypto_skcipher_decrypt(struct skcipher_request *req);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SKCIPHER2, crypto_skcipher_decrypt, int,
+	(struct skcipher_request *req),
+	(req));
 
 /**
  * crypto_skcipher_export() - export partial state
@@ -728,7 +740,9 @@ int crypto_skcipher_decrypt(struct skcipher_request *req);
  *
  * Return: 0 if the cipher operation was successful; < 0 if an error occurred
  */
-int crypto_skcipher_export(struct skcipher_request *req, void *out);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SKCIPHER2, crypto_skcipher_export, int,
+	(struct skcipher_request *req, void *out),
+	(req, out));
 
 /**
  * crypto_skcipher_import() - import partial state
@@ -743,7 +757,9 @@ int crypto_skcipher_export(struct skcipher_request *req, void *out);
  *
  * Return: 0 if the cipher operation was successful; < 0 if an error occurred
  */
-int crypto_skcipher_import(struct skcipher_request *req, const void *in);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SKCIPHER2, crypto_skcipher_import, int,
+	(struct skcipher_request *req, const void *in),
+	(req, in));
 
 /**
  * crypto_lskcipher_encrypt() - encrypt plaintext
@@ -761,8 +777,9 @@ int crypto_skcipher_import(struct skcipher_request *req, const void *in);
  *	   then this many bytes have been left unprocessed;
  *	   < 0 if an error occurred
  */
-int crypto_lskcipher_encrypt(struct crypto_lskcipher *tfm, const u8 *src,
-			     u8 *dst, unsigned len, u8 *siv);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SKCIPHER2, crypto_lskcipher_encrypt, int,
+	(struct crypto_lskcipher *tfm, const u8 *src, u8 *dst, unsigned len, u8 *siv),
+	(tfm, src, dst, len, siv));
 
 /**
  * crypto_lskcipher_decrypt() - decrypt ciphertext
@@ -781,8 +798,9 @@ int crypto_lskcipher_encrypt(struct crypto_lskcipher *tfm, const u8 *src,
  *	   then this many bytes have been left unprocessed;
  *	   < 0 if an error occurred
  */
-int crypto_lskcipher_decrypt(struct crypto_lskcipher *tfm, const u8 *src,
-			     u8 *dst, unsigned len, u8 *siv);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_SKCIPHER2, crypto_lskcipher_decrypt, int,
+	(struct crypto_lskcipher *tfm, const u8 *src, u8 *dst, unsigned len, u8 *siv),
+	(tfm, src, dst, len, siv));
 
 /**
  * DOC: Symmetric Key Cipher Request Handle
-- 
2.47.3


^ permalink raw reply related

* [PATCH 004/106] crypto: convert exported crypto symbol into pluggable interface for CONFIG_CRYPTO_GENIV crypto
From: Jay Wang @ 2026-02-12  2:45 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
	Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
	linux-modules
In-Reply-To: <20260212024725.11264-1-wanjay@amazon.com>

Apply Crypto API wrappers to the exported crypto symbol in
CONFIG_CRYPTO_GENIV-related crypto to convert them into pluggable
interface.

This patch is partially based on work by Vegard Nossum, with
modifications. Unlike the original, we do not include
DEFINE_CRYPTO_API since only one copy of the crypto symbols is
kept, either in the crypto module or in the main kernel, and we ensure
such wrapper do not have impact on crypto already chosen built as
module.

Co-developed-by: Vegard Nossum <vegard.nossum@oracle.com>
Signed-off-by: Jay Wang <wanjay@amazon.com>
---
 crypto/Makefile                 |  2 +-
 crypto/fips140/fips140-api.c    | 13 +++++++++++++
 include/crypto/internal/geniv.h | 14 ++++++++++----
 3 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/crypto/Makefile b/crypto/Makefile
index 9aa52ddebb05..b05fdfacf170 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -16,7 +16,7 @@ crypto_algapi-y := algapi.o scatterwalk.o $(crypto_algapi-y)
 crypto-objs-$(CONFIG_CRYPTO_ALGAPI2) += crypto_algapi.o
 
 crypto-objs-$(CONFIG_CRYPTO_AEAD2) += aead.o
-obj-$(CONFIG_CRYPTO_GENIV) += geniv.o
+crypto-objs-$(CONFIG_CRYPTO_GENIV) += geniv.o
 
 crypto_skcipher-y += lskcipher.o
 crypto_skcipher-y += skcipher.o
diff --git a/crypto/fips140/fips140-api.c b/crypto/fips140/fips140-api.c
index eb02a56cb8b3..55129c62d813 100644
--- a/crypto/fips140/fips140-api.c
+++ b/crypto/fips140/fips140-api.c
@@ -129,4 +129,17 @@ DEFINE_CRYPTO_API_STUB(crypto_register_aeads);
 DEFINE_CRYPTO_API_STUB(crypto_unregister_aeads);
 DEFINE_CRYPTO_API_STUB(aead_register_instance);
 
+#endif
+
+/*
+ * crypto/geniv.c
+ */
+#if IS_BUILTIN(CONFIG_CRYPTO_GENIV)
+
+#include <crypto/internal/geniv.h>
+
+DEFINE_CRYPTO_API_STUB(aead_geniv_alloc);
+DEFINE_CRYPTO_API_STUB(aead_init_geniv);
+DEFINE_CRYPTO_API_STUB(aead_exit_geniv);
+
 #endif
\ No newline at end of file
diff --git a/include/crypto/internal/geniv.h b/include/crypto/internal/geniv.h
index 012f5fb22d43..f6dfe3292b3c 100644
--- a/include/crypto/internal/geniv.h
+++ b/include/crypto/internal/geniv.h
@@ -8,6 +8,7 @@
 #ifndef _CRYPTO_INTERNAL_GENIV_H
 #define _CRYPTO_INTERNAL_GENIV_H
 
+#include <crypto/api.h>
 #include <crypto/internal/aead.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
@@ -18,9 +19,14 @@ struct aead_geniv_ctx {
 	u8 salt[] __attribute__ ((aligned(__alignof__(u32))));
 };
 
-struct aead_instance *aead_geniv_alloc(struct crypto_template *tmpl,
-				       struct rtattr **tb);
-int aead_init_geniv(struct crypto_aead *tfm);
-void aead_exit_geniv(struct crypto_aead *tfm);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_GENIV, aead_geniv_alloc, struct aead_instance *,
+	(struct crypto_template *tmpl, struct rtattr **tb),
+	(tmpl, tb));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_GENIV, aead_init_geniv, int,
+	(struct crypto_aead *tfm),
+	(tfm));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_GENIV, aead_exit_geniv, void,
+	(struct crypto_aead *tfm),
+	(tfm));
 
 #endif	/* _CRYPTO_INTERNAL_GENIV_H */
-- 
2.47.3


^ permalink raw reply related

* [PATCH 003/106] crypto: convert exported crypto symbol into pluggable interface for CONFIG_CRYPTO_AEAD2 crypto
From: Jay Wang @ 2026-02-12  2:45 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
	Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
	linux-modules
In-Reply-To: <20260212024725.11264-1-wanjay@amazon.com>

Apply Crypto API wrappers to the exported crypto symbol in
CONFIG_CRYPTO_AEAD2-related crypto to convert them into pluggable
interface.

This patch is partially based on work by Vegard Nossum, with
modifications. Unlike the original, we do not include
DEFINE_CRYPTO_API since only one copy of the crypto symbols is
kept, either in the crypto module or in the main kernel, and we ensure
such wrapper do not have impact on crypto already chosen built as
module.

Co-developed-by: Vegard Nossum <vegard.nossum@oracle.com>
Signed-off-by: Jay Wang <wanjay@amazon.com>
---
 crypto/Makefile                |  2 +-
 crypto/fips140/fips140-api.c   | 26 ++++++++++++++++++++++++++
 include/crypto/aead.h          | 30 ++++++++++++++++++++++--------
 include/crypto/internal/aead.h | 28 +++++++++++++++++++---------
 4 files changed, 68 insertions(+), 18 deletions(-)

diff --git a/crypto/Makefile b/crypto/Makefile
index da5a7a4aa59b..9aa52ddebb05 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -15,7 +15,7 @@ crypto_algapi-$(CONFIG_PROC_FS) += proc.o
 crypto_algapi-y := algapi.o scatterwalk.o $(crypto_algapi-y)
 crypto-objs-$(CONFIG_CRYPTO_ALGAPI2) += crypto_algapi.o
 
-obj-$(CONFIG_CRYPTO_AEAD2) += aead.o
+crypto-objs-$(CONFIG_CRYPTO_AEAD2) += aead.o
 obj-$(CONFIG_CRYPTO_GENIV) += geniv.o
 
 crypto_skcipher-y += lskcipher.o
diff --git a/crypto/fips140/fips140-api.c b/crypto/fips140/fips140-api.c
index 8a0e1d28615c..eb02a56cb8b3 100644
--- a/crypto/fips140/fips140-api.c
+++ b/crypto/fips140/fips140-api.c
@@ -103,4 +103,30 @@ DEFINE_CRYPTO_API_STUB(crypto_remove_final);
 DEFINE_CRYPTO_API_STUB(crypto_alg_extsize);
 DEFINE_CRYPTO_API_STUB(crypto_type_has_alg);
 
+#endif
+
+/*
+ * crypto/aead.c
+ */
+#if IS_BUILTIN(CONFIG_CRYPTO_AEAD2)
+
+#include <crypto/aead.h>
+
+DEFINE_CRYPTO_API_STUB(crypto_alloc_aead);
+DEFINE_CRYPTO_API_STUB(crypto_alloc_sync_aead);
+DEFINE_CRYPTO_API_STUB(crypto_has_aead);
+DEFINE_CRYPTO_API_STUB(crypto_aead_setkey);
+DEFINE_CRYPTO_API_STUB(crypto_aead_setauthsize);
+DEFINE_CRYPTO_API_STUB(crypto_aead_encrypt);
+DEFINE_CRYPTO_API_STUB(crypto_aead_decrypt);
+
+#include <crypto/internal/aead.h>
+
+DEFINE_CRYPTO_API_STUB(crypto_grab_aead);
+DEFINE_CRYPTO_API_STUB(crypto_register_aead);
+DEFINE_CRYPTO_API_STUB(crypto_unregister_aead);
+DEFINE_CRYPTO_API_STUB(crypto_register_aeads);
+DEFINE_CRYPTO_API_STUB(crypto_unregister_aeads);
+DEFINE_CRYPTO_API_STUB(aead_register_instance);
+
 #endif
\ No newline at end of file
diff --git a/include/crypto/aead.h b/include/crypto/aead.h
index 8e66a1fa9c78..2d3e2bde5c1d 100644
--- a/include/crypto/aead.h
+++ b/include/crypto/aead.h
@@ -8,6 +8,7 @@
 #ifndef _CRYPTO_AEAD_H
 #define _CRYPTO_AEAD_H
 
+#include <crypto/api.h>
 #include <linux/atomic.h>
 #include <linux/container_of.h>
 #include <linux/crypto.h>
@@ -193,9 +194,13 @@ static inline struct crypto_aead *__crypto_aead_cast(struct crypto_tfm *tfm)
  * Return: allocated cipher handle in case of success; IS_ERR() is true in case
  *	   of an error, PTR_ERR() returns the error code.
  */
-struct crypto_aead *crypto_alloc_aead(const char *alg_name, u32 type, u32 mask);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_AEAD2, crypto_alloc_aead, struct crypto_aead *,
+	(const char *alg_name, u32 type, u32 mask),
+	(alg_name, type, mask));
 
-struct crypto_sync_aead *crypto_alloc_sync_aead(const char *alg_name, u32 type, u32 mask);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_AEAD2, crypto_alloc_sync_aead, struct crypto_sync_aead *,
+	(const char *alg_name, u32 type, u32 mask),
+	(alg_name, type, mask));
 
 static inline struct crypto_tfm *crypto_aead_tfm(struct crypto_aead *tfm)
 {
@@ -233,7 +238,9 @@ static inline void crypto_free_sync_aead(struct crypto_sync_aead *tfm)
  * Return: true when the aead is known to the kernel crypto API; false
  *	   otherwise
  */
-int crypto_has_aead(const char *alg_name, u32 type, u32 mask);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_AEAD2, crypto_has_aead, int,
+	(const char *alg_name, u32 type, u32 mask),
+	(alg_name, type, mask));
 
 static inline const char *crypto_aead_driver_name(struct crypto_aead *tfm)
 {
@@ -378,8 +385,9 @@ static inline void crypto_sync_aead_clear_flags(struct crypto_sync_aead *tfm, u3
  *
  * Return: 0 if the setting of the key was successful; < 0 if an error occurred
  */
-int crypto_aead_setkey(struct crypto_aead *tfm,
-		       const u8 *key, unsigned int keylen);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_AEAD2, crypto_aead_setkey, int,
+	(struct crypto_aead *tfm, const u8 *key, unsigned int keylen),
+	(tfm, key, keylen));
 
 static inline int crypto_sync_aead_setkey(struct crypto_sync_aead *tfm,
 					 const u8 *key, unsigned int keylen)
@@ -397,7 +405,9 @@ static inline int crypto_sync_aead_setkey(struct crypto_sync_aead *tfm,
  *
  * Return: 0 if the setting of the key was successful; < 0 if an error occurred
  */
-int crypto_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_AEAD2, crypto_aead_setauthsize, int,
+	(struct crypto_aead *tfm, unsigned int authsize),
+	(tfm, authsize));
 
 static inline int crypto_sync_aead_setauthsize(struct crypto_sync_aead *tfm,
 					       unsigned int authsize)
@@ -436,7 +446,9 @@ static inline struct crypto_sync_aead *crypto_sync_aead_reqtfm(struct aead_reque
  *
  * Return: 0 if the cipher operation was successful; < 0 if an error occurred
  */
-int crypto_aead_encrypt(struct aead_request *req);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_AEAD2, crypto_aead_encrypt, int,
+	(struct aead_request *req),
+	(req));
 
 /**
  * crypto_aead_decrypt() - decrypt ciphertext
@@ -460,7 +472,9 @@ int crypto_aead_encrypt(struct aead_request *req);
  *	   integrity of the ciphertext or the associated data was violated);
  *	   < 0 if an error occurred.
  */
-int crypto_aead_decrypt(struct aead_request *req);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_AEAD2, crypto_aead_decrypt, int,
+	(struct aead_request *req),
+	(req));
 
 /**
  * DOC: Asynchronous AEAD Request Handle
diff --git a/include/crypto/internal/aead.h b/include/crypto/internal/aead.h
index 28a95eb3182d..773e6dbb34d6 100644
--- a/include/crypto/internal/aead.h
+++ b/include/crypto/internal/aead.h
@@ -8,6 +8,7 @@
 #ifndef _CRYPTO_INTERNAL_AEAD_H
 #define _CRYPTO_INTERNAL_AEAD_H
 
+#include <crypto/api.h>
 #include <crypto/aead.h>
 #include <crypto/algapi.h>
 #include <linux/stddef.h>
@@ -96,9 +97,9 @@ static inline struct aead_request *aead_request_cast(
 	return container_of(req, struct aead_request, base);
 }
 
-int crypto_grab_aead(struct crypto_aead_spawn *spawn,
-		     struct crypto_instance *inst,
-		     const char *name, u32 type, u32 mask);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_AEAD2, crypto_grab_aead, int,
+	(struct crypto_aead_spawn *spawn, struct crypto_instance *inst, const char *name, u32 type, u32 mask),
+	(spawn, inst, name, type, mask));
 
 static inline void crypto_drop_aead(struct crypto_aead_spawn *spawn)
 {
@@ -157,12 +158,21 @@ static inline unsigned int crypto_aead_chunksize(struct crypto_aead *tfm)
 	return crypto_aead_alg_chunksize(crypto_aead_alg(tfm));
 }
 
-int crypto_register_aead(struct aead_alg *alg);
-void crypto_unregister_aead(struct aead_alg *alg);
-int crypto_register_aeads(struct aead_alg *algs, int count);
-void crypto_unregister_aeads(struct aead_alg *algs, int count);
-int aead_register_instance(struct crypto_template *tmpl,
-			   struct aead_instance *inst);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_AEAD2, crypto_register_aead, int,
+	(struct aead_alg *alg),
+	(alg));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_AEAD2, crypto_unregister_aead, void,
+	(struct aead_alg *alg),
+	(alg));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_AEAD2, crypto_register_aeads, int,
+	(struct aead_alg *algs, int count),
+	(algs, count));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_AEAD2, crypto_unregister_aeads, void,
+	(struct aead_alg *algs, int count),
+	(algs, count));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_AEAD2, aead_register_instance, int,
+	(struct crypto_template *tmpl, struct aead_instance *inst),
+	(tmpl, inst));
 
 #endif	/* _CRYPTO_INTERNAL_AEAD_H */
 
-- 
2.47.3


^ permalink raw reply related

* [PATCH 002/106] crypto: convert exported crypto symbol into pluggable interface for CONFIG_CRYPTO_AES crypto
From: Jay Wang @ 2026-02-12  2:45 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
	Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
	linux-modules
In-Reply-To: <20260212024725.11264-1-wanjay@amazon.com>

Apply Crypto API wrappers to the exported crypto symbol in
CONFIG_CRYPTO_AES-related crypto to convert them into pluggable
interface.

This patch is partially based on work by Vegard Nossum, with
modifications. Unlike the original, we do not include
DEFINE_CRYPTO_API since only one copy of the crypto symbols is
kept, either in the crypto module or in the main kernel, and we ensure
such wrapper do not have impact on crypto already chosen built as
module.

Co-developed-by: Vegard Nossum <vegard.nossum@oracle.com>
Signed-off-by: Jay Wang <wanjay@amazon.com>
---
 crypto/Makefile | 2 +-
 crypto/aes.c    | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/crypto/Makefile b/crypto/Makefile
index 88de6dcbd7c4..da5a7a4aa59b 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -134,7 +134,7 @@ obj-$(CONFIG_CRYPTO_TWOFISH) += twofish_generic.o
 obj-$(CONFIG_CRYPTO_TWOFISH_COMMON) += twofish_common.o
 obj-$(CONFIG_CRYPTO_SERPENT) += serpent_generic.o
 CFLAGS_serpent_generic.o := $(call cc-option,-fsched-pressure)  # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79149
-obj-$(CONFIG_CRYPTO_AES) += aes.o
+crypto-objs-$(CONFIG_CRYPTO_AES) += aes.o
 obj-$(CONFIG_CRYPTO_SM4) += sm4.o
 obj-$(CONFIG_CRYPTO_SM4_GENERIC) += sm4_generic.o
 obj-$(CONFIG_CRYPTO_CAMELLIA) += camellia_generic.o
diff --git a/crypto/aes.c b/crypto/aes.c
index ae8385df0ce5..bda6a1cba552 100644
--- a/crypto/aes.c
+++ b/crypto/aes.c
@@ -52,13 +52,13 @@ static int __init crypto_aes_mod_init(void)
 {
 	return crypto_register_alg(&alg);
 }
-module_init(crypto_aes_mod_init);
+crypto_module_init(crypto_aes_mod_init);
 
 static void __exit crypto_aes_mod_exit(void)
 {
 	crypto_unregister_alg(&alg);
 }
-module_exit(crypto_aes_mod_exit);
+crypto_module_exit(crypto_aes_mod_exit);
 
 MODULE_DESCRIPTION("Crypto API support for AES block cipher");
 MODULE_LICENSE("GPL");
-- 
2.47.3


^ permalink raw reply related

* [PATCH 001/106] crypto: convert exported crypto symbol into pluggable interface for CONFIG_CRYPTO and CONFIG_CRYPTO_ALGAPI2 crypto
From: Jay Wang @ 2026-02-12  2:45 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
	Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
	linux-modules
In-Reply-To: <20260212024725.11264-1-wanjay@amazon.com>

Apply Crypto API wrappers to the exported crypto symbol in
CONFIG_CRYPTO- and CONFIG_CRYPTO_ALGAPI2-related crypto to convert them
into pluggable interface.

This patch is partially based on work by Vegard Nossum, with
modifications. Unlike the original, we do not include
DEFINE_CRYPTO_API since only one copy of the crypto symbols is
kept, either in the crypto module or in the main kernel, and we ensure
such wrapper do not have impact on crypto already chosen built as
module.

Co-developed-by: Vegard Nossum <vegard.nossum@oracle.com>
Signed-off-by: Jay Wang <wanjay@amazon.com>
---
 crypto/Makefile                  |   4 +-
 crypto/algapi.c                  |   4 +-
 crypto/fips140/fips140-api.c     | 109 +++++++++++++++++++++++++--
 crypto/internal.h                |  86 +++++++++++++--------
 include/crypto/algapi.h          | 125 +++++++++++++++++++++----------
 include/crypto/internal/cipher.h |  20 +++--
 include/crypto/scatterwalk.h     |  36 +++++----
 include/linux/crypto.h           |  22 ++++--
 8 files changed, 302 insertions(+), 104 deletions(-)

diff --git a/crypto/Makefile b/crypto/Makefile
index 5129be5e7208..88de6dcbd7c4 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -5,7 +5,7 @@
 
 CONTEXT_ANALYSIS := y
 
-obj-$(CONFIG_CRYPTO) += crypto.o
+crypto-objs-$(CONFIG_CRYPTO) += crypto.o
 crypto-y := api.o cipher.o
 
 obj-$(CONFIG_CRYPTO_ENGINE) += crypto_engine.o
@@ -13,7 +13,7 @@ obj-$(CONFIG_CRYPTO_FIPS) += fips.o
 
 crypto_algapi-$(CONFIG_PROC_FS) += proc.o
 crypto_algapi-y := algapi.o scatterwalk.o $(crypto_algapi-y)
-obj-$(CONFIG_CRYPTO_ALGAPI2) += crypto_algapi.o
+crypto-objs-$(CONFIG_CRYPTO_ALGAPI2) += crypto_algapi.o
 
 obj-$(CONFIG_CRYPTO_AEAD2) += aead.o
 obj-$(CONFIG_CRYPTO_GENIV) += geniv.o
diff --git a/crypto/algapi.c b/crypto/algapi.c
index 663698e0cd65..0a041a6f6668 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -1123,8 +1123,8 @@ static void __exit crypto_algapi_exit(void)
  * We run this at late_initcall so that all the built-in algorithms
  * have had a chance to register themselves first.
  */
-late_initcall(crypto_algapi_init);
-module_exit(crypto_algapi_exit);
+crypto_late_initcall(crypto_algapi_init);
+crypto_module_exit(crypto_algapi_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Cryptographic algorithms API");
diff --git a/crypto/fips140/fips140-api.c b/crypto/fips140/fips140-api.c
index a11e898ff4bc..8a0e1d28615c 100644
--- a/crypto/fips140/fips140-api.c
+++ b/crypto/fips140/fips140-api.c
@@ -1,7 +1,106 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * crypto/api.c
+ */
+#if IS_BUILTIN(CONFIG_CRYPTO)
+
+#include <linux/crypto.h>
+
+DEFINE_CRYPTO_API_STUB(crypto_req_done);
+DEFINE_CRYPTO_API_STUB(crypto_has_alg);
+DEFINE_CRYPTO_API_STUB(crypto_alloc_base);
+DEFINE_CRYPTO_API_STUB(crypto_destroy_tfm);
+DEFINE_CRYPTO_API_STUB(crypto_request_clone);
+
+#include <crypto/algapi.h>
+
+DEFINE_CRYPTO_API_STUB(crypto_mod_put);
+
+#include <crypto/internal.h>
+
+DEFINE_CRYPTO_API_STUB(crypto_mod_get);
+DEFINE_CRYPTO_API_STUB(crypto_alg_mod_lookup);
+DEFINE_CRYPTO_API_STUB(crypto_larval_alloc);
+DEFINE_CRYPTO_API_STUB(crypto_schedule_test);
+DEFINE_CRYPTO_API_STUB(crypto_shoot_alg);
+DEFINE_CRYPTO_API_STUB(__crypto_alloc_tfmgfp);
+DEFINE_CRYPTO_API_STUB(__crypto_alloc_tfm);
+DEFINE_CRYPTO_API_STUB(crypto_create_tfm_node);
+DEFINE_CRYPTO_API_STUB(crypto_clone_tfm);
+DEFINE_CRYPTO_API_STUB(crypto_find_alg);
+DEFINE_CRYPTO_API_STUB(crypto_alloc_tfm_node);
+DEFINE_CRYPTO_API_STUB(crypto_probing_notify);
+DEFINE_CRYPTO_API_STUB(crypto_destroy_alg);
+
+#endif
+/*
+ * crypto/cipher.c
+ */
+#if IS_BUILTIN(CONFIG_CRYPTO)
+
+#include <crypto/internal/cipher.h>
 
+DEFINE_CRYPTO_API_STUB(crypto_cipher_setkey);
+DEFINE_CRYPTO_API_STUB(crypto_cipher_encrypt_one);
+DEFINE_CRYPTO_API_STUB(crypto_cipher_decrypt_one);
+DEFINE_CRYPTO_API_STUB(crypto_clone_cipher);
+
+#endif
+/*
+ * crypto/scatterwalk.c
+ */
+#if IS_BUILTIN(CONFIG_CRYPTO_ALGAPI2)
+
+#include <crypto/scatterwalk.h>
+
+DEFINE_CRYPTO_API_STUB(scatterwalk_skip);
+DEFINE_CRYPTO_API_STUB(memcpy_from_scatterwalk);
+DEFINE_CRYPTO_API_STUB(memcpy_to_scatterwalk);
+DEFINE_CRYPTO_API_STUB(memcpy_from_sglist);
+DEFINE_CRYPTO_API_STUB(memcpy_to_sglist);
+DEFINE_CRYPTO_API_STUB(memcpy_sglist);
+DEFINE_CRYPTO_API_STUB(scatterwalk_ffwd);
+
+#endif
 /*
- * Define static call keys for any functions which are part of the crypto
- * API and used by the standalone FIPS module but which are not built into
- * vmlinux.
- */
\ No newline at end of file
+ * crypto/algapi.c
+ */
+#if IS_BUILTIN(CONFIG_CRYPTO_ALGAPI2)
+
+#include <crypto/algapi.h>
+
+DEFINE_CRYPTO_API_STUB(crypto_register_alg);
+DEFINE_CRYPTO_API_STUB(crypto_unregister_alg);
+DEFINE_CRYPTO_API_STUB(crypto_register_algs);
+DEFINE_CRYPTO_API_STUB(crypto_unregister_algs);
+DEFINE_CRYPTO_API_STUB(crypto_register_template);
+DEFINE_CRYPTO_API_STUB(crypto_register_templates);
+DEFINE_CRYPTO_API_STUB(crypto_unregister_template);
+DEFINE_CRYPTO_API_STUB(crypto_unregister_templates);
+DEFINE_CRYPTO_API_STUB(crypto_lookup_template);
+DEFINE_CRYPTO_API_STUB(crypto_register_instance);
+DEFINE_CRYPTO_API_STUB(crypto_unregister_instance);
+DEFINE_CRYPTO_API_STUB(crypto_grab_spawn);
+DEFINE_CRYPTO_API_STUB(crypto_drop_spawn);
+DEFINE_CRYPTO_API_STUB(crypto_spawn_tfm);
+DEFINE_CRYPTO_API_STUB(crypto_spawn_tfm2);
+DEFINE_CRYPTO_API_STUB(crypto_get_attr_type);
+DEFINE_CRYPTO_API_STUB(crypto_check_attr_type);
+DEFINE_CRYPTO_API_STUB(crypto_attr_alg_name);
+DEFINE_CRYPTO_API_STUB(__crypto_inst_setname);
+DEFINE_CRYPTO_API_STUB(crypto_init_queue);
+DEFINE_CRYPTO_API_STUB(crypto_enqueue_request);
+DEFINE_CRYPTO_API_STUB(crypto_enqueue_request_head);
+DEFINE_CRYPTO_API_STUB(crypto_dequeue_request);
+DEFINE_CRYPTO_API_STUB(crypto_inc);
+DEFINE_CRYPTO_API_STUB(crypto_register_notifier);
+DEFINE_CRYPTO_API_STUB(crypto_unregister_notifier);
+
+#include <crypto/internal.h>
+
+DEFINE_CRYPTO_API_STUB(crypto_alg_tested);
+DEFINE_CRYPTO_API_STUB(crypto_remove_spawns);
+DEFINE_CRYPTO_API_STUB(crypto_remove_final);
+DEFINE_CRYPTO_API_STUB(crypto_alg_extsize);
+DEFINE_CRYPTO_API_STUB(crypto_type_has_alg);
+
+#endif
\ No newline at end of file
diff --git a/crypto/internal.h b/crypto/internal.h
index 8fbe0226d48e..8ebe4dc336bc 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -109,25 +109,44 @@ static inline unsigned int crypto_compress_ctxsize(struct crypto_alg *alg)
 	return alg->cra_ctxsize;
 }
 
-struct crypto_alg *crypto_mod_get(struct crypto_alg *alg);
-struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask);
-
-struct crypto_larval *crypto_larval_alloc(const char *name, u32 type, u32 mask);
-void crypto_schedule_test(struct crypto_larval *larval);
-void crypto_alg_tested(const char *name, int err);
-
-void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,
-			  struct crypto_alg *nalg);
-void crypto_remove_final(struct list_head *list);
-void crypto_shoot_alg(struct crypto_alg *alg);
-struct crypto_tfm *__crypto_alloc_tfmgfp(struct crypto_alg *alg, u32 type,
-					 u32 mask, gfp_t gfp);
-struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
-				      u32 mask);
-void *crypto_create_tfm_node(struct crypto_alg *alg,
-			const struct crypto_type *frontend, int node);
-void *crypto_clone_tfm(const struct crypto_type *frontend,
-		       struct crypto_tfm *otfm);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO, crypto_mod_get, struct crypto_alg *,
+	(struct crypto_alg *alg),
+	(alg));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO, crypto_alg_mod_lookup, struct crypto_alg *,
+	(const char *name, u32 type, u32 mask),
+	(name, type, mask));
+
+DECLARE_CRYPTO_API(CONFIG_CRYPTO, crypto_larval_alloc, struct crypto_larval *,
+	(const char *name, u32 type, u32 mask),
+	(name, type, mask));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO, crypto_schedule_test, void,
+	(struct crypto_larval *larval),
+	(larval));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, crypto_alg_tested, void,
+	(const char *name, int err),
+	(name, err));
+
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, crypto_remove_spawns, void,
+	(struct crypto_alg *alg, struct list_head *list, struct crypto_alg *nalg),
+	(alg, list, nalg));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, crypto_remove_final, void,
+	(struct list_head *list),
+	(list));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO, crypto_shoot_alg, void,
+	(struct crypto_alg *alg),
+	(alg));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO, __crypto_alloc_tfmgfp, struct crypto_tfm *,
+	(struct crypto_alg *alg, u32 type, u32 mask, gfp_t gfp),
+	(alg, type, mask, gfp));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO, __crypto_alloc_tfm, struct crypto_tfm *,
+	(struct crypto_alg *alg, u32 type, u32 mask),
+	(alg, type, mask));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO, crypto_create_tfm_node, void *,
+	(struct crypto_alg *alg, const struct crypto_type *frontend, int node),
+	(alg, frontend, node));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO, crypto_clone_tfm, void *,
+	(const struct crypto_type *frontend, struct crypto_tfm *otfm),
+	(frontend, otfm));
 
 static inline void *crypto_create_tfm(struct crypto_alg *alg,
 			const struct crypto_type *frontend)
@@ -135,13 +154,13 @@ static inline void *crypto_create_tfm(struct crypto_alg *alg,
 	return crypto_create_tfm_node(alg, frontend, NUMA_NO_NODE);
 }
 
-struct crypto_alg *crypto_find_alg(const char *alg_name,
-				   const struct crypto_type *frontend,
-				   u32 type, u32 mask);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO, crypto_find_alg, struct crypto_alg *,
+	(const char *alg_name, const struct crypto_type *frontend, u32 type, u32 mask),
+	(alg_name, frontend, type, mask));
 
-void *crypto_alloc_tfm_node(const char *alg_name,
-		       const struct crypto_type *frontend, u32 type, u32 mask,
-		       int node);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO, crypto_alloc_tfm_node, void *,
+	(const char *alg_name, const struct crypto_type *frontend, u32 type, u32 mask, int node),
+	(alg_name, frontend, type, mask, node));
 
 static inline void *crypto_alloc_tfm(const char *alg_name,
 		       const struct crypto_type *frontend, u32 type, u32 mask)
@@ -149,12 +168,17 @@ static inline void *crypto_alloc_tfm(const char *alg_name,
 	return crypto_alloc_tfm_node(alg_name, frontend, type, mask, NUMA_NO_NODE);
 }
 
-int crypto_probing_notify(unsigned long val, void *v);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO, crypto_probing_notify, int,
+	(unsigned long val, void *v),
+	(val, v));
 
-unsigned int crypto_alg_extsize(struct crypto_alg *alg);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, crypto_alg_extsize, unsigned int,
+	(struct crypto_alg *alg),
+	(alg));
 
-int crypto_type_has_alg(const char *name, const struct crypto_type *frontend,
-			u32 type, u32 mask);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, crypto_type_has_alg, int,
+	(const char *name, const struct crypto_type *frontend, u32 type, u32 mask),
+	(name, frontend, type, mask));
 
 static inline struct crypto_alg *crypto_alg_get(struct crypto_alg *alg)
 {
@@ -162,7 +186,9 @@ static inline struct crypto_alg *crypto_alg_get(struct crypto_alg *alg)
 	return alg;
 }
 
-void crypto_destroy_alg(struct crypto_alg *alg);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO, crypto_destroy_alg, void,
+	(struct crypto_alg *alg),
+	(alg));
 
 static inline void crypto_alg_put(struct crypto_alg *alg)
 {
diff --git a/include/crypto/algapi.h b/include/crypto/algapi.h
index 05deea9dac5e..455b7c190936 100644
--- a/include/crypto/algapi.h
+++ b/include/crypto/algapi.h
@@ -7,6 +7,7 @@
 #ifndef _CRYPTO_ALGAPI_H
 #define _CRYPTO_ALGAPI_H
 
+#include <crypto/api.h>
 #include <crypto/utils.h>
 #include <linux/align.h>
 #include <linux/cache.h>
@@ -131,35 +132,71 @@ struct crypto_attr_type {
 /*
  * Algorithm registration interface.
  */
-int crypto_register_alg(struct crypto_alg *alg);
-void crypto_unregister_alg(struct crypto_alg *alg);
-int crypto_register_algs(struct crypto_alg *algs, int count);
-void crypto_unregister_algs(struct crypto_alg *algs, int count);
-
-void crypto_mod_put(struct crypto_alg *alg);
-
-int crypto_register_template(struct crypto_template *tmpl);
-int crypto_register_templates(struct crypto_template *tmpls, int count);
-void crypto_unregister_template(struct crypto_template *tmpl);
-void crypto_unregister_templates(struct crypto_template *tmpls, int count);
-struct crypto_template *crypto_lookup_template(const char *name);
-
-int crypto_register_instance(struct crypto_template *tmpl,
-			     struct crypto_instance *inst);
-void crypto_unregister_instance(struct crypto_instance *inst);
-
-int crypto_grab_spawn(struct crypto_spawn *spawn, struct crypto_instance *inst,
-		      const char *name, u32 type, u32 mask);
-void crypto_drop_spawn(struct crypto_spawn *spawn);
-struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type,
-				    u32 mask);
-void *crypto_spawn_tfm2(struct crypto_spawn *spawn);
-
-struct crypto_attr_type *crypto_get_attr_type(struct rtattr **tb);
-int crypto_check_attr_type(struct rtattr **tb, u32 type, u32 *mask_ret);
-const char *crypto_attr_alg_name(struct rtattr *rta);
-int __crypto_inst_setname(struct crypto_instance *inst, const char *name,
-			  const char *driver, struct crypto_alg *alg);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, crypto_register_alg, int,
+	(struct crypto_alg *alg),
+	(alg));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, crypto_unregister_alg, void,
+	(struct crypto_alg *alg),
+	(alg));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, crypto_register_algs, int,
+	(struct crypto_alg *algs, int count),
+	(algs, count));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, crypto_unregister_algs, void,
+	(struct crypto_alg *algs, int count),
+	(algs, count));
+
+DECLARE_CRYPTO_API(CONFIG_CRYPTO, crypto_mod_put, void,
+	(struct crypto_alg *alg),
+	(alg));
+
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, crypto_register_template, int,
+	(struct crypto_template *tmpl),
+	(tmpl));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, crypto_register_templates, int,
+	(struct crypto_template *tmpls, int count),
+	(tmpls, count));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, crypto_unregister_template, void,
+	(struct crypto_template *tmpl),
+	(tmpl));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, crypto_unregister_templates, void,
+	(struct crypto_template *tmpls, int count),
+	(tmpls, count));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, crypto_lookup_template, struct crypto_template *,
+	(const char *name),
+	(name));
+
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, crypto_register_instance, int,
+	(struct crypto_template *tmpl, struct crypto_instance *inst),
+	(tmpl, inst));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, crypto_unregister_instance, void,
+	(struct crypto_instance *inst),
+	(inst));
+
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, crypto_grab_spawn, int,
+	(struct crypto_spawn *spawn, struct crypto_instance *inst, const char *name, u32 type, u32 mask),
+	(spawn, inst, name, type, mask));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, crypto_drop_spawn, void,
+	(struct crypto_spawn *spawn),
+	(spawn));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, crypto_spawn_tfm, struct crypto_tfm *,
+	(struct crypto_spawn *spawn, u32 type, u32 mask),
+	(spawn, type, mask));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, crypto_spawn_tfm2, void *,
+	(struct crypto_spawn *spawn),
+	(spawn));
+
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, crypto_get_attr_type, struct crypto_attr_type *,
+	(struct rtattr **tb),
+	(tb));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, crypto_check_attr_type, int,
+	(struct rtattr **tb, u32 type, u32 *mask_ret),
+	(tb, type, mask_ret));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, crypto_attr_alg_name, const char *,
+	(struct rtattr *rta),
+	(rta));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, __crypto_inst_setname, int,
+	(struct crypto_instance *inst, const char *name, const char *driver, struct crypto_alg *alg),
+	(inst, name, driver, alg));
 
 #define crypto_inst_setname(inst, name, ...) \
 	CONCATENATE(crypto_inst_setname_, COUNT_ARGS(__VA_ARGS__))( \
@@ -169,18 +206,26 @@ int __crypto_inst_setname(struct crypto_instance *inst, const char *name,
 #define crypto_inst_setname_2(inst, name, driver, alg) \
 	__crypto_inst_setname(inst, name, driver, alg)
 
-void crypto_init_queue(struct crypto_queue *queue, unsigned int max_qlen);
-int crypto_enqueue_request(struct crypto_queue *queue,
-			   struct crypto_async_request *request);
-void crypto_enqueue_request_head(struct crypto_queue *queue,
-				 struct crypto_async_request *request);
-struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, crypto_init_queue, void,
+	(struct crypto_queue *queue, unsigned int max_qlen),
+	(queue, max_qlen));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, crypto_enqueue_request, int,
+	(struct crypto_queue *queue, struct crypto_async_request *request),
+	(queue, request));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, crypto_enqueue_request_head, void,
+	(struct crypto_queue *queue, struct crypto_async_request *request),
+	(queue, request));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, crypto_dequeue_request, struct crypto_async_request *,
+	(struct crypto_queue *queue),
+	(queue));
 static inline unsigned int crypto_queue_len(struct crypto_queue *queue)
 {
 	return queue->qlen;
 }
 
-void crypto_inc(u8 *a, unsigned int size);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, crypto_inc, void,
+	(u8 *a, unsigned int size),
+	(a, size));
 
 static inline void *crypto_tfm_ctx(struct crypto_tfm *tfm)
 {
@@ -254,8 +299,12 @@ static inline u32 crypto_algt_inherited_mask(struct crypto_attr_type *algt)
 	return crypto_requires_off(algt, CRYPTO_ALG_INHERITED_FLAGS);
 }
 
-int crypto_register_notifier(struct notifier_block *nb);
-int crypto_unregister_notifier(struct notifier_block *nb);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, crypto_register_notifier, int,
+	(struct notifier_block *nb),
+	(nb));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, crypto_unregister_notifier, int,
+	(struct notifier_block *nb),
+	(nb));
 
 /* Crypto notification events. */
 enum {
diff --git a/include/crypto/internal/cipher.h b/include/crypto/internal/cipher.h
index 5030f6d2df31..62d18c0f5c11 100644
--- a/include/crypto/internal/cipher.h
+++ b/include/crypto/internal/cipher.h
@@ -11,6 +11,7 @@
 #ifndef _CRYPTO_INTERNAL_CIPHER_H
 #define _CRYPTO_INTERNAL_CIPHER_H
 
+#include <crypto/api.h>
 #include <crypto/algapi.h>
 
 struct crypto_cipher {
@@ -149,8 +150,9 @@ static inline void crypto_cipher_clear_flags(struct crypto_cipher *tfm,
  *
  * Return: 0 if the setting of the key was successful; < 0 if an error occurred
  */
-int crypto_cipher_setkey(struct crypto_cipher *tfm,
-			 const u8 *key, unsigned int keylen);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO, crypto_cipher_setkey, int,
+	(struct crypto_cipher *tfm, const u8 *key, unsigned int keylen),
+	(tfm, key, keylen));
 
 /**
  * crypto_cipher_encrypt_one() - encrypt one block of plaintext
@@ -161,8 +163,9 @@ int crypto_cipher_setkey(struct crypto_cipher *tfm,
  * Invoke the encryption operation of one block. The caller must ensure that
  * the plaintext and ciphertext buffers are at least one block in size.
  */
-void crypto_cipher_encrypt_one(struct crypto_cipher *tfm,
-			       u8 *dst, const u8 *src);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO, crypto_cipher_encrypt_one, void,
+	(struct crypto_cipher *tfm, u8 *dst, const u8 *src),
+	(tfm, dst, src));
 
 /**
  * crypto_cipher_decrypt_one() - decrypt one block of ciphertext
@@ -173,10 +176,13 @@ void crypto_cipher_encrypt_one(struct crypto_cipher *tfm,
  * Invoke the decryption operation of one block. The caller must ensure that
  * the plaintext and ciphertext buffers are at least one block in size.
  */
-void crypto_cipher_decrypt_one(struct crypto_cipher *tfm,
-			       u8 *dst, const u8 *src);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO, crypto_cipher_decrypt_one, void,
+	(struct crypto_cipher *tfm, u8 *dst, const u8 *src),
+	(tfm, dst, src));
 
-struct crypto_cipher *crypto_clone_cipher(struct crypto_cipher *cipher);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO, crypto_clone_cipher, struct crypto_cipher *,
+	(struct crypto_cipher *cipher),
+	(cipher));
 
 struct crypto_cipher_spawn {
 	struct crypto_spawn base;
diff --git a/include/crypto/scatterwalk.h b/include/crypto/scatterwalk.h
index 624fab589c2c..4b7daf05719c 100644
--- a/include/crypto/scatterwalk.h
+++ b/include/crypto/scatterwalk.h
@@ -11,6 +11,7 @@
 #ifndef _CRYPTO_SCATTERWALK_H
 #define _CRYPTO_SCATTERWALK_H
 
+#include <crypto/api.h>
 #include <crypto/algapi.h>
 
 #include <linux/highmem.h>
@@ -221,22 +222,29 @@ static inline void scatterwalk_done_dst(struct scatter_walk *walk,
 	scatterwalk_advance(walk, nbytes);
 }
 
-void scatterwalk_skip(struct scatter_walk *walk, unsigned int nbytes);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, scatterwalk_skip, void,
+	(struct scatter_walk *walk, unsigned int nbytes),
+	(walk, nbytes));
 
-void memcpy_from_scatterwalk(void *buf, struct scatter_walk *walk,
-			     unsigned int nbytes);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, memcpy_from_scatterwalk, void,
+	(void *buf, struct scatter_walk *walk, unsigned int nbytes),
+	(buf, walk, nbytes));
 
-void memcpy_to_scatterwalk(struct scatter_walk *walk, const void *buf,
-			   unsigned int nbytes);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, memcpy_to_scatterwalk, void,
+	(struct scatter_walk *walk, const void *buf, unsigned int nbytes),
+	(walk, buf, nbytes));
 
-void memcpy_from_sglist(void *buf, struct scatterlist *sg,
-			unsigned int start, unsigned int nbytes);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, memcpy_from_sglist, void,
+	(void *buf, struct scatterlist *sg, unsigned int start, unsigned int nbytes),
+	(buf, sg, start, nbytes));
 
-void memcpy_to_sglist(struct scatterlist *sg, unsigned int start,
-		      const void *buf, unsigned int nbytes);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, memcpy_to_sglist, void,
+	(struct scatterlist *sg, unsigned int start, const void *buf, unsigned int nbytes),
+	(sg, start, buf, nbytes));
 
-void memcpy_sglist(struct scatterlist *dst, struct scatterlist *src,
-		   unsigned int nbytes);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, memcpy_sglist, void,
+	(struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes),
+	(dst, src, nbytes));
 
 /* In new code, please use memcpy_{from,to}_sglist() directly instead. */
 static inline void scatterwalk_map_and_copy(void *buf, struct scatterlist *sg,
@@ -249,8 +257,8 @@ static inline void scatterwalk_map_and_copy(void *buf, struct scatterlist *sg,
 		memcpy_from_sglist(buf, sg, start, nbytes);
 }
 
-struct scatterlist *scatterwalk_ffwd(struct scatterlist dst[2],
-				     struct scatterlist *src,
-				     unsigned int len);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGAPI2, scatterwalk_ffwd, struct scatterlist *,
+	(struct scatterlist dst[2], struct scatterlist *src, unsigned int len),
+	(dst, src, len));
 
 #endif  /* _CRYPTO_SCATTERWALK_H */
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index a2137e19be7d..20eecf13d0e5 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -12,6 +12,7 @@
 #ifndef _LINUX_CRYPTO_H
 #define _LINUX_CRYPTO_H
 
+#include <crypto/api.h>
 #include <linux/completion.h>
 #include <linux/errno.h>
 #include <linux/refcount_types.h>
@@ -376,7 +377,9 @@ struct crypto_wait {
 /*
  * Async ops completion helper functioons
  */
-void crypto_req_done(void *req, int err);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO, crypto_req_done, void,
+	(void *req, int err),
+	(req, err));
 
 static inline int crypto_wait_req(int err, struct crypto_wait *wait)
 {
@@ -400,7 +403,9 @@ static inline void crypto_init_wait(struct crypto_wait *wait)
 /*
  * Algorithm query interface.
  */
-int crypto_has_alg(const char *name, u32 type, u32 mask);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO, crypto_has_alg, int,
+	(const char *name, u32 type, u32 mask),
+	(name, type, mask));
 
 /*
  * Transforms: user-instantiated objects which encapsulate algorithms
@@ -428,8 +433,12 @@ struct crypto_tfm {
  * Transform user interface.
  */
  
-struct crypto_tfm *crypto_alloc_base(const char *alg_name, u32 type, u32 mask);
-void crypto_destroy_tfm(void *mem, struct crypto_tfm *tfm);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO, crypto_alloc_base, struct crypto_tfm *,
+	(const char *alg_name, u32 type, u32 mask),
+	(alg_name, type, mask));
+DECLARE_CRYPTO_API(CONFIG_CRYPTO, crypto_destroy_tfm, void,
+	(void *mem, struct crypto_tfm *tfm),
+	(mem, tfm));
 
 static inline void crypto_free_tfm(struct crypto_tfm *tfm)
 {
@@ -514,8 +523,9 @@ static inline void crypto_request_set_tfm(struct crypto_async_request *req,
 	req->flags &= ~CRYPTO_TFM_REQ_ON_STACK;
 }
 
-struct crypto_async_request *crypto_request_clone(
-	struct crypto_async_request *req, size_t total, gfp_t gfp);
+DECLARE_CRYPTO_API(CONFIG_CRYPTO, crypto_request_clone, struct crypto_async_request *,
+	(struct crypto_async_request *req, size_t total, gfp_t gfp),
+	(req, total, gfp));
 
 static inline void crypto_stack_request_init(struct crypto_async_request *req,
 					     struct crypto_tfm *tfm)
-- 
2.47.3


^ permalink raw reply related

* [PATCH v1 00/106] crypto: Standalone crypto module (Series 2/4): Arch-independent crypto
From: Jay Wang @ 2026-02-12  2:45 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
	Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
	linux-modules

This patch series is a follow up of Series 1/4:
https://lore.kernel.org/all/20260212024228.6267-1-wanjay@amazon.com/

This feature is organized into four patch series for submission to the mainline (up to the "Merge tag 'landlock-7.0-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mic/linux"):
- Patch Series 1/4: "[PATCH v1 0...17] crypto: Standalone crypto module (Series 1/4): Core implementation"
- Patch Series 2/4: "[PATCH v1 0...106] crypto: Standalone crypto module (Series 2/4): Arch-independent crypto"
- Patch Series 3/4: "[PATCH v1 0...21] crypto: Standalone crypto module (Series 3/4): x86_64 crypto"
- Patch Series 4/4: "[PATCH v1 0...12] crypto: Standalone crypto module (Series 4/4): arm64 crypto"

The full source code is available at https://github.com/amazonlinux/linux/tree/fips-kernel-module.
Details on this feature and what each patch series covers can be found below.

## 1. Introduction

Amazon Linux is releasing a new kernel feature that converts the previously built-in kernel crypto subsystem into a standalone kernel module. This module becomes the carrier of the kernel crypto subsystem and can be loaded at early boot to provide the same functionality as the original built-in crypto. The primary motivation for this modularization is to streamline Federal Information Processing Standards (FIPS) validation, a critical cryptographic certification for cloud computing users doing business with the U.S. government.
 
In a bit more detail, previously, FIPS certification was tied to the entire kernel image, meaning non-crypto updates could potentially invalidate certification. With this feature, FIPS certification is tied only to the crypto module. Therefore, once the module is certified, loading this certified module on newer kernels automatically makes those kernels FIPS-certified. As a result, this approach can save re-certification costs and 12-18 months of waiting time by reducing the need for repeated FIPS re-certification cycles.

This feature is organized into four patch series:
- Patch Series 1 - Core feature implementation
- Patch Series 2 - Architecture-independent crypto: Modularize built-in crypto under `crypto/`
- Patch Series 3 - x86_64 crypto: Modularize built-in crypto under `arch/x86/crypto/`
- Patch Series 4 - arm64 crypto: Modularize built-in crypto under `arch/arm64/crypto/`

This document provides technical details on how this feature is designed and implemented for users or developers who are interested in developing upon it, and is organized as follows:
- Section 2 - Getting Started: Quick start on how to enable the feature
- Section 3 - Workflow Overview: Changes this feature brings to build and runtime
- Section 4 - Design Implementation Details: Technical deep-dive into each component
- Section 5 - Customizing and Extending Crypto Module: How to select crypto to be included and extend to new crypto/architectures
- Section 6 - Related Work and Comparison
- Section 7 - Summary

## 2. Getting Started

This section provides a quick start guide for developers on how to enable, compile and use the standalone cryptography module feature.

### 2.1 Basic Configuration

The feature is controlled by a single configuration option:
```
CONFIG_CRYPTO_FIPS140_EXTMOD=y
```
What it does: When enabled, automatically redirects a set of cryptographic algorithms from the main kernel into a standalone module `crypto/fips140/fips140.ko`. The cryptographic algorithms that are redirected need to satisfy all the following conditions, otherwise the cryptography will remain in its original form:
1. Must be configured as built-in (i.e., `CONFIG_CRYPTO_*=y`). This means cryptography already configured as modular (i.e., `CONFIG_CRYPTO_*=m`) are not redirected as they are already modularized.
2. Must be among a list, which can be customized by developers as described in Section 5.

When disabled, the kernel behaves as before.

### 2.2 Build Process

Once `CONFIG_CRYPTO_FIPS140_EXTMOD=y` is set, no additional steps are required. The standalone module will be built automatically as part of the standard kernel build process:
```
make -j$(nproc)
# or
make vmlinux
```
**What happens automatically (No user action required):**
1. Build the module as `crypto/fips140/fips140.ko`
2. The cryptography module will be loaded at boot time
3. All kernel cryptographic services will provide the same functionality as before (i.e., prior to introducing this new feature) once boot completes.

### 2.3 Advanced Configuration Options

**Using External Cryptography Module:**
```
CONFIG_CRYPTO_FIPS140_EXTMOD_SOURCE=y
```
By default, `CONFIG_CRYPTO_FIPS140_EXTMOD_SOURCE` is not set, meaning the freshly built cryptography module is used. Otherwise, the pre-built standalone cryptography module from `fips140_build/crypto/fips140/fips140.ko` and modular cryptography such as `fips140_build/crypto/aes.ko` (need to manually place pre-built modules in these locations before the build) are included in kernel packaging (e.g., during `make modules_install`) and are used at later boot time.

**Dual Version Support:**
```
CONFIG_CRYPTO_FIPS140_DUAL_VERSION=y
```
Encapsulate two versions of `fips140.ko` into kernel: one is freshly built for non-FIPS mode usage, another is pre-built specified by `fips140_build/crypto/fips140/fips140.ko` for FIPS mode usage. The appropriate version is selected and loaded at boot time based on boot time FIPS mode status.

### 2.4 Verification

To verify the feature is working, after install and boot with the new kernel:
```
# Check if fips140.ko module is loaded
lsmod | grep fips140
```

## 3. Workflow Overview

This section provides an overview without delving into deep technical details of the changes the standalone cryptography module feature introduces. When this feature is enabled, it introduces changes to both the kernel build and booting process. 

3.1 Build-Time Changes

Kernel cryptography subsystem consists of both cryptography management infrastructure (e.g., `crypto/api.c`, `crypto/algapi.c`, etc), along with hundreds of different cryptography algorithms (e.g., `crypto/arc4.c`).

**Traditional Build Process:**
Traditionally, cryptography management infrastructure are always built-in to the kernel, while cryptographic algorithms can be configured to be built either as built-in (`CONFIG_CRYPTO_*=y`) or as separate modular (`CONFIG_CRYPTO_*=m`) `.ko` file depending on kernel configuration:
As a result, the builtin cryptography management infrastructure and cryptographic algorithms are statically linked into the kernel binary:
```
cryptographic algorithms source files → compiled as .o objfiles →  linked into vmlinux → single kernel binary
```
**With Standalone Cryptography Module:**
This feature automatically transforms the builtin cryptographic components into a standalone cryptography module, `fips140.ko`. To do so, it develops a new kernel build rule `crypto-objs-$(CONFIG_CRYPTO_*)` such that, once this build rule is applied to a cryptographic algorithm, such cryptographic algorithm will be automatically collected into the cryptography module if it is configured as built-in (i.e, `CONFIG_CRYPTO_*=y`), for example:
```
// in crypto/asymmetric_keys/Makefile
- obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
+ crypto-objs-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
```
Such build change allows the modularization transformation to only affect selected cryptographic algorithms (i.e, where the `crypto-objs-$(CONFIG_CRYPTO_*`) is applied).

Then, after the `fips140.ko` is generated, it will be embedded back into main kernel vmlinux as a replacement part. The purpose of this embedding, instead of traditionally putting the `fips140.ko` into filesystem, is a preparation to allow the module to be loaded early enough even before the filesystem is ready.

The new build process is illustrated below.
```
cryptographic algorithms source files → compiled as .o objfiles → automatically collected and linked into fips140.ko → embedded fips140.ko into vmlinux as a replaceable binary
```

### 3.2 Runtime Changes

**Traditional Boot Process:**
The kernel initializes the cryptographic subsystem early during boot, executing each cryptographic initialization routine accordingly. These initialization routines may depend on other cryptographic components or other kernel subsystems, so their invocation follows a well-defined execution order to ensure they are initialized before their first use.
```
kernel starts → cryptography subsystem initialization → cryptography subsystem available → other components use cryptography
```
**With Standalone Cryptography Module:**
At the start of kernel boot, compared to a regular kernel, the first major change introduced by this feature is that no cryptography services are initially available — since the entire cryptography subsystem has been decoupled from the main kernel.
To ensure that the cryptography subsystem becomes available early enough (before the first kernel component that requires cryptography services), the standalone cryptography kernel module must be loaded at a very early stage, even before the filesystem becomes available.

However, the regular module loading mechanism relies on placing kernel modules in the filesystem and loading them from there, which creates a chicken-and-egg problem — the cryptography module cannot be loaded until the filesystem is ready, yet some kernel components may require cryptography services even before that point.

To address this, the second change introduced by this feature is that the cryptography kernel module is loaded directly from memory, leveraging the earlier compilation changes that embed the module binary into the main kernel image. Afterward, the feature includes a “plug-in” mechanism that connects the decoupled cryptography subsystem back to the main kernel, ensuring that kernel cryptography users can correctly locate and invoke the cryptography routine entry points.

Finally, to ensure proper initialization, the feature guarantees that all cryptography algorithms and the cryptography management infra execute their initialization routines in the exact same order as they would if they were built-in.

The process described above is illustrated below.
```
kernel starts → no cryptography available → load fips140.ko from memory → plug cryptography back to kernel → module initialization → cryptographic services available → other components use cryptography
```

## 4. Design Implementation Details

While the earlier sections provide a holistic view of how this feature shapes the kernel, this section provides deeper design details on how these functionalities are realized. There are three key design components:
1. A specialized compile rule that automatically compiles and collects all built-in cryptographic algorithm object files to generate the final module binary under arbitrary kernel configurations, and then embeds the generated binary into the main kernel image for early loading.
2. A mechanism to convert interactions between the cryptography subsystem and the main kernel into a pluggable interface.
3. A module loading and initialization process that ensures the cryptography subsystem is properly initialized as if it were built-in.

### 4.1. Specialized Compilation System

**Automatic Collection and Linking of Built-in Cryptographic Algorithm Objects:**
The first step in generating the `fips140.ko` module is to compile and collect built-in cryptographic components (i.e., those specified by `CONFIG_CRYPTO_*=y`).
Traditionally, the existing module build process requires all module components (e.g., source files) to reside in a single directory. However, this approach is not suitable for our case, where hundreds of cryptographic algorithm source files are scattered across multiple directories.

A naïve approach would be to create a separate Makefile that duplicates the original build rules with adjusted paths.
However, this method is not scalable due to the large number of cryptographic build rules, many of which are highly customized and can vary under different Kconfig settings, making such a separate Makefile even more complex.
Moreover, this approach cannot ensure that built-in cryptographic algorithms are completely removed from the main kernel, which would result in redundant cryptographic code being included in both the kernel and the module.

To tackle this challenge, we automated the object collection and linking process by introducing special build logic for the kernel cryptography subsystem.
Specifically, to automatically collect cryptography object files while preserving their original compilation settings (such as flags, headers, and paths), we introduced a new compilation rule:
```
crypto-objs-y += *.o
```
This replaces the original `obj-y += *.o` rule in cryptography Makefiles later, for example:
```
// in crypto/asymmetric_keys/Makefile
- obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
+ crypto-objs-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
asymmetric_keys-y := \    asymmetric_type.o \    restrict.o \    signature.o
```
in the cryptography subsystem Makefiles, allowing most of the existing Makefile logic to be reused.
As a result, when the standalone cryptography module feature is enabled, any cryptographic algorithm configured as built-in (for example, `crypto-objs-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o` where `CONFIG_ASYMMETRIC_KEY_TYPE=y`) will be automatically collected and linked into a single final object binary, `fips140.o`.
During this process, a special compilation flag (`-DFIPS_MODULE=1`) is applied to instruct each object file to be compiled in a module-specific manner. This flag will later be used to generate the pluggable interface on both the main kernel side and the module side from the same source code.

The implementation details are as follows: it follows a similar methodology used by the `obj-y` collection process for building `vmlinux.o`. The `crypto-objs-y` rule is placed in `scripts/Makefile.build`, which is executed by each directory Makefile to collect the corresponding crypto object files. Each directory then creates a `crypto-module.a` archive that contains all `crypto-objs-y += <object>.o` files under that directory. In the parent directories, these `crypto-module.a` archives are recursively included into the parent’s own `crypto-module.a`, and this process continues upward until the final `fips140.o` is generated.

**A Separate Module Generation Pipeline for Building the Final Kernel Module from Linked Cryptographic Algorithm Object:**
With the linked cryptographic algorithm object (i.e., `fips140.o`), the next step is to generate the final kernel module, `fips140.ko`.

A direct approach would be to inject the `fips140.ko` module build into the existing modules generation pipeline (i.e., `make modules`) by providing our pre-generated `fips140.o`. However, we choose not to do this because it would create a circular make rule dependency (which is invalid in Makefiles and causes build failures), resulting in mutual dependencies between the modules and vmlinux targets (i.e., `modules:vmlinux` and `vmlinux:modules` at the same time).
This happens for the following reasons:
1. Since we will later embed `fips140.ko` into the final kernel image (as described in the next section), we must make vmlinux depend on `fips140.ko`. In other words: `vmlinux: fips140.ko`.
2. When the kernel is built with `CONFIG_DEBUG_INFO_BTF_MODULES=y`, it requires: modules: vmlinux. This is because `CONFIG_DEBUG_INFO_BTF_MODULES=y` takes vmlinux as input to generate BTF info for the module, and inserts such info into the `.ko` module by default.
3. If we choose to inject `fips140.ko` into make modules, this would create a make rule dependency: `fips140.ko: modules`. Combined with items 1 and 2, this eventually creates an invalid circular dependency between vmlinux and modules.

Due to these reasons, the design choice is to use a separate make pipeline (defined as `fips140-ready` in the Makefile). This new pipeline reuses the same module generation scripts used by make modules but adds additional logic in `scripts/Makefile.{modfinal|modinst|modpost}` and `scripts/mod/modpost.c` to handle module symbol generation and verification correctly. 

**A Seamless Process That Embeds the Generated Binary Into the Main Kernel Image for Early Loading:**
As mentioned earlier, in order to load the standalone cryptography module early in the boot process—before the filesystem is ready—the module binary must be embedded into the final kernel image (i.e., vmlinux) so that it can be loaded directly from memory.
We intend for this embedding process to be completely seamless and automatically triggered whenever vmlinux is built (i.e., during `make vmlinux`).

To achieve this, the feature adds a Make dependency rule so that vmlinux depends on `fips140.ko`.
It also modifies the vmlinux link rules (i.e., `arch/<arch>/kernel/vmlinux.lds.S`, `scripts/Makefile.vmlinux`, and `scripts/link-vmlinux.sh`) so that the generated module binary is finally combined with `vmlinux.o`.

In addition, we allow multiple cryptography module binary versions (for example, a certified cryptography binary and a latest, up-to-date but uncertified one) to be embedded into the main kernel image to serve different user needs. This design allows regular (non-FIPS) users to benefit from the latest cryptographic updates, while FIPS-mode users continue to use the certified cryptography module.

To support this, we introduce an optional configuration, `CONFIG_CRYPTO_FIPS140_DUAL_VERSION`. When enabled, this option allows two cryptography module versions to be embedded within a single kernel build and ensures that the appropriate module is selected and loaded at boot time based on the system’s FIPS mode status.

### 4.2. Pluggable Interface Between the Built-in Cryptography Subsystem and the Main Kernel

Although the module binary (`fips140.ko`) has been embedded into the final kernel image (`vmlinux`) as described in the previous section, it is not linked to the kernel in any way. This is because `fips140.ko` is embedded in a data-only manner, so the main kernel cannot directly call any functions or access any data defined in the module binary.

Even worse, simply removing the built-in cryptographic algorithms without additional handling would cause the kernel to fail to compile, because traditionally, built-in cryptographic algorithms and the main kernel can interact only through functions and variables whose addresses they assume to know. As a result, even if they have been removed, kernel cryptography users still expect the symbol addresses of cryptographic routines and data to be available at compile time.

To address this, we introduce a pluggable interface between built-in cryptographic functions and variables by placing **address placeholders**. During runtime, once the cryptography kernel module is loaded, these placeholders are updated to the correct addresses. In the rest of this section, we first introduce this pluggable interface mechanism, and then explain how to apply it to the built-in cryptographic algorithms.

**The Pluggable Interface Mechanism:**
There are two types of address holders used to achieve this pluggable interface:
- Function addresses:  We use the “static call” mechanism. Static calls are a Linux mechanism that converts an “indirect call” into something with performance equivalent to a “direct call,” while avoiding the introduction of additional security concerns, such as control-flow–hijacking attack gadgets. We implement this function-address placeholder as the `DECLARE_STATIC_CALL()` and `DEFINE_CRYPTO_API_STUB()` wrappers.
- Variable addresses (the remaining smaller portion): For these, we use a pointer of the corresponding data type. We implement this address placeholder as the `DECLARE_CRYPTO_VAR()` and `DEFINE_CRYPTO_API_STUB()` wrappers:

These wrappers are applied to each symbol-exported (i.e., `EXPORT_SYMBOL()`) cryptographic function and variable (details on how to apply them are described later). Once applied, the wrappers are compiled differently for the main kernel and for the built-in cryptographic algorithm source code—acting as the “outlet” and the “plug,” respectively—using different compilation flags (`-DFIPS_MODULE`) introduced by our customized build rules described earlier.

As a result, the kernel can successfully compile even when the built-in cryptographic algorithms are removed, thanks to these address placeholders. At boot time, the placeholders initially hold NULL, but since no cryptography users exist at that stage, the kernel can still start booting correctly. After the cryptography module is loaded, the placeholders are dynamically updated to the correct addresses later (by `do_crypto_api()` and `do_crypto_var()`, described in later section).

In addition to these address placeholders, there is another important interaction point between the cryptography subsystem and the main kernel—the cryptographic initialization routines. Therefore, we also add a mechanism to collect all cryptographic initialization functions (e.g., those defined using `module_init()`) into a dedicated ELF section. This serves as preparation for the later module and cryptography-subsystem initialization steps described in subsequent sections.

**Applying the Pluggable Interface Mechanism to Cryptographic Algorithms:**

To apply these pluggable interface wrappers to a cryptographic algorithm and make them take effect, we follow the steps below (using `crypto/asymmetric_keys/asymmetric_type.c` as an example):
1. **Apply `crypto-objs-y` compile rule to the cryptographic algorithm:**
```
// in crypto/asymmetric_keys/Makefile
- obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
+ crypto-objs-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
asymmetric_keys-y := \    asymmetric_type.o \    restrict.o \    signature.o
```
2. **Locate the communication point between the cryptographic algorithm and the main kernel:**

The cryptography subsystem is designed such that most interactions between the main kernel and cryptographic algorithms occur through exported symbols using `EXPORT_SYMBOL()` wrappers.
This kernel design exists because most cryptographic algorithm implementations must support both built-in and modular modes. 

Consequently, the cryptographic functions and variables exported by `EXPORT_SYMBOL()` are a well-defined and identifiable interface between the cryptography subsystem and the main kernel: 
```
// in crypto/asymmetric_keys/asymmetric_type.c 
//Exported cryptographic function:
bool asymmetric_key_id_same(const struct asymmetric_key_id *kid1,
                const struct asymmetric_key_id *kid2) {...}
EXPORT_SYMBOL_GPL(asymmetric_key_id_same); 
//Exported cryptographic variable:
struct key_type key_type_asymmetric = {...};
EXPORT_SYMBOL_GPL(key_type_asymmetric); 
```
3. **Replace their declarations in the header file with the address-placeholder declaration wrappers:**
```
// in include/keys/asymmetric-type.h
// for exported cryptographic function:
- bool asymmetric_key_id_same const struct asymmetric_key_id *kid1, const struct asymmetric_key_id *kid2);
+ DECLARE_CRYPTO_API(CONFIG_ASYMMETRIC_KEY_TYPE, asymmetric_key_id_same, bool,
    (const struct asymmetric_key_id *kid1, const struct asymmetric_key_id *kid2),
    (kid1, kid2)); 
// for exported cryptographic variables:
- struct key_type key_type_asymmetric;
+ DECLARE_CRYPTO_VAR(CONFIG_ASYMMETRIC_KEY_TYPE, key_type_asymmetric, struct key_type, );
+ #if defined(CONFIG_CRYPTO_FIPS140_EXTMOD) && !defined(FIPS_MODULE) && IS_BUILTIN(CONFIG_ASYMMETRIC_KEY_TYPE)
+ #define key_type_asymmetric (*((struct key_type*)CRYPTO_VAR_NAME(key_type_asymmetric)))
+ #endif 
```
By replacing the original declarations with the address-placeholder declaration wrappers, we can automatically force all cryptography users to go through the placeholders, because those users already include the same header file.
The wrapper also takes the cryptographic algorithm Kconfig symbol as a parameter, so that when a cryptographic algorithm is built as a module (for example, `CONFIG_ASYMMETRIC_KEY_TYPE=m`), the original function declarations remain unchanged and are not affected.

4. **Add the address-placeholder definition wrappers into a dedicated file `fips140-api.c`:**

This file will be compiled separately and acts as both the “outlet” and the “plug” for the main kernel and the cryptography module, respectively:
```
// in crypto/fips140/fips140-api.c
+ #if IS_BUILTIN(CONFIG_ASYMMETRIC_KEY_TYPE)
+ #include <keys/asymmetric-type.h>
// for exported cryptographic function:
+ DEFINE_CRYPTO_API_STUB(asymmetric_key_id_same);
// for exported cryptographic variables:
+ #undef key_type_asymmetric
+ DEFINE_CRYPTO_VAR_STUB(key_type_asymmetric);
+ #endif
```

5. **Lastly, collect the cryptographic initialization routines for later module and cryptography-subsystem initialization by wrapping the original cryptographic initialization functions:**
```
// in crypto/asymmetric_keys/asymmetric_type.c 
- module_init(asymmetric_key_init);
- module_exit(asymmetric_key_cleanup); 
+ crypto_module_init(asymmetric_key_init);
+ crypto_module_exit(asymmetric_key_cleanup); 
```
We apply the above steps to both architecture-independent and architecture-specific cryptographic algorithms.

### 4.3. Initialization Synchronization

To ensure the embedded `fips140.ko` module binary provides the same cryptography functionality as the regular kernel, the kernel needs:
1. A module loader to load the module binary directly from memory,
2. A mechanism to plug the module back into the kernel by updating the address placeholders, and
3. Correct cryptography subsystem initialization, as if the cryptographic algorithms were still built-in.

**Directly Load Module Binary from Memory:**
Regular modules are loaded from the filesystem and undergo signature verification on the module binary, which relies on cryptographic operations. However, since we have already fully decoupled the cryptography subsystem, we must skip this step for this `fips140.ko` module.
To achieve this, we add a new loader function `load_crypto_module_mem()` that can load the module binary directly from memory at the designed address without checking the signature. Since the module binary is embedded into main kernel in an ELF section, as specified in the linker script:
```
// in arch/<arch>/kernel/vmlinux.lds.S
    .fips140_embedded : AT(ADDR(.fips140_embedded) - LOAD_OFFSET) {
        . = ALIGN(8);
        _binary_fips140_ko_start = .;
        KEEP(*(.fips140_module_data))
        _binary_fips140_ko_end = .;
    }
```
Therefore, the runtime memory address of the module can be accessed directly by the module loader to invoke the new loader function `load_crypto_module_mem()`.

**Plug Back the Module by Updating Address Placeholder Values:**
To update the address placeholders in the main kernel to the correct addresses matching the loaded module, after compilation the placeholders are placed into dedicated ELF sections `_crypto_api_keys` and `_crypto_var_keys`.
This can be seen from the definition of the placeholder-declaration wrappers:
```
#define DEFINE_CRYPTO_API_STUB(name) \    static struct crypto_api_key __##name##_key \        __used \        __section("__crypto_api_keys")  // Place in a dedicated ELF Section
        __aligned(__alignof__(struct crypto_api_key)) = \    { \        .key = &STATIC_CALL_KEY(crypto_##name##_key), \        .tramp = STATIC_CALL_TRAMP_ADDR(crypto_##name##_key), \        .func = &name, \    };

#define DEFINE_CRYPTO_VAR_STUB(name) \    static struct crypto_var_key __crypto_##name##_var_key \        __used \        __section("__crypto_var_keys")  // Place in a dedicated ELF Section
        __aligned(__alignof__(struct crypto_var_key)) = \    { \        .ptr = &CRYPTO_VAR_NAME(name), \        .var = (void*)&name, \    };
```
The purpose of doing this is to allow the main kernel to quickly locate the placeholders and update them to the correct addresses. The update functions are defined as `do_crypto_var()` and `do_crypto_api()`, which are executed at module load.

As a result, all cryptography users in the main kernel can now call the cryptographic functions as if they were built-in.

**Initialize Cryptography Subsystem as if it Were Built-in:**
Cryptographic components must be properly initialized before use, and this initialization is typically achieved through dedicated initialization functions (e.g., `module_init(crypto_init_func)` or `late_initcall(crypto_init_func)`). These functions often have strict execution order requirements and must run during the appropriate boot phase.

Therefore, for our standalone cryptography module feature, we must ensure that these decoupled “built-in” cryptographic algorithms are properly initialized and that their initialization order is preserved as before because failure to follow the correct order can result in kernel panic.

To address this, we introduce a synchronization mechanism between the main kernel and the module to ensure all cryptographic algorithms are executed in the correct kernel boot phase. In more details, we spawn the module initialization process `fips_loader_init()` as an async thread `fips140_sync_thread()`, in which we call `run_initcalls()` to execute the initialization calls of each cryptographic algorithm.
Then, we introduce synchronization helpers such as `wait_until_fips140_level_sync(int level)` to ensure the initialization order of all cryptographic algorithms is synchronized with the main kernel.

## 5. Customization and Extension of Cryptography Module

This section describes how developers can customize which cryptographic algorithms are included in the standalone cryptography module, as well as extend this feature to other cryptographic algorithms or hardware architectures.

### 5.1. Cryptography Selection Mechanism

The feature automatically includes cryptographic algorithms that meet specific criteria:
1. **Built-in Configuration**: Only cryptographic algorithms configured as `CONFIG_CRYPTO_*=y` are candidates for inclusion
2. **Explicit Inclusion**: Cryptographic algorithms must be explicitly converted using the `crypto-objs-$(CONFIG__CRYPTO_*`) build rule

### 5.2. Extend Support to New Cryptographic Algorithms

To extend support to a new cryptographic algorithm in the standalone module, follow these steps:

**Step 1: Update the Makefile**
```
# in crypto/[algorithm]/Makefile
- obj-$(CONFIG_CRYPTO_ALGORITHM) += algorithm.o
+ crypto-objs-$(CONFIG_CRYPTO_ALGORITHM) += algorithm.o
```
For Architecture-Specific Cryptographic Algorithms:
- Apply the `crypto-objs-` rule in the appropriate `arch/*/crypto/Makefile`

**Step 2: Add Pluggable Interface Support**
If the cryptographic algorithm exports symbols via `EXPORT_SYMBOL()`, add the pluggable interface wrappers:
```
# Example: in include/crypto/algorithm.h
- extern int crypto_algorithm_transform(struct crypto_tfm *tfm, const u8 *src, 
                                       u8 *dst, unsigned int len, u32 flags);
+ DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGORITHM, crypto_algorithm_transform, int,
    (struct crypto_tfm *tfm, const u8 *src, u8 *dst, unsigned int len, u32 flags),
    (tfm, src, dst, len, flags));
```
Then, add the corresponding stubs in `crypto/fips140/fips140-api.c`:
```
#if IS_BUILTIN(CONFIG_CRYPTO_ALGORITHM)
#include <crypto/algorithm.h>
DEFINE_CRYPTO_API_STUB(crypto_algorithm_transform);
#endif
```
For Architecture-Specific Cryptographic Algorithms:
- Include architecture-specific stubs in `arch/*/crypto/fips140/fips140-api.c`:
```
# Example: in arch/arm64/crypto/fips140/fips140-api.c
#if IS_BUILTIN(CONFIG_CRYPTO_AES_ARM64_CE)
#include <arch/arm64/crypto/aes-ce-setkey.h>
DEFINE_CRYPTO_API_STUB(ce_aes_setkey);
DEFINE_CRYPTO_API_STUB(ce_aes_expandkey);
#endif
```
**Step 3: Update Initialization**
Replace module initialization calls:
```
# in crypto/algorithm/algorithm.c
- module_init(algorithm_init);
- module_exit(algorithm_exit);
+ crypto_module_init(algorithm_init);
+ crypto_module_exit(algorithm_exit);
```

### 5.3. Architecture-Specific Extensions

**Extending to New Architectures:**
Currently supported architectures are x86_64 and ARM64. To extend this feature to additional architectures:
1. **Update Linker Scripts**: Add ELF sections in `arch/[new-arch]/kernel/vmlinux.lds.S`:
```
.fips140_embedded : AT(ADDR(.fips140_embedded) - LOAD_OFFSET) {
    . = ALIGN(8);
    _binary_fips140_ko_start = .;
    KEEP(*(.fips140_module_data))
    _binary_fips140_ko_end = .;
}
```
2. **Create Architecture-Specific Files**: Set up `arch/[new-arch]/crypto/fips140/` directory with Makefile and `fips140-api.c` following the pattern used in x86_64 and ARM64.

## 6. Related Work and Comparison

The idea of modularizing kernel cryptographic functionality has also attracted attention from other Linux distributions as well as Linux-kernel-based platforms that are not traditional distributions. Specifically, there are two related efforts: one from [Android's GKI kernel](https://source.android.com/docs/core/architecture/kernel/gki-fips140-module) and another from [Oracle Linux](https://git.kernel.org/pub/scm/linux/kernel/git/vegard/linux-fips140.git/log/?h=fips140). While Amazon Linux incorporated several valuable ideas from these efforts (and have acknowledged them in the patch commits—thank you again!), this section highlights the key differences between those approaches and this approach. The goal is to describe the trade-offs and design choices objectively, rather than to criticize other implementations.

### 6.1. Comparison with Android's GKI

Android's work is the earliest one on modularizing kernel cryptographic code, and it targets a non-intrusive approach to the core GKI kernel, with the goal of minimizing modifications to the kernel source. To achieve this, the crypto module relies on several interception or "hijacking" techniques that intervene in the core kernel execution path.

While this approach minimizes kernel code changes, we don't adopt such an approach for several reasons. First, these interception mechanisms tightly depend on internal kernel crypto subsystem behavior, making them fragile across major kernel updates thus less suitable to reuse the same module on newer major kernel versions. Second, this design requires substantial additional cryptographic code duplication, which impacts maintainability. Finally, the solution only supports a fixed set of cryptographic algorithms, making it non-general and difficult to extend.

In contrast, our design integrates directly into the Linux kernel source tree, avoids duplicated cryptographic implementations, supports arbitrary kernel configuration settings, and works with any chosen set of cryptographic algorithms.

### 6.2. Comparison with Oracle Linux

Oracle’s work was developed concurrently with this approach. The primary differences between Oracle’s approach and Amazon's lie in build integration, pluggable interface design, and module initialization.

**Build Integration:**
Oracle's module is implemented as an out-of-tree module with a separate Makefile. This introduces three major reasons we don't adopt such an approach: 

*First*, the separate Makefile duplicates many kernel build rules, which increases maintenance cost, as upstream kernel build changes must be tracked and replicated. One concrete example can be seen below:

in Oracle's module makefile
```
fips140-y += crypto/skcipher.o
fips140-y += crypto/lskcipher.o
```
However, in upstream, the corresponding build logic is more complex and configuration-dependent:
```
crypto_skcipher-y += lskcipher.o
crypto_skcipher-y += skcipher.o
obj-$(CONFIG_CRYPTO_SKCIPHER2) += crypto_skcipher.o
ifeq ($(CONFIG_BPF_SYSCALL),y)
obj-$(CONFIG_CRYPTO_SKCIPHER2) += bpf_crypto_skcipher.o
endif
```
As shown above, when `CONFIG_BPF_SYSCALL` is enabled, `bpf_crypto_skcipher.o` must also be included. Tracking such dependencies is hard in the duplicated Makefile approach. In contrast, our approach integrates seamlessly into the kernel build system by introducing a customized build rule (`crypto-objs-*`) rather than relying on a duplicated Makefile, such that this is handled correctly by reusing the existing kernel build logic:
```
crypto_skcipher-y += lskcipher.o
crypto_skcipher-y += skcipher.o
- obj-$(CONFIG_CRYPTO_SKCIPHER2) += crypto_skcipher.o
+ crypto-objs-$(CONFIG_CRYPTO_SKCIPHER2) += crypto_skcipher.o
ifeq ($(CONFIG_BPF_SYSCALL),y)
- obj-$(CONFIG_CRYPTO_SKCIPHER2) += bpf_crypto_skcipher.o
+ crypto-objs-$(CONFIG_CRYPTO_SKCIPHER2) += bpf_crypto_skcipher.o
endif
```
As a result, such a Makefile-duplication approach does not scale well across all kernel configurations and does not easily support arbitrary sets of cryptographic algorithms.

*Second*, since the module is to be embedded as part of the kernel image (i.e., `vmlinux`) as described earlier, the module build must be triggered automatically as part of the `vmlinux` build process to achieve a seamless build workflow. However, Oracle's module build is not tightly integrated into the kernel build framework and requires special build commands (e.g., first do `make M=fips140/` specifically, then do some shell command and finally `make`). 

In contrast, our approach improves this aspect by integrating the module build tightly into the regular kernel build, so the build process is seamless and automatic with regular build and packaging processes such as `make` or `make vmlinux` or `make install`.

**Pluggable Interface:**
There are several differences in the pluggable interface design.

*First*, we avoid duplicate crypto code so only keep one crypto code in kernel memory, while existing work keeps two crypto code even if these crypto code are from the same source code. This is due to the way Oracle defines pluggable interface macros in `crypto/api`, where its design requires some cryptographic code to remain compiled into the main kernel image in addition to the code inside the standalone cryptography module. Keeping two crypto code is ok if these code are different and designed to be used for different runtime modes (i.e., FIPS/non-FIPS mode), but will be unnecessary if both crypto code are the same.

In contrast, the approach we use can flexibly support both choices: keep one cryptography subsystem, or two different crypto subsystems. To do so, we introduce an option `CRYPTO_FIPS140_DUAL_VERSION` such that when it is disabled, we only keep one cryptographic subsystem in the cryptography module while completely removing it from the main kernel; and when it is enabled, we allow having two different modules carrying different cryptography for different kernel runtime modes (i.e., FIPS and non-FIPS mode).

*Second*, existing approach requires modifications to both the cryptographic implementation (.c) files and the declaration (.h) header files while our approach only requires modifying the header file, making the change less intrusive to the kernel codebase.

*Third*, prior approaches mainly support making cryptographic function calls pluggable, while our approach extends pluggability to cryptographic variables as well.

*Fourth*, prior approach requires all cryptographics that we care (for any purpose such as those within FIPS boundary) to be included within a single kernel module `fips140.ko` (e.g., when `CONFIG_CRYPTO_AES=m`, it cannot be `aes.ko` but must be within fips140.ko). However, this requirement limits the inherent benefit of a kernel module (i.e., on-demand loading for memory efficiency). In contrast, our approach allows the cryptographic we care remain its original modular if it is configured as being so (i.e., if `CONFIG_CRYPTO_AES=m`, the aes will still be as `aes.ko` but not forced to `fips140.ko`) up to the `.config` setting. One benefit of this design is that it does not impose strict requirements on `.config` setting (i.e., a cryptography `.config` can be set to both `=y|m` while existing work must be set as `=y`), preserving configuration flexibility.

To support so, for any cryptography within the interest (i.e., whose makerule has been replaced with `crypto-objs-*`) but configured as build-as-module (i.e., `CONFIG_CRYPTO_*=m`), its compiled `.ko` binary will be marked automatically, such that the loader will have a way to recognize to perform some interest-specific processing (e.g., registered as FIPS-required flag) if needed. And the pluggable interface can also adjust its coverage automatically based on different `CONFIG_CRYPTO_*=y|=m` settings. This is achieved by letting the pluggable interface macro to take `CONFIG_CRYPTO_*` option as a parameter to recognize the `.config` setting.

**Module Initialization:**
Oracle's initialization routine does not guarantee preservation of the original crypto initialization order (i.e., the order they should follow if they were originally built-in in the main kernel), which limits its ability to support arbitrary combinations of cryptographic algorithms. This is because the crypto initialization routine in the module is executed too early, such that all module crypto is initialized before the cryptography init in the main kernel. So if there is a crypto in the module (e.g., a crypto init defined as `late_init()`) that depends on a cryptography (whose init is defined as `module_init()`) in the main kernel, since the one in the main kernel should be executed earlier (but because the module init is too early, it makes the crypto in the main kernel executed too late), such a case will break the kernel boot process.

Our design, on the other hand, introduces explicit initialization synchronization mechanisms between cryptography's init routine in the module and in the main kernel that can preserve the original built-in initialization order. As a result, our module supports any chosen crypto set to be included in the module.

### 6.3. Comparison Summary

Overall, combined with differences in coding style and integration strategy, the proposed approach is more seamlessly integrated with the upstream Linux kernel, making it more generalizable across different kernel configuration settings, and the changed behavior more invisible to kernel users.

## 7. Summary
In this patch series, Amazon Linux proposes a new kernel feature that decouples the built-in crypto subsystem into a dedicated kernel module. To achieve this, several key mechanisms are designed, including specialized compile rules, a novel pluggable interface mechanism, and a module-loading initialization process. This feature is designed in an upstream-friendly manner so that it can support arbitrary kernel configuration settings and arbitrary chosen sets of cryptographic algorithms. It is planned to be officially launched with the Amazon Linux Kernel 6.18 and future kernels.

---
Written by Jay Wang <wanjay@amazon.com>, Amazon Linux


Jay Wang (91):
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO and CONFIG_CRYPTO_ALGAPI2 crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_AES crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_AEAD2 crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_GENIV crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_SKCIPHER2 crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_HASH2 crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_AKCIPHER2 crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_SIG2 crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_KPP2 crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_RSA crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_ACOMP2 crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_MANAGER2 crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_MD5 crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_SHA3 crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_AUTHENC crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_LZO crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_RNG2 crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_ASYMMETRIC_KEY_TYPE crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_X509_CERTIFICATE_PARSER crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_PKCS7_MESSAGE_PARSER crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_ENGINE crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_HKDF crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_DH crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_ECDSA and CONFIG_CRYPTO_ECC crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_USER crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_XCBC crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_NULL crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_MD4 crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_RMD160 crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_SHA1 crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_SM3_GENERIC crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_STREEBOG crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_WP512 crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_BLAKE2B crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_PCBC crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_CTS crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_LRW crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_XTS crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_XCTR and CONFIG_CRYPTO_HCTR2 crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_ADIANTUM crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_CHACHA20 crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_CHACHA20POLY1305 crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_AEGIS128 crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_CRYPTD crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_DES crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_FCRYPT crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_BLOWFISH and CONFIG_CRYPTO_BLOWFISH_COMMON crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_SM4 and CONFIG_CRYPTO_SM4_GENERIC crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_TWOFISH and CONFIG_CRYPTO_TWOFISH_COMMON crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_SERPENT crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_CAMELLIA crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_CAST_COMMON, CONFIG_CRYPTO_CAST5, CONFIG_CRYPTO_CAST6
    crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_ARC4 crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_USER_API crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_USER_API_SKCIPHER crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_TEA crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_KHAZAD crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_ANUBIS crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_SEED crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_ARIA crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_DEFLATE crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_MICHAEL_MIC crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_CRC32C and CONFIG_CRYPTO_CRC32 crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_KRB5ENC crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_LZ4 and CONFIG_CRYPTO_LZ4HC crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_XXHASH crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_842 crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_JITTERENTROPY_TESTINTERFACE crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_BENCHMARK crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_USER_API_HASH crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_USER_API_RNG crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_USER_API_AEAD crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_ZSTD crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_ESSIV crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_ECDH crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_ECRDSA crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_XOR_BLOCKS crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_ASYNC_CORE crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_ASYNC_MEMCPY crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_ASYNC_XOR crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_ASYNC_PQ crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_ASYNC_RAID6_RECOV crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_KDF800108_CTR crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_KRB5 crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_FIPS_SIGNATURE_SELFTEST crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_PKCS8_PRIVATE_KEY_PARSER crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_PKCS7_TEST_KEY crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_SIGNED_PE_FILE_VERIFICATION crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_SIMD crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_ASYNC_RAID6_TEST crypto

Vegard Nossum (15):
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_SEQIV crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_ECHAINIV crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_CMAC crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_HMAC crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_SHA256 crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_SHA512 crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_ECB crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_CBC crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_CTR crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_GCM crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_CCM crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_DRBG crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_JITTERENTROPY crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_GHASH crypto
  crypto: convert exported crypto symbol into pluggable interface for
    CONFIG_CRYPTO_PCRYPT crypto

 certs/system_keyring.c                   |   1 +
 crypto/842.c                             |   4 +-
 crypto/Makefile                          | 204 ++---
 crypto/adiantum.c                        |   4 +-
 crypto/aegis128-core.c                   |   4 +-
 crypto/aes.c                             |   4 +-
 crypto/af_alg.c                          |   4 +-
 crypto/algapi.c                          |   4 +-
 crypto/algboss.c                         |   4 +-
 crypto/algif_aead.c                      |   4 +-
 crypto/algif_hash.c                      |   4 +-
 crypto/algif_rng.c                       |   4 +-
 crypto/algif_skcipher.c                  |   4 +-
 crypto/anubis.c                          |   4 +-
 crypto/arc4.c                            |   4 +-
 crypto/aria_generic.c                    |   4 +-
 crypto/asymmetric_keys/Makefile          |  16 +-
 crypto/asymmetric_keys/asymmetric_type.c |   4 +-
 crypto/asymmetric_keys/pkcs7_key_type.c  |   6 +-
 crypto/asymmetric_keys/pkcs8_parser.c    |   4 +-
 crypto/asymmetric_keys/restrict.c        |   3 +-
 crypto/asymmetric_keys/selftest.c        |   2 +-
 crypto/asymmetric_keys/verify_pefile.c   |   1 +
 crypto/asymmetric_keys/x509_parser.h     |  15 +-
 crypto/asymmetric_keys/x509_public_key.c |   4 +-
 crypto/async_tx/Makefile                 |  12 +-
 crypto/async_tx/async_pq.c               |   4 +-
 crypto/async_tx/async_tx.c               |   4 +-
 crypto/async_tx/raid6test.c              |   4 +-
 crypto/authenc.c                         |   4 +-
 crypto/authencesn.c                      |   4 +-
 crypto/blake2b.c                         |   4 +-
 crypto/blowfish_generic.c                |   4 +-
 crypto/bpf_crypto_skcipher.c             |   4 +-
 crypto/camellia_generic.c                |   4 +-
 crypto/cast5_generic.c                   |   4 +-
 crypto/cast6_generic.c                   |   4 +-
 crypto/cbc.c                             |   4 +-
 crypto/ccm.c                             |   4 +-
 crypto/chacha.c                          |   4 +-
 crypto/chacha20poly1305.c                |   4 +-
 crypto/cmac.c                            |   4 +-
 crypto/crc32.c                           |   4 +-
 crypto/crc32c.c                          |   4 +-
 crypto/cryptd.c                          |   4 +-
 crypto/crypto_null.c                     |   4 +-
 crypto/crypto_user.c                     |   4 +-
 crypto/ctr.c                             |   4 +-
 crypto/cts.c                             |   4 +-
 crypto/deflate.c                         |   4 +-
 crypto/des_generic.c                     |   4 +-
 crypto/dh.c                              |   4 +-
 crypto/drbg.c                            |   4 +-
 crypto/ecb.c                             |   4 +-
 crypto/ecdh.c                            |   4 +-
 crypto/ecdsa.c                           |   4 +-
 crypto/echainiv.c                        |   4 +-
 crypto/ecrdsa.c                          |   4 +-
 crypto/essiv.c                           |   4 +-
 crypto/fcrypt.c                          |   4 +-
 crypto/fips140/fips140-api.c             | 934 ++++++++++++++++++++++-
 crypto/gcm.c                             |   4 +-
 crypto/ghash-generic.c                   |   4 +-
 crypto/hctr2.c                           |   4 +-
 crypto/hkdf.c                            |   4 +-
 crypto/hmac.c                            |   4 +-
 crypto/internal.h                        |  89 ++-
 crypto/jitterentropy-kcapi.c             |   4 +-
 crypto/kdf_sp800108.c                    |   4 +-
 crypto/khazad.c                          |   4 +-
 crypto/krb5/Makefile                     |   2 +-
 crypto/krb5/krb5_api.c                   |   4 +-
 crypto/krb5enc.c                         |   4 +-
 crypto/lrw.c                             |   4 +-
 crypto/lz4.c                             |   4 +-
 crypto/lz4hc.c                           |   4 +-
 crypto/lzo-rle.c                         |   4 +-
 crypto/lzo.c                             |   4 +-
 crypto/md4.c                             |   4 +-
 crypto/md5.c                             |   4 +-
 crypto/michael_mic.c                     |   4 +-
 crypto/pcbc.c                            |   4 +-
 crypto/pcrypt.c                          |   4 +-
 crypto/rmd160.c                          |   4 +-
 crypto/rsa.c                             |   4 +-
 crypto/seed.c                            |   4 +-
 crypto/seqiv.c                           |   4 +-
 crypto/serpent_generic.c                 |   4 +-
 crypto/sha1.c                            |   4 +-
 crypto/sha256.c                          |   4 +-
 crypto/sha3.c                            |   4 +-
 crypto/sha512.c                          |   4 +-
 crypto/sm3_generic.c                     |   4 +-
 crypto/sm4_generic.c                     |   4 +-
 crypto/streebog_generic.c                |   4 +-
 crypto/tcrypt.c                          |   4 +-
 crypto/tea.c                             |   4 +-
 crypto/twofish_generic.c                 |   4 +-
 crypto/wp512.c                           |   4 +-
 crypto/xcbc.c                            |   4 +-
 crypto/xctr.c                            |   4 +-
 crypto/xor.c                             |   4 +-
 crypto/xts.c                             |   4 +-
 crypto/xxhash_generic.c                  |   4 +-
 crypto/zstd.c                            |   4 +-
 include/crypto/acompress.h               |  14 +-
 include/crypto/aead.h                    |  30 +-
 include/crypto/akcipher.h                |  12 +-
 include/crypto/algapi.h                  | 125 ++-
 include/crypto/aria.h                    |  16 +-
 include/crypto/authenc.h                 |  12 +-
 include/crypto/blowfish.h                |   6 +-
 include/crypto/cast5.h                   |  14 +-
 include/crypto/cast6.h                   |  19 +-
 include/crypto/cast_common.h             |  17 +-
 include/crypto/cryptd.h                  |  56 +-
 include/crypto/dh.h                      |  14 +-
 include/crypto/ecc_curve.h               |   9 +-
 include/crypto/ecdh.h                    |  14 +-
 include/crypto/engine.h                  | 140 ++--
 include/crypto/hash.h                    |  53 +-
 include/crypto/hkdf.h                    |  13 +-
 include/crypto/if_alg.h                  |  84 +-
 include/crypto/internal/acompress.h      |  27 +-
 include/crypto/internal/aead.h           |  28 +-
 include/crypto/internal/akcipher.h       |  12 +-
 include/crypto/internal/cipher.h         |  20 +-
 include/crypto/internal/ecc.h            |  91 ++-
 include/crypto/internal/geniv.h          |  14 +-
 include/crypto/internal/hash.h           |  59 +-
 include/crypto/internal/kpp.h            |  12 +-
 include/crypto/internal/rng.h            |  21 +-
 include/crypto/internal/rsa.h            |   7 +-
 include/crypto/internal/scompress.h      |   9 +-
 include/crypto/internal/sig.h            |  12 +-
 include/crypto/internal/simd.h           |  33 +-
 include/crypto/internal/skcipher.h       |  91 ++-
 include/crypto/kdf_sp800108.h            |  14 +-
 include/crypto/kpp.h                     |   5 +-
 include/crypto/krb5.h                    |  78 +-
 include/crypto/md5.h                     |   8 +-
 include/crypto/pkcs7.h                   |  31 +-
 include/crypto/public_key.h              |  44 +-
 include/crypto/rng.h                     |  18 +-
 include/crypto/scatterwalk.h             |  36 +-
 include/crypto/serpent.h                 |  20 +-
 include/crypto/sig.h                     |   3 +-
 include/crypto/skcipher.h                |  56 +-
 include/crypto/sm4.h                     |  22 +-
 include/crypto/twofish.h                 |  11 +-
 include/keys/asymmetric-parser.h         |   8 +-
 include/keys/asymmetric-type.h           |  37 +-
 include/linux/async_tx.h                 |  76 +-
 include/linux/crypto.h                   |  22 +-
 include/linux/raid/xor.h                 |   7 +-
 include/linux/verification.h             |   8 +-
 156 files changed, 2302 insertions(+), 943 deletions(-)

-- 
2.47.3


^ permalink raw reply

* [PATCH 17/17] Add standalone crypto kernel module technical documentation
From: Jay Wang @ 2026-02-12  2:42 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
	Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
	linux-modules
In-Reply-To: <20260212024228.6267-1-wanjay@amazon.com>

Technical guide covering implementation details and usage of the
standalone crypto kernel module feature.

Signed-off-by: Jay Wang <wanjay@amazon.com>
---
 crypto/fips140/README | 401 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 401 insertions(+)
 create mode 100644 crypto/fips140/README

diff --git a/crypto/fips140/README b/crypto/fips140/README
new file mode 100644
index 000000000000..45001037e855
--- /dev/null
+++ b/crypto/fips140/README
@@ -0,0 +1,401 @@
+## 1. Introduction
+
+Amazon Linux is releasing a new kernel feature that converts the previously built-in kernel crypto subsystem into a standalone kernel module. This module becomes the carrier of the kernel crypto subsystem and can be loaded at early boot to provide the same functionality as the original built-in crypto. The primary motivation for this modularization is to streamline Federal Information Processing Standards (FIPS) validation, a critical cryptographic certification for cloud computing users doing business with the U.S. government.
+ 
+In a bit more detail, previously, FIPS certification was tied to the entire kernel image, meaning non-crypto updates could potentially invalidate certification. With this feature, FIPS certification is tied only to the crypto module. Therefore, once the module is certified, loading this certified module on newer kernels automatically makes those kernels FIPS-certified. As a result, this approach can save re-certification costs and 12-18 months of waiting time by reducing the need for repeated FIPS re-certification cycles.
+
+This document provides technical details on how this feature is designed and implemented for users or developers who are interested in developing upon it, and is organized as follows:
+- Section 2 - Getting Started: Quick start on how to enable the feature
+- Section 3 - Workflow Overview: Changes this feature brings to build and runtime
+- Section 4 - Design Implementation Details: Technical deep-dive into each component
+- Section 5 - Customizing and Extending Crypto Module: How to select crypto to be included and extend to new crypto/architectures
+
+## 2. Getting Started
+
+This section provides a quick start guide for developers on how to enable, compile and use the standalone cryptography module feature.
+
+### 2.1 Basic Configuration
+
+The feature is controlled by a single configuration option:
+```
+CONFIG_CRYPTO_FIPS140_EXTMOD=y
+```
+What it does: When enabled, automatically redirects a set of cryptographic algorithms from the main kernel into a standalone module `crypto/fips140/fips140.ko`. The cryptographic algorithms that are redirected need to satisfy all the following conditions, otherwise the cryptography will remain in its original form:
+1. Must be configured as built-in (i.e., `CONFIG_CRYPTO_*=y`). This means cryptography already configured as modular (i.e., `CONFIG_CRYPTO_*=m`) are not redirected as they are already modularized.
+2. Must be among a list, which can be customized by developers as described in Section 5.
+
+When disabled, the kernel behaves as before.
+
+### 2.2 Build Process
+
+Once `CONFIG_CRYPTO_FIPS140_EXTMOD=y` is set, no additional steps are required. The standalone module will be built automatically as part of the standard kernel build process:
+```
+make -j$(nproc)
+# or
+make vmlinux
+```
+**What happens automatically (No user action required):**
+1. Build the module as `crypto/fips140/fips140.ko`
+2. The cryptography module will be loaded at boot time
+3. All kernel cryptographic services will provide the same functionality as before (i.e., prior to introducing this new feature) once boot completes.
+
+### 2.3 Advanced Configuration Options
+
+**Using External Cryptography Module:**
+```
+CONFIG_CRYPTO_FIPS140_EXTMOD_SOURCE=y
+```
+By default, `CONFIG_CRYPTO_FIPS140_EXTMOD_SOURCE` is not set, meaning the freshly built cryptography module is used. Otherwise, the pre-built standalone cryptography module from `fips140_build/crypto/fips140/fips140.ko` and modular cryptography such as `fips140_build/crypto/aes.ko` (need to manually place pre-built modules in these locations before the build) are included in kernel packaging (e.g., during `make modules_install`) and are used at later boot time.
+
+**Dual Version Support:**
+```
+CONFIG_CRYPTO_FIPS140_DUAL_VERSION=y
+```
+Encapsulate two versions of `fips140.ko` into kernel: one is freshly built for non-FIPS mode usage, another is pre-built specified by `fips140_build/crypto/fips140/fips140.ko` for FIPS mode usage. The appropriate version is selected and loaded at boot time based on boot time FIPS mode status.
+
+### 2.4 Verification
+
+To verify the feature is working, after install and boot with the new kernel:
+```
+# Check if fips140.ko module is loaded
+lsmod | grep fips140
+```
+
+## 3. Workflow Overview
+
+This section provides an overview without delving into deep technical details of the changes the standalone cryptography module feature introduces. When this feature is enabled, it introduces changes to both the kernel build and booting process. 
+
+3.1 Build-Time Changes
+
+Kernel cryptography subsystem consists of both cryptography management infrastructure (e.g., `crypto/api.c`, `crypto/algapi.c`, etc), along with hundreds of different cryptography algorithms (e.g., `crypto/arc4.c`).
+
+**Traditional Build Process:**
+Traditionally, cryptography management infrastructure are always built-in to the kernel, while cryptographic algorithms can be configured to be built either as built-in (`CONFIG_CRYPTO_*=y`) or as separate modular (`CONFIG_CRYPTO_*=m`) `.ko` file depending on kernel configuration:
+As a result, the builtin cryptography management infrastructure and cryptographic algorithms are statically linked into the kernel binary:
+```
+cryptographic algorithms source files → compiled as .o objfiles →  linked into vmlinux → single kernel binary
+```
+**With Standalone Cryptography Module:**
+This feature automatically transforms the builtin cryptographic components into a standalone cryptography module, `fips140.ko`. To do so, it develops a new kernel build rule `crypto-objs-$(CONFIG_CRYPTO_*)` such that, once this build rule is applied to a cryptographic algorithm, such cryptographic algorithm will be automatically collected into the cryptography module if it is configured as built-in (i.e, `CONFIG_CRYPTO_*=y`), for example:
+```
+// in crypto/asymmetric_keys/Makefile
+- obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
++ crypto-objs-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
+```
+Such build change allows the modularization transformation to only affect selected cryptographic algorithms (i.e, where the `crypto-objs-$(CONFIG_CRYPTO_*`) is applied).
+
+Then, after the `fips140.ko` is generated, it will be embedded back into main kernel vmlinux as a replacement part. The purpose of this embedding, instead of traditionally putting the `fips140.ko` into filesystem, is a preparation to allow the module to be loaded early enough even before the filesystem is ready.
+
+The new build process is illustrated below.
+```
+cryptographic algorithms source files → compiled as .o objfiles → automatically collected and linked into fips140.ko → embedded fips140.ko into vmlinux as a replaceable binary
+```
+
+### 3.2 Runtime Changes
+
+**Traditional Boot Process:**
+The kernel initializes the cryptographic subsystem early during boot, executing each cryptographic initialization routine accordingly. These initialization routines may depend on other cryptographic components or other kernel subsystems, so their invocation follows a well-defined execution order to ensure they are initialized before their first use.
+```
+kernel starts → cryptography subsystem initialization → cryptography subsystem available → other components use cryptography
+```
+**With Standalone Cryptography Module:**
+At the start of kernel boot, compared to a regular kernel, the first major change introduced by this feature is that no cryptography services are initially available — since the entire cryptography subsystem has been decoupled from the main kernel.
+To ensure that the cryptography subsystem becomes available early enough (before the first kernel component that requires cryptography services), the standalone cryptography kernel module must be loaded at a very early stage, even before the filesystem becomes available.
+
+However, the regular module loading mechanism relies on placing kernel modules in the filesystem and loading them from there, which creates a chicken-and-egg problem — the cryptography module cannot be loaded until the filesystem is ready, yet some kernel components may require cryptography services even before that point.
+
+To address this, the second change introduced by this feature is that the cryptography kernel module is loaded directly from memory, leveraging the earlier compilation changes that embed the module binary into the main kernel image. Afterward, the feature includes a “plug-in” mechanism that connects the decoupled cryptography subsystem back to the main kernel, ensuring that kernel cryptography users can correctly locate and invoke the cryptography routine entry points.
+
+Finally, to ensure proper initialization, the feature guarantees that all cryptography algorithms and the cryptography management infra execute their initialization routines in the exact same order as they would if they were built-in.
+
+The process described above is illustrated below.
+```
+kernel starts → no cryptography available → load fips140.ko from memory → plug cryptography back to kernel → module initialization → cryptographic services available → other components use cryptography
+```
+
+## 4. Design Implementation Details
+
+While the earlier sections provide a holistic view of how this feature shapes the kernel, this section provides deeper design details on how these functionalities are realized. There are three key design components:
+1. A specialized compile rule that automatically compiles and collects all built-in cryptographic algorithm object files to generate the final module binary under arbitrary kernel configurations, and then embeds the generated binary into the main kernel image for early loading.
+2. A mechanism to convert interactions between the cryptography subsystem and the main kernel into a pluggable interface.
+3. A module loading and initialization process that ensures the cryptography subsystem is properly initialized as if it were built-in.
+
+### 4.1. Specialized Compilation System
+
+**Automatic Collection and Linking of Built-in Cryptographic Algorithm Objects:**
+The first step in generating the `fips140.ko` module is to compile and collect built-in cryptographic components (i.e., those specified by `CONFIG_CRYPTO_*=y`).
+Traditionally, the existing module build process requires all module components (e.g., source files) to reside in a single directory. However, this approach is not suitable for our case, where hundreds of cryptographic algorithm source files are scattered across multiple directories.
+
+A naïve approach would be to create a separate Makefile that duplicates the original build rules with adjusted paths.
+However, this method is not scalable due to the large number of cryptographic build rules, many of which are highly customized and can vary under different Kconfig settings, making such a separate Makefile even more complex.
+Moreover, this approach cannot ensure that built-in cryptographic algorithms are completely removed from the main kernel, which would result in redundant cryptographic code being included in both the kernel and the module.
+
+To tackle this challenge, we automated the object collection and linking process by introducing special build logic for the kernel cryptography subsystem.
+Specifically, to automatically collect cryptography object files while preserving their original compilation settings (such as flags, headers, and paths), we introduced a new compilation rule:
+```
+crypto-objs-y += *.o
+```
+This replaces the original `obj-y += *.o` rule in cryptography Makefiles later, for example:
+```
+// in crypto/asymmetric_keys/Makefile
+- obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
++ crypto-objs-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
+asymmetric_keys-y := \
+    asymmetric_type.o \
+    restrict.o \
+    signature.o
+```
+in the cryptography subsystem Makefiles, allowing most of the existing Makefile logic to be reused.
+As a result, when the standalone cryptography module feature is enabled, any cryptographic algorithm configured as built-in (for example, `crypto-objs-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o` where `CONFIG_ASYMMETRIC_KEY_TYPE=y`) will be automatically collected and linked into a single final object binary, `fips140.o`.
+During this process, a special compilation flag (`-DFIPS_MODULE=1`) is applied to instruct each object file to be compiled in a module-specific manner. This flag will later be used to generate the pluggable interface on both the main kernel side and the module side from the same source code.
+
+The implementation details are as follows: it follows a similar methodology used by the `obj-y` collection process for building `vmlinux.o`. The `crypto-objs-y` rule is placed in `scripts/Makefile.build`, which is executed by each directory Makefile to collect the corresponding crypto object files. Each directory then creates a `crypto-module.a` archive that contains all `crypto-objs-y += <object>.o` files under that directory. In the parent directories, these `crypto-module.a` archives are recursively included into the parent’s own `crypto-module.a`, and this process continues upward until the final `fips140.o` is generated.
+
+**A Separate Module Generation Pipeline for Building the Final Kernel Module from Linked Cryptographic Algorithm Object:**
+With the linked cryptographic algorithm object (i.e., `fips140.o`), the next step is to generate the final kernel module, `fips140.ko`.
+
+A direct approach would be to inject the `fips140.ko` module build into the existing modules generation pipeline (i.e., `make modules`) by providing our pre-generated `fips140.o`. However, we choose not to do this because it would create a circular make rule dependency (which is invalid in Makefiles and causes build failures), resulting in mutual dependencies between the modules and vmlinux targets (i.e., `modules:vmlinux` and `vmlinux:modules` at the same time).
+This happens for the following reasons:
+1. Since we will later embed `fips140.ko` into the final kernel image (as described in the next section), we must make vmlinux depend on `fips140.ko`. In other words: `vmlinux: fips140.ko`.
+2. When the kernel is built with `CONFIG_DEBUG_INFO_BTF_MODULES=y`, it requires: modules: vmlinux. This is because `CONFIG_DEBUG_INFO_BTF_MODULES=y` takes vmlinux as input to generate BTF info for the module, and inserts such info into the `.ko` module by default.
+3. If we choose to inject `fips140.ko` into make modules, this would create a make rule dependency: `fips140.ko: modules`. Combined with items 1 and 2, this eventually creates an invalid circular dependency between vmlinux and modules.
+
+Due to these reasons, the design choice is to use a separate make pipeline (defined as `fips140-ready` in the Makefile). This new pipeline reuses the same module generation scripts used by make modules but adds additional logic in `scripts/Makefile.{modfinal|modinst|modpost}` and `scripts/mod/modpost.c` to handle module symbol generation and verification correctly. 
+
+**A Seamless Process That Embeds the Generated Binary Into the Main Kernel Image for Early Loading:**
+As mentioned earlier, in order to load the standalone cryptography module early in the boot process—before the filesystem is ready—the module binary must be embedded into the final kernel image (i.e., vmlinux) so that it can be loaded directly from memory.
+We intend for this embedding process to be completely seamless and automatically triggered whenever vmlinux is built (i.e., during `make vmlinux`).
+
+To achieve this, the feature adds a Make dependency rule so that vmlinux depends on `fips140.ko`.
+It also modifies the vmlinux link rules (i.e., `arch/<arch>/kernel/vmlinux.lds.S`, `scripts/Makefile.vmlinux`, and `scripts/link-vmlinux.sh`) so that the generated module binary is finally combined with `vmlinux.o`.
+
+In addition, we allow multiple cryptography module binary versions (for example, a certified cryptography binary and a latest, up-to-date but uncertified one) to be embedded into the main kernel image to serve different user needs. This design allows regular (non-FIPS) users to benefit from the latest cryptographic updates, while FIPS-mode users continue to use the certified cryptography module.
+
+To support this, we introduce an optional configuration, `CONFIG_CRYPTO_FIPS140_DUAL_VERSION`. When enabled, this option allows two cryptography module versions to be embedded within a single kernel build and ensures that the appropriate module is selected and loaded at boot time based on the system’s FIPS mode status.
+
+### 4.2. Pluggable Interface Between the Built-in Cryptography Subsystem and the Main Kernel
+
+Although the module binary (`fips140.ko`) has been embedded into the final kernel image (`vmlinux`) as described in the previous section, it is not linked to the kernel in any way. This is because `fips140.ko` is embedded in a data-only manner, so the main kernel cannot directly call any functions or access any data defined in the module binary.
+
+Even worse, simply removing the built-in cryptographic algorithms without additional handling would cause the kernel to fail to compile, because traditionally, built-in cryptographic algorithms and the main kernel can interact only through functions and variables whose addresses they assume to know. As a result, even if they have been removed, kernel cryptography users still expect the symbol addresses of cryptographic routines and data to be available at compile time.
+
+To address this, we introduce a pluggable interface between built-in cryptographic functions and variables by placing **address placeholders**. During runtime, once the cryptography kernel module is loaded, these placeholders are updated to the correct addresses. In the rest of this section, we first introduce this pluggable interface mechanism, and then explain how to apply it to the built-in cryptographic algorithms.
+
+**The Pluggable Interface Mechanism:**
+There are two types of address holders used to achieve this pluggable interface:
+- Function addresses:  We use the “static call” mechanism. Static calls are a Linux mechanism that converts an “indirect call” into something with performance equivalent to a “direct call,” while avoiding the introduction of additional security concerns, such as control-flow–hijacking attack gadgets. We implement this function-address placeholder as the `DECLARE_STATIC_CALL()` and `DEFINE_CRYPTO_API_STUB()` wrappers.
+- Variable addresses (the remaining smaller portion): For these, we use a pointer of the corresponding data type. We implement this address placeholder as the `DECLARE_CRYPTO_VAR()` and `DEFINE_CRYPTO_API_STUB()` wrappers:
+
+These wrappers are applied to each symbol-exported (i.e., `EXPORT_SYMBOL()`) cryptographic function and variable (details on how to apply them are described later). Once applied, the wrappers are compiled differently for the main kernel and for the built-in cryptographic algorithm source code—acting as the “outlet” and the “plug,” respectively—using different compilation flags (`-DFIPS_MODULE`) introduced by our customized build rules described earlier.
+
+As a result, the kernel can successfully compile even when the built-in cryptographic algorithms are removed, thanks to these address placeholders. At boot time, the placeholders initially hold NULL, but since no cryptography users exist at that stage, the kernel can still start booting correctly. After the cryptography module is loaded, the placeholders are dynamically updated to the correct addresses later (by `do_crypto_api()` and `do_crypto_var()`, described in later section).
+
+In addition to these address placeholders, there is another important interaction point between the cryptography subsystem and the main kernel—the cryptographic initialization routines. Therefore, we also add a mechanism to collect all cryptographic initialization functions (e.g., those defined using `module_init()`) into a dedicated ELF section. This serves as preparation for the later module and cryptography-subsystem initialization steps described in subsequent sections.
+
+**Applying the Pluggable Interface Mechanism to Cryptographic Algorithms:**
+
+To apply these pluggable interface wrappers to a cryptographic algorithm and make them take effect, we follow the steps below (using `crypto/asymmetric_keys/asymmetric_type.c` as an example):
+1. **Apply `crypto-objs-y` compile rule to the cryptographic algorithm:**
+```
+// in crypto/asymmetric_keys/Makefile
+- obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
++ crypto-objs-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
+asymmetric_keys-y := \
+    asymmetric_type.o \
+    restrict.o \
+    signature.o
+```
+2. **Locate the communication point between the cryptographic algorithm and the main kernel:**
+
+The cryptography subsystem is designed such that most interactions between the main kernel and cryptographic algorithms occur through exported symbols using `EXPORT_SYMBOL()` wrappers.
+This kernel design exists because most cryptographic algorithm implementations must support both built-in and modular modes. 
+
+Consequently, the cryptographic functions and variables exported by `EXPORT_SYMBOL()` are a well-defined and identifiable interface between the cryptography subsystem and the main kernel: 
+```
+// in crypto/asymmetric_keys/asymmetric_type.c 
+//Exported cryptographic function:
+bool asymmetric_key_id_same(const struct asymmetric_key_id *kid1,
+                const struct asymmetric_key_id *kid2) {...}
+EXPORT_SYMBOL_GPL(asymmetric_key_id_same); 
+//Exported cryptographic variable:
+struct key_type key_type_asymmetric = {...};
+EXPORT_SYMBOL_GPL(key_type_asymmetric); 
+```
+3. **Replace their declarations in the header file with the address-placeholder declaration wrappers:**
+```
+// in include/keys/asymmetric-type.h
+// for exported cryptographic function:
+- bool asymmetric_key_id_same const struct asymmetric_key_id *kid1, const struct asymmetric_key_id *kid2);
++ DECLARE_CRYPTO_API(CONFIG_ASYMMETRIC_KEY_TYPE, asymmetric_key_id_same, bool,
+    (const struct asymmetric_key_id *kid1, const struct asymmetric_key_id *kid2),
+    (kid1, kid2)); 
+// for exported cryptographic variables:
+- struct key_type key_type_asymmetric;
++ DECLARE_CRYPTO_VAR(CONFIG_ASYMMETRIC_KEY_TYPE, key_type_asymmetric, struct key_type, );
++ #if defined(CONFIG_CRYPTO_FIPS140_EXTMOD) && !defined(FIPS_MODULE) && IS_BUILTIN(CONFIG_ASYMMETRIC_KEY_TYPE)
++ #define key_type_asymmetric (*((struct key_type*)CRYPTO_VAR_NAME(key_type_asymmetric)))
++ #endif 
+```
+By replacing the original declarations with the address-placeholder declaration wrappers, we can automatically force all cryptography users to go through the placeholders, because those users already include the same header file.
+The wrapper also takes the cryptographic algorithm Kconfig symbol as a parameter, so that when a cryptographic algorithm is built as a module (for example, `CONFIG_ASYMMETRIC_KEY_TYPE=m`), the original function declarations remain unchanged and are not affected.
+
+4. **Add the address-placeholder definition wrappers into a dedicated file `fips140-api.c`:**
+
+This file will be compiled separately and acts as both the “outlet” and the “plug” for the main kernel and the cryptography module, respectively:
+```
+// in crypto/fips140/fips140-api.c
++ #if IS_BUILTIN(CONFIG_ASYMMETRIC_KEY_TYPE)
++ #include <keys/asymmetric-type.h>
+// for exported cryptographic function:
++ DEFINE_CRYPTO_API_STUB(asymmetric_key_id_same);
+// for exported cryptographic variables:
++ #undef key_type_asymmetric
++ DEFINE_CRYPTO_VAR_STUB(key_type_asymmetric);
++ #endif
+```
+
+5. **Lastly, collect the cryptographic initialization routines for later module and cryptography-subsystem initialization by wrapping the original cryptographic initialization functions:**
+```
+// in crypto/asymmetric_keys/asymmetric_type.c 
+- module_init(asymmetric_key_init);
+- module_exit(asymmetric_key_cleanup); 
++ crypto_module_init(asymmetric_key_init);
++ crypto_module_exit(asymmetric_key_cleanup); 
+```
+We apply the above steps to both architecture-independent and architecture-specific cryptographic algorithms.
+
+### 4.3. Initialization Synchronization
+
+To ensure the embedded `fips140.ko` module binary provides the same cryptography functionality as the regular kernel, the kernel needs:
+1. A module loader to load the module binary directly from memory,
+2. A mechanism to plug the module back into the kernel by updating the address placeholders, and
+3. Correct cryptography subsystem initialization, as if the cryptographic algorithms were still built-in.
+
+**Directly Load Module Binary from Memory:**
+Regular modules are loaded from the filesystem and undergo signature verification on the module binary, which relies on cryptographic operations. However, since we have already fully decoupled the cryptography subsystem, we must skip this step for this `fips140.ko` module.
+To achieve this, we add a new loader function `load_crypto_module_mem()` that can load the module binary directly from memory at the designed address without checking the signature. Since the module binary is embedded into main kernel in an ELF section, as specified in the linker script:
+```
+// in arch/<arch>/kernel/vmlinux.lds.S
+    .fips140_embedded : AT(ADDR(.fips140_embedded) - LOAD_OFFSET) {
+        . = ALIGN(8);
+        _binary_fips140_ko_start = .;
+        KEEP(*(.fips140_module_data))
+        _binary_fips140_ko_end = .;
+    }
+```
+Therefore, the runtime memory address of the module can be accessed directly by the module loader to invoke the new loader function `load_crypto_module_mem()`.
+
+**Plug Back the Module by Updating Address Placeholder Values:**
+To update the address placeholders in the main kernel to the correct addresses matching the loaded module, after compilation the placeholders are placed into dedicated ELF sections `_crypto_api_keys` and `_crypto_var_keys`.
+This can be seen from the definition of the placeholder-declaration wrappers:
+```
+#define DEFINE_CRYPTO_API_STUB(name) \
+    static struct crypto_api_key __##name##_key \
+        __used \
+        __section("__crypto_api_keys") \ // Place in a dedicated ELF Section
+        __aligned(__alignof__(struct crypto_api_key)) = \
+    { \
+        .key = &STATIC_CALL_KEY(crypto_##name##_key), \
+        .tramp = STATIC_CALL_TRAMP_ADDR(crypto_##name##_key), \
+        .func = &name, \
+    };
+
+#define DEFINE_CRYPTO_VAR_STUB(name) \
+    static struct crypto_var_key __crypto_##name##_var_key \
+        __used \
+        __section("__crypto_var_keys") \ // Place in a dedicated ELF Section
+        __aligned(__alignof__(struct crypto_var_key)) = \
+    { \
+        .ptr = &CRYPTO_VAR_NAME(name), \
+        .var = (void*)&name, \
+    };
+```
+The purpose of doing this is to allow the main kernel to quickly locate the placeholders and update them to the correct addresses. The update functions are defined as `do_crypto_var()` and `do_crypto_api()`, which are executed at module load.
+
+As a result, all cryptography users in the main kernel can now call the cryptographic functions as if they were built-in.
+
+**Initialize Cryptography Subsystem as if it Were Built-in:**
+Cryptographic components must be properly initialized before use, and this initialization is typically achieved through dedicated initialization functions (e.g., `module_init(crypto_init_func)` or `late_initcall(crypto_init_func)`). These functions often have strict execution order requirements and must run during the appropriate boot phase.
+
+Therefore, for our standalone cryptography module feature, we must ensure that these decoupled “built-in” cryptographic algorithms are properly initialized and that their initialization order is preserved as before because failure to follow the correct order can result in kernel panic.
+
+To address this, we introduce a synchronization mechanism between the main kernel and the module to ensure all cryptographic algorithms are executed in the correct kernel boot phase. In more details, we spawn the module initialization process `fips_loader_init()` as an async thread `fips140_sync_thread()`, in which we call `run_initcalls()` to execute the initialization calls of each cryptographic algorithm.
+Then, we introduce synchronization helpers such as `wait_until_fips140_level_sync(int level)` to ensure the initialization order of all cryptographic algorithms is synchronized with the main kernel.
+
+## 5. Customization and Extension of Cryptography Module
+
+This section describes how developers can customize which cryptographic algorithms are included in the standalone cryptography module, as well as extend this feature to other cryptographic algorithms or hardware architectures.
+
+### 5.1. Cryptography Selection Mechanism
+
+The feature automatically includes cryptographic algorithms that meet specific criteria:
+1. **Built-in Configuration**: Only cryptographic algorithms configured as `CONFIG_CRYPTO_*=y` are candidates for inclusion
+2. **Explicit Inclusion**: Cryptographic algorithms must be explicitly converted using the `crypto-objs-$(CONFIG__CRYPTO_*`) build rule
+
+### 5.2. Extend Support to New Cryptographic Algorithms
+
+To extend support to a new cryptographic algorithm in the standalone module, follow these steps:
+
+**Step 1: Update the Makefile**
+```
+# in crypto/[algorithm]/Makefile
+- obj-$(CONFIG_CRYPTO_ALGORITHM) += algorithm.o
++ crypto-objs-$(CONFIG_CRYPTO_ALGORITHM) += algorithm.o
+```
+For Architecture-Specific Cryptographic Algorithms:
+- Apply the `crypto-objs-` rule in the appropriate `arch/*/crypto/Makefile`
+
+**Step 2: Add Pluggable Interface Support**
+If the cryptographic algorithm exports symbols via `EXPORT_SYMBOL()`, add the pluggable interface wrappers:
+```
+# Example: in include/crypto/algorithm.h
+- extern int crypto_algorithm_transform(struct crypto_tfm *tfm, const u8 *src, 
+                                       u8 *dst, unsigned int len, u32 flags);
++ DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGORITHM, crypto_algorithm_transform, int,
+    (struct crypto_tfm *tfm, const u8 *src, u8 *dst, unsigned int len, u32 flags),
+    (tfm, src, dst, len, flags));
+```
+Then, add the corresponding stubs in `crypto/fips140/fips140-api.c`:
+```
+#if IS_BUILTIN(CONFIG_CRYPTO_ALGORITHM)
+#include <crypto/algorithm.h>
+DEFINE_CRYPTO_API_STUB(crypto_algorithm_transform);
+#endif
+```
+For Architecture-Specific Cryptographic Algorithms:
+- Include architecture-specific stubs in `arch/*/crypto/fips140/fips140-api.c`:
+```
+# Example: in arch/arm64/crypto/fips140/fips140-api.c
+#if IS_BUILTIN(CONFIG_CRYPTO_AES_ARM64_CE)
+#include <arch/arm64/crypto/aes-ce-setkey.h>
+DEFINE_CRYPTO_API_STUB(ce_aes_setkey);
+DEFINE_CRYPTO_API_STUB(ce_aes_expandkey);
+#endif
+```
+**Step 3: Update Initialization**
+Replace module initialization calls:
+```
+# in crypto/algorithm/algorithm.c
+- module_init(algorithm_init);
+- module_exit(algorithm_exit);
++ crypto_module_init(algorithm_init);
++ crypto_module_exit(algorithm_exit);
+```
+
+### 5.3. Architecture-Specific Extensions
+
+**Extending to New Architectures:**
+Currently supported architectures are x86_64 and ARM64. To extend this feature to additional architectures:
+1. **Update Linker Scripts**: Add ELF sections in `arch/[new-arch]/kernel/vmlinux.lds.S`:
+```
+.fips140_embedded : AT(ADDR(.fips140_embedded) - LOAD_OFFSET) {
+    . = ALIGN(8);
+    _binary_fips140_ko_start = .;
+    KEEP(*(.fips140_module_data))
+    _binary_fips140_ko_end = .;
+}
+```
+2. **Create Architecture-Specific Files**: Set up `arch/[new-arch]/crypto/fips140/` directory with Makefile and `fips140-api.c` following the pattern used in x86_64 and ARM64.
+
+---
+Written by Jay Wang <wanjay@amazon.com>, Amazon Linux
\ No newline at end of file
-- 
2.47.3


^ permalink raw reply related

* [PATCH 16/17] arm64: crypto: to convert exported crypto symbols into pluggable interface for arm64 cryptos
From: Jay Wang @ 2026-02-12  2:42 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
	Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
	linux-modules
In-Reply-To: <20260212024228.6267-1-wanjay@amazon.com>

Prepare to convert exported crypto symbols in arm64 cryptos
into pluggable interface. This patch introduces architecture specific
crypto API definition file `fips140-api.c`.

Signed-off-by: Jay Wang <wanjay@amazon.com>
---
 arch/arm64/crypto/Makefile              |  3 +++
 arch/arm64/crypto/fips140/Makefile      | 14 ++++++++++++++
 arch/arm64/crypto/fips140/fips140-api.c |  0
 3 files changed, 17 insertions(+)
 create mode 100644 arch/arm64/crypto/fips140/Makefile
 create mode 100644 arch/arm64/crypto/fips140/fips140-api.c

diff --git a/arch/arm64/crypto/Makefile b/arch/arm64/crypto/Makefile
index 3574e917bc37..9f7106424d66 100644
--- a/arch/arm64/crypto/Makefile
+++ b/arch/arm64/crypto/Makefile
@@ -40,3 +40,6 @@ aes-neon-blk-y := aes-glue-neon.o aes-neon.o
 
 obj-$(CONFIG_CRYPTO_AES_ARM64_BS) += aes-neon-bs.o
 aes-neon-bs-y := aes-neonbs-core.o aes-neonbs-glue.o
+
+# FIPS 140 kernel module
+obj-$(CONFIG_CRYPTO_FIPS140_EXTMOD) += fips140/
\ No newline at end of file
diff --git a/arch/arm64/crypto/fips140/Makefile b/arch/arm64/crypto/fips140/Makefile
new file mode 100644
index 000000000000..0a150ab16027
--- /dev/null
+++ b/arch/arm64/crypto/fips140/Makefile
@@ -0,0 +1,14 @@
+
+crypto-objs-y += fips140-api-fips.o
+
+obj-y += fips140-api-main.o
+
+# Explicit rules to compile same source to different objects
+$(obj)/fips140-api-main.o: $(src)/fips140-api.c FORCE
+	$(call if_changed_rule,cc_o_c)
+
+$(obj)/fips140-api-fips.o: $(src)/fips140-api.c FORCE
+	$(call if_changed_rule,cc_o_c)
+
+CFLAGS_fips140-api-main.o += -I$(srctree)
+CFLAGS_fips140-api-fips.o += -I$(srctree)
\ No newline at end of file
diff --git a/arch/arm64/crypto/fips140/fips140-api.c b/arch/arm64/crypto/fips140/fips140-api.c
new file mode 100644
index 000000000000..e69de29bb2d1
-- 
2.47.3


^ permalink raw reply related

* [PATCH 15/17] x86: crypto: to convert exported crypto symbols into pluggable interface for x86 cryptos
From: Jay Wang @ 2026-02-12  2:42 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
	Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
	linux-modules
In-Reply-To: <20260212024228.6267-1-wanjay@amazon.com>

Prepare to convert exported crypto symbols in x86 cryptos
into pluggable interface. This patch introduces architecture specific
crypto API definition file `fips140-api.c`.

Signed-off-by: Jay Wang <wanjay@amazon.com>
---
 arch/x86/crypto/Makefile              |  3 +++
 arch/x86/crypto/fips140/Makefile      | 14 ++++++++++++++
 arch/x86/crypto/fips140/fips140-api.c |  0
 3 files changed, 17 insertions(+)
 create mode 100644 arch/x86/crypto/fips140/Makefile
 create mode 100644 arch/x86/crypto/fips140/fips140-api.c

diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile
index b21ad0978c52..ab248a1beb00 100644
--- a/arch/x86/crypto/Makefile
+++ b/arch/x86/crypto/Makefile
@@ -70,3 +70,6 @@ aria-aesni-avx2-x86_64-y := aria-aesni-avx2-asm_64.o aria_aesni_avx2_glue.o
 
 obj-$(CONFIG_CRYPTO_ARIA_GFNI_AVX512_X86_64) += aria-gfni-avx512-x86_64.o
 aria-gfni-avx512-x86_64-y := aria-gfni-avx512-asm_64.o aria_gfni_avx512_glue.o
+
+# FIPS 140 kernel module
+obj-$(CONFIG_CRYPTO_FIPS140_EXTMOD) += fips140/
diff --git a/arch/x86/crypto/fips140/Makefile b/arch/x86/crypto/fips140/Makefile
new file mode 100644
index 000000000000..0a150ab16027
--- /dev/null
+++ b/arch/x86/crypto/fips140/Makefile
@@ -0,0 +1,14 @@
+
+crypto-objs-y += fips140-api-fips.o
+
+obj-y += fips140-api-main.o
+
+# Explicit rules to compile same source to different objects
+$(obj)/fips140-api-main.o: $(src)/fips140-api.c FORCE
+	$(call if_changed_rule,cc_o_c)
+
+$(obj)/fips140-api-fips.o: $(src)/fips140-api.c FORCE
+	$(call if_changed_rule,cc_o_c)
+
+CFLAGS_fips140-api-main.o += -I$(srctree)
+CFLAGS_fips140-api-fips.o += -I$(srctree)
\ No newline at end of file
diff --git a/arch/x86/crypto/fips140/fips140-api.c b/arch/x86/crypto/fips140/fips140-api.c
new file mode 100644
index 000000000000..e69de29bb2d1
-- 
2.47.3


^ permalink raw reply related

* [PATCH 14/17] crypto: fips140: add module integrity self-check
From: Jay Wang @ 2026-02-12  2:42 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
	Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
	linux-modules
In-Reply-To: <20260212024228.6267-1-wanjay@amazon.com>

Add verify_integrity() function to perform HMAC-SHA256 self verification
of this standalone crypto module against pre-computed hash. This integrity
self-check is required by FIPS 140-3.

This patch is picked from Vegard Nossum <vegard.nossum@oracle.com> with
minor modifications.

Co-developed-by: Vegard Nossum <vegard.nossum@oracle.com>
Signed-off-by: Jay Wang <wanjay@amazon.com>
---
 crypto/fips140/fips140-module.c | 52 +++++++++++++++++++++++++++++++++
 crypto/fips140/fips140-module.h |  4 +++
 2 files changed, 56 insertions(+)

diff --git a/crypto/fips140/fips140-module.c b/crypto/fips140/fips140-module.c
index e0e669ba1b5e..3bc8865567cb 100644
--- a/crypto/fips140/fips140-module.c
+++ b/crypto/fips140/fips140-module.c
@@ -16,6 +16,54 @@
 
 #define CRYPTO_INTERNAL "CRYPTO_INTERNAL"
 
+static const u8 fips140_integ_hmac_key[] = CONFIG_CRYPTO_FIPS140_HMAC_KEY;
+
+static int verify_integrity(void)
+{
+	extern const u8 *_binary_crypto_ko_start;
+	extern const u8 *_binary_crypto_ko_end;
+	extern const u8 *_binary_crypto_hmac_start;
+	
+	struct crypto_shash *tfm;
+	SHASH_DESC_ON_STACK(desc, tfm);
+	u8 digest[SHA256_DIGEST_SIZE];
+	int err;
+
+	tfm = crypto_alloc_shash("hmac(sha256)", 0, 0);
+	if (IS_ERR(tfm))
+		panic("FIPS 140: failed to allocate hmac tfm (%ld)\n", PTR_ERR(tfm));
+
+	desc->tfm = tfm;
+
+	err = crypto_shash_setkey(tfm, fips140_integ_hmac_key, sizeof(fips140_integ_hmac_key) - 1);
+	if (err)
+		panic("FIPS 140: crypto_shash_setkey() failed: %d\n", err);
+
+	err = crypto_shash_init(desc);
+	if (err)
+		panic("FIPS 140: crypto_shash_init() failed: %d\n", err);
+
+	err = crypto_shash_update(desc, _binary_crypto_ko_start, _binary_crypto_ko_end - _binary_crypto_ko_start);
+	if (err)
+		panic("FIPS 140: crypto_shash_update() failed: %d\n", err);
+
+	err = crypto_shash_final(desc, digest);
+	if (err)
+		panic("FIPS 140: crypto_shash_final() failed: %d\n", err);
+
+	shash_desc_zero(desc);
+
+	if (memcmp(digest, _binary_crypto_hmac_start, sizeof(digest)))
+		panic("FIPS 140: failed integrity check\n");
+
+	pr_info("FIPS 140: integrity verification passed\n");
+
+	crypto_free_shash(tfm);
+	memzero_explicit(digest, sizeof(digest));
+
+	return 0;
+}
+
 static int __init run_initcalls(void)
 {
 	typedef int (*initcall_t)(void);
@@ -68,6 +116,10 @@ static int __init fips140_init(void)
     pr_info("loading " FIPS140_MODULE_NAME "\n");
 
 	run_initcalls();
+
+	if (fips_enabled){
+		verify_integrity(); /* Panics if integrity check fails */
+	}
 	fips140_mark_module_level_complete(2);
     return 0;
 }
diff --git a/crypto/fips140/fips140-module.h b/crypto/fips140/fips140-module.h
index e95dac8eeda9..b8968d54800e 100644
--- a/crypto/fips140/fips140-module.h
+++ b/crypto/fips140/fips140-module.h
@@ -9,9 +9,13 @@
 #include <linux/module.h>
 #include <linux/crypto.h>
 #include <crypto/algapi.h>
+#include <crypto/hash.h>
+#include <crypto/sha2.h>
 #include <linux/init.h>
+#include <linux/string.h>
 #include <linux/atomic.h>
 #include <linux/wait.h>
+#include <linux/fips.h>
 
 /* FIPS140 synchronization between kernel and module */
 extern atomic_t fips140_kernel_level_complete;
-- 
2.47.3


^ permalink raw reply related

* [PATCH 13/17] crypto/algapi.c: skip crypto_check_module_sig() for the standalone crypto module
From: Jay Wang @ 2026-02-12  2:42 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
	Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
	linux-modules
In-Reply-To: <20260212024228.6267-1-wanjay@amazon.com>

From: Vegard Nossum <vegard.nossum@oracle.com>

The signature check in regular module verification process
`crypto_check_module_sig()` is skipped for this standalone crypto module
because its signature has already been checked during load (as described
in later patch).

Signed-off-by: Vegard Nossum <vegard.nossum@oracle.com>
[Revise commit message]
Signed-off-by: Jay Wang <wanjay@amazon.com>
---
 crypto/algapi.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/crypto/algapi.c b/crypto/algapi.c
index 37de377719ae..663698e0cd65 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -24,7 +24,19 @@ static LIST_HEAD(crypto_template_list);
 
 static inline void crypto_check_module_sig(struct module *mod)
 {
-	if (fips_enabled && mod && !module_sig_ok(mod))
+#ifdef FIPS_MODULE
+	/*
+	 * The FIPS module should ignore its own signature check, as it was
+	 * already been verified elsewhere during loading.
+	 */
+	if (mod == THIS_MODULE)
+		return;
+#else
+	if (!fips_enabled)
+		return;
+#endif
+
+	if (mod && !module_sig_ok(mod))
 		panic("Module %s signature verification failed in FIPS mode\n",
 		      module_name(mod));
 }
-- 
2.47.3


^ permalink raw reply related

* [PATCH 12/17] Execute crypto initcalls during module initialization
From: Jay Wang @ 2026-02-12  2:42 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
	Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
	linux-modules
In-Reply-To: <20260212024228.6267-1-wanjay@amazon.com>

After moving builtin cryptos into the standalone crypto module, to ensure
all such cryptos are properly initialized as they were builtin, the
initcalls of the cryptos should be executed at proper booting time.

To do so, this patch adds run_initcalls() function to execute the
initialization calls of the collected cryptos right after the module is
loaded. The function iterates through initcalls in the __fips_initcalls
section (which stores all function addresses of the collected crypto
initcalls) and executes them.

A key consideration is to ensure the crypto initcalls are executed in
proper order, for instance, some crypto initcalls are ought to execute
at `late_initcall` boot time level while some should be executed at
`module_init` boot time level. To do so, this patch enables coordination
between kernel and the crypto module initialization to preserve proper
execution order by hijacking the kernel initialization function
`do_initcall_level` with added synchronization helpers.

Signed-off-by: Jay Wang <wanjay@amazon.com>
---
 crypto/fips140/fips140-loader.c | 92 +++++++++++++++++++++++++++++++++
 crypto/fips140/fips140-module.c | 50 ++++++++++++++++++
 crypto/fips140/fips140-module.h | 12 +++++
 include/linux/init.h            | 10 ++++
 init/main.c                     |  4 ++
 5 files changed, 168 insertions(+)

diff --git a/crypto/fips140/fips140-loader.c b/crypto/fips140/fips140-loader.c
index 826075928723..d9a477421063 100644
--- a/crypto/fips140/fips140-loader.c
+++ b/crypto/fips140/fips140-loader.c
@@ -107,3 +107,95 @@ static int __init fips_loader_init(void)
 	vfree(vmalloc_mem); // Free after successful module loading
 	return ret;
 }
+
+/* FIPS140 synchronization between kernel and module
+ *
+ * Synchronization levels map kernel initcall levels to FIPS module levels:
+ * - Level 0: subsys_initcall (kernel init level 4) - Basic subsystem initialization
+ * - Level 1: device_initcall (kernel init level 6) - Device driver initialization  
+ * - Level 2: late_initcall (kernel init level 7) - Late system initialization
+ *
+ * The kernel marks each level complete and waits for the FIPS module to
+ * complete the corresponding level before proceeding to ensure proper
+ * initialization ordering between kernel crypto and FIPS module.
+ */
+atomic_t fips140_kernel_level_complete = ATOMIC_INIT(0);
+atomic_t fips140_module_level_complete = ATOMIC_INIT(0);
+
+/* Wait queues for efficient synchronization */
+DECLARE_WAIT_QUEUE_HEAD(fips140_kernel_wq);
+DECLARE_WAIT_QUEUE_HEAD(fips140_module_wq);
+
+void fips140_mark_kernel_level_complete(int level)
+{
+	atomic_or(1 << level, &fips140_kernel_level_complete);
+	wake_up(&fips140_kernel_wq);
+}
+
+bool fips140_is_kernel_level_complete(int level)
+{
+	return atomic_read(&fips140_kernel_level_complete) & (1 << level);
+}
+
+bool fips140_is_module_level_complete(int level)
+{
+	return atomic_read(&fips140_module_level_complete) & (1 << level);
+}
+
+void fips140_mark_module_level_complete(int level)
+{
+	atomic_or(1 << level, &fips140_module_level_complete);
+	wake_up(&fips140_module_wq);
+}
+
+static int __init fips140_sync_thread(void *data)
+{
+	pr_info("FIPS 140: starting sync thread\n");
+	
+	/* Call FIPS loader explicitly */
+	int ret = fips_loader_init();
+	if (ret)
+		panic("FIPS 140: loader initialization failed: %d\n", ret);
+	
+	pr_info("FIPS 140: sync thread finished\n");
+	return 0;
+}
+
+void __init start_fips140_loader(void)
+{
+	struct task_struct *task;
+	
+	task = kthread_run(fips140_sync_thread, NULL, "fips140_sync");
+	if (IS_ERR(task)) {
+		panic("FIPS 140: failed to create sync thread\n");
+	}
+}
+
+void __init wait_until_fips140_level_sync(int level)
+{
+	/* Map kernel initcall levels to FIPS module levels */
+	int fips_level = -1;
+	if (level == 3) /* Start FIPS loader thread at arch_initcall_sync level */
+		start_fips140_loader(); 
+	if (level == 4) /* subsys_initcall */
+		fips_level = 0;
+	else if (level == 6) /* device_initcall */
+		fips_level = 1;
+	else if (level == 7) /* late_initcall */
+		fips_level = 2;
+
+	if (fips_level >= 0) {
+		/* Mark kernel level complete and wait for module level completion */
+		fips140_mark_kernel_level_complete(fips_level);
+		wait_event(fips140_module_wq, fips140_is_module_level_complete(fips_level));
+	}
+}
+
+EXPORT_SYMBOL(fips140_kernel_level_complete);
+EXPORT_SYMBOL(fips140_module_level_complete);
+EXPORT_SYMBOL(fips140_kernel_wq);
+EXPORT_SYMBOL(fips140_module_wq);
+EXPORT_SYMBOL(fips140_mark_kernel_level_complete);
+EXPORT_SYMBOL(fips140_is_kernel_level_complete);
+EXPORT_SYMBOL(fips140_is_module_level_complete);
+EXPORT_SYMBOL(fips140_mark_module_level_complete);
\ No newline at end of file
diff --git a/crypto/fips140/fips140-module.c b/crypto/fips140/fips140-module.c
index a942de8780ef..e0e669ba1b5e 100644
--- a/crypto/fips140/fips140-module.c
+++ b/crypto/fips140/fips140-module.c
@@ -16,9 +16,59 @@
 
 #define CRYPTO_INTERNAL "CRYPTO_INTERNAL"
 
+static int __init run_initcalls(void)
+{
+	typedef int (*initcall_t)(void);
+	
+	extern initcall_t __fips140_initcall0_start[], __fips140_initcall0_end[];
+	extern initcall_t __fips140_initcall1_start[], __fips140_initcall1_end[];
+	extern initcall_t __fips140_initcall2_start[], __fips140_initcall2_end[];
+
+	initcall_t *starts[] = {
+		__fips140_initcall0_start,
+		__fips140_initcall1_start,
+		__fips140_initcall2_start,
+	};
+	
+	initcall_t *ends[] = {
+		__fips140_initcall0_end,
+		__fips140_initcall1_end,
+		__fips140_initcall2_end,
+	};
+
+	pr_info("FIPS 140: run_initcalls starting\n");
+
+	for (int level = 0; level < ARRAY_SIZE(starts); level++) {
+		
+		/* Run FIPS initcalls for this level */
+		for (initcall_t *initcall = starts[level]; initcall < ends[level]; ++initcall) {
+			int ret;
+			initcall_t fn = *initcall;
+			
+			ret = fn();
+			if (!ret || ret == -ENODEV)
+				continue;
+
+			pr_err("FIPS 140: initcall %pS failed: %d\n", fn, ret);
+		}
+	
+		if (level < 2)
+			fips140_mark_module_level_complete(level);
+		/* Wait for kernel to complete this level */
+		wait_event(fips140_kernel_wq, fips140_is_kernel_level_complete(level));
+	}
+
+	pr_info("FIPS 140: run_initcalls finished\n");
+	return 0;
+}
+
 /* Initialize the FIPS 140 module */
 static int __init fips140_init(void)
 {
+    pr_info("loading " FIPS140_MODULE_NAME "\n");
+
+	run_initcalls();
+	fips140_mark_module_level_complete(2);
     return 0;
 }
 
diff --git a/crypto/fips140/fips140-module.h b/crypto/fips140/fips140-module.h
index ed2b6e17969f..e95dac8eeda9 100644
--- a/crypto/fips140/fips140-module.h
+++ b/crypto/fips140/fips140-module.h
@@ -10,5 +10,17 @@
 #include <linux/crypto.h>
 #include <crypto/algapi.h>
 #include <linux/init.h>
+#include <linux/atomic.h>
+#include <linux/wait.h>
+
+/* FIPS140 synchronization between kernel and module */
+extern atomic_t fips140_kernel_level_complete;
+extern atomic_t fips140_module_level_complete;
+extern wait_queue_head_t fips140_kernel_wq;
+
+void fips140_mark_kernel_level_complete(int level);
+bool fips140_is_kernel_level_complete(int level);
+bool fips140_is_module_level_complete(int level);
+void fips140_mark_module_level_complete(int level);
 
 #endif /* _CRYPTO_FIPS140_MODULE_H */
diff --git a/include/linux/init.h b/include/linux/init.h
index 40331923b9f4..eefbdfac1d41 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -392,4 +392,14 @@ void __init parse_early_options(char *cmdline);
 #define __exit_p(x) NULL
 #endif
 
+#if defined(CONFIG_CRYPTO_FIPS140_EXTMOD) && !defined(__ASSEMBLY__)
+/* FIPS140 synchronization between kernel and module */
+void fips140_mark_kernel_level_complete(int level);
+bool fips140_is_kernel_level_complete(int level);
+bool fips140_is_module_level_complete(int level);
+void fips140_mark_module_level_complete(int level);
+void start_fips140_loader(void);
+void wait_until_fips140_level_sync(int level);
+#endif /* CONFIG_CRYPTO_FIPS140_EXTMOD && !__ASSEMBLY__ */
+
 #endif /* _LINUX_INIT_H */
diff --git a/init/main.c b/init/main.c
index b84818ad9685..0324226fe7b9 100644
--- a/init/main.c
+++ b/init/main.c
@@ -1438,6 +1438,10 @@ static void __init do_initcall_level(int level, char *command_line)
 	do_trace_initcall_level(initcall_level_names[level]);
 	for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++)
 		do_one_initcall(initcall_from_entry(fn));
+
+#ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+	wait_until_fips140_level_sync(level);
+#endif
 }
 
 static void __init do_initcalls(void)
-- 
2.47.3


^ permalink raw reply related

* [PATCH 11/17] Allow selective crypto module loading at boot based on FIPS mode
From: Jay Wang @ 2026-02-12  2:42 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
	Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
	linux-modules
In-Reply-To: <20260212024228.6267-1-wanjay@amazon.com>

Introduce CONFIG_CRYPTO_FIPS140_DUAL_VERSION to enable dual crypto module
versions within a single kernel build, allowing boot-time selection based on
FIPS mode status.

This configuration allows FIPS mode to use pre-compiled certified crypto
modules from external source, while regular mode uses freshly built kernel
crypto implementation for optimal performance and latest security features.

The implementation embeds both certified and non-certified fips140.ko
modules in vmlinux and adds new linker sections (.nonfips140_embedded,
.nonfips140_btf) for non-FIPS crypto module storage. It modifies
fips140-loader.c to select appropriate module at boot time based on
fips_enabled flag, updates build system to generate and embed both module
versions, and includes BTF support for both module variants when
CONFIG_DEBUG_INFO_BTF_MODULES is enabled.

For modular crypto algorithms (e.g., aes.ko), they are not automatically
duplicated. They should either be built-in to fips140.ko for automatic
duplication, or require userspace utilities like modprobe to handle
proper isolation between FIPS and non-FIPS modular crypto implementations.

Signed-off-by: Jay Wang <wanjay@amazon.com>
---
 Makefile                        | 13 +++++++++++++
 arch/arm64/kernel/vmlinux.lds.S | 16 ++++++++++++++++
 arch/x86/kernel/vmlinux.lds.S   | 16 ++++++++++++++++
 crypto/fips140/Kconfig          | 24 ++++++++++++++++++++++++
 crypto/fips140/Makefile         |  5 ++++-
 crypto/fips140/fips140-loader.c | 28 +++++++++++++++++++++++++++-
 scripts/Makefile.vmlinux        | 29 +++++++++++++++++++++++++++--
 scripts/link-vmlinux.sh         |  6 ++++++
 8 files changed, 133 insertions(+), 4 deletions(-)

diff --git a/Makefile b/Makefile
index 7530009d8081..b3a9f7a17ddf 100644
--- a/Makefile
+++ b/Makefile
@@ -1293,6 +1293,9 @@ vmlinux: private _LDFLAGS_vmlinux := $(LDFLAGS_vmlinux)
 vmlinux: export LDFLAGS_vmlinux = $(_LDFLAGS_vmlinux)
 ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
 vmlinux: crypto/fips140/fips140-embedded.o crypto/fips140/fips140-digest.o
+ifdef CONFIG_CRYPTO_FIPS140_DUAL_VERSION
+vmlinux: crypto/fips140/nonfips140-embedded.o
+endif
 fips140_build = .
 ifeq ($(CONFIG_CRYPTO_FIPS140_EXTMOD_SOURCE),y)
 fips140_build = fips140_build
@@ -1302,6 +1305,14 @@ crypto/fips140/fips140-embedded.o: fips140-ready
 	@$(LD) -r -b binary -o $@ $(fips140_build)/crypto/fips140/fips140.ko
 	@$(OBJCOPY) --rename-section .data=.fips140_module_data $@
 
+ifdef CONFIG_CRYPTO_FIPS140_DUAL_VERSION
+crypto/fips140/nonfips140-embedded.o: fips140-ready
+	@echo "  LD      $@"
+	@$(LD) -r -b binary -o $@ crypto/fips140/fips140.ko
+	@$(OBJCOPY) --rename-section .data=.nonfips140_module_data \
+		--prefix-symbols nonfips140_ $@
+endif
+
 crypto/fips140/.fips140.hmac: crypto/fips140/fips140-embedded.o
 	@echo "  HMAC    $@"
 	@hmac_key=$$(awk -F'"' '/^CONFIG_CRYPTO_FIPS140_HMAC_KEY=/{print $$2}' .config); \
@@ -1319,9 +1330,11 @@ fips140-ready: crypto/fips140/fips140.o crypto/fips140/.fips140.order crypto/fip
 ifneq ($(KBUILD_MODPOST_NOFINAL),1)
 	$(Q)$(MAKE) KBUILD_MODULES=y crypto-module-gen=1 -f $(srctree)/scripts/Makefile.modfinal
 endif
+ifndef CONFIG_CRYPTO_FIPS140_DUAL_VERSION
 ifeq ($(CONFIG_CRYPTO_FIPS140_EXTMOD_SOURCE),y)
 	cp "$(fips140_build)/crypto/fips140/fips140.ko" crypto/fips140/fips140.ko;
 endif
+endif
 
 # Generate fips140.o from crypto-module.a files
 crypto/fips140/fips140.o: crypto-module.a FORCE
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index 41223fa3f14e..0722e07c5551 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -222,6 +222,22 @@ SECTIONS
 		__stop_fips140_btf = .;
 	}
 #endif
+#ifdef CONFIG_CRYPTO_FIPS140_DUAL_VERSION
+	.nonfips140_embedded : {
+		. = ALIGN(8);
+		_binary_nonfips140_ko_start = .;
+		KEEP(*(.nonfips140_module_data))
+		_binary_nonfips140_ko_end = .;
+	}
+#ifdef CONFIG_DEBUG_INFO_BTF_MODULES
+	.nonfips140_btf : {
+		. = ALIGN(8);
+		__start_nonfips140_btf = .;
+		KEEP(*(.nonfips140_btf))
+		__stop_nonfips140_btf = .;
+	}
+#endif
+#endif
 #endif
 
 	HYPERVISOR_RODATA_SECTIONS
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index e07c1b5c52cf..aa1b97d7aabd 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -193,6 +193,22 @@ SECTIONS
 		__stop_fips140_btf = .;
 	}
 #endif
+#ifdef CONFIG_CRYPTO_FIPS140_DUAL_VERSION
+	.nonfips140_embedded : AT(ADDR(.nonfips140_embedded) - LOAD_OFFSET) {
+		. = ALIGN(8);
+		_binary_nonfips140_ko_start = .;
+		KEEP(*(.nonfips140_module_data))
+		_binary_nonfips140_ko_end = .;
+	}
+#ifdef CONFIG_DEBUG_INFO_BTF_MODULES
+	.nonfips140_btf : AT(ADDR(.nonfips140_btf) - LOAD_OFFSET) {
+		. = ALIGN(8);
+		__start_nonfips140_btf = .;
+		KEEP(*(.nonfips140_btf))
+		__stop_nonfips140_btf = .;
+	}
+#endif
+#endif
 #endif
 
 	/* Data */
diff --git a/crypto/fips140/Kconfig b/crypto/fips140/Kconfig
index 68b877f0dbab..7d8997aa1094 100644
--- a/crypto/fips140/Kconfig
+++ b/crypto/fips140/Kconfig
@@ -42,3 +42,27 @@ config CRYPTO_FIPS140_EXTMOD_SOURCE
 	    - fips140_build/crypto/sha256.ko
 	  
 	  If unsure, say N.
+config CRYPTO_FIPS140_DUAL_VERSION
+	bool "Enable dual crypto versions for FIPS and regular modes"
+	depends on CRYPTO_FIPS140_EXTMOD && CRYPTO_FIPS140_EXTMOD_SOURCE
+	default n
+	help
+	  Enable keeping two crypto module versions in the same kernel build
+	  for boot-time switching based on FIPS mode status. This allows:
+	  - Non-FIPS users: Get latest crypto algorithms built from current
+	    kernel sources for optimal performance and security features
+	  - FIPS users: Get pre-compiled certified crypto modules that have
+	    undergone formal validation and certification processes
+
+	  When enabled:
+
+	  For core fips140.ko:
+	  - FIPS mode: Uses certified module from CRYPTO_FIPS140_EXTMOD_SOURCE
+	  - Regular mode: Uses freshly built kernel crypto implementation
+
+	  For modular algorithms (e.g., aes.ko), they are not duplicated
+	  automatically. Either make them built-in to be included into
+	  fips140.ko for automatic duplication, or require OS utilities such
+	  as `modprobe` to correctly isolate modular cryptos in filesystems.
+
+	  If unsure, say N.
\ No newline at end of file
diff --git a/crypto/fips140/Makefile b/crypto/fips140/Makefile
index ac8ae42eb0fa..c99bf2948432 100644
--- a/crypto/fips140/Makefile
+++ b/crypto/fips140/Makefile
@@ -15,4 +15,7 @@ $(obj)/fips140-api-fips.o: $(src)/fips140-api.c FORCE
 CFLAGS_fips140-api-main.o += -I$(srctree)
 CFLAGS_fips140-api-fips.o += -I$(srctree)
 
-clean-files:= .fips140.order .fips140.symvers .fips140.hmac .fips140.ko.btf
\ No newline at end of file
+clean-files:= .fips140.order .fips140.symvers .fips140.hmac .fips140.ko.btf
+ifdef CONFIG_CRYPTO_FIPS140_DUAL_VERSION
+clean-files += .nonfips140.ko.btf
+endif
\ No newline at end of file
diff --git a/crypto/fips140/fips140-loader.c b/crypto/fips140/fips140-loader.c
index 13c82ffdc65b..826075928723 100644
--- a/crypto/fips140/fips140-loader.c
+++ b/crypto/fips140/fips140-loader.c
@@ -11,12 +11,20 @@
 #include <linux/elf.h>
 #include <linux/kthread.h>
 #include <linux/wait.h>
+#include <linux/fips.h>
 
 extern const u8 _binary_fips140_ko_start[];
 extern const u8 _binary_fips140_ko_end[];
 extern const u8 _binary_fips140_hmac_start[];
 extern const u8 _binary_fips140_hmac_end[];
 
+#ifdef CONFIG_CRYPTO_FIPS140_DUAL_VERSION
+/* For non-FIPS mode: no module signature/HMAC is required,
+ * so only include binary start/end address without module sig address */
+extern const u8 _binary_nonfips140_ko_start[];
+extern const u8 _binary_nonfips140_ko_end[];
+#endif
+
 const u8 *_binary_crypto_ko_start;
 EXPORT_SYMBOL_GPL(_binary_crypto_ko_start);
 const u8 *_binary_crypto_ko_end;
@@ -29,6 +37,10 @@ EXPORT_SYMBOL_GPL(_binary_crypto_hmac_end);
 #ifdef CONFIG_DEBUG_INFO_BTF_MODULES
 extern const u8 __start_fips140_btf[];
 extern const u8 __stop_fips140_btf[];
+#ifdef CONFIG_CRYPTO_FIPS140_DUAL_VERSION
+extern const u8 __start_nonfips140_btf[];
+extern const u8 __stop_nonfips140_btf[];
+#endif
 const u8 *__start_crypto_btf;
 const u8 *__stop_crypto_btf;
 #endif
@@ -49,11 +61,25 @@ static void load_prepare(void)
 	_binary_crypto_ko_end = _binary_fips140_ko_end;
 	_binary_crypto_hmac_start = _binary_fips140_hmac_start;
 	_binary_crypto_hmac_end = _binary_fips140_hmac_end;
-	
+
 #ifdef CONFIG_DEBUG_INFO_BTF_MODULES
 	__start_crypto_btf = __start_fips140_btf;
 	__stop_crypto_btf = __stop_fips140_btf;
 #endif
+
+#ifdef CONFIG_CRYPTO_FIPS140_DUAL_VERSION
+	if (!fips_enabled) {
+		_binary_crypto_ko_start = _binary_nonfips140_ko_start;
+		_binary_crypto_ko_end = _binary_nonfips140_ko_end;
+		_binary_crypto_hmac_start = NULL;
+		_binary_crypto_hmac_end = NULL;
+
+#ifdef CONFIG_DEBUG_INFO_BTF_MODULES
+		__start_crypto_btf = __start_nonfips140_btf;
+		__stop_crypto_btf = __stop_nonfips140_btf;
+#endif
+		}
+#endif
 }
 
 static int __init fips_loader_init(void)
diff --git a/scripts/Makefile.vmlinux b/scripts/Makefile.vmlinux
index b30d65f8b6b3..996d016e518c 100644
--- a/scripts/Makefile.vmlinux
+++ b/scripts/Makefile.vmlinux
@@ -81,7 +81,18 @@ ifdef CONFIG_DEBUG_INFO_BTF_MODULES
 	cp crypto/fips140/.fips140.ko.btf crypto/fips140/.fips140.ko.btf.first; \
 	rm -f crypto/fips140/fips140.ko.tmp; \
 	$(LD) -r -b binary -o crypto/fips140/fips140_btf.o crypto/fips140/.fips140.ko.btf; \
-	$(OBJCOPY) --rename-section .data=.fips140_btf crypto/fips140/fips140_btf.o; \
+	$(OBJCOPY) --rename-section .data=.fips140_btf crypto/fips140/fips140_btf.o
+ifdef CONFIG_CRYPTO_FIPS140_DUAL_VERSION
+      cmd_link_vmlinux += ; \
+	cp crypto/fips140/fips140.ko crypto/fips140/nonfips140.ko.tmp; \
+	LLVM_OBJCOPY="$(OBJCOPY)" $(PAHOLE) -J $(PAHOLE_FLAGS) $(MODULE_PAHOLE_FLAGS) --btf_base $@ crypto/fips140/nonfips140.ko.tmp; \
+	$(RESOLVE_BTFIDS) -b $@ crypto/fips140/nonfips140.ko.tmp; \
+	$(OBJCOPY) --dump-section=.BTF=crypto/fips140/.nonfips140.ko.btf crypto/fips140/nonfips140.ko.tmp; \
+	rm -f crypto/fips140/nonfips140.ko.tmp; \
+	$(LD) -r -b binary -o crypto/fips140/nonfips140_btf.o crypto/fips140/.nonfips140.ko.btf; \
+	$(OBJCOPY) --rename-section .data=.nonfips140_btf --prefix-symbols nonfips140_ crypto/fips140/nonfips140_btf.o
+endif
+	  cmd_link_vmlinux += ; \
 	rm -f $@; \
 	FIPS140_BTF_RELINK=1 $< "$(LD)" "$(KBUILD_LDFLAGS)" "$(LDFLAGS_vmlinux)" "$@"; \
 	cp $(fips140_build)/crypto/fips140/fips140.ko crypto/fips140/fips140.ko.tmp2; \
@@ -90,13 +101,27 @@ ifdef CONFIG_DEBUG_INFO_BTF_MODULES
 	$(OBJCOPY) --dump-section=.BTF=crypto/fips140/.fips140.ko.btf.second crypto/fips140/fips140.ko.tmp2; \
 	rm -f crypto/fips140/fips140.ko.tmp2; \
 	diff crypto/fips140/.fips140.ko.btf.first crypto/fips140/.fips140.ko.btf.second >/dev/null || echo "Module BTF differs"; \
-	rm -f crypto/fips140/.fips140.ko.btf.first crypto/fips140/.fips140.ko.btf.second; \
+	rm -f crypto/fips140/.fips140.ko.btf.first crypto/fips140/.fips140.ko.btf.second
+ifdef CONFIG_CRYPTO_FIPS140_DUAL_VERSION
+      cmd_link_vmlinux += ; \
+	cp crypto/fips140/fips140.ko crypto/fips140/nonfips140.ko.tmp2; \
+	LLVM_OBJCOPY="$(OBJCOPY)" $(PAHOLE) -J $(PAHOLE_FLAGS) $(MODULE_PAHOLE_FLAGS) --btf_base $@ crypto/fips140/nonfips140.ko.tmp2; \
+	$(RESOLVE_BTFIDS) -b $@ crypto/fips140/nonfips140.ko.tmp2; \
+	$(OBJCOPY) --dump-section=.BTF=crypto/fips140/.nonfips140.ko.btf.second crypto/fips140/nonfips140.ko.tmp2; \
+	rm -f crypto/fips140/nonfips140.ko.tmp2; \
+	diff crypto/fips140/.nonfips140.ko.btf crypto/fips140/.nonfips140.ko.btf.second >/dev/null || echo "Nonfips140 Module BTF differs"; \
+	rm -f crypto/fips140/.nonfips140.ko.btf.second
+endif
+	  cmd_link_vmlinux += ; \
 	$(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
 endif
 endif
 
 ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
 fips140-deps := crypto/fips140/fips140-embedded.o crypto/fips140/fips140-digest.o
+ifdef CONFIG_CRYPTO_FIPS140_DUAL_VERSION
+fips140-deps += crypto/fips140/nonfips140-embedded.o
+endif
 endif
 
 targets += vmlinux.unstripped .vmlinux.export.o
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index 37c9b8576ec7..43a272e8d3a4 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -78,8 +78,14 @@ vmlinux_link()
 
 	if is_enabled CONFIG_CRYPTO_FIPS140_EXTMOD; then
 		objs="${objs} crypto/fips140/fips140-embedded.o crypto/fips140/fips140-digest.o"
+		if is_enabled CONFIG_CRYPTO_FIPS140_DUAL_VERSION; then
+			objs="${objs} crypto/fips140/nonfips140-embedded.o"
+		fi
 		if is_enabled CONFIG_DEBUG_INFO_BTF_MODULES && [ -n "${FIPS140_BTF_RELINK}" ] && [ -f crypto/fips140/fips140_btf.o ]; then
 			objs="${objs} crypto/fips140/fips140_btf.o"
+			if is_enabled CONFIG_CRYPTO_FIPS140_DUAL_VERSION && [ -f crypto/fips140/nonfips140_btf.o ]; then
+				objs="${objs} crypto/fips140/nonfips140_btf.o"
+			fi
 		fi
 	fi
 
-- 
2.47.3


^ permalink raw reply related

* [PATCH 10/17] build: add CONFIG_DEBUG_INFO_BTF_MODULES support for the standalone crypto kernel module
From: Jay Wang @ 2026-02-12  2:42 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
	Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
	linux-modules
In-Reply-To: <20260212024228.6267-1-wanjay@amazon.com>

When CONFIG_DEBUG_INFO_BTF_MODULES=y, there are two problems for the
standalone crypto kernel module.

First, it requires a make dependency `.ko: vmlinux` because it takes
vmlinux as input to generate BTF info for the module, and inserts such
info into the `.ko` module binary as a dedicated ELF section. This can
cause an unwanted circular make rule dependency `fips140.ko:vmlinux`
because fips140.ko is already embedded into vmlinux.

To address this issue, we reuse the same script to explicitly generate
fips140.ko's BTF info in the vmlinux generation process to avoid the
circular make dependency. We link vmlinux first, then use it to generate
fips140.ko's BTF info, and then embed the fips140.ko and its BTF info
back with vmlinux by re-linking. Since the fips140.ko's BTF info is
embedded as data only into vmlinux, the BTF info generated using the
first linked vmlinux will be the same as if using the latest vmlinux.

Second, CONFIG_DEBUG_INFO_BTF_MODULES=y will insert BTF info into
fips140.ko binary, which means the previously generated module signature
on "fips140.ko" binary becomes invalid, thus needing regeneration.

To avoid this issue, we don't re-insert module's BTF info into
fips140.ko binary (as normally done), but keep such info as a separate
file, and embed into vmlinux as separate ELF section. By doing this,
the fips140.ko binary remains unchanged while its latest up-to-date BTF
info is available to kernel.

Signed-off-by: Jay Wang <wanjay@amazon.com>
---
 arch/arm64/kernel/vmlinux.lds.S |  8 ++++++++
 arch/x86/kernel/vmlinux.lds.S   |  8 ++++++++
 crypto/fips140/Makefile         |  2 +-
 crypto/fips140/fips140-loader.c | 19 +++++++++++++++++++
 kernel/bpf/btf.c                | 20 ++++++++++++++++++++
 kernel/module/main.c            | 27 +++++++++++++++++++++++++++
 scripts/Makefile.vmlinux        | 28 ++++++++++++++++++++++++++++
 scripts/link-vmlinux.sh         |  3 +++
 8 files changed, 114 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index 8de7dba3ac12..41223fa3f14e 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -214,6 +214,14 @@ SECTIONS
 		KEEP(*(.fips140_digest))
 		_binary_fips140_hmac_end = .;
 	}
+#ifdef CONFIG_DEBUG_INFO_BTF_MODULES
+	.fips140_btf : {
+		. = ALIGN(8);
+		__start_fips140_btf = .;
+		KEEP(*(.fips140_btf))
+		__stop_fips140_btf = .;
+	}
+#endif
 #endif
 
 	HYPERVISOR_RODATA_SECTIONS
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 25fdea6b9f27..e07c1b5c52cf 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -185,6 +185,14 @@ SECTIONS
 		KEEP(*(.fips140_digest))
 		_binary_fips140_hmac_end = .;
 	}
+#ifdef CONFIG_DEBUG_INFO_BTF_MODULES
+	.fips140_btf : AT(ADDR(.fips140_btf) - LOAD_OFFSET) {
+		. = ALIGN(8);
+		__start_fips140_btf = .;
+		KEEP(*(.fips140_btf))
+		__stop_fips140_btf = .;
+	}
+#endif
 #endif
 
 	/* Data */
diff --git a/crypto/fips140/Makefile b/crypto/fips140/Makefile
index 8f9d3c06ac98..ac8ae42eb0fa 100644
--- a/crypto/fips140/Makefile
+++ b/crypto/fips140/Makefile
@@ -15,4 +15,4 @@ $(obj)/fips140-api-fips.o: $(src)/fips140-api.c FORCE
 CFLAGS_fips140-api-main.o += -I$(srctree)
 CFLAGS_fips140-api-fips.o += -I$(srctree)
 
-clean-files:= .fips140.order .fips140.symvers .fips140.hmac
\ No newline at end of file
+clean-files:= .fips140.order .fips140.symvers .fips140.hmac .fips140.ko.btf
\ No newline at end of file
diff --git a/crypto/fips140/fips140-loader.c b/crypto/fips140/fips140-loader.c
index 7fcb420997cb..13c82ffdc65b 100644
--- a/crypto/fips140/fips140-loader.c
+++ b/crypto/fips140/fips140-loader.c
@@ -26,6 +26,20 @@ EXPORT_SYMBOL_GPL(_binary_crypto_hmac_start);
 const u8 *_binary_crypto_hmac_end;
 EXPORT_SYMBOL_GPL(_binary_crypto_hmac_end);
 
+#ifdef CONFIG_DEBUG_INFO_BTF_MODULES
+extern const u8 __start_fips140_btf[];
+extern const u8 __stop_fips140_btf[];
+const u8 *__start_crypto_btf;
+const u8 *__stop_crypto_btf;
+#endif
+
+#ifdef CONFIG_DEBUG_INFO_BTF_MODULES
+extern const u8 __start_fips140_btf[];
+extern const u8 __stop_fips140_btf[];
+const u8 *__start_crypto_btf;
+const u8 *__stop_crypto_btf;
+#endif
+
 /* Function to load crypto module from memory */
 extern int load_crypto_module_mem(const char *mem, size_t size);
 
@@ -35,6 +49,11 @@ static void load_prepare(void)
 	_binary_crypto_ko_end = _binary_fips140_ko_end;
 	_binary_crypto_hmac_start = _binary_fips140_hmac_start;
 	_binary_crypto_hmac_end = _binary_fips140_hmac_end;
+	
+#ifdef CONFIG_DEBUG_INFO_BTF_MODULES
+	__start_crypto_btf = __start_fips140_btf;
+	__stop_crypto_btf = __stop_fips140_btf;
+#endif
 }
 
 static int __init fips_loader_init(void)
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 7708958e3fb8..7e3b0d0acb9c 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -8408,6 +8408,26 @@ static int __init btf_module_init(void)
 	return 0;
 }
 
+#if defined(CONFIG_CRYPTO_FIPS140_EXTMOD) && defined(CONFIG_DEBUG_INFO_BTF_MODULES)
+/* Handle deferred BTF registration for FIPS140 loaded before btf_kobj exists */
+struct module *fips140_deferred_mod = NULL;
+
+static int __init register_deferred_fips140_btf(void)
+{	
+	if (fips140_deferred_mod && btf_kobj) {
+		/* Manually trigger BTF registration for FIPS140 */
+		btf_module_notify(NULL, MODULE_STATE_COMING, fips140_deferred_mod);
+		fips140_deferred_mod = NULL;
+		pr_info("FIPS140 BTF registration completed\n");
+	} else {
+		pr_info("FIPS140 BTF registration skipped: deferred_mod=%p, btf_kobj=%p\n",
+			fips140_deferred_mod, btf_kobj);
+	}
+	return 0;
+}
+late_initcall(register_deferred_fips140_btf);
+#endif
+
 fs_initcall(btf_module_init);
 #endif /* CONFIG_DEBUG_INFO_BTF_MODULES */
 
diff --git a/kernel/module/main.c b/kernel/module/main.c
index dad84f0548ac..7e34c8408705 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -2651,6 +2651,23 @@ static int find_module_sections(struct module *mod, struct load_info *info)
 	mod->btf_data = any_section_objs(info, ".BTF", 1, &mod->btf_data_size);
 	mod->btf_base_data = any_section_objs(info, ".BTF.base", 1,
 					      &mod->btf_base_data_size);
+	
+#ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+	/* Inject embedded BTF for FIPS140 module */
+	if (!mod->btf_data && !strcmp(mod->name, "fips140")) {
+		extern u8 *__start_crypto_btf;
+		extern u8 *__stop_crypto_btf;
+		size_t btf_size = __stop_crypto_btf - __start_crypto_btf;
+		
+		pr_info("FIPS140: Attempting BTF injection, btf_size=%zu\n", btf_size);
+		
+		if (btf_size > 0) {
+			mod->btf_data = __start_crypto_btf;
+			mod->btf_data_size = btf_size;
+			pr_info("FIPS140: Injected embedded BTF data, size %zu\n", btf_size);
+		}
+	}
+#endif
 #endif
 #ifdef CONFIG_JUMP_LABEL
 	mod->jump_entries = section_objs(info, "__jump_table",
@@ -3333,6 +3350,16 @@ static int prepare_coming_module(struct module *mod)
 	err = blocking_notifier_call_chain_robust(&module_notify_list,
 			MODULE_STATE_COMING, MODULE_STATE_GOING, mod);
 	err = notifier_to_errno(err);
+#if defined(CONFIG_CRYPTO_FIPS140_EXTMOD) && defined(CONFIG_DEBUG_INFO_BTF_MODULES)
+	/* Since fips140 module is loaded too early when BTF subsystem is not ready,
+	 * record this module for later BTF registration processing */
+	if (!strcmp(mod->name, "fips140")) {
+		pr_info("FIPS140 BTF MODULE_STATE_COMING: processing BTF registration\n");
+		extern struct module *fips140_deferred_mod;
+		fips140_deferred_mod = mod;  /* Store for later reference */
+	}
+#endif
+
 	if (err)
 		klp_module_going(mod);
 
diff --git a/scripts/Makefile.vmlinux b/scripts/Makefile.vmlinux
index 93b382e08892..b30d65f8b6b3 100644
--- a/scripts/Makefile.vmlinux
+++ b/scripts/Makefile.vmlinux
@@ -62,10 +62,38 @@ endif
 
 ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(SRCARCH)/Makefile.postlink)
 
+fips140_build = .
+ifeq ($(CONFIG_CRYPTO_FIPS140_EXTMOD_SOURCE),y)
+fips140_build = fips140_build
+endif
+
 # Final link of vmlinux with optional arch pass after final link
 cmd_link_vmlinux =							\
 	$< "$(LD)" "$(KBUILD_LDFLAGS)" "$(LDFLAGS_vmlinux)" "$@";	\
 	$(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+ifdef CONFIG_DEBUG_INFO_BTF_MODULES
+      cmd_link_vmlinux += ; \
+	cp $(fips140_build)/crypto/fips140/fips140.ko crypto/fips140/fips140.ko.tmp; \
+	LLVM_OBJCOPY="$(OBJCOPY)" $(PAHOLE) -J $(PAHOLE_FLAGS) $(MODULE_PAHOLE_FLAGS) --btf_base $@ crypto/fips140/fips140.ko.tmp; \
+	$(RESOLVE_BTFIDS) -b $@ crypto/fips140/fips140.ko.tmp; \
+	$(OBJCOPY) --dump-section=.BTF=crypto/fips140/.fips140.ko.btf crypto/fips140/fips140.ko.tmp; \
+	cp crypto/fips140/.fips140.ko.btf crypto/fips140/.fips140.ko.btf.first; \
+	rm -f crypto/fips140/fips140.ko.tmp; \
+	$(LD) -r -b binary -o crypto/fips140/fips140_btf.o crypto/fips140/.fips140.ko.btf; \
+	$(OBJCOPY) --rename-section .data=.fips140_btf crypto/fips140/fips140_btf.o; \
+	rm -f $@; \
+	FIPS140_BTF_RELINK=1 $< "$(LD)" "$(KBUILD_LDFLAGS)" "$(LDFLAGS_vmlinux)" "$@"; \
+	cp $(fips140_build)/crypto/fips140/fips140.ko crypto/fips140/fips140.ko.tmp2; \
+	LLVM_OBJCOPY="$(OBJCOPY)" $(PAHOLE) -J $(PAHOLE_FLAGS) $(MODULE_PAHOLE_FLAGS) --btf_base $@ crypto/fips140/fips140.ko.tmp2; \
+	$(RESOLVE_BTFIDS) -b $@ crypto/fips140/fips140.ko.tmp2; \
+	$(OBJCOPY) --dump-section=.BTF=crypto/fips140/.fips140.ko.btf.second crypto/fips140/fips140.ko.tmp2; \
+	rm -f crypto/fips140/fips140.ko.tmp2; \
+	diff crypto/fips140/.fips140.ko.btf.first crypto/fips140/.fips140.ko.btf.second >/dev/null || echo "Module BTF differs"; \
+	rm -f crypto/fips140/.fips140.ko.btf.first crypto/fips140/.fips140.ko.btf.second; \
+	$(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
+endif
+endif
 
 ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
 fips140-deps := crypto/fips140/fips140-embedded.o crypto/fips140/fips140-digest.o
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index 34c0a162da84..37c9b8576ec7 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -78,6 +78,9 @@ vmlinux_link()
 
 	if is_enabled CONFIG_CRYPTO_FIPS140_EXTMOD; then
 		objs="${objs} crypto/fips140/fips140-embedded.o crypto/fips140/fips140-digest.o"
+		if is_enabled CONFIG_DEBUG_INFO_BTF_MODULES && [ -n "${FIPS140_BTF_RELINK}" ] && [ -f crypto/fips140/fips140_btf.o ]; then
+			objs="${objs} crypto/fips140/fips140_btf.o"
+		fi
 	fi
 
 	objs="${objs} init/version-timestamp.o"
-- 
2.47.3


^ permalink raw reply related

* [PATCH 09/17] build: embed the standalone crypto module into vmlinux
From: Jay Wang @ 2026-02-12  2:42 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
	Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
	linux-modules
In-Reply-To: <20260212024228.6267-1-wanjay@amazon.com>

As mentioned in earlier patch, in order to load standalone crypto module
in early boot before filesystem is ready, the module needs to be embedded
into vmlinux image. This patch intends to make such embedded process a
seamless process that will automatically trigger as building vmlinux (i.e.,
during `make vmlinux`). So it adds make dependency rule such that vmlinux
will depend on the `fips140.ko` and its signature `.fips140.hmac`
generation rule. It also modifies vmlinux link rule to finally link them
with vmlinux.o.

The high level idea of embedding fips140.ko into vmlinux stems from
Vegard Nossum <vegard.nossum@oracle.com>.

Signed-off-by: Jay Wang <wanjay@amazon.com>
---
 Makefile                        | 25 +++++++++++++++++++++++--
 arch/arm64/kernel/vmlinux.lds.S | 16 ++++++++++++++++
 arch/x86/kernel/vmlinux.lds.S   | 16 ++++++++++++++++
 crypto/fips140/Kconfig          | 29 +++++++++++++++++++++++++++++
 crypto/fips140/Makefile         | 16 +++++++++++++---
 crypto/fips140/fips140-loader.c |  9 +++++++++
 scripts/Makefile.modfinal       | 18 +++++++++++++++++-
 scripts/Makefile.vmlinux        |  6 +++++-
 scripts/link-vmlinux.sh         |  5 +++++
 9 files changed, 133 insertions(+), 7 deletions(-)

diff --git a/Makefile b/Makefile
index 8413cc02665c..7530009d8081 100644
--- a/Makefile
+++ b/Makefile
@@ -1292,7 +1292,26 @@ PHONY += vmlinux
 vmlinux: private _LDFLAGS_vmlinux := $(LDFLAGS_vmlinux)
 vmlinux: export LDFLAGS_vmlinux = $(_LDFLAGS_vmlinux)
 ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
-vmlinux: fips140-ready
+vmlinux: crypto/fips140/fips140-embedded.o crypto/fips140/fips140-digest.o
+fips140_build = .
+ifeq ($(CONFIG_CRYPTO_FIPS140_EXTMOD_SOURCE),y)
+fips140_build = fips140_build
+endif
+crypto/fips140/fips140-embedded.o: fips140-ready
+	@echo "  LD      $@"
+	@$(LD) -r -b binary -o $@ $(fips140_build)/crypto/fips140/fips140.ko
+	@$(OBJCOPY) --rename-section .data=.fips140_module_data $@
+
+crypto/fips140/.fips140.hmac: crypto/fips140/fips140-embedded.o
+	@echo "  HMAC    $@"
+	@hmac_key=$$(awk -F'"' '/^CONFIG_CRYPTO_FIPS140_HMAC_KEY=/{print $$2}' .config); \
+	openssl dgst -sha256 -hmac "$$hmac_key" -binary -out $@ $(fips140_build)/crypto/fips140/fips140.ko
+
+crypto/fips140/fips140-digest.o: crypto/fips140/.fips140.hmac
+	@echo "  LD      $@"
+	@$(LD) -r -b binary -o $@ crypto/fips140/.fips140.hmac
+	@$(OBJCOPY) --rename-section .data=.fips140_digest $@
+
 # Ensure fips140.ko is built before embedding
 fips140-ready: crypto/fips140/fips140.o crypto/fips140/.fips140.order crypto/fips140/fips140.mod vmlinux.o | modules_prepare
 	$(Q)$(MAKE) KBUILD_MODULES= -f $(srctree)/scripts/Makefile.modpost
@@ -1300,7 +1319,9 @@ fips140-ready: crypto/fips140/fips140.o crypto/fips140/.fips140.order crypto/fip
 ifneq ($(KBUILD_MODPOST_NOFINAL),1)
 	$(Q)$(MAKE) KBUILD_MODULES=y crypto-module-gen=1 -f $(srctree)/scripts/Makefile.modfinal
 endif
-	@:
+ifeq ($(CONFIG_CRYPTO_FIPS140_EXTMOD_SOURCE),y)
+	cp "$(fips140_build)/crypto/fips140/fips140.ko" crypto/fips140/fips140.ko;
+endif
 
 # Generate fips140.o from crypto-module.a files
 crypto/fips140/fips140.o: crypto-module.a FORCE
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index ad6133b89e7a..8de7dba3ac12 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -200,6 +200,22 @@ SECTIONS
 	/* everything from this point to __init_begin will be marked RO NX */
 	RO_DATA(PAGE_SIZE)
 
+#ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+	/* FIPS 140 embedded module data */
+	.fips140_embedded : {
+		. = ALIGN(8);
+		_binary_fips140_ko_start = .;
+		KEEP(*(.fips140_module_data))
+		_binary_fips140_ko_end = .;
+	}
+	.fips140_digest : {
+		. = ALIGN(8);
+		_binary_fips140_hmac_start = .;
+		KEEP(*(.fips140_digest))
+		_binary_fips140_hmac_end = .;
+	}
+#endif
+
 	HYPERVISOR_RODATA_SECTIONS
 
 	.got : { *(.got) }
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 3a24a3fc55f5..25fdea6b9f27 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -171,6 +171,22 @@ SECTIONS
 	RO_DATA(PAGE_SIZE)
 	X86_ALIGN_RODATA_END
 
+#ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+	/* FIPS 140 embedded module data */
+	.fips140_embedded : AT(ADDR(.fips140_embedded) - LOAD_OFFSET) {
+		. = ALIGN(8);
+		_binary_fips140_ko_start = .;
+		KEEP(*(.fips140_module_data))
+		_binary_fips140_ko_end = .;
+	}
+	.fips140_digest : AT(ADDR(.fips140_digest) - LOAD_OFFSET) {
+		. = ALIGN(8);
+		_binary_fips140_hmac_start = .;
+		KEEP(*(.fips140_digest))
+		_binary_fips140_hmac_end = .;
+	}
+#endif
+
 	/* Data */
 	.data : AT(ADDR(.data) - LOAD_OFFSET) {
 		/* Start of data section */
diff --git a/crypto/fips140/Kconfig b/crypto/fips140/Kconfig
index 0665e94b9fe0..68b877f0dbab 100644
--- a/crypto/fips140/Kconfig
+++ b/crypto/fips140/Kconfig
@@ -12,4 +12,33 @@ config CRYPTO_FIPS140_EXTMOD
 	  can be enabled to restrict crypto algorithm usage to only
 	  those provided by this module.
 
+	  If unsure, say N.
+config CRYPTO_FIPS140_HMAC_KEY
+	string "FIPS 140-3 external module HMAC key"
+	depends on CRYPTO_FIPS140_EXTMOD
+	default "The quick brown fox jumps over the lazy dog while the sphinx of black quartz judges my vow"
+	help
+	  This is the HMAC key used to build and verify the integrity of
+	  the FIPS module.
+
+	  Must be at least 80 characters.
+config CRYPTO_FIPS140_EXTMOD_SOURCE
+	bool "Use external FIPS module source"
+	depends on CRYPTO_FIPS140_EXTMOD
+	default n
+	help
+	  Use pre-built FIPS modules from an external build directory instead
+	  of freshly built modules from the current kernel build.
+	  
+	  If N, the kernel uses freshly generated crypto modules from the
+	  current build directory:
+	    - crypto/fips140/fips140.ko
+	    - crypto/aes.ko
+	    - crypto/sha256.ko
+	  
+	  If Y, pre-built modules from fips140_build/ are used:
+	    - fips140_build/crypto/fips140/fips140.ko
+	    - fips140_build/crypto/aes.ko
+	    - fips140_build/crypto/sha256.ko
+	  
 	  If unsure, say N.
diff --git a/crypto/fips140/Makefile b/crypto/fips140/Makefile
index fb083022efbb..8f9d3c06ac98 100644
--- a/crypto/fips140/Makefile
+++ b/crypto/fips140/Makefile
@@ -1,8 +1,18 @@
 
 crypto-objs-y += \
 	fips140-module.o \
-	fips140-api.o
+	fips140-api-fips.o
 
-obj-y += fips140-api.o
+obj-y += fips140-api-main.o fips140-loader.o
 
-clean-files:= .fips140.order .fips140.symvers
\ No newline at end of file
+# Explicit rules to compile same source to different objects
+$(obj)/fips140-api-main.o: $(src)/fips140-api.c FORCE
+	$(call if_changed_rule,cc_o_c)
+
+$(obj)/fips140-api-fips.o: $(src)/fips140-api.c FORCE
+	$(call if_changed_rule,cc_o_c)
+
+CFLAGS_fips140-api-main.o += -I$(srctree)
+CFLAGS_fips140-api-fips.o += -I$(srctree)
+
+clean-files:= .fips140.order .fips140.symvers .fips140.hmac
\ No newline at end of file
diff --git a/crypto/fips140/fips140-loader.c b/crypto/fips140/fips140-loader.c
index cbf5ff59eb2e..7fcb420997cb 100644
--- a/crypto/fips140/fips140-loader.c
+++ b/crypto/fips140/fips140-loader.c
@@ -14,10 +14,17 @@
 
 extern const u8 _binary_fips140_ko_start[];
 extern const u8 _binary_fips140_ko_end[];
+extern const u8 _binary_fips140_hmac_start[];
+extern const u8 _binary_fips140_hmac_end[];
+
 const u8 *_binary_crypto_ko_start;
 EXPORT_SYMBOL_GPL(_binary_crypto_ko_start);
 const u8 *_binary_crypto_ko_end;
 EXPORT_SYMBOL_GPL(_binary_crypto_ko_end);
+const u8 *_binary_crypto_hmac_start;
+EXPORT_SYMBOL_GPL(_binary_crypto_hmac_start);
+const u8 *_binary_crypto_hmac_end;
+EXPORT_SYMBOL_GPL(_binary_crypto_hmac_end);
 
 /* Function to load crypto module from memory */
 extern int load_crypto_module_mem(const char *mem, size_t size);
@@ -26,6 +33,8 @@ static void load_prepare(void)
 {
 	_binary_crypto_ko_start = _binary_fips140_ko_start;
 	_binary_crypto_ko_end = _binary_fips140_ko_end;
+	_binary_crypto_hmac_start = _binary_fips140_hmac_start;
+	_binary_crypto_hmac_end = _binary_fips140_hmac_end;
 }
 
 static int __init fips_loader_init(void)
diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
index c68dab4d6584..6a2219582258 100644
--- a/scripts/Makefile.modfinal
+++ b/scripts/Makefile.modfinal
@@ -69,11 +69,27 @@ ifeq ($(crypto-module-gen),1)
 	+$(call if_changed,ld_ko_o)
 else
 %.ko: %.o %.mod.o .module-common.o $(objtree)/scripts/module.lds $(and $(CONFIG_DEBUG_INFO_BTF_MODULES),$(KBUILD_BUILTIN),$(objtree)/vmlinux) FORCE
-	+$(call if_changed_except,ld_ko_o,$(objtree)/vmlinux)
+	+$(call if_changed_except,ld_ko_o_and_cp_extmod,$(objtree)/vmlinux)
 ifdef CONFIG_DEBUG_INFO_BTF_MODULES
 	+$(if $(newer-prereqs),$(call cmd,btf_ko))
 endif
 endif
+
+fips140_build = .
+ifeq ($(CONFIG_CRYPTO_FIPS140_EXTMOD_SOURCE),y)
+fips140_build = fips140_build
+endif
+
+quiet_cmd_ld_ko_o_and_cp_extmod = LD [M]  $@
+      cmd_ld_ko_o_and_cp_extmod = \
+	$(LD) -r $(KBUILD_LDFLAGS) \
+		$(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
+		-T $(objtree)/scripts/module.lds -o $@ $(filter %.o, $^); \
+	if [ "$(CONFIG_CRYPTO_FIPS140_EXTMOD_SOURCE)" = "y" ] && \
+	   [ -f "$(fips140_build)/$@" ]; then \
+		echo "  CP [M]  $@"; \
+		cp "$(fips140_build)/$@" "$@"; \
+	fi
 else
 %.ko: %.o %.mod.o .module-common.o $(objtree)/scripts/module.lds $(and $(CONFIG_DEBUG_INFO_BTF_MODULES),$(KBUILD_BUILTIN),$(objtree)/vmlinux) FORCE
 	+$(call if_changed_except,ld_ko_o,$(objtree)/vmlinux)
diff --git a/scripts/Makefile.vmlinux b/scripts/Makefile.vmlinux
index fcae1e432d9a..93b382e08892 100644
--- a/scripts/Makefile.vmlinux
+++ b/scripts/Makefile.vmlinux
@@ -67,8 +67,12 @@ cmd_link_vmlinux =							\
 	$< "$(LD)" "$(KBUILD_LDFLAGS)" "$(LDFLAGS_vmlinux)" "$@";	\
 	$(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
 
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+fips140-deps := crypto/fips140/fips140-embedded.o crypto/fips140/fips140-digest.o
+endif
+
 targets += vmlinux.unstripped .vmlinux.export.o
-vmlinux.unstripped: scripts/link-vmlinux.sh vmlinux.o .vmlinux.export.o $(KBUILD_LDS) FORCE
+vmlinux.unstripped: scripts/link-vmlinux.sh vmlinux.o .vmlinux.export.o $(KBUILD_LDS) $(fips140-deps) FORCE
 	+$(call if_changed_dep,link_vmlinux)
 ifdef CONFIG_DEBUG_INFO_BTF
 vmlinux.unstripped: $(RESOLVE_BTFIDS) $(srctree)/scripts/gen-btf.sh
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index f99e196abeea..34c0a162da84 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -75,6 +75,11 @@ vmlinux_link()
 	fi
 
 	objs="${objs} .vmlinux.export.o"
+
+	if is_enabled CONFIG_CRYPTO_FIPS140_EXTMOD; then
+		objs="${objs} crypto/fips140/fips140-embedded.o crypto/fips140/fips140-digest.o"
+	fi
+
 	objs="${objs} init/version-timestamp.o"
 
 	if [ "${SRCARCH}" = "um" ]; then
-- 
2.47.3


^ permalink raw reply related

* [PATCH 08/17] crypto: fips140: add crypto module loader
From: Jay Wang @ 2026-02-12  2:42 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
	Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
	linux-modules
In-Reply-To: <20260212024228.6267-1-wanjay@amazon.com>

Add a crypto module loader mechanism that loads a precompiled crypto
kernel module that is embedded in vmlinux image directly from memory
(whose address stored in _binary_fips140_ko_start/end) during early boot.

This is built based on Vegard Nossum <vegard.nossum@oracle.com> and
Saeed Mirzamohammadi <saeed.mirzamohammadi@oracle.com>, the
fips_loader_init is picked up. But different from them, such loader is
not executed as arch_initcall_sync(), but rather as a thread along main
kernel init to ensure proper initialization sequencing (Details are in
later patch).

Signed-off-by: Jay Wang <wanjay@amazon.com>
---
 crypto/fips140/fips140-loader.c | 55 +++++++++++++++++++++++++++++++++
 1 file changed, 55 insertions(+)
 create mode 100644 crypto/fips140/fips140-loader.c

diff --git a/crypto/fips140/fips140-loader.c b/crypto/fips140/fips140-loader.c
new file mode 100644
index 000000000000..cbf5ff59eb2e
--- /dev/null
+++ b/crypto/fips140/fips140-loader.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * FIPS 140 Early Loader
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/printk.h>
+#include <linux/vmalloc.h>
+#include <linux/string.h>
+#include <linux/elf.h>
+#include <linux/kthread.h>
+#include <linux/wait.h>
+
+extern const u8 _binary_fips140_ko_start[];
+extern const u8 _binary_fips140_ko_end[];
+const u8 *_binary_crypto_ko_start;
+EXPORT_SYMBOL_GPL(_binary_crypto_ko_start);
+const u8 *_binary_crypto_ko_end;
+EXPORT_SYMBOL_GPL(_binary_crypto_ko_end);
+
+/* Function to load crypto module from memory */
+extern int load_crypto_module_mem(const char *mem, size_t size);
+
+static void load_prepare(void)
+{
+	_binary_crypto_ko_start = _binary_fips140_ko_start;
+	_binary_crypto_ko_end = _binary_fips140_ko_end;
+}
+
+static int __init fips_loader_init(void)
+{
+	load_prepare();
+	
+	const void *ko_mem = _binary_crypto_ko_start;
+	size_t ko_size = _binary_crypto_ko_end - _binary_crypto_ko_start;
+	void *vmalloc_mem;
+	int ret;
+	
+	// Copy to vmalloc'd memory since load_module expects to free it
+	vmalloc_mem = vmalloc(ko_size);
+	if (!vmalloc_mem) {
+		pr_err("FIPS140 loader: failed to allocate memory\n");
+		return -ENOMEM;
+	}
+	
+	memcpy(vmalloc_mem, ko_mem, ko_size);
+	
+	ret = load_crypto_module_mem(vmalloc_mem, ko_size); // Skip signature check
+	if (ret)
+		panic("FIPS140 loader: module loading error\n");
+
+	vfree(vmalloc_mem); // Free after successful module loading
+	return ret;
+}
-- 
2.47.3


^ permalink raw reply related

* [PATCH 07/17] crypto: dedicated ELF sections for collected crypto initcalls
From: Jay Wang @ 2026-02-12  2:42 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
	Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
	linux-modules
In-Reply-To: <20260212024228.6267-1-wanjay@amazon.com>

The addresses of init functions for crypto collected into the standalone
modules are placed into a dedicated ELF section. This is achieved by
introducing a custom linker script crypto/fips140/fips140.lds. Since in
later patch the init crypto will be called in the proper ordering (e.g.,
device_initcall should be earlier than late_initcall), the linker script
allocates different levels of ELF section (e.g.,
__fips140_initcall0_start and __fips140_initcall1_start) to preserve the
proper ordering.

Signed-off-by: Jay Wang <wanjay@amazon.com>
---
 Makefile                   |  2 +-
 crypto/fips140/fips140.lds | 17 +++++++++++++++++
 2 files changed, 18 insertions(+), 1 deletion(-)
 create mode 100644 crypto/fips140/fips140.lds

diff --git a/Makefile b/Makefile
index b5ae385ed5f3..8413cc02665c 100644
--- a/Makefile
+++ b/Makefile
@@ -1313,7 +1313,7 @@ crypto/fips140/.fips140.symvers: fips140-ready
 	@:
 modpost: crypto/fips140/.fips140.symvers
 quiet_cmd_ld_fips140 = LD [M]  $@
-      cmd_ld_fips140 = $(LD) -r $(KBUILD_LDFLAGS) $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) --build-id=none --whole-archive $< --no-whole-archive -o $@
+      cmd_ld_fips140 = $(LD) -r $(KBUILD_LDFLAGS) $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) --build-id=none -T $(srctree)/crypto/fips140/fips140.lds --whole-archive $< --no-whole-archive -o $@
 
 cmd_fips140_mod = ar -t $< > $@
 
diff --git a/crypto/fips140/fips140.lds b/crypto/fips140/fips140.lds
new file mode 100644
index 000000000000..1adb3ccb5b9d
--- /dev/null
+++ b/crypto/fips140/fips140.lds
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+SECTIONS {
+	.init.data : {
+		__fips140_initcalls_start = .;
+		__fips140_initcall0_start = .;
+		*(.fips_initcall0)
+		__fips140_initcall0_end = .;
+		__fips140_initcall1_start = .;
+		*(.fips_initcall1)
+		__fips140_initcall1_end = .;
+		__fips140_initcall2_start = .;
+		*(.fips_initcall2)
+		__fips140_initcall2_end = .;
+		__fips140_initcalls_end = .;
+	}
+}
\ No newline at end of file
-- 
2.47.3


^ permalink raw reply related

* [PATCH 06/17] crypto: add pluggable interface for builtin crypto modules
From: Jay Wang @ 2026-02-12  2:42 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
	Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
	linux-modules
In-Reply-To: <20260212024228.6267-1-wanjay@amazon.com>

Traditionally, builtin cryptos interact with the main kernel through
exported functions and variables via EXPORT_SYMBOL. The exported
symbols are statically tied with the main kernel, so not suitable
after those builtin cryptos moved to a standalone kernel module
(e.g., main kernel will not even be compilable since users need the
exact function/variable address).

To address this, introduce a pluggable interface between builtin
crypto functions and variables by placing address placeholders.
During runtime once the crypto kernel module is loaded, the address
placeholder gets updated (by `do_crypto_api` and `do_crypto_var`) to
correct address.

In more details, there are two types of address holders: for function
addresses, "static call" mechanism is used; for variable addresses, a
var_type* pointer is used. To apply this pluggable interface, just
wrap the function/variable header declaration with the placeholder
declaration wrappers (implemented as `DECLARE_STATIC_CALL()`/
`DECLARE_CRYPTO_VAR()`), and place the placeholder definition wrappers
for each crypto function/variable in fips140-api.c (implemented as
`DEFINE_CRYPTO_API_STUB()`/`DEFINE_CRYPTO_VAR_STUB()`). Those wrappers
will be compiled differently for main kernel and the crypto kernel
module using different compilation flags. To make such pluggable
interface only affect cryptos chosen as builtin but not crypto chosen
built as modules already, associate wrappers with CONFIG_CRYPTO_{NAME}
parameter.

In addition to the pluggable interface, this patch also adds a way to
collect crypto init functions, such as `module_init()` into a
dedicated ELF section for later module entry to initialize each
crypto.

The idea of using "static call" as pluggable interface for function
address stems from Vegard Nossum <vegard.nossum@oracle.com>, while
we additionally make the following core differences: avoid duplicate
crypto code in main kernel, allow variable pluggable, make this
feature not affect cryptos already chosen to be module-built, and
make this adapt to any .config choices.

Signed-off-by: Jay Wang <wanjay@amazon.com>
---
 crypto/fips140/Makefile           |   5 +-
 crypto/fips140/fips140-api.c      |   7 ++
 include/asm-generic/vmlinux.lds.h |   1 +
 include/crypto/api.h              | 197 ++++++++++++++++++++++++++++++
 kernel/module/main.c              |  46 ++++++-
 5 files changed, 253 insertions(+), 3 deletions(-)
 create mode 100644 crypto/fips140/fips140-api.c
 create mode 100644 include/crypto/api.h

diff --git a/crypto/fips140/Makefile b/crypto/fips140/Makefile
index 3b4a74ccf41e..fb083022efbb 100644
--- a/crypto/fips140/Makefile
+++ b/crypto/fips140/Makefile
@@ -1,5 +1,8 @@
 
 crypto-objs-y += \
-	fips140-module.o 
+	fips140-module.o \
+	fips140-api.o
+
+obj-y += fips140-api.o
 
 clean-files:= .fips140.order .fips140.symvers
\ No newline at end of file
diff --git a/crypto/fips140/fips140-api.c b/crypto/fips140/fips140-api.c
new file mode 100644
index 000000000000..a11e898ff4bc
--- /dev/null
+++ b/crypto/fips140/fips140-api.c
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/*
+ * Define static call keys for any functions which are part of the crypto
+ * API and used by the standalone FIPS module but which are not built into
+ * vmlinux.
+ */
\ No newline at end of file
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index eeb070f330bd..e25b44d29362 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -724,6 +724,7 @@
 	KERNEL_CTORS()							\
 	MCOUNT_REC()							\
 	*(.init.rodata .init.rodata.*)					\
+	BOUNDED_SECTION(__crypto_api_keys)				\
 	FTRACE_EVENTS()							\
 	TRACE_SYSCALLS()						\
 	KPROBE_BLACKLIST()						\
diff --git a/include/crypto/api.h b/include/crypto/api.h
new file mode 100644
index 000000000000..b58240ffd173
--- /dev/null
+++ b/include/crypto/api.h
@@ -0,0 +1,197 @@
+#ifndef _CRYPTO_API_H
+#define _CRYPTO_API_H
+
+#include <linux/static_call.h>
+
+#define CRYPTO_VAR_NAME(name) __crypto_##name##_ptr
+
+#define __CAT(a,b) a##b
+#define _CAT(a,b)  __CAT(a,b)
+
+#define __IF_1(...) __VA_ARGS__
+#define __IF_0(...)
+#define __IFNOT_1(...)
+#define __IFNOT_0(...) __VA_ARGS__
+
+/* Emit __VA_ARGS__ only if cfg is built into vmlinux (=y) */
+#define IF_BUILTIN(cfg, ...)     _CAT(__IF_,    IS_BUILTIN(cfg))(__VA_ARGS__)
+/* Emit __VA_ARGS__ only if cfg is NOT built in (i.e., =m or unset) */
+#define IF_NOT_BUILTIN(cfg, ...) _CAT(__IFNOT_, IS_BUILTIN(cfg))(__VA_ARGS__)
+
+#if !defined(CONFIG_CRYPTO_FIPS140_EXTMOD)
+
+/*
+ * These are the definitions that get used when no standalone FIPS module
+ * is used: we simply forward everything to normal functions and function
+ * calls.
+ */
+
+#define DECLARE_CRYPTO_API(cfg, name, ret_type, args_decl, args_call)       \
+	ret_type name args_decl;
+
+#define DECLARE_CRYPTO_VAR(cfg, name, var_type, ...) \
+	extern var_type name __VA_ARGS__;
+
+#define crypto_module_init(fn) module_init(fn)
+#define crypto_module_exit(fn) module_exit(fn)
+
+#define crypto_subsys_initcall(fn)	subsys_initcall(fn)
+#define crypto_late_initcall(fn)	late_initcall(fn)
+
+#define crypto_module_cpu_feature_match(x, __initfunc) \
+	module_cpu_feature_match(x, __initfunc)
+
+#else
+
+struct crypto_api_key {
+	struct static_call_key *key;
+	void *tramp;
+	void *func;
+};
+
+struct crypto_var_key {
+	void **ptr;
+	void *var;
+};
+
+#ifndef FIPS_MODULE
+
+/*
+ * These are the definitions that get used for vmlinux and in-tree
+ * kernel modules.
+ *
+ * In this case, all references to the kernel crypto API functions will
+ * be replaced by wrappers that perform a call using the kernel's static_call
+ * functionality.
+ */
+
+/* Consolidated version of different DECLARE_CRYPTO_API versions */
+
+/*
+ *  - If cfg is built-in (=y): declare nonfips_<name>, a static_call key,
+ *    and an inline wrapper <name>() that dispatches via static_call.
+ *  - Else (cfg =m or unset): only declare <name>() prototype.
+ */
+#define DECLARE_CRYPTO_API(cfg, name, ret_type, args_decl, args_call)       \
+	IF_BUILTIN(cfg,                                                      \
+		ret_type nonfips_##name args_decl;                           \
+		DECLARE_STATIC_CALL(crypto_##name##_key, nonfips_##name);    \
+		static inline ret_type name args_decl                        \
+		{                                                            \
+			return static_call(crypto_##name##_key) args_call;   \
+		}                                                            \
+	)                                                                   \
+	IF_NOT_BUILTIN(cfg,                                                 \
+		ret_type name args_decl;                                    \
+	)
+
+#define DECLARE_CRYPTO_VAR(cfg, name, var_type, ...) \
+	IF_BUILTIN(cfg, \
+		extern void *CRYPTO_VAR_NAME(name); \
+	) \
+	IF_NOT_BUILTIN(cfg, \
+		extern var_type name __VA_ARGS__; \
+	)
+
+#define DEFINE_CRYPTO_API_STUB(name) \
+	DEFINE_STATIC_CALL_NULL(crypto_##name##_key, name); \
+	EXPORT_STATIC_CALL(crypto_##name##_key)
+
+#define DEFINE_CRYPTO_VAR_STUB(name) \
+	void* CRYPTO_VAR_NAME(name) = NULL;\
+	EXPORT_SYMBOL(CRYPTO_VAR_NAME(name));
+
+#define crypto_module_init(fn) module_init(fn)
+#define crypto_module_exit(fn) module_exit(fn)
+
+#define crypto_subsys_initcall(fn)	subsys_initcall(fn)
+#define crypto_late_initcall(fn)	late_initcall(fn)
+
+#define crypto_module_cpu_feature_match(x, __initfunc) \
+	module_cpu_feature_match(x, __initfunc)
+	
+#else /* defined(FIPS_MODULE) */
+
+/* Consolidated version of different DECLARE_CRYPTO_API versions,
+   within FIPS module, API remains the same, only declare static 
+   call key */
+#define DECLARE_CRYPTO_API(cfg, name, ret_type, args_decl, args_call) \
+	IF_BUILTIN(cfg,                                                   \
+		ret_type name args_decl;                                      \
+		DECLARE_STATIC_CALL(crypto_##name##_key, name)                \
+	)                                                                 \
+	IF_NOT_BUILTIN(cfg,                                               \
+		ret_type name args_decl;                                      \
+	)
+
+#define DECLARE_CRYPTO_VAR(cfg, name, var_type, ...)               \
+	IF_BUILTIN(cfg,                                             \
+		extern var_type name __VA_ARGS__;                   \
+		extern void *CRYPTO_VAR_NAME(name);                  \
+	)                                                            \
+	IF_NOT_BUILTIN(cfg,                                          \
+		extern var_type name __VA_ARGS__;                   \
+	)
+
+#define DEFINE_CRYPTO_VAR_STUB(name) \
+	static struct crypto_var_key __crypto_##name##_var_key \
+		__used \
+		__section("__crypto_var_keys") \
+		__aligned(__alignof__(struct crypto_var_key)) = \
+	{ \
+		.ptr = &CRYPTO_VAR_NAME(name), \
+		.var = (void*)&name, \
+	};
+
+/*
+ * These are the definitions that get used for the main kernel.
+ *
+ * In this case, initialize crypto static call key with original name
+ */
+
+#define DEFINE_CRYPTO_API_STUB(name) \
+	static struct crypto_api_key __##name##_key \
+		__used \
+		__section("__crypto_api_keys") \
+		__aligned(__alignof__(struct crypto_api_key)) = \
+	{ \
+		.key = &STATIC_CALL_KEY(crypto_##name##_key), \
+		.tramp = STATIC_CALL_TRAMP_ADDR(crypto_##name##_key), \
+		.func = &name, \
+	};
+
+#define crypto_module_init(fn) \
+	static initcall_t __used __section(".fips_initcall1") \
+		__fips_##fn = fn;
+#define crypto_module_exit(fn) \
+		static unsigned long __used __section(".fips_exitcall") \
+		__fips_##fn = (unsigned long) &fn;
+#define crypto_subsys_initcall(fn) \
+	static initcall_t __used __section(".fips_initcall0") \
+		__fips_##fn = fn;
+#define crypto_subsys_exitcall(fn) \
+		static unsigned long __used __section(".fips_exitcall") \
+		__fips_##fn = (unsigned long) &fn;
+#define crypto_late_initcall(fn) \
+	static initcall_t __used __section(".fips_initcall2") \
+		__fips_##fn = fn;
+#define crypto_late_exitcall(fn) \
+		static unsigned long __used __section(".fips_exitcall") \
+		__fips_##fn = (unsigned long) &fn;
+
+#define crypto_module_cpu_feature_match(x, __initfunc) \
+static struct cpu_feature const __maybe_unused cpu_feature_match_ ## x[] = \
+	{ { .feature = cpu_feature(x) }, { } }; \
+MODULE_DEVICE_TABLE(cpu, cpu_feature_match_ ## x); \
+static int __init cpu_feature_match_ ## x ## _init(void) \
+{ \
+	if (!cpu_have_feature(cpu_feature(x))) \
+		return -ENODEV; \
+	return __initfunc(); \
+} \
+crypto_module_init(cpu_feature_match_ ## x ## _init)
+
+#endif /* defined(FIPS_MODULE) */
+#endif /* defined(CONFIG_CRYPTO_FIPS140_EXTMOD) */
+
+#endif /* !_CRYPTO_API_H */
diff --git a/kernel/module/main.c b/kernel/module/main.c
index 2914e7619766..dad84f0548ac 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -7,6 +7,7 @@
 
 #define INCLUDE_VERMAGIC
 
+#include <crypto/api.h>
 #include <linux/export.h>
 #include <linux/extable.h>
 #include <linux/moduleloader.h>
@@ -2956,6 +2957,39 @@ static int post_relocation(struct module *mod, const struct load_info *info)
 	return module_finalize(info->hdr, info->sechdrs, mod);
 }
 
+#ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+static void do_crypto_api(struct load_info *info)
+{
+	struct crypto_api_key *crypto_api_keys;
+	unsigned int num_crypto_api_keys;
+
+	unsigned int i;
+
+	crypto_api_keys = section_objs(info, "__crypto_api_keys",
+		sizeof(*crypto_api_keys), &num_crypto_api_keys);
+
+	for (i = 0; i < num_crypto_api_keys; ++i) {
+		struct crypto_api_key *key = &crypto_api_keys[i];
+		__static_call_update(key->key, key->tramp, key->func);
+	}
+}
+
+static void do_crypto_var(struct load_info *info)
+{
+	struct crypto_var_key *crypto_var_keys;
+	unsigned int num_crypto_var_keys;
+	unsigned int i;
+
+	crypto_var_keys = section_objs(info, "__crypto_var_keys",
+		sizeof(*crypto_var_keys), &num_crypto_var_keys);
+
+	for (i = 0; i < num_crypto_var_keys; ++i) {
+		struct crypto_var_key *var_key = &crypto_var_keys[i];
+		*(var_key->ptr) = var_key->var;
+	}
+}
+#endif
+
 /* Call module constructors. */
 static void do_mod_ctors(struct module *mod)
 {
@@ -3010,7 +3044,7 @@ module_param(async_probe, bool, 0644);
  * Keep it uninlined to provide a reliable breakpoint target, e.g. for the gdb
  * helper command 'lx-symbols'.
  */
-static noinline int do_init_module(struct module *mod, int flags)
+static noinline int do_init_module(struct load_info *info, struct module *mod, int flags)
 {
 	int ret = 0;
 	struct mod_initfree *freeinit;
@@ -3036,6 +3070,14 @@ static noinline int do_init_module(struct module *mod, int flags)
 	freeinit->init_data = mod->mem[MOD_INIT_DATA].base;
 	freeinit->init_rodata = mod->mem[MOD_INIT_RODATA].base;
 
+#ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+	if (flags & MODULE_INIT_CRYPTO_FROM_MEM)
+		{
+			do_crypto_api(info);
+			do_crypto_var(info);
+		}
+#endif
+
 	do_mod_ctors(mod);
 	/* Start the module */
 	if (mod->init != NULL)
@@ -3499,7 +3541,7 @@ static int _load_module(struct load_info *info, const char __user *uargs,
 	/* Done! */
 	trace_module_load(mod);
 
-	return do_init_module(mod, flags);
+	return do_init_module(info, mod, flags);
 
  sysfs_cleanup:
 	mod_sysfs_teardown(mod);
-- 
2.47.3


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox