diff --git a/code_sign/Kconfig b/code_sign/Kconfig index 0c6a9aae8358853c3ea4a4ce04f79bdd90ebdf1b..e042f8707d85fcc7f307384096c06d1e1060d14f 100644 --- a/code_sign/Kconfig +++ b/code_sign/Kconfig @@ -2,12 +2,13 @@ # Copyright (c) 2023 Huawei Device Co., Ltd. # config SECURITY_CODE_SIGN - bool "Advanced code signing feature based on FS Verity" + bool "Advanced code signing features based on FS Verity" depends on FS_VERITY default n help - This option enables additional code signing verify features - based on fs-verity, including verify if a certificate's subject - and issuer can be trusted, etc. + This option enables additional code signing features based + on fs-verity, such as 1) protecting part of file to support + carried signature and Merkle tree, 2) verifying if a signing + certificate can be trusted, etc. If unsure, say N. diff --git a/code_sign/Makefile b/code_sign/Makefile index ab3b9826b20de2b84a83b86f2994c2fa91ba88e4..894ea26ad788bec815fa9567de0968eea49bb976 100644 --- a/code_sign/Makefile +++ b/code_sign/Makefile @@ -4,7 +4,8 @@ obj-$(CONFIG_SECURITY_CODE_SIGN) += \ code_sign_misc.o \ verify_cert_chain.o \ - code_sign_ioctl.o + code_sign_ioctl.o \ + code_sign_ext.o ccflags-$(CONFIG_SECURITY_CODE_SIGN) += \ -I$(srctree)/fs/code_sign \ diff --git a/code_sign/code_sign_ext.c b/code_sign/code_sign_ext.c new file mode 100644 index 0000000000000000000000000000000000000000..c5d21265f53a6464b8ed72b561700e5e73a1aaa1 --- /dev/null +++ b/code_sign/code_sign_ext.c @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + */ + +#include +#include + +#include "code_sign_ext.h" +#include "code_sign_log.h" + +/** + * Validate code sign descriptor + * + * Return: 1 on code sign version, 0 on basic version, and -errno on failure + */ +static inline int check_code_sign_descriptor(const struct inode *inode, + const struct code_sign_descriptor *desc) +{ + u64 tree_offset = le64_to_cpu(desc->tree_offset); + + if (!desc->cs_version) + return 0; + + if (desc->__reserved1 || + memchr_inv(desc->__reserved2, 0, sizeof(desc->__reserved2))) + return -EINVAL; + + if (le64_to_cpu(desc->data_size) > inode->i_size) { + code_sign_log_error("Wrong data_size: %llu (desc) > %lld (inode)", + le64_to_cpu(desc->data_size), inode->i_size); + return -EINVAL; + } + + if (desc->salt_size > sizeof(desc->salt)) { + code_sign_log_error("Invalid salt_size: %u", desc->salt_size); + return -EINVAL; + } + + if (IS_INSIDE_TREE(desc)) { + if ((tree_offset > inode->i_size) || (tree_offset % PAGE_SIZE != 0)) { + code_sign_log_error( + "Wrong tree_offset: %llu (desc) > %lld (file size) or alignment is wrong", + tree_offset, inode->i_size); + return -EINVAL; + } + } else { + if (tree_offset != 0) { + code_sign_log_error( + "Wrong tree_offset without tree: %llu (desc) != 0", + tree_offset); + return -EINVAL; + } + } + return 1; +} + +void code_sign_check_descriptor(const struct inode *inode, const void *desc, int *ret) +{ + *ret = check_code_sign_descriptor(inode, CONST_CAST_CODE_SIGN_DESC(desc)); +} + +void code_sign_before_measurement(void *_desc, int *ret) +{ + struct code_sign_descriptor *desc = CAST_CODE_SIGN_DESC(_desc); + + if (desc->cs_version) { + // replace version with cs_version + desc->version = desc->cs_version; + desc->cs_version = 0; + *ret = desc->version; + } +} + +void code_sign_after_measurement(void *_desc, int version) +{ + struct code_sign_descriptor *desc = CAST_CODE_SIGN_DESC(_desc); + + if (version) { + // restore cs_version + desc->cs_version = desc->version; + desc->version = version; + } +} diff --git a/code_sign/code_sign_ext.h b/code_sign/code_sign_ext.h new file mode 100644 index 0000000000000000000000000000000000000000..d424907344541442339a11d43743065db5f27273 --- /dev/null +++ b/code_sign/code_sign_ext.h @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + */ + +#ifndef _CODE_SIGN_EXT_H +#define _CODE_SIGN_EXT_H + +/* + * code_sign_ext.c + */ +void code_sign_check_descriptor(const struct inode *inode, + const void *desc, int *ret); + +void code_sign_before_measurement(void *_desc, int *ret); + +void code_sign_after_measurement(void *_desc, int version); + +#endif /* _CODE_SIGN_H */ diff --git a/code_sign/code_sign_misc.c b/code_sign/code_sign_misc.c index c2237bd4fe3e9ee3d2ab9809a630d97f859d5577..0fe17ee61a82a4f23ccc71c167c4527fe4562366 100644 --- a/code_sign/code_sign_misc.c +++ b/code_sign/code_sign_misc.c @@ -10,6 +10,7 @@ #include "code_sign_ioctl.h" #include "code_sign_log.h" +#include "code_sign_ext.h" static const struct file_operations code_sign_ops = { .owner = THIS_MODULE, @@ -28,6 +29,9 @@ static struct miscdevice code_sign_misc = { static void code_sign_register_hck_hooks(void) { REGISTER_HCK_LITE_HOOK(code_sign_verify_certchain_lhck, code_sign_verify_certchain); + REGISTER_HCK_LITE_HOOK(code_sign_check_descriptor_lhck, code_sign_check_descriptor); + REGISTER_HCK_LITE_HOOK(code_sign_before_measurement_lhck, code_sign_before_measurement); + REGISTER_HCK_LITE_HOOK(code_sign_after_measurement_lhck, code_sign_after_measurement); } static int __init code_sign_init(void) @@ -46,4 +50,4 @@ static void __exit code_sign_exit(void) module_init(code_sign_init); module_exit(code_sign_exit); -MODULE_LICENSE("GPL"); \ No newline at end of file +MODULE_LICENSE("GPL");