| 1 | // SPDX-License-Identifier: GPL-2.0-or-later | 
|---|
| 2 | /* Instantiate a public key crypto key from an X.509 Certificate | 
|---|
| 3 | * | 
|---|
| 4 | * Copyright (C) 2012, 2016 Red Hat, Inc. All Rights Reserved. | 
|---|
| 5 | * Written by David Howells (dhowells@redhat.com) | 
|---|
| 6 | */ | 
|---|
| 7 |  | 
|---|
| 8 | #define pr_fmt(fmt) "ASYM: "fmt | 
|---|
| 9 | #include <linux/module.h> | 
|---|
| 10 | #include <linux/kernel.h> | 
|---|
| 11 | #include <linux/err.h> | 
|---|
| 12 | #include <crypto/public_key.h> | 
|---|
| 13 | #include "asymmetric_keys.h" | 
|---|
| 14 |  | 
|---|
| 15 | static bool use_builtin_keys; | 
|---|
| 16 | static struct asymmetric_key_id *ca_keyid; | 
|---|
| 17 |  | 
|---|
| 18 | #ifndef MODULE | 
|---|
| 19 | static struct { | 
|---|
| 20 | struct asymmetric_key_id id; | 
|---|
| 21 | unsigned char data[10]; | 
|---|
| 22 | } cakey; | 
|---|
| 23 |  | 
|---|
| 24 | static int __init ca_keys_setup(char *str) | 
|---|
| 25 | { | 
|---|
| 26 | if (!str)		/* default system keyring */ | 
|---|
| 27 | return 1; | 
|---|
| 28 |  | 
|---|
| 29 | if (strncmp(str, "id:", 3) == 0) { | 
|---|
| 30 | struct asymmetric_key_id *p = &cakey.id; | 
|---|
| 31 | size_t hexlen = (strlen(str) - 3) / 2; | 
|---|
| 32 | int ret; | 
|---|
| 33 |  | 
|---|
| 34 | if (hexlen == 0 || hexlen > sizeof(cakey.data)) { | 
|---|
| 35 | pr_err( "Missing or invalid ca_keys id\n"); | 
|---|
| 36 | return 1; | 
|---|
| 37 | } | 
|---|
| 38 |  | 
|---|
| 39 | ret = __asymmetric_key_hex_to_key_id(id: str + 3, match_id: p, hexlen); | 
|---|
| 40 | if (ret < 0) | 
|---|
| 41 | pr_err( "Unparsable ca_keys id hex string\n"); | 
|---|
| 42 | else | 
|---|
| 43 | ca_keyid = p;	/* owner key 'id:xxxxxx' */ | 
|---|
| 44 | } else if (strcmp(str, "builtin") == 0) { | 
|---|
| 45 | use_builtin_keys = true; | 
|---|
| 46 | } | 
|---|
| 47 |  | 
|---|
| 48 | return 1; | 
|---|
| 49 | } | 
|---|
| 50 | __setup( "ca_keys=", ca_keys_setup); | 
|---|
| 51 | #endif | 
|---|
| 52 |  | 
|---|
| 53 | /** | 
|---|
| 54 | * restrict_link_by_signature - Restrict additions to a ring of public keys | 
|---|
| 55 | * @dest_keyring: Keyring being linked to. | 
|---|
| 56 | * @type: The type of key being added. | 
|---|
| 57 | * @payload: The payload of the new key. | 
|---|
| 58 | * @trust_keyring: A ring of keys that can be used to vouch for the new cert. | 
|---|
| 59 | * | 
|---|
| 60 | * Check the new certificate against the ones in the trust keyring.  If one of | 
|---|
| 61 | * those is the signing key and validates the new certificate, then mark the | 
|---|
| 62 | * new certificate as being trusted. | 
|---|
| 63 | * | 
|---|
| 64 | * Returns 0 if the new certificate was accepted, -ENOKEY if we couldn't find a | 
|---|
| 65 | * matching parent certificate in the trusted list, -EKEYREJECTED if the | 
|---|
| 66 | * signature check fails or the key is blacklisted, -ENOPKG if the signature | 
|---|
| 67 | * uses unsupported crypto, or some other error if there is a matching | 
|---|
| 68 | * certificate but the signature check cannot be performed. | 
|---|
| 69 | */ | 
|---|
| 70 | int restrict_link_by_signature(struct key *dest_keyring, | 
|---|
| 71 | const struct key_type *type, | 
|---|
| 72 | const union key_payload *payload, | 
|---|
| 73 | struct key *trust_keyring) | 
|---|
| 74 | { | 
|---|
| 75 | const struct public_key_signature *sig; | 
|---|
| 76 | struct key *key; | 
|---|
| 77 | int ret; | 
|---|
| 78 |  | 
|---|
| 79 | pr_devel( "==>%s()\n", __func__); | 
|---|
| 80 |  | 
|---|
| 81 | if (!trust_keyring) | 
|---|
| 82 | return -ENOKEY; | 
|---|
| 83 |  | 
|---|
| 84 | if (type != &key_type_asymmetric) | 
|---|
| 85 | return -EOPNOTSUPP; | 
|---|
| 86 |  | 
|---|
| 87 | sig = payload->data[asym_auth]; | 
|---|
| 88 | if (!sig) | 
|---|
| 89 | return -ENOPKG; | 
|---|
| 90 | if (!sig->auth_ids[0] && !sig->auth_ids[1] && !sig->auth_ids[2]) | 
|---|
| 91 | return -ENOKEY; | 
|---|
| 92 |  | 
|---|
| 93 | if (ca_keyid && !asymmetric_key_id_partial(kid1: sig->auth_ids[1], kid2: ca_keyid)) | 
|---|
| 94 | return -EPERM; | 
|---|
| 95 |  | 
|---|
| 96 | /* See if we have a key that signed this one. */ | 
|---|
| 97 | key = find_asymmetric_key(keyring: trust_keyring, | 
|---|
| 98 | id_0: sig->auth_ids[0], id_1: sig->auth_ids[1], | 
|---|
| 99 | id_2: sig->auth_ids[2], partial: false); | 
|---|
| 100 | if (IS_ERR(ptr: key)) | 
|---|
| 101 | return -ENOKEY; | 
|---|
| 102 |  | 
|---|
| 103 | if (use_builtin_keys && !test_bit(KEY_FLAG_BUILTIN, &key->flags)) | 
|---|
| 104 | ret = -ENOKEY; | 
|---|
| 105 | else if (IS_BUILTIN(CONFIG_SECONDARY_TRUSTED_KEYRING_SIGNED_BY_BUILTIN) && | 
|---|
| 106 | !strcmp(dest_keyring->description, ".secondary_trusted_keys") && | 
|---|
| 107 | !test_bit(KEY_FLAG_BUILTIN, &key->flags)) | 
|---|
| 108 | ret = -ENOKEY; | 
|---|
| 109 | else | 
|---|
| 110 | ret = verify_signature(key, sig); | 
|---|
| 111 | key_put(key); | 
|---|
| 112 | return ret; | 
|---|
| 113 | } | 
|---|
| 114 |  | 
|---|
| 115 | /** | 
|---|
| 116 | * restrict_link_by_ca - Restrict additions to a ring of CA keys | 
|---|
| 117 | * @dest_keyring: Keyring being linked to. | 
|---|
| 118 | * @type: The type of key being added. | 
|---|
| 119 | * @payload: The payload of the new key. | 
|---|
| 120 | * @trust_keyring: Unused. | 
|---|
| 121 | * | 
|---|
| 122 | * Check if the new certificate is a CA. If it is a CA, then mark the new | 
|---|
| 123 | * certificate as being ok to link. | 
|---|
| 124 | * | 
|---|
| 125 | * Returns 0 if the new certificate was accepted, -ENOKEY if the | 
|---|
| 126 | * certificate is not a CA. -ENOPKG if the signature uses unsupported | 
|---|
| 127 | * crypto, or some other error if there is a matching certificate but | 
|---|
| 128 | * the signature check cannot be performed. | 
|---|
| 129 | */ | 
|---|
| 130 | int restrict_link_by_ca(struct key *dest_keyring, | 
|---|
| 131 | const struct key_type *type, | 
|---|
| 132 | const union key_payload *payload, | 
|---|
| 133 | struct key *trust_keyring) | 
|---|
| 134 | { | 
|---|
| 135 | const struct public_key *pkey; | 
|---|
| 136 |  | 
|---|
| 137 | if (type != &key_type_asymmetric) | 
|---|
| 138 | return -EOPNOTSUPP; | 
|---|
| 139 |  | 
|---|
| 140 | pkey = payload->data[asym_crypto]; | 
|---|
| 141 | if (!pkey) | 
|---|
| 142 | return -ENOPKG; | 
|---|
| 143 | if (!test_bit(KEY_EFLAG_CA, &pkey->key_eflags)) | 
|---|
| 144 | return -ENOKEY; | 
|---|
| 145 | if (!test_bit(KEY_EFLAG_KEYCERTSIGN, &pkey->key_eflags)) | 
|---|
| 146 | return -ENOKEY; | 
|---|
| 147 | if (!IS_ENABLED(CONFIG_INTEGRITY_CA_MACHINE_KEYRING_MAX)) | 
|---|
| 148 | return 0; | 
|---|
| 149 | if (test_bit(KEY_EFLAG_DIGITALSIG, &pkey->key_eflags)) | 
|---|
| 150 | return -ENOKEY; | 
|---|
| 151 |  | 
|---|
| 152 | return 0; | 
|---|
| 153 | } | 
|---|
| 154 |  | 
|---|
| 155 | /** | 
|---|
| 156 | * restrict_link_by_digsig - Restrict additions to a ring of digsig keys | 
|---|
| 157 | * @dest_keyring: Keyring being linked to. | 
|---|
| 158 | * @type: The type of key being added. | 
|---|
| 159 | * @payload: The payload of the new key. | 
|---|
| 160 | * @trust_keyring: A ring of keys that can be used to vouch for the new cert. | 
|---|
| 161 | * | 
|---|
| 162 | * Check if the new certificate has digitalSignature usage set. If it is, | 
|---|
| 163 | * then mark the new certificate as being ok to link. Afterwards verify | 
|---|
| 164 | * the new certificate against the ones in the trust_keyring. | 
|---|
| 165 | * | 
|---|
| 166 | * Returns 0 if the new certificate was accepted, -ENOKEY if the | 
|---|
| 167 | * certificate is not a digsig. -ENOPKG if the signature uses unsupported | 
|---|
| 168 | * crypto, or some other error if there is a matching certificate but | 
|---|
| 169 | * the signature check cannot be performed. | 
|---|
| 170 | */ | 
|---|
| 171 | int restrict_link_by_digsig(struct key *dest_keyring, | 
|---|
| 172 | const struct key_type *type, | 
|---|
| 173 | const union key_payload *payload, | 
|---|
| 174 | struct key *trust_keyring) | 
|---|
| 175 | { | 
|---|
| 176 | const struct public_key *pkey; | 
|---|
| 177 |  | 
|---|
| 178 | if (type != &key_type_asymmetric) | 
|---|
| 179 | return -EOPNOTSUPP; | 
|---|
| 180 |  | 
|---|
| 181 | pkey = payload->data[asym_crypto]; | 
|---|
| 182 |  | 
|---|
| 183 | if (!pkey) | 
|---|
| 184 | return -ENOPKG; | 
|---|
| 185 |  | 
|---|
| 186 | if (!test_bit(KEY_EFLAG_DIGITALSIG, &pkey->key_eflags)) | 
|---|
| 187 | return -ENOKEY; | 
|---|
| 188 |  | 
|---|
| 189 | if (test_bit(KEY_EFLAG_CA, &pkey->key_eflags)) | 
|---|
| 190 | return -ENOKEY; | 
|---|
| 191 |  | 
|---|
| 192 | if (test_bit(KEY_EFLAG_KEYCERTSIGN, &pkey->key_eflags)) | 
|---|
| 193 | return -ENOKEY; | 
|---|
| 194 |  | 
|---|
| 195 | return restrict_link_by_signature(dest_keyring, type, payload, | 
|---|
| 196 | trust_keyring); | 
|---|
| 197 | } | 
|---|
| 198 |  | 
|---|
| 199 | static bool match_either_id(const struct asymmetric_key_id **pair, | 
|---|
| 200 | const struct asymmetric_key_id *single) | 
|---|
| 201 | { | 
|---|
| 202 | return (asymmetric_key_id_same(kid1: pair[0], kid2: single) || | 
|---|
| 203 | asymmetric_key_id_same(kid1: pair[1], kid2: single)); | 
|---|
| 204 | } | 
|---|
| 205 |  | 
|---|
| 206 | static int key_or_keyring_common(struct key *dest_keyring, | 
|---|
| 207 | const struct key_type *type, | 
|---|
| 208 | const union key_payload *payload, | 
|---|
| 209 | struct key *trusted, bool check_dest) | 
|---|
| 210 | { | 
|---|
| 211 | const struct public_key_signature *sig; | 
|---|
| 212 | struct key *key = NULL; | 
|---|
| 213 | int ret; | 
|---|
| 214 |  | 
|---|
| 215 | pr_devel( "==>%s()\n", __func__); | 
|---|
| 216 |  | 
|---|
| 217 | if (!dest_keyring) | 
|---|
| 218 | return -ENOKEY; | 
|---|
| 219 | else if (dest_keyring->type != &key_type_keyring) | 
|---|
| 220 | return -EOPNOTSUPP; | 
|---|
| 221 |  | 
|---|
| 222 | if (!trusted && !check_dest) | 
|---|
| 223 | return -ENOKEY; | 
|---|
| 224 |  | 
|---|
| 225 | if (type != &key_type_asymmetric) | 
|---|
| 226 | return -EOPNOTSUPP; | 
|---|
| 227 |  | 
|---|
| 228 | sig = payload->data[asym_auth]; | 
|---|
| 229 | if (!sig) | 
|---|
| 230 | return -ENOPKG; | 
|---|
| 231 | if (!sig->auth_ids[0] && !sig->auth_ids[1] && !sig->auth_ids[2]) | 
|---|
| 232 | return -ENOKEY; | 
|---|
| 233 |  | 
|---|
| 234 | if (trusted) { | 
|---|
| 235 | if (trusted->type == &key_type_keyring) { | 
|---|
| 236 | /* See if we have a key that signed this one. */ | 
|---|
| 237 | key = find_asymmetric_key(keyring: trusted, id_0: sig->auth_ids[0], | 
|---|
| 238 | id_1: sig->auth_ids[1], | 
|---|
| 239 | id_2: sig->auth_ids[2], partial: false); | 
|---|
| 240 | if (IS_ERR(ptr: key)) | 
|---|
| 241 | key = NULL; | 
|---|
| 242 | } else if (trusted->type == &key_type_asymmetric) { | 
|---|
| 243 | const struct asymmetric_key_id **signer_ids; | 
|---|
| 244 |  | 
|---|
| 245 | signer_ids = (const struct asymmetric_key_id **) | 
|---|
| 246 | asymmetric_key_ids(key: trusted)->id; | 
|---|
| 247 |  | 
|---|
| 248 | /* | 
|---|
| 249 | * The auth_ids come from the candidate key (the | 
|---|
| 250 | * one that is being considered for addition to | 
|---|
| 251 | * dest_keyring) and identify the key that was | 
|---|
| 252 | * used to sign. | 
|---|
| 253 | * | 
|---|
| 254 | * The signer_ids are identifiers for the | 
|---|
| 255 | * signing key specified for dest_keyring. | 
|---|
| 256 | * | 
|---|
| 257 | * The first auth_id is the preferred id, 2nd and | 
|---|
| 258 | * 3rd are the fallbacks. If exactly one of | 
|---|
| 259 | * auth_ids[0] and auth_ids[1] is present, it may | 
|---|
| 260 | * match either signer_ids[0] or signed_ids[1]. | 
|---|
| 261 | * If both are present the first one may match | 
|---|
| 262 | * either signed_id but the second one must match | 
|---|
| 263 | * the second signer_id. If neither of them is | 
|---|
| 264 | * available, auth_ids[2] is matched against | 
|---|
| 265 | * signer_ids[2] as a fallback. | 
|---|
| 266 | */ | 
|---|
| 267 | if (!sig->auth_ids[0] && !sig->auth_ids[1]) { | 
|---|
| 268 | if (asymmetric_key_id_same(kid1: signer_ids[2], | 
|---|
| 269 | kid2: sig->auth_ids[2])) | 
|---|
| 270 | key = __key_get(key: trusted); | 
|---|
| 271 |  | 
|---|
| 272 | } else if (!sig->auth_ids[0] || !sig->auth_ids[1]) { | 
|---|
| 273 | const struct asymmetric_key_id *auth_id; | 
|---|
| 274 |  | 
|---|
| 275 | auth_id = sig->auth_ids[0] ?: sig->auth_ids[1]; | 
|---|
| 276 | if (match_either_id(pair: signer_ids, single: auth_id)) | 
|---|
| 277 | key = __key_get(key: trusted); | 
|---|
| 278 |  | 
|---|
| 279 | } else if (asymmetric_key_id_same(kid1: signer_ids[1], | 
|---|
| 280 | kid2: sig->auth_ids[1]) && | 
|---|
| 281 | match_either_id(pair: signer_ids, | 
|---|
| 282 | single: sig->auth_ids[0])) { | 
|---|
| 283 | key = __key_get(key: trusted); | 
|---|
| 284 | } | 
|---|
| 285 | } else { | 
|---|
| 286 | return -EOPNOTSUPP; | 
|---|
| 287 | } | 
|---|
| 288 | } | 
|---|
| 289 |  | 
|---|
| 290 | if (check_dest && !key) { | 
|---|
| 291 | /* See if the destination has a key that signed this one. */ | 
|---|
| 292 | key = find_asymmetric_key(keyring: dest_keyring, id_0: sig->auth_ids[0], | 
|---|
| 293 | id_1: sig->auth_ids[1], id_2: sig->auth_ids[2], | 
|---|
| 294 | partial: false); | 
|---|
| 295 | if (IS_ERR(ptr: key)) | 
|---|
| 296 | key = NULL; | 
|---|
| 297 | } | 
|---|
| 298 |  | 
|---|
| 299 | if (!key) | 
|---|
| 300 | return -ENOKEY; | 
|---|
| 301 |  | 
|---|
| 302 | ret = key_validate(key); | 
|---|
| 303 | if (ret == 0) | 
|---|
| 304 | ret = verify_signature(key, sig); | 
|---|
| 305 |  | 
|---|
| 306 | key_put(key); | 
|---|
| 307 | return ret; | 
|---|
| 308 | } | 
|---|
| 309 |  | 
|---|
| 310 | /** | 
|---|
| 311 | * restrict_link_by_key_or_keyring - Restrict additions to a ring of public | 
|---|
| 312 | * keys using the restrict_key information stored in the ring. | 
|---|
| 313 | * @dest_keyring: Keyring being linked to. | 
|---|
| 314 | * @type: The type of key being added. | 
|---|
| 315 | * @payload: The payload of the new key. | 
|---|
| 316 | * @trusted: A key or ring of keys that can be used to vouch for the new cert. | 
|---|
| 317 | * | 
|---|
| 318 | * Check the new certificate only against the key or keys passed in the data | 
|---|
| 319 | * parameter. If one of those is the signing key and validates the new | 
|---|
| 320 | * certificate, then mark the new certificate as being ok to link. | 
|---|
| 321 | * | 
|---|
| 322 | * Returns 0 if the new certificate was accepted, -ENOKEY if we | 
|---|
| 323 | * couldn't find a matching parent certificate in the trusted list, | 
|---|
| 324 | * -EKEYREJECTED if the signature check fails, -ENOPKG if the signature uses | 
|---|
| 325 | * unsupported crypto, or some other error if there is a matching certificate | 
|---|
| 326 | * but the signature check cannot be performed. | 
|---|
| 327 | */ | 
|---|
| 328 | int restrict_link_by_key_or_keyring(struct key *dest_keyring, | 
|---|
| 329 | const struct key_type *type, | 
|---|
| 330 | const union key_payload *payload, | 
|---|
| 331 | struct key *trusted) | 
|---|
| 332 | { | 
|---|
| 333 | return key_or_keyring_common(dest_keyring, type, payload, trusted, | 
|---|
| 334 | check_dest: false); | 
|---|
| 335 | } | 
|---|
| 336 |  | 
|---|
| 337 | /** | 
|---|
| 338 | * restrict_link_by_key_or_keyring_chain - Restrict additions to a ring of | 
|---|
| 339 | * public keys using the restrict_key information stored in the ring. | 
|---|
| 340 | * @dest_keyring: Keyring being linked to. | 
|---|
| 341 | * @type: The type of key being added. | 
|---|
| 342 | * @payload: The payload of the new key. | 
|---|
| 343 | * @trusted: A key or ring of keys that can be used to vouch for the new cert. | 
|---|
| 344 | * | 
|---|
| 345 | * Check the new certificate against the key or keys passed in the data | 
|---|
| 346 | * parameter and against the keys already linked to the destination keyring. If | 
|---|
| 347 | * one of those is the signing key and validates the new certificate, then mark | 
|---|
| 348 | * the new certificate as being ok to link. | 
|---|
| 349 | * | 
|---|
| 350 | * Returns 0 if the new certificate was accepted, -ENOKEY if we | 
|---|
| 351 | * couldn't find a matching parent certificate in the trusted list, | 
|---|
| 352 | * -EKEYREJECTED if the signature check fails, -ENOPKG if the signature uses | 
|---|
| 353 | * unsupported crypto, or some other error if there is a matching certificate | 
|---|
| 354 | * but the signature check cannot be performed. | 
|---|
| 355 | */ | 
|---|
| 356 | int restrict_link_by_key_or_keyring_chain(struct key *dest_keyring, | 
|---|
| 357 | const struct key_type *type, | 
|---|
| 358 | const union key_payload *payload, | 
|---|
| 359 | struct key *trusted) | 
|---|
| 360 | { | 
|---|
| 361 | return key_or_keyring_common(dest_keyring, type, payload, trusted, | 
|---|
| 362 | check_dest: true); | 
|---|
| 363 | } | 
|---|
| 364 |  | 
|---|