Snap for 7941660 from a50661b8f4
to android12-5.10-keystone-qcom-release
Change-Id: I000a9530bd8f32f400cf21bc478e20a3344f2105
This commit is contained in:
@@ -280,6 +280,7 @@
|
||||
<elf-symbol name='__traceiter_android_rvh_dequeue_task_fair' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes' crc='0x37a9a528'/>
|
||||
<elf-symbol name='__traceiter_android_rvh_die_kernel_fault' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes' crc='0x91f68209'/>
|
||||
<elf-symbol name='__traceiter_android_rvh_do_mem_abort' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes' crc='0x669812d6'/>
|
||||
<elf-symbol name='__traceiter_android_rvh_do_sched_yield' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes' crc='0xe0fb88e'/>
|
||||
<elf-symbol name='__traceiter_android_rvh_do_sp_pc_abort' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes' crc='0x47243dfd'/>
|
||||
<elf-symbol name='__traceiter_android_rvh_enqueue_entity' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes' crc='0xb0c4e55d'/>
|
||||
<elf-symbol name='__traceiter_android_rvh_enqueue_task' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes' crc='0x58dae35a'/>
|
||||
@@ -5680,6 +5681,7 @@
|
||||
<elf-symbol name='__tracepoint_android_rvh_dequeue_task_idle' size='72' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes' crc='0x82ae67dd'/>
|
||||
<elf-symbol name='__tracepoint_android_rvh_die_kernel_fault' size='72' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes' crc='0x33c9af1e'/>
|
||||
<elf-symbol name='__tracepoint_android_rvh_do_mem_abort' size='72' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes' crc='0xadec6b55'/>
|
||||
<elf-symbol name='__tracepoint_android_rvh_do_sched_yield' size='72' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes' crc='0xe4ee9cad'/>
|
||||
<elf-symbol name='__tracepoint_android_rvh_do_sea' size='72' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes' crc='0x23501356'/>
|
||||
<elf-symbol name='__tracepoint_android_rvh_do_sp_pc_abort' size='72' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes' crc='0x1ed564a9'/>
|
||||
<elf-symbol name='__tracepoint_android_rvh_do_undefinstr' size='72' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes' crc='0x48a1e8c'/>
|
||||
@@ -114561,6 +114563,11 @@
|
||||
<parameter type-id='80f4b756' name='msg' filepath='include/trace/hooks/fault.h' line='23' column='1'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='__traceiter_android_rvh_do_sched_yield' mangled-name='__traceiter_android_rvh_do_sched_yield' filepath='include/trace/hooks/sched.h' line='294' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='__traceiter_android_rvh_do_sched_yield'>
|
||||
<parameter type-id='eaa32e2f' name='__data' filepath='include/trace/hooks/sched.h' line='294' column='1'/>
|
||||
<parameter type-id='6ed6b432' name='rq' filepath='include/trace/hooks/sched.h' line='294' column='1'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='__traceiter_android_rvh_do_sp_pc_abort' mangled-name='__traceiter_android_rvh_do_sp_pc_abort' filepath='include/trace/hooks/fault.h' line='27' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='__traceiter_android_rvh_do_sp_pc_abort'>
|
||||
<parameter type-id='eaa32e2f' name='__data' filepath='include/trace/hooks/fault.h' line='27' column='1'/>
|
||||
<parameter type-id='4616a179' name='regs' filepath='include/trace/hooks/fault.h' line='27' column='1'/>
|
||||
@@ -116568,6 +116575,7 @@
|
||||
<var-decl name='__tracepoint_android_rvh_dequeue_task_idle' type-id='4ca0c298' mangled-name='__tracepoint_android_rvh_dequeue_task_idle' visibility='default' filepath='include/trace/hooks/sched.h' line='246' column='1' elf-symbol-id='__tracepoint_android_rvh_dequeue_task_idle'/>
|
||||
<var-decl name='__tracepoint_android_rvh_die_kernel_fault' type-id='4ca0c298' mangled-name='__tracepoint_android_rvh_die_kernel_fault' visibility='default' filepath='include/trace/hooks/fault.h' line='15' column='1' elf-symbol-id='__tracepoint_android_rvh_die_kernel_fault'/>
|
||||
<var-decl name='__tracepoint_android_rvh_do_mem_abort' type-id='4ca0c298' mangled-name='__tracepoint_android_rvh_do_mem_abort' visibility='default' filepath='include/trace/hooks/fault.h' line='23' column='1' elf-symbol-id='__tracepoint_android_rvh_do_mem_abort'/>
|
||||
<var-decl name='__tracepoint_android_rvh_do_sched_yield' type-id='4ca0c298' mangled-name='__tracepoint_android_rvh_do_sched_yield' visibility='default' filepath='include/trace/hooks/sched.h' line='294' column='1' elf-symbol-id='__tracepoint_android_rvh_do_sched_yield'/>
|
||||
<var-decl name='__tracepoint_android_rvh_do_sea' type-id='4ca0c298' mangled-name='__tracepoint_android_rvh_do_sea' visibility='default' filepath='include/trace/hooks/fault.h' line='19' column='1' elf-symbol-id='__tracepoint_android_rvh_do_sea'/>
|
||||
<var-decl name='__tracepoint_android_rvh_do_sp_pc_abort' type-id='4ca0c298' mangled-name='__tracepoint_android_rvh_do_sp_pc_abort' visibility='default' filepath='include/trace/hooks/fault.h' line='27' column='1' elf-symbol-id='__tracepoint_android_rvh_do_sp_pc_abort'/>
|
||||
<var-decl name='__tracepoint_android_rvh_do_undefinstr' type-id='4ca0c298' mangled-name='__tracepoint_android_rvh_do_undefinstr' visibility='default' filepath='include/trace/hooks/traps.h' line='15' column='1' elf-symbol-id='__tracepoint_android_rvh_do_undefinstr'/>
|
||||
|
@@ -2501,6 +2501,7 @@
|
||||
__traceiter_android_rvh_cpu_cgroup_online
|
||||
__traceiter_android_rvh_cpufreq_transition
|
||||
__traceiter_android_rvh_dequeue_task
|
||||
__traceiter_android_rvh_do_sched_yield
|
||||
__traceiter_android_rvh_enqueue_task
|
||||
__traceiter_android_rvh_find_busiest_queue
|
||||
__traceiter_android_rvh_find_lowest_rq
|
||||
@@ -2612,6 +2613,7 @@
|
||||
__tracepoint_android_rvh_cpu_cgroup_online
|
||||
__tracepoint_android_rvh_cpufreq_transition
|
||||
__tracepoint_android_rvh_dequeue_task
|
||||
__tracepoint_android_rvh_do_sched_yield
|
||||
__tracepoint_android_rvh_enqueue_task
|
||||
__tracepoint_android_rvh_find_busiest_queue
|
||||
__tracepoint_android_rvh_find_lowest_rq
|
||||
|
@@ -53,14 +53,14 @@ config CRYPTO_FIPS140_MOD
|
||||
meet FIPS 140 and NIAP FPT_TST_EXT.1 requirements. It shouldn't be
|
||||
used if you don't need to meet these requirements.
|
||||
|
||||
config CRYPTO_FIPS140_MOD_ERROR_INJECTION
|
||||
bool "Support injecting failures into the FIPS 140 self-tests"
|
||||
config CRYPTO_FIPS140_MOD_EVAL_TESTING
|
||||
bool "Enable evaluation testing features in FIPS 140 module"
|
||||
depends on CRYPTO_FIPS140_MOD
|
||||
help
|
||||
This option adds a module parameter "broken_alg" to the fips140 module
|
||||
which can be used to fail the self-tests for a particular algorithm,
|
||||
causing a kernel panic. This option is for FIPS lab testing only, and
|
||||
it shouldn't be enabled on production systems.
|
||||
This option adds some features to the FIPS 140 module which are needed
|
||||
for lab evaluation testing of the module, e.g. support for injecting
|
||||
errors and support for a userspace interface to some of the module's
|
||||
services. This option should not be enabled in production builds.
|
||||
|
||||
config CRYPTO_ALGAPI
|
||||
tristate
|
||||
|
@@ -239,11 +239,14 @@ fips140-objs := \
|
||||
fips140-refs.o \
|
||||
fips140-selftests.o \
|
||||
crypto-fips.a
|
||||
fips140-$(CONFIG_CRYPTO_FIPS140_MOD_EVAL_TESTING) += \
|
||||
fips140-eval-testing.o
|
||||
obj-m += fips140.o
|
||||
|
||||
CFLAGS_fips140-alg-registration.o += $(FIPS140_CFLAGS)
|
||||
CFLAGS_fips140-module.o += $(FIPS140_CFLAGS)
|
||||
CFLAGS_fips140-selftests.o += $(FIPS140_CFLAGS)
|
||||
CFLAGS_fips140-eval-testing.o += $(FIPS140_CFLAGS)
|
||||
|
||||
hostprogs-always-y := fips140_gen_hmac
|
||||
HOSTLDLIBS_fips140_gen_hmac := -lcrypto -lelf
|
||||
|
30
crypto/fips140-eval-testing-uapi.h
Normal file
30
crypto/fips140-eval-testing-uapi.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
|
||||
#ifndef _CRYPTO_FIPS140_EVAL_TESTING_H
|
||||
#define _CRYPTO_FIPS140_EVAL_TESTING_H
|
||||
|
||||
#include <linux/ioctl.h>
|
||||
|
||||
/*
|
||||
* This header defines the ioctls that are available on the fips140 character
|
||||
* device. These ioctls expose some of the module's services to userspace so
|
||||
* that they can be tested by the FIPS certification lab; this is a required
|
||||
* part of getting a FIPS 140 certification. These ioctls do not have any other
|
||||
* purpose, and they do not need to be present in production builds.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Call the fips140_is_approved_service() function. The argument must be the
|
||||
* service name as a NUL-terminated string. The return value will be 1 if
|
||||
* fips140_is_approved_service() returned true, or 0 if it returned false.
|
||||
*/
|
||||
#define FIPS140_IOCTL_IS_APPROVED_SERVICE _IO('F', 0)
|
||||
|
||||
/*
|
||||
* Call the fips140_module_version() function. The argument must be a pointer
|
||||
* to a buffer of size >= 256 chars. The NUL-terminated string returned by
|
||||
* fips140_module_version() will be written to this buffer.
|
||||
*/
|
||||
#define FIPS140_IOCTL_MODULE_VERSION _IOR('F', 1, char[256])
|
||||
|
||||
#endif /* _CRYPTO_FIPS140_EVAL_TESTING_H */
|
129
crypto/fips140-eval-testing.c
Normal file
129
crypto/fips140-eval-testing.c
Normal file
@@ -0,0 +1,129 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright 2021 Google LLC
|
||||
*
|
||||
* This file can optionally be built into fips140.ko in order to support certain
|
||||
* types of testing that the FIPS lab has to do to evaluate the module. It
|
||||
* should not be included in production builds of the module.
|
||||
*/
|
||||
|
||||
/*
|
||||
* We have to redefine inline to mean always_inline, so that _copy_to_user()
|
||||
* gets inlined. This is needed for it to be placed into the correct section.
|
||||
* See fips140_copy_to_user().
|
||||
*
|
||||
* We also need to undefine BUILD_FIPS140_KO to allow the use of the code
|
||||
* patching which copy_to_user() requires.
|
||||
*/
|
||||
#undef inline
|
||||
#define inline inline __attribute__((__always_inline__)) __gnu_inline \
|
||||
__inline_maybe_unused notrace
|
||||
#undef BUILD_FIPS140_KO
|
||||
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "fips140-module.h"
|
||||
#include "fips140-eval-testing-uapi.h"
|
||||
|
||||
/*
|
||||
* This option allows deliberately failing the self-tests for a particular
|
||||
* algorithm.
|
||||
*/
|
||||
static char *fips140_fail_selftest;
|
||||
module_param_named(fail_selftest, fips140_fail_selftest, charp, 0);
|
||||
|
||||
/* This option allows deliberately failing the integrity check. */
|
||||
static bool fips140_fail_integrity_check;
|
||||
module_param_named(fail_integrity_check, fips140_fail_integrity_check, bool, 0);
|
||||
|
||||
static dev_t fips140_devnum;
|
||||
static struct cdev fips140_cdev;
|
||||
|
||||
/* Inject a self-test failure (via corrupting the result) if requested. */
|
||||
void fips140_inject_selftest_failure(const char *impl, u8 *result)
|
||||
{
|
||||
if (fips140_fail_selftest && strcmp(impl, fips140_fail_selftest) == 0)
|
||||
result[0] ^= 0xff;
|
||||
}
|
||||
|
||||
/* Inject an integrity check failure (via corrupting the text) if requested. */
|
||||
void fips140_inject_integrity_failure(u8 *textcopy)
|
||||
{
|
||||
if (fips140_fail_integrity_check)
|
||||
textcopy[0] ^= 0xff;
|
||||
}
|
||||
|
||||
static long fips140_ioctl_is_approved_service(unsigned long arg)
|
||||
{
|
||||
const char *service_name = strndup_user((const char __user *)arg, 256);
|
||||
long ret;
|
||||
|
||||
if (IS_ERR(service_name))
|
||||
return PTR_ERR(service_name);
|
||||
|
||||
ret = fips140_is_approved_service(service_name);
|
||||
|
||||
kfree(service_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Code in fips140.ko is covered by an integrity check by default, and this
|
||||
* check breaks if copy_to_user() is called. This is because copy_to_user() is
|
||||
* an inline function that relies on code patching. However, since this is
|
||||
* "evaluation testing" code which isn't included in the production builds of
|
||||
* fips140.ko, it's acceptable to just exclude it from the integrity check.
|
||||
*/
|
||||
static noinline unsigned long __section("text.._fips140_unchecked")
|
||||
fips140_copy_to_user(void __user *to, const void *from, unsigned long n)
|
||||
{
|
||||
return copy_to_user(to, from, n);
|
||||
}
|
||||
|
||||
static long fips140_ioctl_module_version(unsigned long arg)
|
||||
{
|
||||
const char *version = fips140_module_version();
|
||||
size_t len = strlen(version) + 1;
|
||||
|
||||
if (len > 256)
|
||||
return -EOVERFLOW;
|
||||
|
||||
if (fips140_copy_to_user((void __user *)arg, version, len))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long fips140_ioctl(struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
switch (cmd) {
|
||||
case FIPS140_IOCTL_IS_APPROVED_SERVICE:
|
||||
return fips140_ioctl_is_approved_service(arg);
|
||||
case FIPS140_IOCTL_MODULE_VERSION:
|
||||
return fips140_ioctl_module_version(arg);
|
||||
default:
|
||||
return -ENOTTY;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct file_operations fips140_fops = {
|
||||
.unlocked_ioctl = fips140_ioctl,
|
||||
};
|
||||
|
||||
bool fips140_eval_testing_init(void)
|
||||
{
|
||||
if (alloc_chrdev_region(&fips140_devnum, 1, 1, "fips140") != 0) {
|
||||
pr_err("failed to allocate device number\n");
|
||||
return false;
|
||||
}
|
||||
cdev_init(&fips140_cdev, &fips140_fops);
|
||||
if (cdev_add(&fips140_cdev, fips140_devnum, 1) != 0) {
|
||||
pr_err("failed to add fips140 character device\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
@@ -29,15 +29,6 @@
|
||||
#include "fips140-module.h"
|
||||
#include "internal.h"
|
||||
|
||||
/*
|
||||
* This option allows deliberately failing the self-tests for a particular
|
||||
* algorithm. This is for FIPS lab testing only.
|
||||
*/
|
||||
#ifdef CONFIG_CRYPTO_FIPS140_MOD_ERROR_INJECTION
|
||||
char *fips140_broken_alg;
|
||||
module_param_named(broken_alg, fips140_broken_alg, charp, 0);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* FIPS 140-2 prefers the use of HMAC with a public key over a plain hash.
|
||||
*/
|
||||
@@ -397,6 +388,8 @@ static bool __init check_fips140_module_hmac(void)
|
||||
offset_to_ptr(&fips140_rela_rodata.offset),
|
||||
fips140_rela_rodata.count);
|
||||
|
||||
fips140_inject_integrity_failure(textcopy);
|
||||
|
||||
tfm = crypto_alloc_shash("hmac(sha256)", 0, 0);
|
||||
if (IS_ERR(tfm)) {
|
||||
pr_err("failed to allocate hmac tfm (%ld)\n", PTR_ERR(tfm));
|
||||
@@ -545,6 +538,9 @@ fips140_init(void)
|
||||
if (!update_fips140_library_routines())
|
||||
goto panic;
|
||||
|
||||
if (!fips140_eval_testing_init())
|
||||
goto panic;
|
||||
|
||||
pr_info("module successfully loaded\n");
|
||||
return 0;
|
||||
|
||||
|
@@ -20,16 +20,31 @@
|
||||
#define FIPS140_MODULE_NAME "Android Kernel Cryptographic Module"
|
||||
#define FIPS140_MODULE_VERSION UTS_RELEASE
|
||||
|
||||
#ifdef CONFIG_CRYPTO_FIPS140_MOD_ERROR_INJECTION
|
||||
extern char *fips140_broken_alg;
|
||||
#endif
|
||||
/* fips140-eval-testing.c */
|
||||
#ifdef CONFIG_CRYPTO_FIPS140_MOD_EVAL_TESTING
|
||||
void fips140_inject_selftest_failure(const char *impl, u8 *result);
|
||||
void fips140_inject_integrity_failure(u8 *textcopy);
|
||||
bool fips140_eval_testing_init(void);
|
||||
#else
|
||||
static inline void fips140_inject_selftest_failure(const char *impl, u8 *result)
|
||||
{
|
||||
}
|
||||
static inline void fips140_inject_integrity_failure(u8 *textcopy)
|
||||
{
|
||||
}
|
||||
static inline bool fips140_eval_testing_init(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif /* !CONFIG_CRYPTO_FIPS140_MOD_EVAL_TESTING */
|
||||
|
||||
/* fips140-module.c */
|
||||
extern struct completion fips140_tests_done;
|
||||
extern struct task_struct *fips140_init_thread;
|
||||
|
||||
bool __init __must_check fips140_run_selftests(void);
|
||||
|
||||
bool fips140_is_approved_service(const char *name);
|
||||
const char *fips140_module_version(void);
|
||||
|
||||
/* fips140-selftests.c */
|
||||
bool __init __must_check fips140_run_selftests(void);
|
||||
|
||||
#endif /* _CRYPTO_FIPS140_MODULE_H */
|
||||
|
@@ -146,11 +146,7 @@ static int __init __must_check
|
||||
fips_check_result(u8 *result, const u8 *expected_result, size_t result_size,
|
||||
const char *impl, const char *operation)
|
||||
{
|
||||
#ifdef CONFIG_CRYPTO_FIPS140_MOD_ERROR_INJECTION
|
||||
/* Inject a failure (via corrupting the result) if requested. */
|
||||
if (fips140_broken_alg && strcmp(impl, fips140_broken_alg) == 0)
|
||||
result[0] ^= 0xff;
|
||||
#endif
|
||||
fips140_inject_selftest_failure(impl, result);
|
||||
if (memcmp(result, expected_result, result_size) != 0) {
|
||||
pr_err("wrong result from %s %s\n", impl, operation);
|
||||
return -EBADMSG;
|
||||
|
@@ -239,6 +239,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_create_worker);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_check_preempt_tick);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_check_preempt_wakeup_ignore);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_replace_next_task_fair);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_do_sched_yield);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_wait_for_work);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_sync_txn_recvd);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_build_sched_domains);
|
||||
|
@@ -291,6 +291,10 @@ DECLARE_RESTRICTED_HOOK(android_rvh_replace_next_task_fair,
|
||||
bool simple, struct task_struct *prev),
|
||||
TP_ARGS(rq, p, se, repick, simple, prev), 1);
|
||||
|
||||
DECLARE_RESTRICTED_HOOK(android_rvh_do_sched_yield,
|
||||
TP_PROTO(struct rq *rq),
|
||||
TP_ARGS(rq), 1);
|
||||
|
||||
DECLARE_RESTRICTED_HOOK(android_rvh_util_est_update,
|
||||
TP_PROTO(struct cfs_rq *cfs_rq, struct task_struct *p, bool task_sleep, int *ret),
|
||||
TP_ARGS(cfs_rq, p, task_sleep, ret), 1);
|
||||
|
@@ -6343,6 +6343,8 @@ static void do_sched_yield(void)
|
||||
schedstat_inc(rq->yld_count);
|
||||
current->sched_class->yield_task(rq);
|
||||
|
||||
trace_android_rvh_do_sched_yield(rq);
|
||||
|
||||
preempt_disable();
|
||||
rq_unlock_irq(rq, &rf);
|
||||
sched_preempt_enable_no_resched();
|
||||
|
187
samples/crypto/fips140_lab_test.c
Normal file
187
samples/crypto/fips140_lab_test.c
Normal file
@@ -0,0 +1,187 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright 2021 Google LLC
|
||||
*
|
||||
* This is a sample program which calls some ioctls on /dev/fips140 and prints
|
||||
* the results. The purpose of this program is to allow the FIPS certification
|
||||
* lab to test some services of fips140.ko, which they are required to do. This
|
||||
* is a sample program only, and it can be modified by the lab as needed. This
|
||||
* program must be run as root, and it only works if the system has loaded a
|
||||
* build of fips140.ko with evaluation testing support enabled.
|
||||
*
|
||||
* This program can be compiled and run on an Android device as follows:
|
||||
*
|
||||
* NDK_DIR=$HOME/android-ndk-r23b # adjust directory path as needed
|
||||
* $NDK_DIR/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android31-clang \
|
||||
* fips140_lab_test.c -O2 -Wall -o fips140_lab_test
|
||||
* adb push fips140_lab_test /data/local/tmp/
|
||||
* adb root
|
||||
* adb shell /data/local/tmp/fips140_lab_test
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysmacros.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../../crypto/fips140-eval-testing-uapi.h"
|
||||
|
||||
static int fips140_dev_fd = -1;
|
||||
|
||||
#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
|
||||
|
||||
static const char *booltostr(bool b)
|
||||
{
|
||||
return b ? "true" : "false";
|
||||
}
|
||||
|
||||
static void __attribute__((noreturn))
|
||||
do_die(const char *format, va_list va, int err)
|
||||
{
|
||||
fputs("ERROR: ", stderr);
|
||||
vfprintf(stderr, format, va);
|
||||
if (err)
|
||||
fprintf(stderr, ": %s", strerror(err));
|
||||
putc('\n', stderr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void __attribute__((noreturn, format(printf, 1, 2)))
|
||||
die_errno(const char *format, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
va_start(va, format);
|
||||
do_die(format, va, errno);
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
static void __attribute__((noreturn, format(printf, 1, 2)))
|
||||
die(const char *format, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
va_start(va, format);
|
||||
do_die(format, va, 0);
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
static int get_fips140_device_number(void)
|
||||
{
|
||||
FILE *f;
|
||||
char line[128];
|
||||
int number;
|
||||
char name[32];
|
||||
|
||||
f = fopen("/proc/devices", "r");
|
||||
if (!f)
|
||||
die_errno("failed to open /proc/devices");
|
||||
while (fgets(line, sizeof(line), f)) {
|
||||
if (sscanf(line, "%d %31s", &number, name) == 2 &&
|
||||
strcmp(name, "fips140") == 0)
|
||||
return number;
|
||||
}
|
||||
fclose(f);
|
||||
die("fips140 device node is unavailable.\n"
|
||||
"The fips140 device node is only available when the fips140 module is loaded\n"
|
||||
"and has been built with evaluation testing support.");
|
||||
}
|
||||
|
||||
static void create_fips140_node_if_needed(void)
|
||||
{
|
||||
struct stat stbuf;
|
||||
int major;
|
||||
|
||||
if (stat("/dev/fips140", &stbuf) == 0)
|
||||
return;
|
||||
|
||||
major = get_fips140_device_number();
|
||||
if (mknod("/dev/fips140", S_IFCHR | 0600, makedev(major, 1)) != 0)
|
||||
die_errno("failed to create fips140 device node");
|
||||
}
|
||||
|
||||
static bool fips140_is_approved_service(const char *name)
|
||||
{
|
||||
int ret = ioctl(fips140_dev_fd, FIPS140_IOCTL_IS_APPROVED_SERVICE, name);
|
||||
|
||||
if (ret < 0)
|
||||
die_errno("FIPS140_IOCTL_IS_APPROVED_SERVICE unexpectedly failed");
|
||||
if (ret == 1)
|
||||
return true;
|
||||
if (ret == 0)
|
||||
return false;
|
||||
die("FIPS140_IOCTL_IS_APPROVED_SERVICE returned unexpected value %d",
|
||||
ret);
|
||||
}
|
||||
|
||||
static const char *fips140_module_version(void)
|
||||
{
|
||||
char buf[256];
|
||||
char *str;
|
||||
int ret = ioctl(fips140_dev_fd, FIPS140_IOCTL_MODULE_VERSION, buf);
|
||||
|
||||
if (ret < 0)
|
||||
die_errno("FIPS140_IOCTL_MODULE_VERSION unexpectedly failed");
|
||||
if (ret != 0)
|
||||
die("FIPS140_IOCTL_MODULE_VERSION returned unexpected value %d", ret);
|
||||
str = strdup(buf);
|
||||
if (!str)
|
||||
die("out of memory");
|
||||
return str;
|
||||
}
|
||||
|
||||
static const char * const services_to_check[] = {
|
||||
"aes",
|
||||
"cbc(aes)",
|
||||
"cbcmac(aes)",
|
||||
"cmac(aes)",
|
||||
"ctr(aes)",
|
||||
"cts(cbc(aes))",
|
||||
"ecb(aes)",
|
||||
"essiv(cbc(aes),sha256)",
|
||||
"gcm(aes)",
|
||||
"hmac(sha1)",
|
||||
"hmac(sha224)",
|
||||
"hmac(sha256)",
|
||||
"hmac(sha384)",
|
||||
"hmac(sha512)",
|
||||
"jitterentropy_rng",
|
||||
"sha1",
|
||||
"sha224",
|
||||
"sha256",
|
||||
"sha384",
|
||||
"sha512",
|
||||
"stdrng",
|
||||
"xcbc(aes)",
|
||||
"xts(aes)",
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (getuid() != 0)
|
||||
die("This program requires root. Run 'adb root' first.");
|
||||
|
||||
create_fips140_node_if_needed();
|
||||
|
||||
fips140_dev_fd = open("/dev/fips140", O_RDONLY);
|
||||
if (fips140_dev_fd < 0)
|
||||
die_errno("failed to open /dev/fips140");
|
||||
|
||||
printf("fips140_module_version() => \"%s\"\n", fips140_module_version());
|
||||
for (i = 0; i < ARRAY_SIZE(services_to_check); i++) {
|
||||
const char *service = services_to_check[i];
|
||||
|
||||
printf("fips140_is_approved_service(\"%s\") => %s\n", service,
|
||||
booltostr(fips140_is_approved_service(service)));
|
||||
}
|
||||
return 0;
|
||||
}
|
@@ -71,6 +71,7 @@ SECTIONS {
|
||||
*(.text..L.cfi.jumptable .text..L.cfi.jumptable.*)
|
||||
__cfi_jt_end = .;
|
||||
*(.text.._end)
|
||||
*(.text.._fips140_unchecked)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
Reference in New Issue
Block a user