1 /* Asymmetric public-key cryptography key type 2 * 3 * See Documentation/security/asymmetric-keys.txt 4 * 5 * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. 6 * Written by David Howells (dhowells@redhat.com) 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public Licence 10 * as published by the Free Software Foundation; either version 11 * 2 of the Licence, or (at your option) any later version. 12 */ 13 #include <keys/asymmetric-subtype.h> 14 #include <keys/asymmetric-parser.h> 15 #include <crypto/public_key.h> 16 #include <linux/seq_file.h> 17 #include <linux/module.h> 18 #include <linux/slab.h> 19 #include <linux/ctype.h> 20 #include "asymmetric_keys.h" 21 22 MODULE_LICENSE("GPL"); 23 24 const char *const key_being_used_for[NR__KEY_BEING_USED_FOR] = { 25 [VERIFYING_MODULE_SIGNATURE] = "mod sig", 26 [VERIFYING_FIRMWARE_SIGNATURE] = "firmware sig", 27 [VERIFYING_KEXEC_PE_SIGNATURE] = "kexec PE sig", 28 [VERIFYING_KEY_SIGNATURE] = "key sig", 29 [VERIFYING_KEY_SELF_SIGNATURE] = "key self sig", 30 [VERIFYING_UNSPECIFIED_SIGNATURE] = "unspec sig", 31 }; 32 EXPORT_SYMBOL_GPL(key_being_used_for); 33 34 static LIST_HEAD(asymmetric_key_parsers); 35 static DECLARE_RWSEM(asymmetric_key_parsers_sem); 36 37 /** 38 * find_asymmetric_key - Find a key by ID. 39 * @keyring: The keys to search. 40 * @id_0: The first ID to look for or NULL. 41 * @id_1: The second ID to look for or NULL. 42 * @partial: Use partial match if true, exact if false. 43 * 44 * Find a key in the given keyring by identifier. The preferred identifier is 45 * the id_0 and the fallback identifier is the id_1. If both are given, the 46 * lookup is by the former, but the latter must also match. 47 */ 48 struct key *find_asymmetric_key(struct key *keyring, 49 const struct asymmetric_key_id *id_0, 50 const struct asymmetric_key_id *id_1, 51 bool partial) 52 { 53 struct key *key; 54 key_ref_t ref; 55 const char *lookup; 56 char *req, *p; 57 int len; 58 59 if (id_0) { 60 lookup = id_0->data; 61 len = id_0->len; 62 } else { 63 lookup = id_1->data; 64 len = id_1->len; 65 } 66 67 /* Construct an identifier "id:<keyid>". */ 68 p = req = kmalloc(2 + 1 + len * 2 + 1, GFP_KERNEL); 69 if (!req) 70 return ERR_PTR(-ENOMEM); 71 72 if (partial) { 73 *p++ = 'i'; 74 *p++ = 'd'; 75 } else { 76 *p++ = 'e'; 77 *p++ = 'x'; 78 } 79 *p++ = ':'; 80 p = bin2hex(p, lookup, len); 81 *p = 0; 82 83 pr_debug("Look up: \"%s\"\n", req); 84 85 ref = keyring_search(make_key_ref(keyring, 1), 86 &key_type_asymmetric, req); 87 if (IS_ERR(ref)) 88 pr_debug("Request for key '%s' err %ld\n", req, PTR_ERR(ref)); 89 kfree(req); 90 91 if (IS_ERR(ref)) { 92 switch (PTR_ERR(ref)) { 93 /* Hide some search errors */ 94 case -EACCES: 95 case -ENOTDIR: 96 case -EAGAIN: 97 return ERR_PTR(-ENOKEY); 98 default: 99 return ERR_CAST(ref); 100 } 101 } 102 103 key = key_ref_to_ptr(ref); 104 if (id_0 && id_1) { 105 const struct asymmetric_key_ids *kids = asymmetric_key_ids(key); 106 107 if (!kids->id[0]) { 108 pr_debug("First ID matches, but second is missing\n"); 109 goto reject; 110 } 111 if (!asymmetric_key_id_same(id_1, kids->id[1])) { 112 pr_debug("First ID matches, but second does not\n"); 113 goto reject; 114 } 115 } 116 117 pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key)); 118 return key; 119 120 reject: 121 key_put(key); 122 return ERR_PTR(-EKEYREJECTED); 123 } 124 EXPORT_SYMBOL_GPL(find_asymmetric_key); 125 126 /** 127 * asymmetric_key_generate_id: Construct an asymmetric key ID 128 * @val_1: First binary blob 129 * @len_1: Length of first binary blob 130 * @val_2: Second binary blob 131 * @len_2: Length of second binary blob 132 * 133 * Construct an asymmetric key ID from a pair of binary blobs. 134 */ 135 struct asymmetric_key_id *asymmetric_key_generate_id(const void *val_1, 136 size_t len_1, 137 const void *val_2, 138 size_t len_2) 139 { 140 struct asymmetric_key_id *kid; 141 142 kid = kmalloc(sizeof(struct asymmetric_key_id) + len_1 + len_2, 143 GFP_KERNEL); 144 if (!kid) 145 return ERR_PTR(-ENOMEM); 146 kid->len = len_1 + len_2; 147 memcpy(kid->data, val_1, len_1); 148 memcpy(kid->data + len_1, val_2, len_2); 149 return kid; 150 } 151 EXPORT_SYMBOL_GPL(asymmetric_key_generate_id); 152 153 /** 154 * asymmetric_key_id_same - Return true if two asymmetric keys IDs are the same. 155 * @kid_1, @kid_2: The key IDs to compare 156 */ 157 bool asymmetric_key_id_same(const struct asymmetric_key_id *kid1, 158 const struct asymmetric_key_id *kid2) 159 { 160 if (!kid1 || !kid2) 161 return false; 162 if (kid1->len != kid2->len) 163 return false; 164 return memcmp(kid1->data, kid2->data, kid1->len) == 0; 165 } 166 EXPORT_SYMBOL_GPL(asymmetric_key_id_same); 167 168 /** 169 * asymmetric_key_id_partial - Return true if two asymmetric keys IDs 170 * partially match 171 * @kid_1, @kid_2: The key IDs to compare 172 */ 173 bool asymmetric_key_id_partial(const struct asymmetric_key_id *kid1, 174 const struct asymmetric_key_id *kid2) 175 { 176 if (!kid1 || !kid2) 177 return false; 178 if (kid1->len < kid2->len) 179 return false; 180 return memcmp(kid1->data + (kid1->len - kid2->len), 181 kid2->data, kid2->len) == 0; 182 } 183 EXPORT_SYMBOL_GPL(asymmetric_key_id_partial); 184 185 /** 186 * asymmetric_match_key_ids - Search asymmetric key IDs 187 * @kids: The list of key IDs to check 188 * @match_id: The key ID we're looking for 189 * @match: The match function to use 190 */ 191 static bool asymmetric_match_key_ids( 192 const struct asymmetric_key_ids *kids, 193 const struct asymmetric_key_id *match_id, 194 bool (*match)(const struct asymmetric_key_id *kid1, 195 const struct asymmetric_key_id *kid2)) 196 { 197 int i; 198 199 if (!kids || !match_id) 200 return false; 201 for (i = 0; i < ARRAY_SIZE(kids->id); i++) 202 if (match(kids->id[i], match_id)) 203 return true; 204 return false; 205 } 206 207 /* helper function can be called directly with pre-allocated memory */ 208 inline int __asymmetric_key_hex_to_key_id(const char *id, 209 struct asymmetric_key_id *match_id, 210 size_t hexlen) 211 { 212 match_id->len = hexlen; 213 return hex2bin(match_id->data, id, hexlen); 214 } 215 216 /** 217 * asymmetric_key_hex_to_key_id - Convert a hex string into a key ID. 218 * @id: The ID as a hex string. 219 */ 220 struct asymmetric_key_id *asymmetric_key_hex_to_key_id(const char *id) 221 { 222 struct asymmetric_key_id *match_id; 223 size_t asciihexlen; 224 int ret; 225 226 if (!*id) 227 return ERR_PTR(-EINVAL); 228 asciihexlen = strlen(id); 229 if (asciihexlen & 1) 230 return ERR_PTR(-EINVAL); 231 232 match_id = kmalloc(sizeof(struct asymmetric_key_id) + asciihexlen / 2, 233 GFP_KERNEL); 234 if (!match_id) 235 return ERR_PTR(-ENOMEM); 236 ret = __asymmetric_key_hex_to_key_id(id, match_id, asciihexlen / 2); 237 if (ret < 0) { 238 kfree(match_id); 239 return ERR_PTR(-EINVAL); 240 } 241 return match_id; 242 } 243 244 /* 245 * Match asymmetric keys by an exact match on an ID. 246 */ 247 static bool asymmetric_key_cmp(const struct key *key, 248 const struct key_match_data *match_data) 249 { 250 const struct asymmetric_key_ids *kids = asymmetric_key_ids(key); 251 const struct asymmetric_key_id *match_id = match_data->preparsed; 252 253 return asymmetric_match_key_ids(kids, match_id, 254 asymmetric_key_id_same); 255 } 256 257 /* 258 * Match asymmetric keys by a partial match on an IDs. 259 */ 260 static bool asymmetric_key_cmp_partial(const struct key *key, 261 const struct key_match_data *match_data) 262 { 263 const struct asymmetric_key_ids *kids = asymmetric_key_ids(key); 264 const struct asymmetric_key_id *match_id = match_data->preparsed; 265 266 return asymmetric_match_key_ids(kids, match_id, 267 asymmetric_key_id_partial); 268 } 269 270 /* 271 * Preparse the match criterion. If we don't set lookup_type and cmp, 272 * the default will be an exact match on the key description. 273 * 274 * There are some specifiers for matching key IDs rather than by the key 275 * description: 276 * 277 * "id:<id>" - find a key by partial match on any available ID 278 * "ex:<id>" - find a key by exact match on any available ID 279 * 280 * These have to be searched by iteration rather than by direct lookup because 281 * the key is hashed according to its description. 282 */ 283 static int asymmetric_key_match_preparse(struct key_match_data *match_data) 284 { 285 struct asymmetric_key_id *match_id; 286 const char *spec = match_data->raw_data; 287 const char *id; 288 bool (*cmp)(const struct key *, const struct key_match_data *) = 289 asymmetric_key_cmp; 290 291 if (!spec || !*spec) 292 return -EINVAL; 293 if (spec[0] == 'i' && 294 spec[1] == 'd' && 295 spec[2] == ':') { 296 id = spec + 3; 297 cmp = asymmetric_key_cmp_partial; 298 } else if (spec[0] == 'e' && 299 spec[1] == 'x' && 300 spec[2] == ':') { 301 id = spec + 3; 302 } else { 303 goto default_match; 304 } 305 306 match_id = asymmetric_key_hex_to_key_id(id); 307 if (IS_ERR(match_id)) 308 return PTR_ERR(match_id); 309 310 match_data->preparsed = match_id; 311 match_data->cmp = cmp; 312 match_data->lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE; 313 return 0; 314 315 default_match: 316 return 0; 317 } 318 319 /* 320 * Free the preparsed the match criterion. 321 */ 322 static void asymmetric_key_match_free(struct key_match_data *match_data) 323 { 324 kfree(match_data->preparsed); 325 } 326 327 /* 328 * Describe the asymmetric key 329 */ 330 static void asymmetric_key_describe(const struct key *key, struct seq_file *m) 331 { 332 const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); 333 const struct asymmetric_key_ids *kids = asymmetric_key_ids(key); 334 const struct asymmetric_key_id *kid; 335 const unsigned char *p; 336 int n; 337 338 seq_puts(m, key->description); 339 340 if (subtype) { 341 seq_puts(m, ": "); 342 subtype->describe(key, m); 343 344 if (kids && kids->id[1]) { 345 kid = kids->id[1]; 346 seq_putc(m, ' '); 347 n = kid->len; 348 p = kid->data; 349 if (n > 4) { 350 p += n - 4; 351 n = 4; 352 } 353 seq_printf(m, "%*phN", n, p); 354 } 355 356 seq_puts(m, " ["); 357 /* put something here to indicate the key's capabilities */ 358 seq_putc(m, ']'); 359 } 360 } 361 362 /* 363 * Preparse a asymmetric payload to get format the contents appropriately for the 364 * internal payload to cut down on the number of scans of the data performed. 365 * 366 * We also generate a proposed description from the contents of the key that 367 * can be used to name the key if the user doesn't want to provide one. 368 */ 369 static int asymmetric_key_preparse(struct key_preparsed_payload *prep) 370 { 371 struct asymmetric_key_parser *parser; 372 int ret; 373 374 pr_devel("==>%s()\n", __func__); 375 376 if (prep->datalen == 0) 377 return -EINVAL; 378 379 down_read(&asymmetric_key_parsers_sem); 380 381 ret = -EBADMSG; 382 list_for_each_entry(parser, &asymmetric_key_parsers, link) { 383 pr_debug("Trying parser '%s'\n", parser->name); 384 385 ret = parser->parse(prep); 386 if (ret != -EBADMSG) { 387 pr_debug("Parser recognised the format (ret %d)\n", 388 ret); 389 break; 390 } 391 } 392 393 up_read(&asymmetric_key_parsers_sem); 394 pr_devel("<==%s() = %d\n", __func__, ret); 395 return ret; 396 } 397 398 /* 399 * Clean up the key ID list 400 */ 401 static void asymmetric_key_free_kids(struct asymmetric_key_ids *kids) 402 { 403 int i; 404 405 if (kids) { 406 for (i = 0; i < ARRAY_SIZE(kids->id); i++) 407 kfree(kids->id[i]); 408 kfree(kids); 409 } 410 } 411 412 /* 413 * Clean up the preparse data 414 */ 415 static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep) 416 { 417 struct asymmetric_key_subtype *subtype = prep->payload.data[asym_subtype]; 418 struct asymmetric_key_ids *kids = prep->payload.data[asym_key_ids]; 419 420 pr_devel("==>%s()\n", __func__); 421 422 if (subtype) { 423 subtype->destroy(prep->payload.data[asym_crypto], 424 prep->payload.data[asym_auth]); 425 module_put(subtype->owner); 426 } 427 asymmetric_key_free_kids(kids); 428 kfree(prep->description); 429 } 430 431 /* 432 * dispose of the data dangling from the corpse of a asymmetric key 433 */ 434 static void asymmetric_key_destroy(struct key *key) 435 { 436 struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); 437 struct asymmetric_key_ids *kids = key->payload.data[asym_key_ids]; 438 void *data = key->payload.data[asym_crypto]; 439 void *auth = key->payload.data[asym_auth]; 440 441 key->payload.data[asym_crypto] = NULL; 442 key->payload.data[asym_subtype] = NULL; 443 key->payload.data[asym_key_ids] = NULL; 444 key->payload.data[asym_auth] = NULL; 445 446 if (subtype) { 447 subtype->destroy(data, auth); 448 module_put(subtype->owner); 449 } 450 451 asymmetric_key_free_kids(kids); 452 } 453 454 struct key_type key_type_asymmetric = { 455 .name = "asymmetric", 456 .preparse = asymmetric_key_preparse, 457 .free_preparse = asymmetric_key_free_preparse, 458 .instantiate = generic_key_instantiate, 459 .match_preparse = asymmetric_key_match_preparse, 460 .match_free = asymmetric_key_match_free, 461 .destroy = asymmetric_key_destroy, 462 .describe = asymmetric_key_describe, 463 }; 464 EXPORT_SYMBOL_GPL(key_type_asymmetric); 465 466 /** 467 * register_asymmetric_key_parser - Register a asymmetric key blob parser 468 * @parser: The parser to register 469 */ 470 int register_asymmetric_key_parser(struct asymmetric_key_parser *parser) 471 { 472 struct asymmetric_key_parser *cursor; 473 int ret; 474 475 down_write(&asymmetric_key_parsers_sem); 476 477 list_for_each_entry(cursor, &asymmetric_key_parsers, link) { 478 if (strcmp(cursor->name, parser->name) == 0) { 479 pr_err("Asymmetric key parser '%s' already registered\n", 480 parser->name); 481 ret = -EEXIST; 482 goto out; 483 } 484 } 485 486 list_add_tail(&parser->link, &asymmetric_key_parsers); 487 488 pr_notice("Asymmetric key parser '%s' registered\n", parser->name); 489 ret = 0; 490 491 out: 492 up_write(&asymmetric_key_parsers_sem); 493 return ret; 494 } 495 EXPORT_SYMBOL_GPL(register_asymmetric_key_parser); 496 497 /** 498 * unregister_asymmetric_key_parser - Unregister a asymmetric key blob parser 499 * @parser: The parser to unregister 500 */ 501 void unregister_asymmetric_key_parser(struct asymmetric_key_parser *parser) 502 { 503 down_write(&asymmetric_key_parsers_sem); 504 list_del(&parser->link); 505 up_write(&asymmetric_key_parsers_sem); 506 507 pr_notice("Asymmetric key parser '%s' unregistered\n", parser->name); 508 } 509 EXPORT_SYMBOL_GPL(unregister_asymmetric_key_parser); 510 511 /* 512 * Module stuff 513 */ 514 static int __init asymmetric_key_init(void) 515 { 516 return register_key_type(&key_type_asymmetric); 517 } 518 519 static void __exit asymmetric_key_cleanup(void) 520 { 521 unregister_key_type(&key_type_asymmetric); 522 } 523 524 module_init(asymmetric_key_init); 525 module_exit(asymmetric_key_cleanup); 526