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