162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * FIPS 200 support. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2008 Neil Horman <nhorman@tuxdriver.com> 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/export.h> 962306a36Sopenharmony_ci#include <linux/fips.h> 1062306a36Sopenharmony_ci#include <linux/init.h> 1162306a36Sopenharmony_ci#include <linux/module.h> 1262306a36Sopenharmony_ci#include <linux/kernel.h> 1362306a36Sopenharmony_ci#include <linux/sysctl.h> 1462306a36Sopenharmony_ci#include <linux/notifier.h> 1562306a36Sopenharmony_ci#include <generated/utsrelease.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ciint fips_enabled; 1862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(fips_enabled); 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ciATOMIC_NOTIFIER_HEAD(fips_fail_notif_chain); 2162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(fips_fail_notif_chain); 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci/* Process kernel command-line parameter at boot time. fips=0 or fips=1 */ 2462306a36Sopenharmony_cistatic int fips_enable(char *str) 2562306a36Sopenharmony_ci{ 2662306a36Sopenharmony_ci fips_enabled = !!simple_strtol(str, NULL, 0); 2762306a36Sopenharmony_ci printk(KERN_INFO "fips mode: %s\n", 2862306a36Sopenharmony_ci fips_enabled ? "enabled" : "disabled"); 2962306a36Sopenharmony_ci return 1; 3062306a36Sopenharmony_ci} 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci__setup("fips=", fips_enable); 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#define FIPS_MODULE_NAME CONFIG_CRYPTO_FIPS_NAME 3562306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_FIPS_CUSTOM_VERSION 3662306a36Sopenharmony_ci#define FIPS_MODULE_VERSION CONFIG_CRYPTO_FIPS_VERSION 3762306a36Sopenharmony_ci#else 3862306a36Sopenharmony_ci#define FIPS_MODULE_VERSION UTS_RELEASE 3962306a36Sopenharmony_ci#endif 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cistatic char fips_name[] = FIPS_MODULE_NAME; 4262306a36Sopenharmony_cistatic char fips_version[] = FIPS_MODULE_VERSION; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cistatic struct ctl_table crypto_sysctl_table[] = { 4562306a36Sopenharmony_ci { 4662306a36Sopenharmony_ci .procname = "fips_enabled", 4762306a36Sopenharmony_ci .data = &fips_enabled, 4862306a36Sopenharmony_ci .maxlen = sizeof(int), 4962306a36Sopenharmony_ci .mode = 0444, 5062306a36Sopenharmony_ci .proc_handler = proc_dointvec 5162306a36Sopenharmony_ci }, 5262306a36Sopenharmony_ci { 5362306a36Sopenharmony_ci .procname = "fips_name", 5462306a36Sopenharmony_ci .data = &fips_name, 5562306a36Sopenharmony_ci .maxlen = 64, 5662306a36Sopenharmony_ci .mode = 0444, 5762306a36Sopenharmony_ci .proc_handler = proc_dostring 5862306a36Sopenharmony_ci }, 5962306a36Sopenharmony_ci { 6062306a36Sopenharmony_ci .procname = "fips_version", 6162306a36Sopenharmony_ci .data = &fips_version, 6262306a36Sopenharmony_ci .maxlen = 64, 6362306a36Sopenharmony_ci .mode = 0444, 6462306a36Sopenharmony_ci .proc_handler = proc_dostring 6562306a36Sopenharmony_ci }, 6662306a36Sopenharmony_ci {} 6762306a36Sopenharmony_ci}; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistatic struct ctl_table_header *crypto_sysctls; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_cistatic void crypto_proc_fips_init(void) 7262306a36Sopenharmony_ci{ 7362306a36Sopenharmony_ci crypto_sysctls = register_sysctl("crypto", crypto_sysctl_table); 7462306a36Sopenharmony_ci} 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_cistatic void crypto_proc_fips_exit(void) 7762306a36Sopenharmony_ci{ 7862306a36Sopenharmony_ci unregister_sysctl_table(crypto_sysctls); 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_civoid fips_fail_notify(void) 8262306a36Sopenharmony_ci{ 8362306a36Sopenharmony_ci if (fips_enabled) 8462306a36Sopenharmony_ci atomic_notifier_call_chain(&fips_fail_notif_chain, 0, NULL); 8562306a36Sopenharmony_ci} 8662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(fips_fail_notify); 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_cistatic int __init fips_init(void) 8962306a36Sopenharmony_ci{ 9062306a36Sopenharmony_ci crypto_proc_fips_init(); 9162306a36Sopenharmony_ci return 0; 9262306a36Sopenharmony_ci} 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_cistatic void __exit fips_exit(void) 9562306a36Sopenharmony_ci{ 9662306a36Sopenharmony_ci crypto_proc_fips_exit(); 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cisubsys_initcall(fips_init); 10062306a36Sopenharmony_cimodule_exit(fips_exit); 101