18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2005-2010 IBM Corporation 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Authors: 68c2ecf20Sopenharmony_ci * Mimi Zohar <zohar@us.ibm.com> 78c2ecf20Sopenharmony_ci * Kylene Hall <kjhall@us.ibm.com> 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * File: evm_crypto.c 108c2ecf20Sopenharmony_ci * Using root's kernel master key (kmk), calculate the HMAC 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <linux/export.h> 148c2ecf20Sopenharmony_ci#include <linux/crypto.h> 158c2ecf20Sopenharmony_ci#include <linux/xattr.h> 168c2ecf20Sopenharmony_ci#include <linux/evm.h> 178c2ecf20Sopenharmony_ci#include <keys/encrypted-type.h> 188c2ecf20Sopenharmony_ci#include <crypto/hash.h> 198c2ecf20Sopenharmony_ci#include <crypto/hash_info.h> 208c2ecf20Sopenharmony_ci#include "evm.h" 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#define EVMKEY "evm-key" 238c2ecf20Sopenharmony_ci#define MAX_KEY_SIZE 128 248c2ecf20Sopenharmony_cistatic unsigned char evmkey[MAX_KEY_SIZE]; 258c2ecf20Sopenharmony_cistatic const int evmkey_len = MAX_KEY_SIZE; 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistruct crypto_shash *hmac_tfm; 288c2ecf20Sopenharmony_cistatic struct crypto_shash *evm_tfm[HASH_ALGO__LAST]; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(mutex); 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#define EVM_SET_KEY_BUSY 0 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_cistatic unsigned long evm_set_key_flags; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistatic const char evm_hmac[] = "hmac(sha1)"; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci/** 398c2ecf20Sopenharmony_ci * evm_set_key() - set EVM HMAC key from the kernel 408c2ecf20Sopenharmony_ci * @key: pointer to a buffer with the key data 418c2ecf20Sopenharmony_ci * @size: length of the key data 428c2ecf20Sopenharmony_ci * 438c2ecf20Sopenharmony_ci * This function allows setting the EVM HMAC key from the kernel 448c2ecf20Sopenharmony_ci * without using the "encrypted" key subsystem keys. It can be used 458c2ecf20Sopenharmony_ci * by the crypto HW kernel module which has its own way of managing 468c2ecf20Sopenharmony_ci * keys. 478c2ecf20Sopenharmony_ci * 488c2ecf20Sopenharmony_ci * key length should be between 32 and 128 bytes long 498c2ecf20Sopenharmony_ci */ 508c2ecf20Sopenharmony_ciint evm_set_key(void *key, size_t keylen) 518c2ecf20Sopenharmony_ci{ 528c2ecf20Sopenharmony_ci int rc; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci rc = -EBUSY; 558c2ecf20Sopenharmony_ci if (test_and_set_bit(EVM_SET_KEY_BUSY, &evm_set_key_flags)) 568c2ecf20Sopenharmony_ci goto busy; 578c2ecf20Sopenharmony_ci rc = -EINVAL; 588c2ecf20Sopenharmony_ci if (keylen > MAX_KEY_SIZE) 598c2ecf20Sopenharmony_ci goto inval; 608c2ecf20Sopenharmony_ci memcpy(evmkey, key, keylen); 618c2ecf20Sopenharmony_ci evm_initialized |= EVM_INIT_HMAC; 628c2ecf20Sopenharmony_ci pr_info("key initialized\n"); 638c2ecf20Sopenharmony_ci return 0; 648c2ecf20Sopenharmony_ciinval: 658c2ecf20Sopenharmony_ci clear_bit(EVM_SET_KEY_BUSY, &evm_set_key_flags); 668c2ecf20Sopenharmony_cibusy: 678c2ecf20Sopenharmony_ci pr_err("key initialization failed\n"); 688c2ecf20Sopenharmony_ci return rc; 698c2ecf20Sopenharmony_ci} 708c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(evm_set_key); 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cistatic struct shash_desc *init_desc(char type, uint8_t hash_algo) 738c2ecf20Sopenharmony_ci{ 748c2ecf20Sopenharmony_ci long rc; 758c2ecf20Sopenharmony_ci const char *algo; 768c2ecf20Sopenharmony_ci struct crypto_shash **tfm, *tmp_tfm; 778c2ecf20Sopenharmony_ci struct shash_desc *desc; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci if (type == EVM_XATTR_HMAC) { 808c2ecf20Sopenharmony_ci if (!(evm_initialized & EVM_INIT_HMAC)) { 818c2ecf20Sopenharmony_ci pr_err_once("HMAC key is not set\n"); 828c2ecf20Sopenharmony_ci return ERR_PTR(-ENOKEY); 838c2ecf20Sopenharmony_ci } 848c2ecf20Sopenharmony_ci tfm = &hmac_tfm; 858c2ecf20Sopenharmony_ci algo = evm_hmac; 868c2ecf20Sopenharmony_ci } else { 878c2ecf20Sopenharmony_ci if (hash_algo >= HASH_ALGO__LAST) 888c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci tfm = &evm_tfm[hash_algo]; 918c2ecf20Sopenharmony_ci algo = hash_algo_name[hash_algo]; 928c2ecf20Sopenharmony_ci } 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci if (*tfm) 958c2ecf20Sopenharmony_ci goto alloc; 968c2ecf20Sopenharmony_ci mutex_lock(&mutex); 978c2ecf20Sopenharmony_ci if (*tfm) 988c2ecf20Sopenharmony_ci goto unlock; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci tmp_tfm = crypto_alloc_shash(algo, 0, CRYPTO_NOLOAD); 1018c2ecf20Sopenharmony_ci if (IS_ERR(tmp_tfm)) { 1028c2ecf20Sopenharmony_ci pr_err("Can not allocate %s (reason: %ld)\n", algo, 1038c2ecf20Sopenharmony_ci PTR_ERR(tmp_tfm)); 1048c2ecf20Sopenharmony_ci mutex_unlock(&mutex); 1058c2ecf20Sopenharmony_ci return ERR_CAST(tmp_tfm); 1068c2ecf20Sopenharmony_ci } 1078c2ecf20Sopenharmony_ci if (type == EVM_XATTR_HMAC) { 1088c2ecf20Sopenharmony_ci rc = crypto_shash_setkey(tmp_tfm, evmkey, evmkey_len); 1098c2ecf20Sopenharmony_ci if (rc) { 1108c2ecf20Sopenharmony_ci crypto_free_shash(tmp_tfm); 1118c2ecf20Sopenharmony_ci mutex_unlock(&mutex); 1128c2ecf20Sopenharmony_ci return ERR_PTR(rc); 1138c2ecf20Sopenharmony_ci } 1148c2ecf20Sopenharmony_ci } 1158c2ecf20Sopenharmony_ci *tfm = tmp_tfm; 1168c2ecf20Sopenharmony_ciunlock: 1178c2ecf20Sopenharmony_ci mutex_unlock(&mutex); 1188c2ecf20Sopenharmony_cialloc: 1198c2ecf20Sopenharmony_ci desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(*tfm), 1208c2ecf20Sopenharmony_ci GFP_KERNEL); 1218c2ecf20Sopenharmony_ci if (!desc) 1228c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci desc->tfm = *tfm; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci rc = crypto_shash_init(desc); 1278c2ecf20Sopenharmony_ci if (rc) { 1288c2ecf20Sopenharmony_ci kfree(desc); 1298c2ecf20Sopenharmony_ci return ERR_PTR(rc); 1308c2ecf20Sopenharmony_ci } 1318c2ecf20Sopenharmony_ci return desc; 1328c2ecf20Sopenharmony_ci} 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci/* Protect against 'cutting & pasting' security.evm xattr, include inode 1358c2ecf20Sopenharmony_ci * specific info. 1368c2ecf20Sopenharmony_ci * 1378c2ecf20Sopenharmony_ci * (Additional directory/file metadata needs to be added for more complete 1388c2ecf20Sopenharmony_ci * protection.) 1398c2ecf20Sopenharmony_ci */ 1408c2ecf20Sopenharmony_cistatic void hmac_add_misc(struct shash_desc *desc, struct inode *inode, 1418c2ecf20Sopenharmony_ci char type, char *digest) 1428c2ecf20Sopenharmony_ci{ 1438c2ecf20Sopenharmony_ci struct h_misc { 1448c2ecf20Sopenharmony_ci unsigned long ino; 1458c2ecf20Sopenharmony_ci __u32 generation; 1468c2ecf20Sopenharmony_ci uid_t uid; 1478c2ecf20Sopenharmony_ci gid_t gid; 1488c2ecf20Sopenharmony_ci umode_t mode; 1498c2ecf20Sopenharmony_ci } hmac_misc; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci memset(&hmac_misc, 0, sizeof(hmac_misc)); 1528c2ecf20Sopenharmony_ci /* Don't include the inode or generation number in portable 1538c2ecf20Sopenharmony_ci * signatures 1548c2ecf20Sopenharmony_ci */ 1558c2ecf20Sopenharmony_ci if (type != EVM_XATTR_PORTABLE_DIGSIG) { 1568c2ecf20Sopenharmony_ci hmac_misc.ino = inode->i_ino; 1578c2ecf20Sopenharmony_ci hmac_misc.generation = inode->i_generation; 1588c2ecf20Sopenharmony_ci } 1598c2ecf20Sopenharmony_ci /* The hmac uid and gid must be encoded in the initial user 1608c2ecf20Sopenharmony_ci * namespace (not the filesystems user namespace) as encoding 1618c2ecf20Sopenharmony_ci * them in the filesystems user namespace allows an attack 1628c2ecf20Sopenharmony_ci * where first they are written in an unprivileged fuse mount 1638c2ecf20Sopenharmony_ci * of a filesystem and then the system is tricked to mount the 1648c2ecf20Sopenharmony_ci * filesystem for real on next boot and trust it because 1658c2ecf20Sopenharmony_ci * everything is signed. 1668c2ecf20Sopenharmony_ci */ 1678c2ecf20Sopenharmony_ci hmac_misc.uid = from_kuid(&init_user_ns, inode->i_uid); 1688c2ecf20Sopenharmony_ci hmac_misc.gid = from_kgid(&init_user_ns, inode->i_gid); 1698c2ecf20Sopenharmony_ci hmac_misc.mode = inode->i_mode; 1708c2ecf20Sopenharmony_ci crypto_shash_update(desc, (const u8 *)&hmac_misc, sizeof(hmac_misc)); 1718c2ecf20Sopenharmony_ci if ((evm_hmac_attrs & EVM_ATTR_FSUUID) && 1728c2ecf20Sopenharmony_ci type != EVM_XATTR_PORTABLE_DIGSIG) 1738c2ecf20Sopenharmony_ci crypto_shash_update(desc, (u8 *)&inode->i_sb->s_uuid, UUID_SIZE); 1748c2ecf20Sopenharmony_ci crypto_shash_final(desc, digest); 1758c2ecf20Sopenharmony_ci} 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci/* 1788c2ecf20Sopenharmony_ci * Calculate the HMAC value across the set of protected security xattrs. 1798c2ecf20Sopenharmony_ci * 1808c2ecf20Sopenharmony_ci * Instead of retrieving the requested xattr, for performance, calculate 1818c2ecf20Sopenharmony_ci * the hmac using the requested xattr value. Don't alloc/free memory for 1828c2ecf20Sopenharmony_ci * each xattr, but attempt to re-use the previously allocated memory. 1838c2ecf20Sopenharmony_ci */ 1848c2ecf20Sopenharmony_cistatic int evm_calc_hmac_or_hash(struct dentry *dentry, 1858c2ecf20Sopenharmony_ci const char *req_xattr_name, 1868c2ecf20Sopenharmony_ci const char *req_xattr_value, 1878c2ecf20Sopenharmony_ci size_t req_xattr_value_len, 1888c2ecf20Sopenharmony_ci uint8_t type, struct evm_digest *data) 1898c2ecf20Sopenharmony_ci{ 1908c2ecf20Sopenharmony_ci struct inode *inode = d_backing_inode(dentry); 1918c2ecf20Sopenharmony_ci struct xattr_list *xattr; 1928c2ecf20Sopenharmony_ci struct shash_desc *desc; 1938c2ecf20Sopenharmony_ci size_t xattr_size = 0; 1948c2ecf20Sopenharmony_ci char *xattr_value = NULL; 1958c2ecf20Sopenharmony_ci int error; 1968c2ecf20Sopenharmony_ci int size; 1978c2ecf20Sopenharmony_ci bool ima_present = false; 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci if (!(inode->i_opflags & IOP_XATTR) || 2008c2ecf20Sopenharmony_ci inode->i_sb->s_user_ns != &init_user_ns) 2018c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci desc = init_desc(type, data->hdr.algo); 2048c2ecf20Sopenharmony_ci if (IS_ERR(desc)) 2058c2ecf20Sopenharmony_ci return PTR_ERR(desc); 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci data->hdr.length = crypto_shash_digestsize(desc->tfm); 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci error = -ENODATA; 2108c2ecf20Sopenharmony_ci list_for_each_entry_lockless(xattr, &evm_config_xattrnames, list) { 2118c2ecf20Sopenharmony_ci bool is_ima = false; 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci if (strcmp(xattr->name, XATTR_NAME_IMA) == 0) 2148c2ecf20Sopenharmony_ci is_ima = true; 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci if ((req_xattr_name && req_xattr_value) 2178c2ecf20Sopenharmony_ci && !strcmp(xattr->name, req_xattr_name)) { 2188c2ecf20Sopenharmony_ci error = 0; 2198c2ecf20Sopenharmony_ci crypto_shash_update(desc, (const u8 *)req_xattr_value, 2208c2ecf20Sopenharmony_ci req_xattr_value_len); 2218c2ecf20Sopenharmony_ci if (is_ima) 2228c2ecf20Sopenharmony_ci ima_present = true; 2238c2ecf20Sopenharmony_ci continue; 2248c2ecf20Sopenharmony_ci } 2258c2ecf20Sopenharmony_ci size = vfs_getxattr_alloc(dentry, xattr->name, 2268c2ecf20Sopenharmony_ci &xattr_value, xattr_size, GFP_NOFS); 2278c2ecf20Sopenharmony_ci if (size == -ENOMEM) { 2288c2ecf20Sopenharmony_ci error = -ENOMEM; 2298c2ecf20Sopenharmony_ci goto out; 2308c2ecf20Sopenharmony_ci } 2318c2ecf20Sopenharmony_ci if (size < 0) 2328c2ecf20Sopenharmony_ci continue; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci error = 0; 2358c2ecf20Sopenharmony_ci xattr_size = size; 2368c2ecf20Sopenharmony_ci crypto_shash_update(desc, (const u8 *)xattr_value, xattr_size); 2378c2ecf20Sopenharmony_ci if (is_ima) 2388c2ecf20Sopenharmony_ci ima_present = true; 2398c2ecf20Sopenharmony_ci } 2408c2ecf20Sopenharmony_ci hmac_add_misc(desc, inode, type, data->digest); 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci /* Portable EVM signatures must include an IMA hash */ 2438c2ecf20Sopenharmony_ci if (type == EVM_XATTR_PORTABLE_DIGSIG && !ima_present) 2448c2ecf20Sopenharmony_ci error = -EPERM; 2458c2ecf20Sopenharmony_ciout: 2468c2ecf20Sopenharmony_ci kfree(xattr_value); 2478c2ecf20Sopenharmony_ci kfree(desc); 2488c2ecf20Sopenharmony_ci return error; 2498c2ecf20Sopenharmony_ci} 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ciint evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name, 2528c2ecf20Sopenharmony_ci const char *req_xattr_value, size_t req_xattr_value_len, 2538c2ecf20Sopenharmony_ci struct evm_digest *data) 2548c2ecf20Sopenharmony_ci{ 2558c2ecf20Sopenharmony_ci return evm_calc_hmac_or_hash(dentry, req_xattr_name, req_xattr_value, 2568c2ecf20Sopenharmony_ci req_xattr_value_len, EVM_XATTR_HMAC, data); 2578c2ecf20Sopenharmony_ci} 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ciint evm_calc_hash(struct dentry *dentry, const char *req_xattr_name, 2608c2ecf20Sopenharmony_ci const char *req_xattr_value, size_t req_xattr_value_len, 2618c2ecf20Sopenharmony_ci char type, struct evm_digest *data) 2628c2ecf20Sopenharmony_ci{ 2638c2ecf20Sopenharmony_ci return evm_calc_hmac_or_hash(dentry, req_xattr_name, req_xattr_value, 2648c2ecf20Sopenharmony_ci req_xattr_value_len, type, data); 2658c2ecf20Sopenharmony_ci} 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_cistatic int evm_is_immutable(struct dentry *dentry, struct inode *inode) 2688c2ecf20Sopenharmony_ci{ 2698c2ecf20Sopenharmony_ci const struct evm_ima_xattr_data *xattr_data = NULL; 2708c2ecf20Sopenharmony_ci struct integrity_iint_cache *iint; 2718c2ecf20Sopenharmony_ci int rc = 0; 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci iint = integrity_iint_find(inode); 2748c2ecf20Sopenharmony_ci if (iint && (iint->flags & EVM_IMMUTABLE_DIGSIG)) 2758c2ecf20Sopenharmony_ci return 1; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci /* Do this the hard way */ 2788c2ecf20Sopenharmony_ci rc = vfs_getxattr_alloc(dentry, XATTR_NAME_EVM, (char **)&xattr_data, 0, 2798c2ecf20Sopenharmony_ci GFP_NOFS); 2808c2ecf20Sopenharmony_ci if (rc <= 0) { 2818c2ecf20Sopenharmony_ci if (rc == -ENODATA) 2828c2ecf20Sopenharmony_ci return 0; 2838c2ecf20Sopenharmony_ci return rc; 2848c2ecf20Sopenharmony_ci } 2858c2ecf20Sopenharmony_ci if (xattr_data->type == EVM_XATTR_PORTABLE_DIGSIG) 2868c2ecf20Sopenharmony_ci rc = 1; 2878c2ecf20Sopenharmony_ci else 2888c2ecf20Sopenharmony_ci rc = 0; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci kfree(xattr_data); 2918c2ecf20Sopenharmony_ci return rc; 2928c2ecf20Sopenharmony_ci} 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci/* 2968c2ecf20Sopenharmony_ci * Calculate the hmac and update security.evm xattr 2978c2ecf20Sopenharmony_ci * 2988c2ecf20Sopenharmony_ci * Expects to be called with i_mutex locked. 2998c2ecf20Sopenharmony_ci */ 3008c2ecf20Sopenharmony_ciint evm_update_evmxattr(struct dentry *dentry, const char *xattr_name, 3018c2ecf20Sopenharmony_ci const char *xattr_value, size_t xattr_value_len) 3028c2ecf20Sopenharmony_ci{ 3038c2ecf20Sopenharmony_ci struct inode *inode = d_backing_inode(dentry); 3048c2ecf20Sopenharmony_ci struct evm_digest data; 3058c2ecf20Sopenharmony_ci int rc = 0; 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci /* 3088c2ecf20Sopenharmony_ci * Don't permit any transformation of the EVM xattr if the signature 3098c2ecf20Sopenharmony_ci * is of an immutable type 3108c2ecf20Sopenharmony_ci */ 3118c2ecf20Sopenharmony_ci rc = evm_is_immutable(dentry, inode); 3128c2ecf20Sopenharmony_ci if (rc < 0) 3138c2ecf20Sopenharmony_ci return rc; 3148c2ecf20Sopenharmony_ci if (rc) 3158c2ecf20Sopenharmony_ci return -EPERM; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci data.hdr.algo = HASH_ALGO_SHA1; 3188c2ecf20Sopenharmony_ci rc = evm_calc_hmac(dentry, xattr_name, xattr_value, 3198c2ecf20Sopenharmony_ci xattr_value_len, &data); 3208c2ecf20Sopenharmony_ci if (rc == 0) { 3218c2ecf20Sopenharmony_ci data.hdr.xattr.sha1.type = EVM_XATTR_HMAC; 3228c2ecf20Sopenharmony_ci rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_EVM, 3238c2ecf20Sopenharmony_ci &data.hdr.xattr.data[1], 3248c2ecf20Sopenharmony_ci SHA1_DIGEST_SIZE + 1, 0); 3258c2ecf20Sopenharmony_ci } else if (rc == -ENODATA && (inode->i_opflags & IOP_XATTR)) { 3268c2ecf20Sopenharmony_ci rc = __vfs_removexattr(dentry, XATTR_NAME_EVM); 3278c2ecf20Sopenharmony_ci } 3288c2ecf20Sopenharmony_ci return rc; 3298c2ecf20Sopenharmony_ci} 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ciint evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr, 3328c2ecf20Sopenharmony_ci char *hmac_val) 3338c2ecf20Sopenharmony_ci{ 3348c2ecf20Sopenharmony_ci struct shash_desc *desc; 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci desc = init_desc(EVM_XATTR_HMAC, HASH_ALGO_SHA1); 3378c2ecf20Sopenharmony_ci if (IS_ERR(desc)) { 3388c2ecf20Sopenharmony_ci pr_info("init_desc failed\n"); 3398c2ecf20Sopenharmony_ci return PTR_ERR(desc); 3408c2ecf20Sopenharmony_ci } 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci crypto_shash_update(desc, lsm_xattr->value, lsm_xattr->value_len); 3438c2ecf20Sopenharmony_ci hmac_add_misc(desc, inode, EVM_XATTR_HMAC, hmac_val); 3448c2ecf20Sopenharmony_ci kfree(desc); 3458c2ecf20Sopenharmony_ci return 0; 3468c2ecf20Sopenharmony_ci} 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci/* 3498c2ecf20Sopenharmony_ci * Get the key from the TPM for the SHA1-HMAC 3508c2ecf20Sopenharmony_ci */ 3518c2ecf20Sopenharmony_ciint evm_init_key(void) 3528c2ecf20Sopenharmony_ci{ 3538c2ecf20Sopenharmony_ci struct key *evm_key; 3548c2ecf20Sopenharmony_ci struct encrypted_key_payload *ekp; 3558c2ecf20Sopenharmony_ci int rc; 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci evm_key = request_key(&key_type_encrypted, EVMKEY, NULL); 3588c2ecf20Sopenharmony_ci if (IS_ERR(evm_key)) 3598c2ecf20Sopenharmony_ci return -ENOENT; 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci down_read(&evm_key->sem); 3628c2ecf20Sopenharmony_ci ekp = evm_key->payload.data[0]; 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci rc = evm_set_key(ekp->decrypted_data, ekp->decrypted_datalen); 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci /* burn the original key contents */ 3678c2ecf20Sopenharmony_ci memset(ekp->decrypted_data, 0, ekp->decrypted_datalen); 3688c2ecf20Sopenharmony_ci up_read(&evm_key->sem); 3698c2ecf20Sopenharmony_ci key_put(evm_key); 3708c2ecf20Sopenharmony_ci return rc; 3718c2ecf20Sopenharmony_ci} 372