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