Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge remote-tracking branch 'integrity/next-with-keys' into keys-next

Signed-off-by: David Howells <dhowells@redhat.com>

+225 -25
+5
Documentation/kernel-parameters.txt
··· 566 566 possible to determine what the correct size should be. 567 567 This option provides an override for these situations. 568 568 569 + ca_keys= [KEYS] This parameter identifies a specific key(s) on 570 + the system trusted keyring to be used for certificate 571 + trust validation. 572 + format: { id:<keyid> | builtin } 573 + 569 574 ccw_timeout_log [S390] 570 575 See Documentation/s390/CommonIO for details. 571 576
+2
crypto/asymmetric_keys/asymmetric_keys.h
··· 9 9 * 2 of the Licence, or (at your option) any later version. 10 10 */ 11 11 12 + int asymmetric_keyid_match(const char *kid, const char *id); 13 + 12 14 static inline const char *asymmetric_key_id(const struct key *key) 13 15 { 14 16 return key->type_data.p[1];
+32 -19
crypto/asymmetric_keys/asymmetric_type.c
··· 23 23 static DECLARE_RWSEM(asymmetric_key_parsers_sem); 24 24 25 25 /* 26 + * Match asymmetric key id with partial match 27 + * @id: key id to match in a form "id:<id>" 28 + */ 29 + int asymmetric_keyid_match(const char *kid, const char *id) 30 + { 31 + size_t idlen, kidlen; 32 + 33 + if (!kid || !id) 34 + return 0; 35 + 36 + /* make it possible to use id as in the request: "id:<id>" */ 37 + if (strncmp(id, "id:", 3) == 0) 38 + id += 3; 39 + 40 + /* Anything after here requires a partial match on the ID string */ 41 + idlen = strlen(id); 42 + kidlen = strlen(kid); 43 + if (idlen > kidlen) 44 + return 0; 45 + 46 + kid += kidlen - idlen; 47 + if (strcasecmp(id, kid) != 0) 48 + return 0; 49 + 50 + return 1; 51 + } 52 + EXPORT_SYMBOL_GPL(asymmetric_keyid_match); 53 + 54 + /* 26 55 * Match asymmetric keys on (part of) their name 27 56 * We have some shorthand methods for matching keys. We allow: 28 57 * ··· 63 34 { 64 35 const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); 65 36 const char *spec = description; 66 - const char *id, *kid; 37 + const char *id; 67 38 ptrdiff_t speclen; 68 - size_t idlen, kidlen; 69 39 70 40 if (!subtype || !spec || !*spec) 71 41 return 0; ··· 83 55 speclen = id - spec; 84 56 id++; 85 57 86 - /* Anything after here requires a partial match on the ID string */ 87 - kid = asymmetric_key_id(key); 88 - if (!kid) 89 - return 0; 90 - 91 - idlen = strlen(id); 92 - kidlen = strlen(kid); 93 - if (idlen > kidlen) 94 - return 0; 95 - 96 - kid += kidlen - idlen; 97 - if (strcasecmp(id, kid) != 0) 98 - return 0; 99 - 100 - if (speclen == 2 && 101 - memcmp(spec, "id", 2) == 0) 102 - return 1; 58 + if (speclen == 2 && memcmp(spec, "id", 2) == 0) 59 + return asymmetric_keyid_match(asymmetric_key_id(key), id); 103 60 104 61 if (speclen == subtype->name_len && 105 62 memcmp(spec, subtype->name, speclen) == 0)
+108 -1
crypto/asymmetric_keys/x509_public_key.c
··· 18 18 #include <linux/asn1_decoder.h> 19 19 #include <keys/asymmetric-subtype.h> 20 20 #include <keys/asymmetric-parser.h> 21 + #include <keys/system_keyring.h> 21 22 #include <crypto/hash.h> 22 23 #include "asymmetric_keys.h" 23 24 #include "public_key.h" 24 25 #include "x509_parser.h" 26 + 27 + static bool use_builtin_keys; 28 + static char *ca_keyid; 29 + 30 + #ifndef MODULE 31 + static int __init ca_keys_setup(char *str) 32 + { 33 + if (!str) /* default system keyring */ 34 + return 1; 35 + 36 + if (strncmp(str, "id:", 3) == 0) 37 + ca_keyid = str; /* owner key 'id:xxxxxx' */ 38 + else if (strcmp(str, "builtin") == 0) 39 + use_builtin_keys = true; 40 + 41 + return 1; 42 + } 43 + __setup("ca_keys=", ca_keys_setup); 44 + #endif 45 + 46 + /* 47 + * Find a key in the given keyring by issuer and authority. 48 + */ 49 + static struct key *x509_request_asymmetric_key(struct key *keyring, 50 + const char *signer, 51 + size_t signer_len, 52 + const char *authority, 53 + size_t auth_len) 54 + { 55 + key_ref_t key; 56 + char *id; 57 + 58 + /* Construct an identifier. */ 59 + id = kmalloc(signer_len + 2 + auth_len + 1, GFP_KERNEL); 60 + if (!id) 61 + return ERR_PTR(-ENOMEM); 62 + 63 + memcpy(id, signer, signer_len); 64 + id[signer_len + 0] = ':'; 65 + id[signer_len + 1] = ' '; 66 + memcpy(id + signer_len + 2, authority, auth_len); 67 + id[signer_len + 2 + auth_len] = 0; 68 + 69 + pr_debug("Look up: \"%s\"\n", id); 70 + 71 + key = keyring_search(make_key_ref(keyring, 1), 72 + &key_type_asymmetric, id); 73 + if (IS_ERR(key)) 74 + pr_debug("Request for module key '%s' err %ld\n", 75 + id, PTR_ERR(key)); 76 + kfree(id); 77 + 78 + if (IS_ERR(key)) { 79 + switch (PTR_ERR(key)) { 80 + /* Hide some search errors */ 81 + case -EACCES: 82 + case -ENOTDIR: 83 + case -EAGAIN: 84 + return ERR_PTR(-ENOKEY); 85 + default: 86 + return ERR_CAST(key); 87 + } 88 + } 89 + 90 + pr_devel("<==%s() = 0 [%x]\n", __func__, 91 + key_serial(key_ref_to_ptr(key))); 92 + return key_ref_to_ptr(key); 93 + } 25 94 26 95 /* 27 96 * Set up the signature parameters in an X.509 certificate. This involves ··· 172 103 EXPORT_SYMBOL_GPL(x509_check_signature); 173 104 174 105 /* 106 + * Check the new certificate against the ones in the trust keyring. If one of 107 + * those is the signing key and validates the new certificate, then mark the 108 + * new certificate as being trusted. 109 + * 110 + * Return 0 if the new certificate was successfully validated, 1 if we couldn't 111 + * find a matching parent certificate in the trusted list and an error if there 112 + * is a matching certificate but the signature check fails. 113 + */ 114 + static int x509_validate_trust(struct x509_certificate *cert, 115 + struct key *trust_keyring) 116 + { 117 + struct key *key; 118 + int ret = 1; 119 + 120 + if (!trust_keyring) 121 + return -EOPNOTSUPP; 122 + 123 + if (ca_keyid && !asymmetric_keyid_match(cert->authority, ca_keyid)) 124 + return -EPERM; 125 + 126 + key = x509_request_asymmetric_key(trust_keyring, 127 + cert->issuer, strlen(cert->issuer), 128 + cert->authority, 129 + strlen(cert->authority)); 130 + if (!IS_ERR(key)) { 131 + if (!use_builtin_keys 132 + || test_bit(KEY_FLAG_BUILTIN, &key->flags)) 133 + ret = x509_check_signature(key->payload.data, cert); 134 + key_put(key); 135 + } 136 + return ret; 137 + } 138 + 139 + /* 175 140 * Attempt to parse a data blob for a key as an X509 certificate. 176 141 */ 177 142 static int x509_key_preparse(struct key_preparsed_payload *prep) ··· 258 155 /* Check the signature on the key if it appears to be self-signed */ 259 156 if (!cert->authority || 260 157 strcmp(cert->fingerprint, cert->authority) == 0) { 261 - ret = x509_check_signature(cert->pub, cert); 158 + ret = x509_check_signature(cert->pub, cert); /* self-signed */ 262 159 if (ret < 0) 263 160 goto error_free_cert; 161 + } else if (!prep->trusted) { 162 + ret = x509_validate_trust(cert, get_system_trusted_keyring()); 163 + if (!ret) 164 + prep->trusted = 1; 264 165 } 265 166 266 167 /* Propose a description */
+9 -1
include/keys/system_keyring.h
··· 17 17 #include <linux/key.h> 18 18 19 19 extern struct key *system_trusted_keyring; 20 - 20 + static inline struct key *get_system_trusted_keyring(void) 21 + { 22 + return system_trusted_keyring; 23 + } 24 + #else 25 + static inline struct key *get_system_trusted_keyring(void) 26 + { 27 + return NULL; 28 + } 21 29 #endif 22 30 23 31 #endif /* _KEYS_SYSTEM_KEYRING_H */
+1
include/linux/key.h
··· 170 170 #define KEY_FLAG_INVALIDATED 7 /* set if key has been invalidated */ 171 171 #define KEY_FLAG_TRUSTED 8 /* set if key is trusted */ 172 172 #define KEY_FLAG_TRUSTED_ONLY 9 /* set if keyring only accepts links to trusted keys */ 173 + #define KEY_FLAG_BUILTIN 10 /* set if key is builtin */ 173 174 174 175 /* the key type and key description string 175 176 * - the desc is used to match a key against search criteria
+1
kernel/system_keyring.c
··· 89 89 pr_err("Problem loading in-kernel X.509 certificate (%ld)\n", 90 90 PTR_ERR(key)); 91 91 } else { 92 + set_bit(KEY_FLAG_BUILTIN, &key_ref_to_ptr(key)->flags); 92 93 pr_notice("Loaded X.509 cert '%s'\n", 93 94 key_ref_to_ptr(key)->description); 94 95 key_ref_put(key);
+28
security/integrity/digsig.c
··· 13 13 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 14 14 15 15 #include <linux/err.h> 16 + #include <linux/sched.h> 16 17 #include <linux/rbtree.h> 18 + #include <linux/cred.h> 17 19 #include <linux/key-type.h> 18 20 #include <linux/digsig.h> 19 21 ··· 26 24 static const char *keyring_name[INTEGRITY_KEYRING_MAX] = { 27 25 "_evm", 28 26 "_module", 27 + #ifndef CONFIG_IMA_TRUSTED_KEYRING 29 28 "_ima", 29 + #else 30 + ".ima", 31 + #endif 30 32 }; 31 33 32 34 int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, ··· 61 55 } 62 56 63 57 return -EOPNOTSUPP; 58 + } 59 + 60 + int integrity_init_keyring(const unsigned int id) 61 + { 62 + const struct cred *cred = current_cred(); 63 + int err = 0; 64 + 65 + keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0), 66 + KGIDT_INIT(0), cred, 67 + ((KEY_POS_ALL & ~KEY_POS_SETATTR) | 68 + KEY_USR_VIEW | KEY_USR_READ | 69 + KEY_USR_WRITE | KEY_USR_SEARCH), 70 + KEY_ALLOC_NOT_IN_QUOTA, NULL); 71 + if (!IS_ERR(keyring[id])) 72 + set_bit(KEY_FLAG_TRUSTED_ONLY, &keyring[id]->flags); 73 + else { 74 + err = PTR_ERR(keyring[id]); 75 + pr_info("Can't allocate %s keyring (%d)\n", 76 + keyring_name[id], err); 77 + keyring[id] = NULL; 78 + } 79 + return err; 64 80 }
+10
security/integrity/ima/Kconfig
··· 123 123 For more information on integrity appraisal refer to: 124 124 <http://linux-ima.sourceforge.net> 125 125 If unsure, say N. 126 + 127 + config IMA_TRUSTED_KEYRING 128 + bool "Require all keys on the .ima keyring be signed" 129 + depends on IMA_APPRAISE && SYSTEM_TRUSTED_KEYRING 130 + depends on INTEGRITY_ASYMMETRIC_KEYS 131 + select KEYS_DEBUG_PROC_KEYS 132 + default y 133 + help 134 + This option requires that all keys added to the .ima 135 + keyring be signed by a key on the system trusted keyring.
+12
security/integrity/ima/ima.h
··· 249 249 return -EINVAL; 250 250 } 251 251 #endif /* CONFIG_IMA_LSM_RULES */ 252 + 253 + #ifdef CONFIG_IMA_TRUSTED_KEYRING 254 + static inline int ima_init_keyring(const unsigned int id) 255 + { 256 + return integrity_init_keyring(id); 257 + } 258 + #else 259 + static inline int ima_init_keyring(const unsigned int id) 260 + { 261 + return 0; 262 + } 263 + #endif /* CONFIG_IMA_TRUSTED_KEYRING */ 252 264 #endif
+8 -2
security/integrity/ima/ima_main.c
··· 325 325 326 326 hash_setup(CONFIG_IMA_DEFAULT_HASH); 327 327 error = ima_init(); 328 - if (!error) 329 - ima_initialized = 1; 328 + if (error) 329 + goto out; 330 + 331 + error = ima_init_keyring(INTEGRITY_KEYRING_IMA); 332 + if (error) 333 + goto out; 334 + ima_initialized = 1; 335 + out: 330 336 return error; 331 337 } 332 338
+5
security/integrity/integrity.h
··· 124 124 int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, 125 125 const char *digest, int digestlen); 126 126 127 + int integrity_init_keyring(const unsigned int id); 127 128 #else 128 129 129 130 static inline int integrity_digsig_verify(const unsigned int id, ··· 134 133 return -EOPNOTSUPP; 135 134 } 136 135 136 + static inline int integrity_init_keyring(const unsigned int id) 137 + { 138 + return 0; 139 + } 137 140 #endif /* CONFIG_INTEGRITY_SIGNATURE */ 138 141 139 142 #ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS
+4 -2
security/keys/keyctl.c
··· 37 37 return ret; 38 38 if (ret == 0 || ret >= len) 39 39 return -EINVAL; 40 - if (type[0] == '.') 41 - return -EPERM; 42 40 type[len - 1] = '\0'; 43 41 return 0; 44 42 } ··· 84 86 if (!*description) { 85 87 kfree(description); 86 88 description = NULL; 89 + } else if ((description[0] == '.') && 90 + (strncmp(type, "keyring", 7) == 0)) { 91 + ret = -EPERM; 92 + goto error2; 87 93 } 88 94 } 89 95