1b886d83cSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2e0751257SDmitry Kasatkin /*
3e0751257SDmitry Kasatkin * Copyright (C) 2013 Intel Corporation
4e0751257SDmitry Kasatkin *
5e0751257SDmitry Kasatkin * Author:
6e0751257SDmitry Kasatkin * Dmitry Kasatkin <dmitry.kasatkin@intel.com>
7e0751257SDmitry Kasatkin */
8e0751257SDmitry Kasatkin
9e0751257SDmitry Kasatkin #include <linux/err.h>
10d9a2e5d7SDmitry Kasatkin #include <linux/ratelimit.h>
11e0751257SDmitry Kasatkin #include <linux/key-type.h>
12e0751257SDmitry Kasatkin #include <crypto/public_key.h>
134e8ae72aSDavid Howells #include <crypto/hash_info.h>
14e0751257SDmitry Kasatkin #include <keys/asymmetric-type.h>
1541c89b64SPetko Manolov #include <keys/system_keyring.h>
16e0751257SDmitry Kasatkin
17e0751257SDmitry Kasatkin #include "integrity.h"
18e0751257SDmitry Kasatkin
19e0751257SDmitry Kasatkin /*
20e0751257SDmitry Kasatkin * Request an asymmetric key.
21e0751257SDmitry Kasatkin */
request_asymmetric_key(struct key * keyring,uint32_t keyid)22e0751257SDmitry Kasatkin static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid)
23e0751257SDmitry Kasatkin {
24e0751257SDmitry Kasatkin struct key *key;
25e0751257SDmitry Kasatkin char name[12];
26e0751257SDmitry Kasatkin
27594081eeSDmitry Kasatkin sprintf(name, "id:%08x", keyid);
28e0751257SDmitry Kasatkin
29e0751257SDmitry Kasatkin pr_debug("key search: \"%s\"\n", name);
30e0751257SDmitry Kasatkin
3141c89b64SPetko Manolov key = get_ima_blacklist_keyring();
3241c89b64SPetko Manolov if (key) {
3341c89b64SPetko Manolov key_ref_t kref;
3441c89b64SPetko Manolov
3541c89b64SPetko Manolov kref = keyring_search(make_key_ref(key, 1),
36dcf49dbcSDavid Howells &key_type_asymmetric, name, true);
3741c89b64SPetko Manolov if (!IS_ERR(kref)) {
3841c89b64SPetko Manolov pr_err("Key '%s' is in ima_blacklist_keyring\n", name);
3941c89b64SPetko Manolov return ERR_PTR(-EKEYREJECTED);
4041c89b64SPetko Manolov }
4141c89b64SPetko Manolov }
4241c89b64SPetko Manolov
43e0751257SDmitry Kasatkin if (keyring) {
44e0751257SDmitry Kasatkin /* search in specific keyring */
45e0751257SDmitry Kasatkin key_ref_t kref;
4641c89b64SPetko Manolov
47e0751257SDmitry Kasatkin kref = keyring_search(make_key_ref(keyring, 1),
48dcf49dbcSDavid Howells &key_type_asymmetric, name, true);
49e0751257SDmitry Kasatkin if (IS_ERR(kref))
50e0751257SDmitry Kasatkin key = ERR_CAST(kref);
51e0751257SDmitry Kasatkin else
52e0751257SDmitry Kasatkin key = key_ref_to_ptr(kref);
53e0751257SDmitry Kasatkin } else {
54028db3e2SLinus Torvalds key = request_key(&key_type_asymmetric, name, NULL);
55e0751257SDmitry Kasatkin }
56e0751257SDmitry Kasatkin
57e0751257SDmitry Kasatkin if (IS_ERR(key)) {
588c2f516cSBruno Meneguele if (keyring)
598c2f516cSBruno Meneguele pr_err_ratelimited("Request for unknown key '%s' in '%s' keyring. err %ld\n",
608c2f516cSBruno Meneguele name, keyring->description,
618c2f516cSBruno Meneguele PTR_ERR(key));
628c2f516cSBruno Meneguele else
63d9a2e5d7SDmitry Kasatkin pr_err_ratelimited("Request for unknown key '%s' err %ld\n",
64e0751257SDmitry Kasatkin name, PTR_ERR(key));
658c2f516cSBruno Meneguele
66e0751257SDmitry Kasatkin switch (PTR_ERR(key)) {
67e0751257SDmitry Kasatkin /* Hide some search errors */
68e0751257SDmitry Kasatkin case -EACCES:
69e0751257SDmitry Kasatkin case -ENOTDIR:
70e0751257SDmitry Kasatkin case -EAGAIN:
71e0751257SDmitry Kasatkin return ERR_PTR(-ENOKEY);
72e0751257SDmitry Kasatkin default:
73e0751257SDmitry Kasatkin return key;
74e0751257SDmitry Kasatkin }
75e0751257SDmitry Kasatkin }
76e0751257SDmitry Kasatkin
77e0751257SDmitry Kasatkin pr_debug("%s() = 0 [%x]\n", __func__, key_serial(key));
78e0751257SDmitry Kasatkin
79e0751257SDmitry Kasatkin return key;
80e0751257SDmitry Kasatkin }
81e0751257SDmitry Kasatkin
asymmetric_verify(struct key * keyring,const char * sig,int siglen,const char * data,int datalen)82e0751257SDmitry Kasatkin int asymmetric_verify(struct key *keyring, const char *sig,
83e0751257SDmitry Kasatkin int siglen, const char *data, int datalen)
84e0751257SDmitry Kasatkin {
85e0751257SDmitry Kasatkin struct public_key_signature pks;
86e0751257SDmitry Kasatkin struct signature_v2_hdr *hdr = (struct signature_v2_hdr *)sig;
87947d7059SStefan Berger const struct public_key *pk;
88e0751257SDmitry Kasatkin struct key *key;
893db0d0c2SColin Ian King int ret;
90e0751257SDmitry Kasatkin
91e0751257SDmitry Kasatkin if (siglen <= sizeof(*hdr))
92e0751257SDmitry Kasatkin return -EBADMSG;
93e0751257SDmitry Kasatkin
94e0751257SDmitry Kasatkin siglen -= sizeof(*hdr);
95e0751257SDmitry Kasatkin
96bb543e39SThiago Jung Bauermann if (siglen != be16_to_cpu(hdr->sig_size))
97e0751257SDmitry Kasatkin return -EBADMSG;
98e0751257SDmitry Kasatkin
994e8ae72aSDavid Howells if (hdr->hash_algo >= HASH_ALGO__LAST)
100e0751257SDmitry Kasatkin return -ENOPKG;
101e0751257SDmitry Kasatkin
102bb543e39SThiago Jung Bauermann key = request_asymmetric_key(keyring, be32_to_cpu(hdr->keyid));
103e0751257SDmitry Kasatkin if (IS_ERR(key))
104e0751257SDmitry Kasatkin return PTR_ERR(key);
105e0751257SDmitry Kasatkin
106e0751257SDmitry Kasatkin memset(&pks, 0, sizeof(pks));
107e0751257SDmitry Kasatkin
1084e8ae72aSDavid Howells pks.hash_algo = hash_algo_name[hdr->hash_algo];
109947d7059SStefan Berger
110947d7059SStefan Berger pk = asymmetric_key_public_key(key);
111947d7059SStefan Berger pks.pkey_algo = pk->pkey_algo;
112*0838d6d6SEric Biggers if (!strcmp(pk->pkey_algo, "rsa")) {
113fd35f192SMimi Zohar pks.encoding = "pkcs1";
114*0838d6d6SEric Biggers } else if (!strncmp(pk->pkey_algo, "ecdsa-", 6)) {
115947d7059SStefan Berger /* edcsa-nist-p192 etc. */
116947d7059SStefan Berger pks.encoding = "x962";
117*0838d6d6SEric Biggers } else if (!strcmp(pk->pkey_algo, "ecrdsa") ||
118*0838d6d6SEric Biggers !strcmp(pk->pkey_algo, "sm2")) {
119947d7059SStefan Berger pks.encoding = "raw";
120*0838d6d6SEric Biggers } else {
121*0838d6d6SEric Biggers ret = -ENOPKG;
122*0838d6d6SEric Biggers goto out;
123*0838d6d6SEric Biggers }
124947d7059SStefan Berger
125e0751257SDmitry Kasatkin pks.digest = (u8 *)data;
126e0751257SDmitry Kasatkin pks.digest_size = datalen;
127eb5798f2STadeusz Struk pks.s = hdr->sig;
128eb5798f2STadeusz Struk pks.s_size = siglen;
129e0751257SDmitry Kasatkin ret = verify_signature(key, &pks);
130*0838d6d6SEric Biggers out:
131e0751257SDmitry Kasatkin key_put(key);
132e0751257SDmitry Kasatkin pr_debug("%s() = %d\n", __func__, ret);
133e0751257SDmitry Kasatkin return ret;
134e0751257SDmitry Kasatkin }
1356eb864c1SMikhail Kurinnoi
1366eb864c1SMikhail Kurinnoi /**
1376eb864c1SMikhail Kurinnoi * integrity_kernel_module_request - prevent crypto-pkcs1pad(rsa,*) requests
1386eb864c1SMikhail Kurinnoi * @kmod_name: kernel module name
1396eb864c1SMikhail Kurinnoi *
1406eb864c1SMikhail Kurinnoi * We have situation, when public_key_verify_signature() in case of RSA
1416eb864c1SMikhail Kurinnoi * algorithm use alg_name to store internal information in order to
1426eb864c1SMikhail Kurinnoi * construct an algorithm on the fly, but crypto_larval_lookup() will try
1436eb864c1SMikhail Kurinnoi * to use alg_name in order to load kernel module with same name.
1446eb864c1SMikhail Kurinnoi * Since we don't have any real "crypto-pkcs1pad(rsa,*)" kernel modules,
1456eb864c1SMikhail Kurinnoi * we are safe to fail such module request from crypto_larval_lookup().
1466eb864c1SMikhail Kurinnoi *
1476eb864c1SMikhail Kurinnoi * In this way we prevent modprobe execution during digsig verification
1486eb864c1SMikhail Kurinnoi * and avoid possible deadlock if modprobe and/or it's dependencies
1496eb864c1SMikhail Kurinnoi * also signed with digsig.
1506eb864c1SMikhail Kurinnoi */
integrity_kernel_module_request(char * kmod_name)1516eb864c1SMikhail Kurinnoi int integrity_kernel_module_request(char *kmod_name)
1526eb864c1SMikhail Kurinnoi {
1536eb864c1SMikhail Kurinnoi if (strncmp(kmod_name, "crypto-pkcs1pad(rsa,", 20) == 0)
1546eb864c1SMikhail Kurinnoi return -EINVAL;
1556eb864c1SMikhail Kurinnoi
1566eb864c1SMikhail Kurinnoi return 0;
1576eb864c1SMikhail Kurinnoi }
158