diff options
author | Mimi Zohar <zohar@linux.vnet.ibm.com> | 2010-12-13 16:53:12 -0500 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2010-12-15 01:44:32 -0500 |
commit | 1f35065a9e2573427ce3fd6c4a40b355c2ddfb92 (patch) | |
tree | 9ee6990e21b34dda09efc625a8bca4fa6c4e5d67 /security | |
parent | 1bdbb4024c309e470711b434a24fb356fc92edea (diff) |
encrypted-keys: verify datablob size before converting to binary
Verify the hex ascii datablob length is correct before converting the IV,
encrypted data, and HMAC to binary.
Reported-by: David Howells <dhowells@redhat.com>
Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
Acked-by: David Howells <dhowells@redhat.com>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security')
-rw-r--r-- | security/keys/encrypted_defined.c | 29 |
1 files changed, 15 insertions, 14 deletions
diff --git a/security/keys/encrypted_defined.c b/security/keys/encrypted_defined.c index 3f4085703e6c..d653e991c694 100644 --- a/security/keys/encrypted_defined.c +++ b/security/keys/encrypted_defined.c | |||
@@ -129,8 +129,7 @@ out: | |||
129 | * On success returns 0, otherwise -EINVAL. | 129 | * On success returns 0, otherwise -EINVAL. |
130 | */ | 130 | */ |
131 | static int datablob_parse(char *datablob, char **master_desc, | 131 | static int datablob_parse(char *datablob, char **master_desc, |
132 | char **decrypted_datalen, char **hex_encoded_iv, | 132 | char **decrypted_datalen, char **hex_encoded_iv) |
133 | char **hex_encoded_data) | ||
134 | { | 133 | { |
135 | substring_t args[MAX_OPT_ARGS]; | 134 | substring_t args[MAX_OPT_ARGS]; |
136 | int ret = -EINVAL; | 135 | int ret = -EINVAL; |
@@ -167,7 +166,6 @@ static int datablob_parse(char *datablob, char **master_desc, | |||
167 | *hex_encoded_iv = strsep(&datablob, " \t"); | 166 | *hex_encoded_iv = strsep(&datablob, " \t"); |
168 | if (!*hex_encoded_iv) | 167 | if (!*hex_encoded_iv) |
169 | break; | 168 | break; |
170 | *hex_encoded_data = *hex_encoded_iv + (2 * ivsize) + 2; | ||
171 | ret = 0; | 169 | ret = 0; |
172 | break; | 170 | break; |
173 | case Opt_update: | 171 | case Opt_update: |
@@ -558,18 +556,24 @@ static struct encrypted_key_payload *encrypted_key_alloc(struct key *key, | |||
558 | } | 556 | } |
559 | 557 | ||
560 | static int encrypted_key_decrypt(struct encrypted_key_payload *epayload, | 558 | static int encrypted_key_decrypt(struct encrypted_key_payload *epayload, |
561 | const char *hex_encoded_iv, | 559 | const char *hex_encoded_iv) |
562 | const char *hex_encoded_data) | ||
563 | { | 560 | { |
564 | struct key *mkey; | 561 | struct key *mkey; |
565 | u8 derived_key[HASH_SIZE]; | 562 | u8 derived_key[HASH_SIZE]; |
566 | u8 *master_key; | 563 | u8 *master_key; |
567 | u8 *hmac; | 564 | u8 *hmac; |
565 | const char *hex_encoded_data; | ||
568 | unsigned int master_keylen; | 566 | unsigned int master_keylen; |
569 | unsigned int encrypted_datalen; | 567 | unsigned int encrypted_datalen; |
568 | size_t asciilen; | ||
570 | int ret; | 569 | int ret; |
571 | 570 | ||
572 | encrypted_datalen = roundup(epayload->decrypted_datalen, blksize); | 571 | encrypted_datalen = roundup(epayload->decrypted_datalen, blksize); |
572 | asciilen = (ivsize + 1 + encrypted_datalen + HASH_SIZE) * 2; | ||
573 | if (strlen(hex_encoded_iv) != asciilen) | ||
574 | return -EINVAL; | ||
575 | |||
576 | hex_encoded_data = hex_encoded_iv + (2 * ivsize) + 2; | ||
573 | hex2bin(epayload->iv, hex_encoded_iv, ivsize); | 577 | hex2bin(epayload->iv, hex_encoded_iv, ivsize); |
574 | hex2bin(epayload->encrypted_data, hex_encoded_data, encrypted_datalen); | 578 | hex2bin(epayload->encrypted_data, hex_encoded_data, encrypted_datalen); |
575 | 579 | ||
@@ -620,20 +624,18 @@ static void __ekey_init(struct encrypted_key_payload *epayload, | |||
620 | */ | 624 | */ |
621 | static int encrypted_init(struct encrypted_key_payload *epayload, | 625 | static int encrypted_init(struct encrypted_key_payload *epayload, |
622 | const char *master_desc, const char *datalen, | 626 | const char *master_desc, const char *datalen, |
623 | const char *hex_encoded_iv, | 627 | const char *hex_encoded_iv) |
624 | const char *hex_encoded_data) | ||
625 | { | 628 | { |
626 | int ret = 0; | 629 | int ret = 0; |
627 | 630 | ||
628 | __ekey_init(epayload, master_desc, datalen); | 631 | __ekey_init(epayload, master_desc, datalen); |
629 | if (!hex_encoded_data) { | 632 | if (!hex_encoded_iv) { |
630 | get_random_bytes(epayload->iv, ivsize); | 633 | get_random_bytes(epayload->iv, ivsize); |
631 | 634 | ||
632 | get_random_bytes(epayload->decrypted_data, | 635 | get_random_bytes(epayload->decrypted_data, |
633 | epayload->decrypted_datalen); | 636 | epayload->decrypted_datalen); |
634 | } else | 637 | } else |
635 | ret = encrypted_key_decrypt(epayload, hex_encoded_iv, | 638 | ret = encrypted_key_decrypt(epayload, hex_encoded_iv); |
636 | hex_encoded_data); | ||
637 | return ret; | 639 | return ret; |
638 | } | 640 | } |
639 | 641 | ||
@@ -653,7 +655,6 @@ static int encrypted_instantiate(struct key *key, const void *data, | |||
653 | char *master_desc = NULL; | 655 | char *master_desc = NULL; |
654 | char *decrypted_datalen = NULL; | 656 | char *decrypted_datalen = NULL; |
655 | char *hex_encoded_iv = NULL; | 657 | char *hex_encoded_iv = NULL; |
656 | char *hex_encoded_data = NULL; | ||
657 | int ret; | 658 | int ret; |
658 | 659 | ||
659 | if (datalen <= 0 || datalen > 32767 || !data) | 660 | if (datalen <= 0 || datalen > 32767 || !data) |
@@ -665,7 +666,7 @@ static int encrypted_instantiate(struct key *key, const void *data, | |||
665 | datablob[datalen] = 0; | 666 | datablob[datalen] = 0; |
666 | memcpy(datablob, data, datalen); | 667 | memcpy(datablob, data, datalen); |
667 | ret = datablob_parse(datablob, &master_desc, &decrypted_datalen, | 668 | ret = datablob_parse(datablob, &master_desc, &decrypted_datalen, |
668 | &hex_encoded_iv, &hex_encoded_data); | 669 | &hex_encoded_iv); |
669 | if (ret < 0) | 670 | if (ret < 0) |
670 | goto out; | 671 | goto out; |
671 | 672 | ||
@@ -675,7 +676,7 @@ static int encrypted_instantiate(struct key *key, const void *data, | |||
675 | goto out; | 676 | goto out; |
676 | } | 677 | } |
677 | ret = encrypted_init(epayload, master_desc, decrypted_datalen, | 678 | ret = encrypted_init(epayload, master_desc, decrypted_datalen, |
678 | hex_encoded_iv, hex_encoded_data); | 679 | hex_encoded_iv); |
679 | if (ret < 0) { | 680 | if (ret < 0) { |
680 | kfree(epayload); | 681 | kfree(epayload); |
681 | goto out; | 682 | goto out; |
@@ -722,7 +723,7 @@ static int encrypted_update(struct key *key, const void *data, size_t datalen) | |||
722 | 723 | ||
723 | buf[datalen] = 0; | 724 | buf[datalen] = 0; |
724 | memcpy(buf, data, datalen); | 725 | memcpy(buf, data, datalen); |
725 | ret = datablob_parse(buf, &new_master_desc, NULL, NULL, NULL); | 726 | ret = datablob_parse(buf, &new_master_desc, NULL, NULL); |
726 | if (ret < 0) | 727 | if (ret < 0) |
727 | goto out; | 728 | goto out; |
728 | 729 | ||