1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (C) 2013 Intel Corporation |
4 | * |
5 | * Author: |
6 | * Dmitry Kasatkin <dmitry.kasatkin@intel.com> |
7 | */ |
8 | |
9 | #include <linux/err.h> |
10 | #include <linux/ratelimit.h> |
11 | #include <linux/key-type.h> |
12 | #include <crypto/public_key.h> |
13 | #include <crypto/hash_info.h> |
14 | #include <keys/asymmetric-type.h> |
15 | #include <keys/system_keyring.h> |
16 | |
17 | #include "integrity.h" |
18 | |
19 | /* |
20 | * Request an asymmetric key. |
21 | */ |
22 | static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid) |
23 | { |
24 | struct key *key; |
25 | char name[12]; |
26 | |
27 | sprintf(buf: name, fmt: "id:%08x" , keyid); |
28 | |
29 | pr_debug("key search: \"%s\"\n" , name); |
30 | |
31 | key = get_ima_blacklist_keyring(); |
32 | if (key) { |
33 | key_ref_t kref; |
34 | |
35 | kref = keyring_search(keyring: make_key_ref(key, possession: 1), |
36 | type: &key_type_asymmetric, description: name, recurse: true); |
37 | if (!IS_ERR(ptr: kref)) { |
38 | pr_err("Key '%s' is in ima_blacklist_keyring\n" , name); |
39 | return ERR_PTR(error: -EKEYREJECTED); |
40 | } |
41 | } |
42 | |
43 | if (keyring) { |
44 | /* search in specific keyring */ |
45 | key_ref_t kref; |
46 | |
47 | kref = keyring_search(keyring: make_key_ref(key: keyring, possession: 1), |
48 | type: &key_type_asymmetric, description: name, recurse: true); |
49 | if (IS_ERR(ptr: kref)) |
50 | key = ERR_CAST(ptr: kref); |
51 | else |
52 | key = key_ref_to_ptr(key_ref: kref); |
53 | } else { |
54 | key = request_key(type: &key_type_asymmetric, description: name, NULL); |
55 | } |
56 | |
57 | if (IS_ERR(ptr: key)) { |
58 | if (keyring) |
59 | pr_err_ratelimited("Request for unknown key '%s' in '%s' keyring. err %ld\n" , |
60 | name, keyring->description, |
61 | PTR_ERR(key)); |
62 | else |
63 | pr_err_ratelimited("Request for unknown key '%s' err %ld\n" , |
64 | name, PTR_ERR(key)); |
65 | |
66 | switch (PTR_ERR(ptr: key)) { |
67 | /* Hide some search errors */ |
68 | case -EACCES: |
69 | case -ENOTDIR: |
70 | case -EAGAIN: |
71 | return ERR_PTR(error: -ENOKEY); |
72 | default: |
73 | return key; |
74 | } |
75 | } |
76 | |
77 | pr_debug("%s() = 0 [%x]\n" , __func__, key_serial(key)); |
78 | |
79 | return key; |
80 | } |
81 | |
82 | int asymmetric_verify(struct key *keyring, const char *sig, |
83 | int siglen, const char *data, int datalen) |
84 | { |
85 | struct public_key_signature pks; |
86 | struct signature_v2_hdr *hdr = (struct signature_v2_hdr *)sig; |
87 | const struct public_key *pk; |
88 | struct key *key; |
89 | int ret; |
90 | |
91 | if (siglen <= sizeof(*hdr)) |
92 | return -EBADMSG; |
93 | |
94 | siglen -= sizeof(*hdr); |
95 | |
96 | if (siglen != be16_to_cpu(hdr->sig_size)) |
97 | return -EBADMSG; |
98 | |
99 | if (hdr->hash_algo >= HASH_ALGO__LAST) |
100 | return -ENOPKG; |
101 | |
102 | key = request_asymmetric_key(keyring, be32_to_cpu(hdr->keyid)); |
103 | if (IS_ERR(ptr: key)) |
104 | return PTR_ERR(ptr: key); |
105 | |
106 | memset(&pks, 0, sizeof(pks)); |
107 | |
108 | pks.hash_algo = hash_algo_name[hdr->hash_algo]; |
109 | |
110 | pk = asymmetric_key_public_key(key); |
111 | pks.pkey_algo = pk->pkey_algo; |
112 | if (!strcmp(pk->pkey_algo, "rsa" )) { |
113 | pks.encoding = "pkcs1" ; |
114 | } else if (!strncmp(pk->pkey_algo, "ecdsa-" , 6)) { |
115 | /* edcsa-nist-p192 etc. */ |
116 | pks.encoding = "x962" ; |
117 | } else if (!strcmp(pk->pkey_algo, "ecrdsa" ) || |
118 | !strcmp(pk->pkey_algo, "sm2" )) { |
119 | pks.encoding = "raw" ; |
120 | } else { |
121 | ret = -ENOPKG; |
122 | goto out; |
123 | } |
124 | |
125 | pks.digest = (u8 *)data; |
126 | pks.digest_size = datalen; |
127 | pks.s = hdr->sig; |
128 | pks.s_size = siglen; |
129 | ret = verify_signature(key, &pks); |
130 | out: |
131 | key_put(key); |
132 | pr_debug("%s() = %d\n" , __func__, ret); |
133 | return ret; |
134 | } |
135 | |
136 | /** |
137 | * integrity_kernel_module_request - prevent crypto-pkcs1pad(rsa,*) requests |
138 | * @kmod_name: kernel module name |
139 | * |
140 | * We have situation, when public_key_verify_signature() in case of RSA |
141 | * algorithm use alg_name to store internal information in order to |
142 | * construct an algorithm on the fly, but crypto_larval_lookup() will try |
143 | * to use alg_name in order to load kernel module with same name. |
144 | * Since we don't have any real "crypto-pkcs1pad(rsa,*)" kernel modules, |
145 | * we are safe to fail such module request from crypto_larval_lookup(). |
146 | * |
147 | * In this way we prevent modprobe execution during digsig verification |
148 | * and avoid possible deadlock if modprobe and/or it's dependencies |
149 | * also signed with digsig. |
150 | */ |
151 | int integrity_kernel_module_request(char *kmod_name) |
152 | { |
153 | if (strncmp(kmod_name, "crypto-pkcs1pad(rsa," , 20) == 0) |
154 | return -EINVAL; |
155 | |
156 | return 0; |
157 | } |
158 | |