1 /* 2 * Copyright (C) 2011 Intel Corporation 3 * 4 * Author: 5 * Dmitry Kasatkin <dmitry.kasatkin@intel.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, version 2 of the License. 10 * 11 */ 12 13 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 14 15 #include <linux/err.h> 16 #include <linux/sched.h> 17 #include <linux/slab.h> 18 #include <linux/cred.h> 19 #include <linux/key-type.h> 20 #include <linux/digsig.h> 21 #include <crypto/public_key.h> 22 #include <keys/system_keyring.h> 23 24 #include "integrity.h" 25 26 static struct key *keyring[INTEGRITY_KEYRING_MAX]; 27 28 static const char *keyring_name[INTEGRITY_KEYRING_MAX] = { 29 #ifndef CONFIG_INTEGRITY_TRUSTED_KEYRING 30 "_evm", 31 "_ima", 32 #else 33 ".evm", 34 ".ima", 35 #endif 36 "_module", 37 }; 38 39 #ifdef CONFIG_INTEGRITY_TRUSTED_KEYRING 40 static bool init_keyring __initdata = true; 41 #else 42 static bool init_keyring __initdata; 43 #endif 44 45 #ifdef CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY 46 #define restrict_link_to_ima restrict_link_by_builtin_and_secondary_trusted 47 #else 48 #define restrict_link_to_ima restrict_link_by_builtin_trusted 49 #endif 50 51 int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, 52 const char *digest, int digestlen) 53 { 54 if (id >= INTEGRITY_KEYRING_MAX) 55 return -EINVAL; 56 57 if (!keyring[id]) { 58 keyring[id] = 59 request_key(&key_type_keyring, keyring_name[id], NULL); 60 if (IS_ERR(keyring[id])) { 61 int err = PTR_ERR(keyring[id]); 62 pr_err("no %s keyring: %d\n", keyring_name[id], err); 63 keyring[id] = NULL; 64 return err; 65 } 66 } 67 68 switch (sig[1]) { 69 case 1: 70 /* v1 API expect signature without xattr type */ 71 return digsig_verify(keyring[id], sig + 1, siglen - 1, 72 digest, digestlen); 73 case 2: 74 return asymmetric_verify(keyring[id], sig, siglen, 75 digest, digestlen); 76 } 77 78 return -EOPNOTSUPP; 79 } 80 81 int __init integrity_init_keyring(const unsigned int id) 82 { 83 const struct cred *cred = current_cred(); 84 int err = 0; 85 86 if (!init_keyring) 87 return 0; 88 89 keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0), 90 KGIDT_INIT(0), cred, 91 ((KEY_POS_ALL & ~KEY_POS_SETATTR) | 92 KEY_USR_VIEW | KEY_USR_READ | 93 KEY_USR_WRITE | KEY_USR_SEARCH), 94 KEY_ALLOC_NOT_IN_QUOTA, 95 restrict_link_to_ima, NULL); 96 if (IS_ERR(keyring[id])) { 97 err = PTR_ERR(keyring[id]); 98 pr_info("Can't allocate %s keyring (%d)\n", 99 keyring_name[id], err); 100 keyring[id] = NULL; 101 } 102 return err; 103 } 104 105 int __init integrity_load_x509(const unsigned int id, const char *path) 106 { 107 key_ref_t key; 108 char *data; 109 int rc; 110 111 if (!keyring[id]) 112 return -EINVAL; 113 114 rc = integrity_read_file(path, &data); 115 if (rc < 0) 116 return rc; 117 118 key = key_create_or_update(make_key_ref(keyring[id], 1), 119 "asymmetric", 120 NULL, 121 data, 122 rc, 123 ((KEY_POS_ALL & ~KEY_POS_SETATTR) | 124 KEY_USR_VIEW | KEY_USR_READ), 125 KEY_ALLOC_NOT_IN_QUOTA); 126 if (IS_ERR(key)) { 127 rc = PTR_ERR(key); 128 pr_err("Problem loading X.509 certificate (%d): %s\n", 129 rc, path); 130 } else { 131 pr_notice("Loaded X.509 cert '%s': %s\n", 132 key_ref_to_ptr(key)->description, path); 133 key_ref_put(key); 134 } 135 kfree(data); 136 return 0; 137 } 138