digsig.c (5248B)
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 22static struct key *keyring[INTEGRITY_KEYRING_MAX]; 23 24static 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 ".machine", 34}; 35 36#ifdef CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY 37#define restrict_link_to_ima restrict_link_by_builtin_and_secondary_trusted 38#else 39#define restrict_link_to_ima restrict_link_by_builtin_trusted 40#endif 41 42static struct key *integrity_keyring_from_id(const unsigned int id) 43{ 44 if (id >= INTEGRITY_KEYRING_MAX) 45 return ERR_PTR(-EINVAL); 46 47 if (!keyring[id]) { 48 keyring[id] = 49 request_key(&key_type_keyring, keyring_name[id], NULL); 50 if (IS_ERR(keyring[id])) { 51 int err = PTR_ERR(keyring[id]); 52 pr_err("no %s keyring: %d\n", keyring_name[id], err); 53 keyring[id] = NULL; 54 return ERR_PTR(err); 55 } 56 } 57 58 return keyring[id]; 59} 60 61int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, 62 const char *digest, int digestlen) 63{ 64 struct key *keyring; 65 66 if (siglen < 2) 67 return -EINVAL; 68 69 keyring = integrity_keyring_from_id(id); 70 if (IS_ERR(keyring)) 71 return PTR_ERR(keyring); 72 73 switch (sig[1]) { 74 case 1: 75 /* v1 API expect signature without xattr type */ 76 return digsig_verify(keyring, sig + 1, siglen - 1, digest, 77 digestlen); 78 case 2: /* regular file data hash based signature */ 79 case 3: /* struct ima_file_id data based signature */ 80 return asymmetric_verify(keyring, sig, siglen, digest, 81 digestlen); 82 } 83 84 return -EOPNOTSUPP; 85} 86 87int integrity_modsig_verify(const unsigned int id, const struct modsig *modsig) 88{ 89 struct key *keyring; 90 91 keyring = integrity_keyring_from_id(id); 92 if (IS_ERR(keyring)) 93 return PTR_ERR(keyring); 94 95 return ima_modsig_verify(keyring, modsig); 96} 97 98static int __init __integrity_init_keyring(const unsigned int id, 99 key_perm_t perm, 100 struct key_restriction *restriction) 101{ 102 const struct cred *cred = current_cred(); 103 int err = 0; 104 105 keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0), 106 KGIDT_INIT(0), cred, perm, 107 KEY_ALLOC_NOT_IN_QUOTA, restriction, NULL); 108 if (IS_ERR(keyring[id])) { 109 err = PTR_ERR(keyring[id]); 110 pr_info("Can't allocate %s keyring (%d)\n", 111 keyring_name[id], err); 112 keyring[id] = NULL; 113 } else { 114 if (id == INTEGRITY_KEYRING_PLATFORM) 115 set_platform_trusted_keys(keyring[id]); 116 if (id == INTEGRITY_KEYRING_MACHINE && trust_moklist()) 117 set_machine_trusted_keys(keyring[id]); 118 if (id == INTEGRITY_KEYRING_IMA) 119 load_module_cert(keyring[id]); 120 } 121 122 return err; 123} 124 125int __init integrity_init_keyring(const unsigned int id) 126{ 127 struct key_restriction *restriction; 128 key_perm_t perm; 129 130 perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW 131 | KEY_USR_READ | KEY_USR_SEARCH; 132 133 if (id == INTEGRITY_KEYRING_PLATFORM || 134 id == INTEGRITY_KEYRING_MACHINE) { 135 restriction = NULL; 136 goto out; 137 } 138 139 if (!IS_ENABLED(CONFIG_INTEGRITY_TRUSTED_KEYRING)) 140 return 0; 141 142 restriction = kzalloc(sizeof(struct key_restriction), GFP_KERNEL); 143 if (!restriction) 144 return -ENOMEM; 145 146 restriction->check = restrict_link_to_ima; 147 148 /* 149 * MOK keys can only be added through a read-only runtime services 150 * UEFI variable during boot. No additional keys shall be allowed to 151 * load into the machine keyring following init from userspace. 152 */ 153 if (id != INTEGRITY_KEYRING_MACHINE) 154 perm |= KEY_USR_WRITE; 155 156out: 157 return __integrity_init_keyring(id, perm, restriction); 158} 159 160static int __init integrity_add_key(const unsigned int id, const void *data, 161 off_t size, key_perm_t perm) 162{ 163 key_ref_t key; 164 int rc = 0; 165 166 if (!keyring[id]) 167 return -EINVAL; 168 169 key = key_create_or_update(make_key_ref(keyring[id], 1), "asymmetric", 170 NULL, data, size, perm, 171 KEY_ALLOC_NOT_IN_QUOTA); 172 if (IS_ERR(key)) { 173 rc = PTR_ERR(key); 174 pr_err("Problem loading X.509 certificate %d\n", rc); 175 } else { 176 pr_notice("Loaded X.509 cert '%s'\n", 177 key_ref_to_ptr(key)->description); 178 key_ref_put(key); 179 } 180 181 return rc; 182 183} 184 185int __init integrity_load_x509(const unsigned int id, const char *path) 186{ 187 void *data = NULL; 188 size_t size; 189 int rc; 190 key_perm_t perm; 191 192 rc = kernel_read_file_from_path(path, 0, &data, INT_MAX, NULL, 193 READING_X509_CERTIFICATE); 194 if (rc < 0) { 195 pr_err("Unable to open file: %s (%d)", path, rc); 196 return rc; 197 } 198 size = rc; 199 200 perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ; 201 202 pr_info("Loading X.509 certificate: %s\n", path); 203 rc = integrity_add_key(id, (const void *)data, size, perm); 204 205 vfree(data); 206 return rc; 207} 208 209int __init integrity_load_cert(const unsigned int id, const char *source, 210 const void *data, size_t len, key_perm_t perm) 211{ 212 if (!data) 213 return -EINVAL; 214 215 pr_info("Loading X.509 certificate: %s\n", source); 216 return integrity_add_key(id, data, len, perm); 217}