diff options
| -rw-r--r-- | Documentation/security/keys-trusted-encrypted.txt | 48 | ||||
| -rw-r--r-- | include/keys/encrypted-type.h | 13 | ||||
| -rw-r--r-- | security/keys/encrypted.c | 141 |
3 files changed, 142 insertions, 60 deletions
diff --git a/Documentation/security/keys-trusted-encrypted.txt b/Documentation/security/keys-trusted-encrypted.txt index 8fb79bc1ac4b..0afcb5023c75 100644 --- a/Documentation/security/keys-trusted-encrypted.txt +++ b/Documentation/security/keys-trusted-encrypted.txt | |||
| @@ -53,12 +53,19 @@ they are only as secure as the user key encrypting them. The master user key | |||
| 53 | should therefore be loaded in as secure a way as possible, preferably early in | 53 | should therefore be loaded in as secure a way as possible, preferably early in |
| 54 | boot. | 54 | boot. |
| 55 | 55 | ||
| 56 | The decrypted portion of encrypted keys can contain either a simple symmetric | ||
| 57 | key or a more complex structure. The format of the more complex structure is | ||
| 58 | application specific, which is identified by 'format'. | ||
| 59 | |||
| 56 | Usage: | 60 | Usage: |
| 57 | keyctl add encrypted name "new key-type:master-key-name keylen" ring | 61 | keyctl add encrypted name "new [format] key-type:master-key-name keylen" |
| 58 | keyctl add encrypted name "load hex_blob" ring | 62 | ring |
| 59 | keyctl update keyid "update key-type:master-key-name" | 63 | keyctl add encrypted name "load hex_blob" ring |
| 64 | keyctl update keyid "update key-type:master-key-name" | ||
| 65 | |||
| 66 | format:= 'default' | ||
| 67 | key-type:= 'trusted' | 'user' | ||
| 60 | 68 | ||
| 61 | where 'key-type' is either 'trusted' or 'user'. | ||
| 62 | 69 | ||
| 63 | Examples of trusted and encrypted key usage: | 70 | Examples of trusted and encrypted key usage: |
| 64 | 71 | ||
| @@ -114,15 +121,25 @@ Reseal a trusted key under new pcr values: | |||
| 114 | 7ef6a24defe4846104209bf0c3eced7fa1a672ed5b125fc9d8cd88b476a658a4434644ef | 121 | 7ef6a24defe4846104209bf0c3eced7fa1a672ed5b125fc9d8cd88b476a658a4434644ef |
| 115 | df8ae9a178e9f83ba9f08d10fa47e4226b98b0702f06b3b8 | 122 | df8ae9a178e9f83ba9f08d10fa47e4226b98b0702f06b3b8 |
| 116 | 123 | ||
| 117 | Create and save an encrypted key "evm" using the above trusted key "kmk": | 124 | The initial consumer of trusted keys is EVM, which at boot time needs a high |
| 125 | quality symmetric key for HMAC protection of file metadata. The use of a | ||
| 126 | trusted key provides strong guarantees that the EVM key has not been | ||
| 127 | compromised by a user level problem, and when sealed to specific boot PCR | ||
| 128 | values, protects against boot and offline attacks. Create and save an | ||
| 129 | encrypted key "evm" using the above trusted key "kmk": | ||
| 118 | 130 | ||
| 131 | option 1: omitting 'format' | ||
| 119 | $ keyctl add encrypted evm "new trusted:kmk 32" @u | 132 | $ keyctl add encrypted evm "new trusted:kmk 32" @u |
| 120 | 159771175 | 133 | 159771175 |
| 121 | 134 | ||
| 135 | option 2: explicitly defining 'format' as 'default' | ||
| 136 | $ keyctl add encrypted evm "new default trusted:kmk 32" @u | ||
| 137 | 159771175 | ||
| 138 | |||
| 122 | $ keyctl print 159771175 | 139 | $ keyctl print 159771175 |
| 123 | trusted:kmk 32 2375725ad57798846a9bbd240de8906f006e66c03af53b1b382dbbc55 | 140 | default trusted:kmk 32 2375725ad57798846a9bbd240de8906f006e66c03af53b1b3 |
| 124 | be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e024717c64 | 141 | 82dbbc55be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e0 |
| 125 | 5972dcb82ab2dde83376d82b2e3c09ffc | 142 | 24717c64 5972dcb82ab2dde83376d82b2e3c09ffc |
| 126 | 143 | ||
| 127 | $ keyctl pipe 159771175 > evm.blob | 144 | $ keyctl pipe 159771175 > evm.blob |
| 128 | 145 | ||
| @@ -132,14 +149,9 @@ Load an encrypted key "evm" from saved blob: | |||
| 132 | 831684262 | 149 | 831684262 |
| 133 | 150 | ||
| 134 | $ keyctl print 831684262 | 151 | $ keyctl print 831684262 |
| 135 | trusted:kmk 32 2375725ad57798846a9bbd240de8906f006e66c03af53b1b382dbbc55 | 152 | default trusted:kmk 32 2375725ad57798846a9bbd240de8906f006e66c03af53b1b3 |
| 136 | be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e024717c64 | 153 | 82dbbc55be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e0 |
| 137 | 5972dcb82ab2dde83376d82b2e3c09ffc | 154 | 24717c64 5972dcb82ab2dde83376d82b2e3c09ffc |
| 138 | |||
| 139 | 155 | ||
| 140 | The initial consumer of trusted keys is EVM, which at boot time needs a high | 156 | Other uses for trusted and encrypted keys, such as for disk and file encryption |
| 141 | quality symmetric key for HMAC protection of file metadata. The use of a | 157 | are anticipated. |
| 142 | trusted key provides strong guarantees that the EVM key has not been | ||
| 143 | compromised by a user level problem, and when sealed to specific boot PCR | ||
| 144 | values, protects against boot and offline attacks. Other uses for trusted and | ||
| 145 | encrypted keys, such as for disk and file encryption are anticipated. | ||
diff --git a/include/keys/encrypted-type.h b/include/keys/encrypted-type.h index 95855017a32b..1d4541370a64 100644 --- a/include/keys/encrypted-type.h +++ b/include/keys/encrypted-type.h | |||
| @@ -1,6 +1,11 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2010 IBM Corporation | 2 | * Copyright (C) 2010 IBM Corporation |
| 3 | * Author: Mimi Zohar <zohar@us.ibm.com> | 3 | * Copyright (C) 2010 Politecnico di Torino, Italy |
| 4 | * TORSEC group -- http://security.polito.it | ||
| 5 | * | ||
| 6 | * Authors: | ||
| 7 | * Mimi Zohar <zohar@us.ibm.com> | ||
| 8 | * Roberto Sassu <roberto.sassu@polito.it> | ||
| 4 | * | 9 | * |
| 5 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 6 | * it under the terms of the GNU General Public License as published by | 11 | * it under the terms of the GNU General Public License as published by |
| @@ -15,13 +20,17 @@ | |||
| 15 | 20 | ||
| 16 | struct encrypted_key_payload { | 21 | struct encrypted_key_payload { |
| 17 | struct rcu_head rcu; | 22 | struct rcu_head rcu; |
| 23 | char *format; /* datablob: format */ | ||
| 18 | char *master_desc; /* datablob: master key name */ | 24 | char *master_desc; /* datablob: master key name */ |
| 19 | char *datalen; /* datablob: decrypted key length */ | 25 | char *datalen; /* datablob: decrypted key length */ |
| 20 | u8 *iv; /* datablob: iv */ | 26 | u8 *iv; /* datablob: iv */ |
| 21 | u8 *encrypted_data; /* datablob: encrypted data */ | 27 | u8 *encrypted_data; /* datablob: encrypted data */ |
| 22 | unsigned short datablob_len; /* length of datablob */ | 28 | unsigned short datablob_len; /* length of datablob */ |
| 23 | unsigned short decrypted_datalen; /* decrypted data length */ | 29 | unsigned short decrypted_datalen; /* decrypted data length */ |
| 24 | u8 decrypted_data[0]; /* decrypted data + datablob + hmac */ | 30 | unsigned short payload_datalen; /* payload data length */ |
| 31 | unsigned short encrypted_key_format; /* encrypted key format */ | ||
| 32 | u8 *decrypted_data; /* decrypted data */ | ||
| 33 | u8 payload_data[0]; /* payload data + datablob + hmac */ | ||
| 25 | }; | 34 | }; |
| 26 | 35 | ||
| 27 | extern struct key_type key_type_encrypted; | 36 | extern struct key_type key_type_encrypted; |
diff --git a/security/keys/encrypted.c b/security/keys/encrypted.c index f36a105de791..89981c987ba7 100644 --- a/security/keys/encrypted.c +++ b/security/keys/encrypted.c | |||
| @@ -1,8 +1,11 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2010 IBM Corporation | 2 | * Copyright (C) 2010 IBM Corporation |
| 3 | * Copyright (C) 2010 Politecnico di Torino, Italy | ||
| 4 | * TORSEC group -- http://security.polito.it | ||
| 3 | * | 5 | * |
| 4 | * Author: | 6 | * Authors: |
| 5 | * Mimi Zohar <zohar@us.ibm.com> | 7 | * Mimi Zohar <zohar@us.ibm.com> |
| 8 | * Roberto Sassu <roberto.sassu@polito.it> | ||
| 6 | * | 9 | * |
| 7 | * This program is free software; you can redistribute it and/or modify | 10 | * 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 | 11 | * it under the terms of the GNU General Public License as published by |
| @@ -37,6 +40,7 @@ static const char KEY_USER_PREFIX[] = "user:"; | |||
| 37 | static const char hash_alg[] = "sha256"; | 40 | static const char hash_alg[] = "sha256"; |
| 38 | static const char hmac_alg[] = "hmac(sha256)"; | 41 | static const char hmac_alg[] = "hmac(sha256)"; |
| 39 | static const char blkcipher_alg[] = "cbc(aes)"; | 42 | static const char blkcipher_alg[] = "cbc(aes)"; |
| 43 | static const char key_format_default[] = "default"; | ||
| 40 | static unsigned int ivsize; | 44 | static unsigned int ivsize; |
| 41 | static int blksize; | 45 | static int blksize; |
| 42 | 46 | ||
| @@ -58,6 +62,15 @@ enum { | |||
| 58 | Opt_err = -1, Opt_new, Opt_load, Opt_update | 62 | Opt_err = -1, Opt_new, Opt_load, Opt_update |
| 59 | }; | 63 | }; |
| 60 | 64 | ||
| 65 | enum { | ||
| 66 | Opt_error = -1, Opt_default | ||
| 67 | }; | ||
| 68 | |||
| 69 | static const match_table_t key_format_tokens = { | ||
| 70 | {Opt_default, "default"}, | ||
| 71 | {Opt_error, NULL} | ||
| 72 | }; | ||
| 73 | |||
| 61 | static const match_table_t key_tokens = { | 74 | static const match_table_t key_tokens = { |
| 62 | {Opt_new, "new"}, | 75 | {Opt_new, "new"}, |
| 63 | {Opt_load, "load"}, | 76 | {Opt_load, "load"}, |
| @@ -118,8 +131,9 @@ out: | |||
| 118 | * datablob_parse - parse the keyctl data | 131 | * datablob_parse - parse the keyctl data |
| 119 | * | 132 | * |
| 120 | * datablob format: | 133 | * datablob format: |
| 121 | * new <master-key name> <decrypted data length> | 134 | * new [<format>] <master-key name> <decrypted data length> |
| 122 | * load <master-key name> <decrypted data length> <encrypted iv + data> | 135 | * load [<format>] <master-key name> <decrypted data length> |
| 136 | * <encrypted iv + data> | ||
| 123 | * update <new-master-key name> | 137 | * update <new-master-key name> |
| 124 | * | 138 | * |
| 125 | * Tokenizes a copy of the keyctl data, returning a pointer to each token, | 139 | * Tokenizes a copy of the keyctl data, returning a pointer to each token, |
| @@ -127,13 +141,15 @@ out: | |||
| 127 | * | 141 | * |
| 128 | * On success returns 0, otherwise -EINVAL. | 142 | * On success returns 0, otherwise -EINVAL. |
| 129 | */ | 143 | */ |
| 130 | static int datablob_parse(char *datablob, char **master_desc, | 144 | static int datablob_parse(char *datablob, const char **format, |
| 131 | char **decrypted_datalen, char **hex_encoded_iv) | 145 | char **master_desc, char **decrypted_datalen, |
| 146 | char **hex_encoded_iv) | ||
| 132 | { | 147 | { |
| 133 | substring_t args[MAX_OPT_ARGS]; | 148 | substring_t args[MAX_OPT_ARGS]; |
| 134 | int ret = -EINVAL; | 149 | int ret = -EINVAL; |
| 135 | int key_cmd; | 150 | int key_cmd; |
| 136 | char *keyword; | 151 | int key_format; |
| 152 | char *p, *keyword; | ||
| 137 | 153 | ||
| 138 | keyword = strsep(&datablob, " \t"); | 154 | keyword = strsep(&datablob, " \t"); |
| 139 | if (!keyword) { | 155 | if (!keyword) { |
| @@ -142,7 +158,24 @@ static int datablob_parse(char *datablob, char **master_desc, | |||
| 142 | } | 158 | } |
| 143 | key_cmd = match_token(keyword, key_tokens, args); | 159 | key_cmd = match_token(keyword, key_tokens, args); |
| 144 | 160 | ||
| 145 | *master_desc = strsep(&datablob, " \t"); | 161 | /* Get optional format: default */ |
| 162 | p = strsep(&datablob, " \t"); | ||
| 163 | if (!p) { | ||
| 164 | pr_err("encrypted_key: insufficient parameters specified\n"); | ||
| 165 | return ret; | ||
| 166 | } | ||
| 167 | |||
| 168 | key_format = match_token(p, key_format_tokens, args); | ||
| 169 | switch (key_format) { | ||
| 170 | case Opt_default: | ||
| 171 | *format = p; | ||
| 172 | *master_desc = strsep(&datablob, " \t"); | ||
| 173 | break; | ||
| 174 | case Opt_error: | ||
| 175 | *master_desc = p; | ||
| 176 | break; | ||
| 177 | } | ||
| 178 | |||
| 146 | if (!*master_desc) { | 179 | if (!*master_desc) { |
| 147 | pr_info("encrypted_key: master key parameter is missing\n"); | 180 | pr_info("encrypted_key: master key parameter is missing\n"); |
| 148 | goto out; | 181 | goto out; |
| @@ -220,8 +253,8 @@ static char *datablob_format(struct encrypted_key_payload *epayload, | |||
| 220 | ascii_buf[asciiblob_len] = '\0'; | 253 | ascii_buf[asciiblob_len] = '\0'; |
| 221 | 254 | ||
| 222 | /* copy datablob master_desc and datalen strings */ | 255 | /* copy datablob master_desc and datalen strings */ |
| 223 | len = sprintf(ascii_buf, "%s %s ", epayload->master_desc, | 256 | len = sprintf(ascii_buf, "%s %s %s ", epayload->format, |
| 224 | epayload->datalen); | 257 | epayload->master_desc, epayload->datalen); |
| 225 | 258 | ||
| 226 | /* convert the hex encoded iv, encrypted-data and HMAC to ascii */ | 259 | /* convert the hex encoded iv, encrypted-data and HMAC to ascii */ |
| 227 | bufp = &ascii_buf[len]; | 260 | bufp = &ascii_buf[len]; |
| @@ -464,9 +497,9 @@ static int datablob_hmac_append(struct encrypted_key_payload *epayload, | |||
| 464 | if (ret < 0) | 497 | if (ret < 0) |
| 465 | goto out; | 498 | goto out; |
| 466 | 499 | ||
| 467 | digest = epayload->master_desc + epayload->datablob_len; | 500 | digest = epayload->format + epayload->datablob_len; |
| 468 | ret = calc_hmac(digest, derived_key, sizeof derived_key, | 501 | ret = calc_hmac(digest, derived_key, sizeof derived_key, |
| 469 | epayload->master_desc, epayload->datablob_len); | 502 | epayload->format, epayload->datablob_len); |
| 470 | if (!ret) | 503 | if (!ret) |
| 471 | dump_hmac(NULL, digest, HASH_SIZE); | 504 | dump_hmac(NULL, digest, HASH_SIZE); |
| 472 | out: | 505 | out: |
| @@ -475,26 +508,35 @@ out: | |||
| 475 | 508 | ||
| 476 | /* verify HMAC before decrypting encrypted key */ | 509 | /* verify HMAC before decrypting encrypted key */ |
| 477 | static int datablob_hmac_verify(struct encrypted_key_payload *epayload, | 510 | static int datablob_hmac_verify(struct encrypted_key_payload *epayload, |
| 478 | const u8 *master_key, size_t master_keylen) | 511 | const u8 *format, const u8 *master_key, |
| 512 | size_t master_keylen) | ||
| 479 | { | 513 | { |
| 480 | u8 derived_key[HASH_SIZE]; | 514 | u8 derived_key[HASH_SIZE]; |
| 481 | u8 digest[HASH_SIZE]; | 515 | u8 digest[HASH_SIZE]; |
| 482 | int ret; | 516 | int ret; |
| 517 | char *p; | ||
| 518 | unsigned short len; | ||
| 483 | 519 | ||
| 484 | ret = get_derived_key(derived_key, AUTH_KEY, master_key, master_keylen); | 520 | ret = get_derived_key(derived_key, AUTH_KEY, master_key, master_keylen); |
| 485 | if (ret < 0) | 521 | if (ret < 0) |
| 486 | goto out; | 522 | goto out; |
| 487 | 523 | ||
| 488 | ret = calc_hmac(digest, derived_key, sizeof derived_key, | 524 | len = epayload->datablob_len; |
| 489 | epayload->master_desc, epayload->datablob_len); | 525 | if (!format) { |
| 526 | p = epayload->master_desc; | ||
| 527 | len -= strlen(epayload->format) + 1; | ||
| 528 | } else | ||
| 529 | p = epayload->format; | ||
| 530 | |||
| 531 | ret = calc_hmac(digest, derived_key, sizeof derived_key, p, len); | ||
| 490 | if (ret < 0) | 532 | if (ret < 0) |
| 491 | goto out; | 533 | goto out; |
| 492 | ret = memcmp(digest, epayload->master_desc + epayload->datablob_len, | 534 | ret = memcmp(digest, epayload->format + epayload->datablob_len, |
| 493 | sizeof digest); | 535 | sizeof digest); |
| 494 | if (ret) { | 536 | if (ret) { |
| 495 | ret = -EINVAL; | 537 | ret = -EINVAL; |
| 496 | dump_hmac("datablob", | 538 | dump_hmac("datablob", |
| 497 | epayload->master_desc + epayload->datablob_len, | 539 | epayload->format + epayload->datablob_len, |
| 498 | HASH_SIZE); | 540 | HASH_SIZE); |
| 499 | dump_hmac("calc", digest, HASH_SIZE); | 541 | dump_hmac("calc", digest, HASH_SIZE); |
| 500 | } | 542 | } |
| @@ -539,13 +581,16 @@ out: | |||
| 539 | 581 | ||
| 540 | /* Allocate memory for decrypted key and datablob. */ | 582 | /* Allocate memory for decrypted key and datablob. */ |
| 541 | static struct encrypted_key_payload *encrypted_key_alloc(struct key *key, | 583 | static struct encrypted_key_payload *encrypted_key_alloc(struct key *key, |
| 584 | const char *format, | ||
| 542 | const char *master_desc, | 585 | const char *master_desc, |
| 543 | const char *datalen) | 586 | const char *datalen) |
| 544 | { | 587 | { |
| 545 | struct encrypted_key_payload *epayload = NULL; | 588 | struct encrypted_key_payload *epayload = NULL; |
| 546 | unsigned short datablob_len; | 589 | unsigned short datablob_len; |
| 547 | unsigned short decrypted_datalen; | 590 | unsigned short decrypted_datalen; |
| 591 | unsigned short payload_datalen; | ||
| 548 | unsigned int encrypted_datalen; | 592 | unsigned int encrypted_datalen; |
| 593 | unsigned int format_len; | ||
| 549 | long dlen; | 594 | long dlen; |
| 550 | int ret; | 595 | int ret; |
| 551 | 596 | ||
| @@ -553,29 +598,32 @@ static struct encrypted_key_payload *encrypted_key_alloc(struct key *key, | |||
| 553 | if (ret < 0 || dlen < MIN_DATA_SIZE || dlen > MAX_DATA_SIZE) | 598 | if (ret < 0 || dlen < MIN_DATA_SIZE || dlen > MAX_DATA_SIZE) |
| 554 | return ERR_PTR(-EINVAL); | 599 | return ERR_PTR(-EINVAL); |
| 555 | 600 | ||
| 601 | format_len = (!format) ? strlen(key_format_default) : strlen(format); | ||
| 556 | decrypted_datalen = dlen; | 602 | decrypted_datalen = dlen; |
| 603 | payload_datalen = decrypted_datalen; | ||
| 557 | encrypted_datalen = roundup(decrypted_datalen, blksize); | 604 | encrypted_datalen = roundup(decrypted_datalen, blksize); |
| 558 | 605 | ||
| 559 | datablob_len = strlen(master_desc) + 1 + strlen(datalen) + 1 | 606 | datablob_len = format_len + 1 + strlen(master_desc) + 1 |
| 560 | + ivsize + 1 + encrypted_datalen; | 607 | + strlen(datalen) + 1 + ivsize + 1 + encrypted_datalen; |
| 561 | 608 | ||
| 562 | ret = key_payload_reserve(key, decrypted_datalen + datablob_len | 609 | ret = key_payload_reserve(key, payload_datalen + datablob_len |
| 563 | + HASH_SIZE + 1); | 610 | + HASH_SIZE + 1); |
| 564 | if (ret < 0) | 611 | if (ret < 0) |
| 565 | return ERR_PTR(ret); | 612 | return ERR_PTR(ret); |
| 566 | 613 | ||
| 567 | epayload = kzalloc(sizeof(*epayload) + decrypted_datalen + | 614 | epayload = kzalloc(sizeof(*epayload) + payload_datalen + |
| 568 | datablob_len + HASH_SIZE + 1, GFP_KERNEL); | 615 | datablob_len + HASH_SIZE + 1, GFP_KERNEL); |
| 569 | if (!epayload) | 616 | if (!epayload) |
| 570 | return ERR_PTR(-ENOMEM); | 617 | return ERR_PTR(-ENOMEM); |
| 571 | 618 | ||
| 619 | epayload->payload_datalen = payload_datalen; | ||
| 572 | epayload->decrypted_datalen = decrypted_datalen; | 620 | epayload->decrypted_datalen = decrypted_datalen; |
| 573 | epayload->datablob_len = datablob_len; | 621 | epayload->datablob_len = datablob_len; |
| 574 | return epayload; | 622 | return epayload; |
| 575 | } | 623 | } |
| 576 | 624 | ||
| 577 | static int encrypted_key_decrypt(struct encrypted_key_payload *epayload, | 625 | static int encrypted_key_decrypt(struct encrypted_key_payload *epayload, |
| 578 | const char *hex_encoded_iv) | 626 | const char *format, const char *hex_encoded_iv) |
| 579 | { | 627 | { |
| 580 | struct key *mkey; | 628 | struct key *mkey; |
| 581 | u8 derived_key[HASH_SIZE]; | 629 | u8 derived_key[HASH_SIZE]; |
| @@ -596,14 +644,14 @@ static int encrypted_key_decrypt(struct encrypted_key_payload *epayload, | |||
| 596 | hex2bin(epayload->iv, hex_encoded_iv, ivsize); | 644 | hex2bin(epayload->iv, hex_encoded_iv, ivsize); |
| 597 | hex2bin(epayload->encrypted_data, hex_encoded_data, encrypted_datalen); | 645 | hex2bin(epayload->encrypted_data, hex_encoded_data, encrypted_datalen); |
| 598 | 646 | ||
| 599 | hmac = epayload->master_desc + epayload->datablob_len; | 647 | hmac = epayload->format + epayload->datablob_len; |
| 600 | hex2bin(hmac, hex_encoded_data + (encrypted_datalen * 2), HASH_SIZE); | 648 | hex2bin(hmac, hex_encoded_data + (encrypted_datalen * 2), HASH_SIZE); |
| 601 | 649 | ||
| 602 | mkey = request_master_key(epayload, &master_key, &master_keylen); | 650 | mkey = request_master_key(epayload, &master_key, &master_keylen); |
| 603 | if (IS_ERR(mkey)) | 651 | if (IS_ERR(mkey)) |
| 604 | return PTR_ERR(mkey); | 652 | return PTR_ERR(mkey); |
| 605 | 653 | ||
| 606 | ret = datablob_hmac_verify(epayload, master_key, master_keylen); | 654 | ret = datablob_hmac_verify(epayload, format, master_key, master_keylen); |
| 607 | if (ret < 0) { | 655 | if (ret < 0) { |
| 608 | pr_err("encrypted_key: bad hmac (%d)\n", ret); | 656 | pr_err("encrypted_key: bad hmac (%d)\n", ret); |
| 609 | goto out; | 657 | goto out; |
| @@ -623,14 +671,23 @@ out: | |||
| 623 | } | 671 | } |
| 624 | 672 | ||
| 625 | static void __ekey_init(struct encrypted_key_payload *epayload, | 673 | static void __ekey_init(struct encrypted_key_payload *epayload, |
| 626 | const char *master_desc, const char *datalen) | 674 | const char *format, const char *master_desc, |
| 675 | const char *datalen) | ||
| 627 | { | 676 | { |
| 628 | epayload->master_desc = epayload->decrypted_data | 677 | unsigned int format_len; |
| 629 | + epayload->decrypted_datalen; | 678 | |
| 679 | format_len = (!format) ? strlen(key_format_default) : strlen(format); | ||
| 680 | epayload->format = epayload->payload_data + epayload->payload_datalen; | ||
| 681 | epayload->master_desc = epayload->format + format_len + 1; | ||
| 630 | epayload->datalen = epayload->master_desc + strlen(master_desc) + 1; | 682 | epayload->datalen = epayload->master_desc + strlen(master_desc) + 1; |
| 631 | epayload->iv = epayload->datalen + strlen(datalen) + 1; | 683 | epayload->iv = epayload->datalen + strlen(datalen) + 1; |
| 632 | epayload->encrypted_data = epayload->iv + ivsize + 1; | 684 | epayload->encrypted_data = epayload->iv + ivsize + 1; |
| 685 | epayload->decrypted_data = epayload->payload_data; | ||
| 633 | 686 | ||
| 687 | if (!format) | ||
| 688 | memcpy(epayload->format, key_format_default, format_len); | ||
| 689 | else | ||
| 690 | memcpy(epayload->format, format, format_len); | ||
| 634 | memcpy(epayload->master_desc, master_desc, strlen(master_desc)); | 691 | memcpy(epayload->master_desc, master_desc, strlen(master_desc)); |
| 635 | memcpy(epayload->datalen, datalen, strlen(datalen)); | 692 | memcpy(epayload->datalen, datalen, strlen(datalen)); |
| 636 | } | 693 | } |
| @@ -642,19 +699,19 @@ static void __ekey_init(struct encrypted_key_payload *epayload, | |||
| 642 | * itself. For an old key, decrypt the hex encoded data. | 699 | * itself. For an old key, decrypt the hex encoded data. |
| 643 | */ | 700 | */ |
| 644 | static int encrypted_init(struct encrypted_key_payload *epayload, | 701 | static int encrypted_init(struct encrypted_key_payload *epayload, |
| 645 | const char *master_desc, const char *datalen, | 702 | const char *format, const char *master_desc, |
| 646 | const char *hex_encoded_iv) | 703 | const char *datalen, const char *hex_encoded_iv) |
| 647 | { | 704 | { |
| 648 | int ret = 0; | 705 | int ret = 0; |
| 649 | 706 | ||
| 650 | __ekey_init(epayload, master_desc, datalen); | 707 | __ekey_init(epayload, format, master_desc, datalen); |
| 651 | if (!hex_encoded_iv) { | 708 | if (!hex_encoded_iv) { |
| 652 | get_random_bytes(epayload->iv, ivsize); | 709 | get_random_bytes(epayload->iv, ivsize); |
| 653 | 710 | ||
| 654 | get_random_bytes(epayload->decrypted_data, | 711 | get_random_bytes(epayload->decrypted_data, |
| 655 | epayload->decrypted_datalen); | 712 | epayload->decrypted_datalen); |
| 656 | } else | 713 | } else |
| 657 | ret = encrypted_key_decrypt(epayload, hex_encoded_iv); | 714 | ret = encrypted_key_decrypt(epayload, format, hex_encoded_iv); |
| 658 | return ret; | 715 | return ret; |
| 659 | } | 716 | } |
| 660 | 717 | ||
| @@ -671,6 +728,7 @@ static int encrypted_instantiate(struct key *key, const void *data, | |||
| 671 | { | 728 | { |
| 672 | struct encrypted_key_payload *epayload = NULL; | 729 | struct encrypted_key_payload *epayload = NULL; |
| 673 | char *datablob = NULL; | 730 | char *datablob = NULL; |
| 731 | const char *format = NULL; | ||
| 674 | char *master_desc = NULL; | 732 | char *master_desc = NULL; |
| 675 | char *decrypted_datalen = NULL; | 733 | char *decrypted_datalen = NULL; |
| 676 | char *hex_encoded_iv = NULL; | 734 | char *hex_encoded_iv = NULL; |
| @@ -684,17 +742,18 @@ static int encrypted_instantiate(struct key *key, const void *data, | |||
| 684 | return -ENOMEM; | 742 | return -ENOMEM; |
| 685 | datablob[datalen] = 0; | 743 | datablob[datalen] = 0; |
| 686 | memcpy(datablob, data, datalen); | 744 | memcpy(datablob, data, datalen); |
| 687 | ret = datablob_parse(datablob, &master_desc, &decrypted_datalen, | 745 | ret = datablob_parse(datablob, &format, &master_desc, |
| 688 | &hex_encoded_iv); | 746 | &decrypted_datalen, &hex_encoded_iv); |
| 689 | if (ret < 0) | 747 | if (ret < 0) |
| 690 | goto out; | 748 | goto out; |
| 691 | 749 | ||
| 692 | epayload = encrypted_key_alloc(key, master_desc, decrypted_datalen); | 750 | epayload = encrypted_key_alloc(key, format, master_desc, |
| 751 | decrypted_datalen); | ||
| 693 | if (IS_ERR(epayload)) { | 752 | if (IS_ERR(epayload)) { |
| 694 | ret = PTR_ERR(epayload); | 753 | ret = PTR_ERR(epayload); |
| 695 | goto out; | 754 | goto out; |
| 696 | } | 755 | } |
| 697 | ret = encrypted_init(epayload, master_desc, decrypted_datalen, | 756 | ret = encrypted_init(epayload, format, master_desc, decrypted_datalen, |
| 698 | hex_encoded_iv); | 757 | hex_encoded_iv); |
| 699 | if (ret < 0) { | 758 | if (ret < 0) { |
| 700 | kfree(epayload); | 759 | kfree(epayload); |
| @@ -731,6 +790,7 @@ static int encrypted_update(struct key *key, const void *data, size_t datalen) | |||
| 731 | struct encrypted_key_payload *new_epayload; | 790 | struct encrypted_key_payload *new_epayload; |
| 732 | char *buf; | 791 | char *buf; |
| 733 | char *new_master_desc = NULL; | 792 | char *new_master_desc = NULL; |
| 793 | const char *format = NULL; | ||
| 734 | int ret = 0; | 794 | int ret = 0; |
| 735 | 795 | ||
| 736 | if (datalen <= 0 || datalen > 32767 || !data) | 796 | if (datalen <= 0 || datalen > 32767 || !data) |
| @@ -742,7 +802,7 @@ static int encrypted_update(struct key *key, const void *data, size_t datalen) | |||
| 742 | 802 | ||
| 743 | buf[datalen] = 0; | 803 | buf[datalen] = 0; |
| 744 | memcpy(buf, data, datalen); | 804 | memcpy(buf, data, datalen); |
| 745 | ret = datablob_parse(buf, &new_master_desc, NULL, NULL); | 805 | ret = datablob_parse(buf, &format, &new_master_desc, NULL, NULL); |
| 746 | if (ret < 0) | 806 | if (ret < 0) |
| 747 | goto out; | 807 | goto out; |
| 748 | 808 | ||
| @@ -750,18 +810,19 @@ static int encrypted_update(struct key *key, const void *data, size_t datalen) | |||
| 750 | if (ret < 0) | 810 | if (ret < 0) |
| 751 | goto out; | 811 | goto out; |
| 752 | 812 | ||
| 753 | new_epayload = encrypted_key_alloc(key, new_master_desc, | 813 | new_epayload = encrypted_key_alloc(key, epayload->format, |
| 754 | epayload->datalen); | 814 | new_master_desc, epayload->datalen); |
| 755 | if (IS_ERR(new_epayload)) { | 815 | if (IS_ERR(new_epayload)) { |
| 756 | ret = PTR_ERR(new_epayload); | 816 | ret = PTR_ERR(new_epayload); |
| 757 | goto out; | 817 | goto out; |
| 758 | } | 818 | } |
| 759 | 819 | ||
| 760 | __ekey_init(new_epayload, new_master_desc, epayload->datalen); | 820 | __ekey_init(new_epayload, epayload->format, new_master_desc, |
| 821 | epayload->datalen); | ||
| 761 | 822 | ||
| 762 | memcpy(new_epayload->iv, epayload->iv, ivsize); | 823 | memcpy(new_epayload->iv, epayload->iv, ivsize); |
| 763 | memcpy(new_epayload->decrypted_data, epayload->decrypted_data, | 824 | memcpy(new_epayload->payload_data, epayload->payload_data, |
| 764 | epayload->decrypted_datalen); | 825 | epayload->payload_datalen); |
| 765 | 826 | ||
| 766 | rcu_assign_pointer(key->payload.data, new_epayload); | 827 | rcu_assign_pointer(key->payload.data, new_epayload); |
| 767 | call_rcu(&epayload->rcu, encrypted_rcu_free); | 828 | call_rcu(&epayload->rcu, encrypted_rcu_free); |
