1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (C) 2011 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/sched.h>
11*4882a593Smuzhiyun #include <linux/slab.h>
12*4882a593Smuzhiyun #include <linux/cred.h>
13*4882a593Smuzhiyun #include <linux/kernel_read_file.h>
14*4882a593Smuzhiyun #include <linux/key-type.h>
15*4882a593Smuzhiyun #include <linux/digsig.h>
16*4882a593Smuzhiyun #include <linux/vmalloc.h>
17*4882a593Smuzhiyun #include <crypto/public_key.h>
18*4882a593Smuzhiyun #include <keys/system_keyring.h>
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun #include "integrity.h"
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun static struct key *keyring[INTEGRITY_KEYRING_MAX];
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun static const char * const keyring_name[INTEGRITY_KEYRING_MAX] = {
25*4882a593Smuzhiyun #ifndef CONFIG_INTEGRITY_TRUSTED_KEYRING
26*4882a593Smuzhiyun "_evm",
27*4882a593Smuzhiyun "_ima",
28*4882a593Smuzhiyun #else
29*4882a593Smuzhiyun ".evm",
30*4882a593Smuzhiyun ".ima",
31*4882a593Smuzhiyun #endif
32*4882a593Smuzhiyun ".platform",
33*4882a593Smuzhiyun };
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun #ifdef CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY
36*4882a593Smuzhiyun #define restrict_link_to_ima restrict_link_by_builtin_and_secondary_trusted
37*4882a593Smuzhiyun #else
38*4882a593Smuzhiyun #define restrict_link_to_ima restrict_link_by_builtin_trusted
39*4882a593Smuzhiyun #endif
40*4882a593Smuzhiyun
integrity_keyring_from_id(const unsigned int id)41*4882a593Smuzhiyun static struct key *integrity_keyring_from_id(const unsigned int id)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun if (id >= INTEGRITY_KEYRING_MAX)
44*4882a593Smuzhiyun return ERR_PTR(-EINVAL);
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun if (!keyring[id]) {
47*4882a593Smuzhiyun keyring[id] =
48*4882a593Smuzhiyun request_key(&key_type_keyring, keyring_name[id], NULL);
49*4882a593Smuzhiyun if (IS_ERR(keyring[id])) {
50*4882a593Smuzhiyun int err = PTR_ERR(keyring[id]);
51*4882a593Smuzhiyun pr_err("no %s keyring: %d\n", keyring_name[id], err);
52*4882a593Smuzhiyun keyring[id] = NULL;
53*4882a593Smuzhiyun return ERR_PTR(err);
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun return keyring[id];
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun
integrity_digsig_verify(const unsigned int id,const char * sig,int siglen,const char * digest,int digestlen)60*4882a593Smuzhiyun int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
61*4882a593Smuzhiyun const char *digest, int digestlen)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun struct key *keyring;
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun if (siglen < 2)
66*4882a593Smuzhiyun return -EINVAL;
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun keyring = integrity_keyring_from_id(id);
69*4882a593Smuzhiyun if (IS_ERR(keyring))
70*4882a593Smuzhiyun return PTR_ERR(keyring);
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun switch (sig[1]) {
73*4882a593Smuzhiyun case 1:
74*4882a593Smuzhiyun /* v1 API expect signature without xattr type */
75*4882a593Smuzhiyun return digsig_verify(keyring, sig + 1, siglen - 1, digest,
76*4882a593Smuzhiyun digestlen);
77*4882a593Smuzhiyun case 2:
78*4882a593Smuzhiyun return asymmetric_verify(keyring, sig, siglen, digest,
79*4882a593Smuzhiyun digestlen);
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun return -EOPNOTSUPP;
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun
integrity_modsig_verify(const unsigned int id,const struct modsig * modsig)85*4882a593Smuzhiyun int integrity_modsig_verify(const unsigned int id, const struct modsig *modsig)
86*4882a593Smuzhiyun {
87*4882a593Smuzhiyun struct key *keyring;
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun keyring = integrity_keyring_from_id(id);
90*4882a593Smuzhiyun if (IS_ERR(keyring))
91*4882a593Smuzhiyun return PTR_ERR(keyring);
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun return ima_modsig_verify(keyring, modsig);
94*4882a593Smuzhiyun }
95*4882a593Smuzhiyun
__integrity_init_keyring(const unsigned int id,key_perm_t perm,struct key_restriction * restriction)96*4882a593Smuzhiyun static int __init __integrity_init_keyring(const unsigned int id,
97*4882a593Smuzhiyun key_perm_t perm,
98*4882a593Smuzhiyun struct key_restriction *restriction)
99*4882a593Smuzhiyun {
100*4882a593Smuzhiyun const struct cred *cred = current_cred();
101*4882a593Smuzhiyun int err = 0;
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0),
104*4882a593Smuzhiyun KGIDT_INIT(0), cred, perm,
105*4882a593Smuzhiyun KEY_ALLOC_NOT_IN_QUOTA, restriction, NULL);
106*4882a593Smuzhiyun if (IS_ERR(keyring[id])) {
107*4882a593Smuzhiyun err = PTR_ERR(keyring[id]);
108*4882a593Smuzhiyun pr_info("Can't allocate %s keyring (%d)\n",
109*4882a593Smuzhiyun keyring_name[id], err);
110*4882a593Smuzhiyun keyring[id] = NULL;
111*4882a593Smuzhiyun } else {
112*4882a593Smuzhiyun if (id == INTEGRITY_KEYRING_PLATFORM)
113*4882a593Smuzhiyun set_platform_trusted_keys(keyring[id]);
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun return err;
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun
integrity_init_keyring(const unsigned int id)119*4882a593Smuzhiyun int __init integrity_init_keyring(const unsigned int id)
120*4882a593Smuzhiyun {
121*4882a593Smuzhiyun struct key_restriction *restriction;
122*4882a593Smuzhiyun key_perm_t perm;
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW
125*4882a593Smuzhiyun | KEY_USR_READ | KEY_USR_SEARCH;
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun if (id == INTEGRITY_KEYRING_PLATFORM) {
128*4882a593Smuzhiyun restriction = NULL;
129*4882a593Smuzhiyun goto out;
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun if (!IS_ENABLED(CONFIG_INTEGRITY_TRUSTED_KEYRING))
133*4882a593Smuzhiyun return 0;
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun restriction = kzalloc(sizeof(struct key_restriction), GFP_KERNEL);
136*4882a593Smuzhiyun if (!restriction)
137*4882a593Smuzhiyun return -ENOMEM;
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun restriction->check = restrict_link_to_ima;
140*4882a593Smuzhiyun perm |= KEY_USR_WRITE;
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun out:
143*4882a593Smuzhiyun return __integrity_init_keyring(id, perm, restriction);
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun
integrity_add_key(const unsigned int id,const void * data,off_t size,key_perm_t perm)146*4882a593Smuzhiyun int __init integrity_add_key(const unsigned int id, const void *data,
147*4882a593Smuzhiyun off_t size, key_perm_t perm)
148*4882a593Smuzhiyun {
149*4882a593Smuzhiyun key_ref_t key;
150*4882a593Smuzhiyun int rc = 0;
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun if (!keyring[id])
153*4882a593Smuzhiyun return -EINVAL;
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun key = key_create_or_update(make_key_ref(keyring[id], 1), "asymmetric",
156*4882a593Smuzhiyun NULL, data, size, perm,
157*4882a593Smuzhiyun KEY_ALLOC_NOT_IN_QUOTA);
158*4882a593Smuzhiyun if (IS_ERR(key)) {
159*4882a593Smuzhiyun rc = PTR_ERR(key);
160*4882a593Smuzhiyun pr_err("Problem loading X.509 certificate %d\n", rc);
161*4882a593Smuzhiyun } else {
162*4882a593Smuzhiyun pr_notice("Loaded X.509 cert '%s'\n",
163*4882a593Smuzhiyun key_ref_to_ptr(key)->description);
164*4882a593Smuzhiyun key_ref_put(key);
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun return rc;
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun }
170*4882a593Smuzhiyun
integrity_load_x509(const unsigned int id,const char * path)171*4882a593Smuzhiyun int __init integrity_load_x509(const unsigned int id, const char *path)
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun void *data = NULL;
174*4882a593Smuzhiyun size_t size;
175*4882a593Smuzhiyun int rc;
176*4882a593Smuzhiyun key_perm_t perm;
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun rc = kernel_read_file_from_path(path, 0, &data, INT_MAX, NULL,
179*4882a593Smuzhiyun READING_X509_CERTIFICATE);
180*4882a593Smuzhiyun if (rc < 0) {
181*4882a593Smuzhiyun pr_err("Unable to open file: %s (%d)", path, rc);
182*4882a593Smuzhiyun return rc;
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun size = rc;
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ;
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun pr_info("Loading X.509 certificate: %s\n", path);
189*4882a593Smuzhiyun rc = integrity_add_key(id, (const void *)data, size, perm);
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun vfree(data);
192*4882a593Smuzhiyun return rc;
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun
integrity_load_cert(const unsigned int id,const char * source,const void * data,size_t len,key_perm_t perm)195*4882a593Smuzhiyun int __init integrity_load_cert(const unsigned int id, const char *source,
196*4882a593Smuzhiyun const void *data, size_t len, key_perm_t perm)
197*4882a593Smuzhiyun {
198*4882a593Smuzhiyun if (!data)
199*4882a593Smuzhiyun return -EINVAL;
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun pr_info("Loading X.509 certificate: %s\n", source);
202*4882a593Smuzhiyun return integrity_add_key(id, data, len, perm);
203*4882a593Smuzhiyun }
204