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