1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * AppArmor security module |
4 | * |
5 | * This file contains AppArmor policy loading interface function definitions. |
6 | * |
7 | * Copyright 2013 Canonical Ltd. |
8 | * |
9 | * Fns to provide a checksum of policy that has been loaded this can be |
10 | * compared to userspace policy compiles to check loaded policy is what |
11 | * it should be. |
12 | */ |
13 | |
14 | #include <crypto/hash.h> |
15 | |
16 | #include "include/apparmor.h" |
17 | #include "include/crypto.h" |
18 | |
19 | static unsigned int apparmor_hash_size; |
20 | |
21 | static struct crypto_shash *apparmor_tfm; |
22 | |
23 | unsigned int aa_hash_size(void) |
24 | { |
25 | return apparmor_hash_size; |
26 | } |
27 | |
28 | char *aa_calc_hash(void *data, size_t len) |
29 | { |
30 | SHASH_DESC_ON_STACK(desc, apparmor_tfm); |
31 | char *hash; |
32 | int error; |
33 | |
34 | if (!apparmor_tfm) |
35 | return NULL; |
36 | |
37 | hash = kzalloc(size: apparmor_hash_size, GFP_KERNEL); |
38 | if (!hash) |
39 | return ERR_PTR(error: -ENOMEM); |
40 | |
41 | desc->tfm = apparmor_tfm; |
42 | |
43 | error = crypto_shash_init(desc); |
44 | if (error) |
45 | goto fail; |
46 | error = crypto_shash_update(desc, data: (u8 *) data, len); |
47 | if (error) |
48 | goto fail; |
49 | error = crypto_shash_final(desc, out: hash); |
50 | if (error) |
51 | goto fail; |
52 | |
53 | return hash; |
54 | |
55 | fail: |
56 | kfree(objp: hash); |
57 | |
58 | return ERR_PTR(error); |
59 | } |
60 | |
61 | int aa_calc_profile_hash(struct aa_profile *profile, u32 version, void *start, |
62 | size_t len) |
63 | { |
64 | SHASH_DESC_ON_STACK(desc, apparmor_tfm); |
65 | int error; |
66 | __le32 le32_version = cpu_to_le32(version); |
67 | |
68 | if (!aa_g_hash_policy) |
69 | return 0; |
70 | |
71 | if (!apparmor_tfm) |
72 | return 0; |
73 | |
74 | profile->hash = kzalloc(size: apparmor_hash_size, GFP_KERNEL); |
75 | if (!profile->hash) |
76 | return -ENOMEM; |
77 | |
78 | desc->tfm = apparmor_tfm; |
79 | |
80 | error = crypto_shash_init(desc); |
81 | if (error) |
82 | goto fail; |
83 | error = crypto_shash_update(desc, data: (u8 *) &le32_version, len: 4); |
84 | if (error) |
85 | goto fail; |
86 | error = crypto_shash_update(desc, data: (u8 *) start, len); |
87 | if (error) |
88 | goto fail; |
89 | error = crypto_shash_final(desc, out: profile->hash); |
90 | if (error) |
91 | goto fail; |
92 | |
93 | return 0; |
94 | |
95 | fail: |
96 | kfree(objp: profile->hash); |
97 | profile->hash = NULL; |
98 | |
99 | return error; |
100 | } |
101 | |
102 | static int __init init_profile_hash(void) |
103 | { |
104 | struct crypto_shash *tfm; |
105 | |
106 | if (!apparmor_initialized) |
107 | return 0; |
108 | |
109 | tfm = crypto_alloc_shash(alg_name: "sha1" , type: 0, mask: 0); |
110 | if (IS_ERR(ptr: tfm)) { |
111 | int error = PTR_ERR(ptr: tfm); |
112 | AA_ERROR("failed to setup profile sha1 hashing: %d\n" , error); |
113 | return error; |
114 | } |
115 | apparmor_tfm = tfm; |
116 | apparmor_hash_size = crypto_shash_digestsize(tfm: apparmor_tfm); |
117 | |
118 | aa_info_message(str: "AppArmor sha1 policy hashing enabled" ); |
119 | |
120 | return 0; |
121 | } |
122 | |
123 | late_initcall(init_profile_hash); |
124 | |