12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2ccb778e1SNeil Horman /*
3ccb778e1SNeil Horman * FIPS 200 support.
4ccb778e1SNeil Horman *
5ccb778e1SNeil Horman * Copyright (c) 2008 Neil Horman <nhorman@tuxdriver.com>
6ccb778e1SNeil Horman */
7ccb778e1SNeil Horman
876450f93SHerbert Xu #include <linux/export.h>
976450f93SHerbert Xu #include <linux/fips.h>
1076450f93SHerbert Xu #include <linux/init.h>
1194072cb2SHerbert Xu #include <linux/module.h>
1276450f93SHerbert Xu #include <linux/kernel.h>
1394072cb2SHerbert Xu #include <linux/sysctl.h>
149552389cSGilad Ben-Yossef #include <linux/notifier.h>
155a44749fSVladis Dronov #include <generated/utsrelease.h>
16ccb778e1SNeil Horman
17ccb778e1SNeil Horman int fips_enabled;
18ccb778e1SNeil Horman EXPORT_SYMBOL_GPL(fips_enabled);
19ccb778e1SNeil Horman
209552389cSGilad Ben-Yossef ATOMIC_NOTIFIER_HEAD(fips_fail_notif_chain);
219552389cSGilad Ben-Yossef EXPORT_SYMBOL_GPL(fips_fail_notif_chain);
229552389cSGilad Ben-Yossef
23ccb778e1SNeil Horman /* Process kernel command-line parameter at boot time. fips=0 or fips=1 */
fips_enable(char * str)24ccb778e1SNeil Horman static int fips_enable(char *str)
25ccb778e1SNeil Horman {
26ccb778e1SNeil Horman fips_enabled = !!simple_strtol(str, NULL, 0);
27ccb778e1SNeil Horman printk(KERN_INFO "fips mode: %s\n",
28ccb778e1SNeil Horman fips_enabled ? "enabled" : "disabled");
29ccb778e1SNeil Horman return 1;
30ccb778e1SNeil Horman }
31ccb778e1SNeil Horman
32ccb778e1SNeil Horman __setup("fips=", fips_enable);
3394072cb2SHerbert Xu
345a44749fSVladis Dronov #define FIPS_MODULE_NAME CONFIG_CRYPTO_FIPS_NAME
355a44749fSVladis Dronov #ifdef CONFIG_CRYPTO_FIPS_CUSTOM_VERSION
365a44749fSVladis Dronov #define FIPS_MODULE_VERSION CONFIG_CRYPTO_FIPS_VERSION
375a44749fSVladis Dronov #else
385a44749fSVladis Dronov #define FIPS_MODULE_VERSION UTS_RELEASE
395a44749fSVladis Dronov #endif
405a44749fSVladis Dronov
415a44749fSVladis Dronov static char fips_name[] = FIPS_MODULE_NAME;
425a44749fSVladis Dronov static char fips_version[] = FIPS_MODULE_VERSION;
435a44749fSVladis Dronov
4494072cb2SHerbert Xu static struct ctl_table crypto_sysctl_table[] = {
4594072cb2SHerbert Xu {
4694072cb2SHerbert Xu .procname = "fips_enabled",
4794072cb2SHerbert Xu .data = &fips_enabled,
4894072cb2SHerbert Xu .maxlen = sizeof(int),
4994072cb2SHerbert Xu .mode = 0444,
5094072cb2SHerbert Xu .proc_handler = proc_dointvec
5194072cb2SHerbert Xu },
525a44749fSVladis Dronov {
535a44749fSVladis Dronov .procname = "fips_name",
545a44749fSVladis Dronov .data = &fips_name,
555a44749fSVladis Dronov .maxlen = 64,
565a44749fSVladis Dronov .mode = 0444,
575a44749fSVladis Dronov .proc_handler = proc_dostring
585a44749fSVladis Dronov },
595a44749fSVladis Dronov {
605a44749fSVladis Dronov .procname = "fips_version",
615a44749fSVladis Dronov .data = &fips_version,
625a44749fSVladis Dronov .maxlen = 64,
635a44749fSVladis Dronov .mode = 0444,
645a44749fSVladis Dronov .proc_handler = proc_dostring
655a44749fSVladis Dronov },
6694072cb2SHerbert Xu {}
6794072cb2SHerbert Xu };
6894072cb2SHerbert Xu
6994072cb2SHerbert Xu static struct ctl_table_header *crypto_sysctls;
7094072cb2SHerbert Xu
crypto_proc_fips_init(void)7194072cb2SHerbert Xu static void crypto_proc_fips_init(void)
7294072cb2SHerbert Xu {
73*68629182SLuis Chamberlain crypto_sysctls = register_sysctl("crypto", crypto_sysctl_table);
7494072cb2SHerbert Xu }
7594072cb2SHerbert Xu
crypto_proc_fips_exit(void)7694072cb2SHerbert Xu static void crypto_proc_fips_exit(void)
7794072cb2SHerbert Xu {
7894072cb2SHerbert Xu unregister_sysctl_table(crypto_sysctls);
7994072cb2SHerbert Xu }
8094072cb2SHerbert Xu
fips_fail_notify(void)819552389cSGilad Ben-Yossef void fips_fail_notify(void)
829552389cSGilad Ben-Yossef {
839552389cSGilad Ben-Yossef if (fips_enabled)
849552389cSGilad Ben-Yossef atomic_notifier_call_chain(&fips_fail_notif_chain, 0, NULL);
859552389cSGilad Ben-Yossef }
869552389cSGilad Ben-Yossef EXPORT_SYMBOL_GPL(fips_fail_notify);
879552389cSGilad Ben-Yossef
fips_init(void)8894072cb2SHerbert Xu static int __init fips_init(void)
8994072cb2SHerbert Xu {
9094072cb2SHerbert Xu crypto_proc_fips_init();
9194072cb2SHerbert Xu return 0;
9294072cb2SHerbert Xu }
9394072cb2SHerbert Xu
fips_exit(void)9494072cb2SHerbert Xu static void __exit fips_exit(void)
9594072cb2SHerbert Xu {
9694072cb2SHerbert Xu crypto_proc_fips_exit();
9794072cb2SHerbert Xu }
9894072cb2SHerbert Xu
99c4741b23SEric Biggers subsys_initcall(fips_init);
10094072cb2SHerbert Xu module_exit(fips_exit);
101