1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (c) 2023 Huawei Device Co., Ltd. 4 */ 5 6#include <linux/code_sign.h> 7#include <linux/fsverity.h> 8#include <linux/stringhash.h> 9 10#include "code_sign_ext.h" 11#include "code_sign_log.h" 12 13static time64_t cs_salt; 14 15/** 16 * Validate code sign descriptor 17 * 18 * Return: 1 on code sign version, 0 on basic version, and -errno on failure 19 */ 20static inline int check_code_sign_descriptor(const struct inode *inode, 21 const struct code_sign_descriptor *desc) 22{ 23 u64 tree_offset = le64_to_cpu(desc->tree_offset); 24 25 if (!desc->cs_version) 26 return 0; 27 28 // when calc pgtypeinfo_size, trans bit size to byte size 29 u32 pgtypeinfo_size_bytes = le32_to_cpu(desc->pgtypeinfo_size) / 8; 30 if (le64_to_cpu(desc->pgtypeinfo_off) > le64_to_cpu(desc->data_size) - pgtypeinfo_size_bytes) { 31 code_sign_log_error("Wrong offset: %llu (pgtypeinfo_off) > %llu (data_size) - %u (pgtypeinfo_size)", 32 le64_to_cpu(desc->pgtypeinfo_off), le64_to_cpu(desc->data_size), pgtypeinfo_size_bytes); 33 return -EINVAL; 34 } 35 36 if (le64_to_cpu(desc->data_size) > inode->i_size) { 37 code_sign_log_error("Wrong data_size: %llu (desc) > %lld (inode)", 38 le64_to_cpu(desc->data_size), inode->i_size); 39 return -EINVAL; 40 } 41 42 if (desc->salt_size > sizeof(desc->salt)) { 43 code_sign_log_error("Invalid salt_size: %u", desc->salt_size); 44 return -EINVAL; 45 } 46 47 if (IS_INSIDE_TREE(desc)) { 48 if ((tree_offset > inode->i_size) || (tree_offset % PAGE_SIZE != 0)) { 49 code_sign_log_error( 50 "Wrong tree_offset: %llu (desc) > %lld (file size) or alignment is wrong", 51 tree_offset, inode->i_size); 52 return -EINVAL; 53 } 54 } else { 55 if (tree_offset != 0) { 56 code_sign_log_error( 57 "Wrong tree_offset without tree: %llu (desc) != 0", 58 tree_offset); 59 return -EINVAL; 60 } 61 } 62 return 1; 63} 64 65void code_sign_check_descriptor(const struct inode *inode, const void *desc, int *ret) 66{ 67 *ret = check_code_sign_descriptor(inode, CONST_CAST_CODE_SIGN_DESC(desc)); 68} 69 70void code_sign_before_measurement(void *_desc, int *ret) 71{ 72 struct code_sign_descriptor *desc = CAST_CODE_SIGN_DESC(_desc); 73 74 if (desc->cs_version == 1) { 75 *ret = desc->cs_version; 76 desc->cs_version = 0; 77 } else { 78 *ret = desc->cs_version; 79 } 80} 81 82void code_sign_after_measurement(void *_desc, int version) 83{ 84 struct code_sign_descriptor *desc = CAST_CODE_SIGN_DESC(_desc); 85 86 if (version == 1) { 87 // restore cs_version 88 desc->cs_version = desc->version; 89 desc->version = version; 90 } 91} 92 93void code_sign_init_salt(void) 94{ 95 cs_salt = ktime_get_real_seconds(); 96} 97 98void code_sign_set_ownerid(struct cs_info *cs_info, uint32_t id_type, 99 const char *id_str, uint32_t id_len) 100{ 101 if (!cs_info) { 102 code_sign_log_error("Input cs_info is NULL"); 103 return; 104 } 105 106 cs_info->id_type = id_type; 107 if (!id_str || id_len == 0) 108 cs_info->ownerid = 0; 109 else 110 cs_info->ownerid = full_name_hash(cs_salt, id_str, id_len); 111}