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