18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * FIPS 200 support.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 2008 Neil Horman <nhorman@tuxdriver.com>
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/export.h>
98c2ecf20Sopenharmony_ci#include <linux/fips.h>
108c2ecf20Sopenharmony_ci#include <linux/init.h>
118c2ecf20Sopenharmony_ci#include <linux/module.h>
128c2ecf20Sopenharmony_ci#include <linux/kernel.h>
138c2ecf20Sopenharmony_ci#include <linux/sysctl.h>
148c2ecf20Sopenharmony_ci#include <linux/notifier.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ciint fips_enabled;
178c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(fips_enabled);
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ciATOMIC_NOTIFIER_HEAD(fips_fail_notif_chain);
208c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(fips_fail_notif_chain);
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci/* Process kernel command-line parameter at boot time. fips=0 or fips=1 */
238c2ecf20Sopenharmony_cistatic int fips_enable(char *str)
248c2ecf20Sopenharmony_ci{
258c2ecf20Sopenharmony_ci	fips_enabled = !!simple_strtol(str, NULL, 0);
268c2ecf20Sopenharmony_ci	printk(KERN_INFO "fips mode: %s\n",
278c2ecf20Sopenharmony_ci		fips_enabled ? "enabled" : "disabled");
288c2ecf20Sopenharmony_ci	return 1;
298c2ecf20Sopenharmony_ci}
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci__setup("fips=", fips_enable);
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_cistatic struct ctl_table crypto_sysctl_table[] = {
348c2ecf20Sopenharmony_ci	{
358c2ecf20Sopenharmony_ci		.procname       = "fips_enabled",
368c2ecf20Sopenharmony_ci		.data           = &fips_enabled,
378c2ecf20Sopenharmony_ci		.maxlen         = sizeof(int),
388c2ecf20Sopenharmony_ci		.mode           = 0444,
398c2ecf20Sopenharmony_ci		.proc_handler   = proc_dointvec
408c2ecf20Sopenharmony_ci	},
418c2ecf20Sopenharmony_ci	{}
428c2ecf20Sopenharmony_ci};
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_cistatic struct ctl_table crypto_dir_table[] = {
458c2ecf20Sopenharmony_ci	{
468c2ecf20Sopenharmony_ci		.procname       = "crypto",
478c2ecf20Sopenharmony_ci		.mode           = 0555,
488c2ecf20Sopenharmony_ci		.child          = crypto_sysctl_table
498c2ecf20Sopenharmony_ci	},
508c2ecf20Sopenharmony_ci	{}
518c2ecf20Sopenharmony_ci};
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_cistatic struct ctl_table_header *crypto_sysctls;
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_cistatic void crypto_proc_fips_init(void)
568c2ecf20Sopenharmony_ci{
578c2ecf20Sopenharmony_ci	crypto_sysctls = register_sysctl_table(crypto_dir_table);
588c2ecf20Sopenharmony_ci}
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_cistatic void crypto_proc_fips_exit(void)
618c2ecf20Sopenharmony_ci{
628c2ecf20Sopenharmony_ci	unregister_sysctl_table(crypto_sysctls);
638c2ecf20Sopenharmony_ci}
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_civoid fips_fail_notify(void)
668c2ecf20Sopenharmony_ci{
678c2ecf20Sopenharmony_ci	if (fips_enabled)
688c2ecf20Sopenharmony_ci		atomic_notifier_call_chain(&fips_fail_notif_chain, 0, NULL);
698c2ecf20Sopenharmony_ci}
708c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(fips_fail_notify);
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_cistatic int __init fips_init(void)
738c2ecf20Sopenharmony_ci{
748c2ecf20Sopenharmony_ci	crypto_proc_fips_init();
758c2ecf20Sopenharmony_ci	return 0;
768c2ecf20Sopenharmony_ci}
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_cistatic void __exit fips_exit(void)
798c2ecf20Sopenharmony_ci{
808c2ecf20Sopenharmony_ci	crypto_proc_fips_exit();
818c2ecf20Sopenharmony_ci}
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_cisubsys_initcall(fips_init);
848c2ecf20Sopenharmony_cimodule_exit(fips_exit);
85