18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * AppArmor security module 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * This file contains AppArmor policy loading interface function definitions. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright 2013 Canonical Ltd. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Fns to provide a checksum of policy that has been loaded this can be 108c2ecf20Sopenharmony_ci * compared to userspace policy compiles to check loaded policy is what 118c2ecf20Sopenharmony_ci * it should be. 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include <crypto/hash.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include "include/apparmor.h" 178c2ecf20Sopenharmony_ci#include "include/crypto.h" 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_cistatic unsigned int apparmor_hash_size; 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_cistatic struct crypto_shash *apparmor_tfm; 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ciunsigned int aa_hash_size(void) 248c2ecf20Sopenharmony_ci{ 258c2ecf20Sopenharmony_ci return apparmor_hash_size; 268c2ecf20Sopenharmony_ci} 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cichar *aa_calc_hash(void *data, size_t len) 298c2ecf20Sopenharmony_ci{ 308c2ecf20Sopenharmony_ci SHASH_DESC_ON_STACK(desc, apparmor_tfm); 318c2ecf20Sopenharmony_ci char *hash = NULL; 328c2ecf20Sopenharmony_ci int error = -ENOMEM; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci if (!apparmor_tfm) 358c2ecf20Sopenharmony_ci return NULL; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci hash = kzalloc(apparmor_hash_size, GFP_KERNEL); 388c2ecf20Sopenharmony_ci if (!hash) 398c2ecf20Sopenharmony_ci goto fail; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci desc->tfm = apparmor_tfm; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci error = crypto_shash_init(desc); 448c2ecf20Sopenharmony_ci if (error) 458c2ecf20Sopenharmony_ci goto fail; 468c2ecf20Sopenharmony_ci error = crypto_shash_update(desc, (u8 *) data, len); 478c2ecf20Sopenharmony_ci if (error) 488c2ecf20Sopenharmony_ci goto fail; 498c2ecf20Sopenharmony_ci error = crypto_shash_final(desc, hash); 508c2ecf20Sopenharmony_ci if (error) 518c2ecf20Sopenharmony_ci goto fail; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci return hash; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cifail: 568c2ecf20Sopenharmony_ci kfree(hash); 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci return ERR_PTR(error); 598c2ecf20Sopenharmony_ci} 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ciint aa_calc_profile_hash(struct aa_profile *profile, u32 version, void *start, 628c2ecf20Sopenharmony_ci size_t len) 638c2ecf20Sopenharmony_ci{ 648c2ecf20Sopenharmony_ci SHASH_DESC_ON_STACK(desc, apparmor_tfm); 658c2ecf20Sopenharmony_ci int error = -ENOMEM; 668c2ecf20Sopenharmony_ci __le32 le32_version = cpu_to_le32(version); 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci if (!aa_g_hash_policy) 698c2ecf20Sopenharmony_ci return 0; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci if (!apparmor_tfm) 728c2ecf20Sopenharmony_ci return 0; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci profile->hash = kzalloc(apparmor_hash_size, GFP_KERNEL); 758c2ecf20Sopenharmony_ci if (!profile->hash) 768c2ecf20Sopenharmony_ci goto fail; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci desc->tfm = apparmor_tfm; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci error = crypto_shash_init(desc); 818c2ecf20Sopenharmony_ci if (error) 828c2ecf20Sopenharmony_ci goto fail; 838c2ecf20Sopenharmony_ci error = crypto_shash_update(desc, (u8 *) &le32_version, 4); 848c2ecf20Sopenharmony_ci if (error) 858c2ecf20Sopenharmony_ci goto fail; 868c2ecf20Sopenharmony_ci error = crypto_shash_update(desc, (u8 *) start, len); 878c2ecf20Sopenharmony_ci if (error) 888c2ecf20Sopenharmony_ci goto fail; 898c2ecf20Sopenharmony_ci error = crypto_shash_final(desc, profile->hash); 908c2ecf20Sopenharmony_ci if (error) 918c2ecf20Sopenharmony_ci goto fail; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci return 0; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cifail: 968c2ecf20Sopenharmony_ci kfree(profile->hash); 978c2ecf20Sopenharmony_ci profile->hash = NULL; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci return error; 1008c2ecf20Sopenharmony_ci} 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_cistatic int __init init_profile_hash(void) 1038c2ecf20Sopenharmony_ci{ 1048c2ecf20Sopenharmony_ci struct crypto_shash *tfm; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci if (!apparmor_initialized) 1078c2ecf20Sopenharmony_ci return 0; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci tfm = crypto_alloc_shash("sha1", 0, 0); 1108c2ecf20Sopenharmony_ci if (IS_ERR(tfm)) { 1118c2ecf20Sopenharmony_ci int error = PTR_ERR(tfm); 1128c2ecf20Sopenharmony_ci AA_ERROR("failed to setup profile sha1 hashing: %d\n", error); 1138c2ecf20Sopenharmony_ci return error; 1148c2ecf20Sopenharmony_ci } 1158c2ecf20Sopenharmony_ci apparmor_tfm = tfm; 1168c2ecf20Sopenharmony_ci apparmor_hash_size = crypto_shash_digestsize(apparmor_tfm); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci aa_info_message("AppArmor sha1 policy hashing enabled"); 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci return 0; 1218c2ecf20Sopenharmony_ci} 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_cilate_initcall(init_profile_hash); 124