diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/keys/Makefile | 2 | ||||
-rw-r--r-- | security/keys/ecryptfs_format.c | 81 | ||||
-rw-r--r-- | security/keys/ecryptfs_format.h | 30 | ||||
-rw-r--r-- | security/keys/encrypted.c | 75 |
4 files changed, 180 insertions, 8 deletions
diff --git a/security/keys/Makefile b/security/keys/Makefile index 1bf090a885fe..b34cc6ee6900 100644 --- a/security/keys/Makefile +++ b/security/keys/Makefile | |||
@@ -14,7 +14,7 @@ obj-y := \ | |||
14 | user_defined.o | 14 | user_defined.o |
15 | 15 | ||
16 | obj-$(CONFIG_TRUSTED_KEYS) += trusted.o | 16 | obj-$(CONFIG_TRUSTED_KEYS) += trusted.o |
17 | obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted.o | 17 | obj-$(CONFIG_ENCRYPTED_KEYS) += ecryptfs_format.o encrypted.o |
18 | obj-$(CONFIG_KEYS_COMPAT) += compat.o | 18 | obj-$(CONFIG_KEYS_COMPAT) += compat.o |
19 | obj-$(CONFIG_PROC_FS) += proc.o | 19 | obj-$(CONFIG_PROC_FS) += proc.o |
20 | obj-$(CONFIG_SYSCTL) += sysctl.o | 20 | obj-$(CONFIG_SYSCTL) += sysctl.o |
diff --git a/security/keys/ecryptfs_format.c b/security/keys/ecryptfs_format.c new file mode 100644 index 000000000000..6daa3b6ff9ed --- /dev/null +++ b/security/keys/ecryptfs_format.c | |||
@@ -0,0 +1,81 @@ | |||
1 | /* | ||
2 | * ecryptfs_format.c: helper functions for the encrypted key type | ||
3 | * | ||
4 | * Copyright (C) 2006 International Business Machines Corp. | ||
5 | * Copyright (C) 2010 Politecnico di Torino, Italy | ||
6 | * TORSEC group -- http://security.polito.it | ||
7 | * | ||
8 | * Authors: | ||
9 | * Michael A. Halcrow <mahalcro@us.ibm.com> | ||
10 | * Tyler Hicks <tyhicks@ou.edu> | ||
11 | * Roberto Sassu <roberto.sassu@polito.it> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation, version 2 of the License. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include "ecryptfs_format.h" | ||
20 | |||
21 | u8 *ecryptfs_get_auth_tok_key(struct ecryptfs_auth_tok *auth_tok) | ||
22 | { | ||
23 | return auth_tok->token.password.session_key_encryption_key; | ||
24 | } | ||
25 | EXPORT_SYMBOL(ecryptfs_get_auth_tok_key); | ||
26 | |||
27 | /* | ||
28 | * ecryptfs_get_versions() | ||
29 | * | ||
30 | * Source code taken from the software 'ecryptfs-utils' version 83. | ||
31 | * | ||
32 | */ | ||
33 | void ecryptfs_get_versions(int *major, int *minor, int *file_version) | ||
34 | { | ||
35 | *major = ECRYPTFS_VERSION_MAJOR; | ||
36 | *minor = ECRYPTFS_VERSION_MINOR; | ||
37 | if (file_version) | ||
38 | *file_version = ECRYPTFS_SUPPORTED_FILE_VERSION; | ||
39 | } | ||
40 | EXPORT_SYMBOL(ecryptfs_get_versions); | ||
41 | |||
42 | /* | ||
43 | * ecryptfs_fill_auth_tok - fill the ecryptfs_auth_tok structure | ||
44 | * | ||
45 | * Fill the ecryptfs_auth_tok structure with required ecryptfs data. | ||
46 | * The source code is inspired to the original function generate_payload() | ||
47 | * shipped with the software 'ecryptfs-utils' version 83. | ||
48 | * | ||
49 | */ | ||
50 | int ecryptfs_fill_auth_tok(struct ecryptfs_auth_tok *auth_tok, | ||
51 | const char *key_desc) | ||
52 | { | ||
53 | int major, minor; | ||
54 | |||
55 | ecryptfs_get_versions(&major, &minor, NULL); | ||
56 | auth_tok->version = (((uint16_t)(major << 8) & 0xFF00) | ||
57 | | ((uint16_t)minor & 0x00FF)); | ||
58 | auth_tok->token_type = ECRYPTFS_PASSWORD; | ||
59 | strncpy((char *)auth_tok->token.password.signature, key_desc, | ||
60 | ECRYPTFS_PASSWORD_SIG_SIZE); | ||
61 | auth_tok->token.password.session_key_encryption_key_bytes = | ||
62 | ECRYPTFS_MAX_KEY_BYTES; | ||
63 | /* | ||
64 | * Removed auth_tok->token.password.salt and | ||
65 | * auth_tok->token.password.session_key_encryption_key | ||
66 | * initialization from the original code | ||
67 | */ | ||
68 | /* TODO: Make the hash parameterizable via policy */ | ||
69 | auth_tok->token.password.flags |= | ||
70 | ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET; | ||
71 | /* The kernel code will encrypt the session key. */ | ||
72 | auth_tok->session_key.encrypted_key[0] = 0; | ||
73 | auth_tok->session_key.encrypted_key_size = 0; | ||
74 | /* Default; subject to change by kernel eCryptfs */ | ||
75 | auth_tok->token.password.hash_algo = PGP_DIGEST_ALGO_SHA512; | ||
76 | auth_tok->token.password.flags &= ~(ECRYPTFS_PERSISTENT_PASSWORD); | ||
77 | return 0; | ||
78 | } | ||
79 | EXPORT_SYMBOL(ecryptfs_fill_auth_tok); | ||
80 | |||
81 | MODULE_LICENSE("GPL"); | ||
diff --git a/security/keys/ecryptfs_format.h b/security/keys/ecryptfs_format.h new file mode 100644 index 000000000000..40294de238bb --- /dev/null +++ b/security/keys/ecryptfs_format.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * ecryptfs_format.h: helper functions for the encrypted key type | ||
3 | * | ||
4 | * Copyright (C) 2006 International Business Machines Corp. | ||
5 | * Copyright (C) 2010 Politecnico di Torino, Italy | ||
6 | * TORSEC group -- http://security.polito.it | ||
7 | * | ||
8 | * Authors: | ||
9 | * Michael A. Halcrow <mahalcro@us.ibm.com> | ||
10 | * Tyler Hicks <tyhicks@ou.edu> | ||
11 | * Roberto Sassu <roberto.sassu@polito.it> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation, version 2 of the License. | ||
16 | */ | ||
17 | |||
18 | #ifndef __KEYS_ECRYPTFS_H | ||
19 | #define __KEYS_ECRYPTFS_H | ||
20 | |||
21 | #include <linux/ecryptfs.h> | ||
22 | |||
23 | #define PGP_DIGEST_ALGO_SHA512 10 | ||
24 | |||
25 | u8 *ecryptfs_get_auth_tok_key(struct ecryptfs_auth_tok *auth_tok); | ||
26 | void ecryptfs_get_versions(int *major, int *minor, int *file_version); | ||
27 | int ecryptfs_fill_auth_tok(struct ecryptfs_auth_tok *auth_tok, | ||
28 | const char *key_desc); | ||
29 | |||
30 | #endif /* __KEYS_ECRYPTFS_H */ | ||
diff --git a/security/keys/encrypted.c b/security/keys/encrypted.c index 89981c987ba7..e7eca9ec4c65 100644 --- a/security/keys/encrypted.c +++ b/security/keys/encrypted.c | |||
@@ -29,11 +29,13 @@ | |||
29 | #include <linux/rcupdate.h> | 29 | #include <linux/rcupdate.h> |
30 | #include <linux/scatterlist.h> | 30 | #include <linux/scatterlist.h> |
31 | #include <linux/crypto.h> | 31 | #include <linux/crypto.h> |
32 | #include <linux/ctype.h> | ||
32 | #include <crypto/hash.h> | 33 | #include <crypto/hash.h> |
33 | #include <crypto/sha.h> | 34 | #include <crypto/sha.h> |
34 | #include <crypto/aes.h> | 35 | #include <crypto/aes.h> |
35 | 36 | ||
36 | #include "encrypted.h" | 37 | #include "encrypted.h" |
38 | #include "ecryptfs_format.h" | ||
37 | 39 | ||
38 | static const char KEY_TRUSTED_PREFIX[] = "trusted:"; | 40 | static const char KEY_TRUSTED_PREFIX[] = "trusted:"; |
39 | static const char KEY_USER_PREFIX[] = "user:"; | 41 | static const char KEY_USER_PREFIX[] = "user:"; |
@@ -41,11 +43,13 @@ static const char hash_alg[] = "sha256"; | |||
41 | static const char hmac_alg[] = "hmac(sha256)"; | 43 | static const char hmac_alg[] = "hmac(sha256)"; |
42 | static const char blkcipher_alg[] = "cbc(aes)"; | 44 | static const char blkcipher_alg[] = "cbc(aes)"; |
43 | static const char key_format_default[] = "default"; | 45 | static const char key_format_default[] = "default"; |
46 | static const char key_format_ecryptfs[] = "ecryptfs"; | ||
44 | static unsigned int ivsize; | 47 | static unsigned int ivsize; |
45 | static int blksize; | 48 | static int blksize; |
46 | 49 | ||
47 | #define KEY_TRUSTED_PREFIX_LEN (sizeof (KEY_TRUSTED_PREFIX) - 1) | 50 | #define KEY_TRUSTED_PREFIX_LEN (sizeof (KEY_TRUSTED_PREFIX) - 1) |
48 | #define KEY_USER_PREFIX_LEN (sizeof (KEY_USER_PREFIX) - 1) | 51 | #define KEY_USER_PREFIX_LEN (sizeof (KEY_USER_PREFIX) - 1) |
52 | #define KEY_ECRYPTFS_DESC_LEN 16 | ||
49 | #define HASH_SIZE SHA256_DIGEST_SIZE | 53 | #define HASH_SIZE SHA256_DIGEST_SIZE |
50 | #define MAX_DATA_SIZE 4096 | 54 | #define MAX_DATA_SIZE 4096 |
51 | #define MIN_DATA_SIZE 20 | 55 | #define MIN_DATA_SIZE 20 |
@@ -63,11 +67,12 @@ enum { | |||
63 | }; | 67 | }; |
64 | 68 | ||
65 | enum { | 69 | enum { |
66 | Opt_error = -1, Opt_default | 70 | Opt_error = -1, Opt_default, Opt_ecryptfs |
67 | }; | 71 | }; |
68 | 72 | ||
69 | static const match_table_t key_format_tokens = { | 73 | static const match_table_t key_format_tokens = { |
70 | {Opt_default, "default"}, | 74 | {Opt_default, "default"}, |
75 | {Opt_ecryptfs, "ecryptfs"}, | ||
71 | {Opt_error, NULL} | 76 | {Opt_error, NULL} |
72 | }; | 77 | }; |
73 | 78 | ||
@@ -95,6 +100,34 @@ static int aes_get_sizes(void) | |||
95 | } | 100 | } |
96 | 101 | ||
97 | /* | 102 | /* |
103 | * valid_ecryptfs_desc - verify the description of a new/loaded encrypted key | ||
104 | * | ||
105 | * The description of a encrypted key with format 'ecryptfs' must contain | ||
106 | * exactly 16 hexadecimal characters. | ||
107 | * | ||
108 | */ | ||
109 | static int valid_ecryptfs_desc(const char *ecryptfs_desc) | ||
110 | { | ||
111 | int i; | ||
112 | |||
113 | if (strlen(ecryptfs_desc) != KEY_ECRYPTFS_DESC_LEN) { | ||
114 | pr_err("encrypted_key: key description must be %d hexadecimal " | ||
115 | "characters long\n", KEY_ECRYPTFS_DESC_LEN); | ||
116 | return -EINVAL; | ||
117 | } | ||
118 | |||
119 | for (i = 0; i < KEY_ECRYPTFS_DESC_LEN; i++) { | ||
120 | if (!isxdigit(ecryptfs_desc[i])) { | ||
121 | pr_err("encrypted_key: key description must contain " | ||
122 | "only hexadecimal characters\n"); | ||
123 | return -EINVAL; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | /* | ||
98 | * valid_master_desc - verify the 'key-type:desc' of a new/updated master-key | 131 | * valid_master_desc - verify the 'key-type:desc' of a new/updated master-key |
99 | * | 132 | * |
100 | * key-type:= "trusted:" | "user:" | 133 | * key-type:= "trusted:" | "user:" |
@@ -158,7 +191,7 @@ static int datablob_parse(char *datablob, const char **format, | |||
158 | } | 191 | } |
159 | key_cmd = match_token(keyword, key_tokens, args); | 192 | key_cmd = match_token(keyword, key_tokens, args); |
160 | 193 | ||
161 | /* Get optional format: default */ | 194 | /* Get optional format: default | ecryptfs */ |
162 | p = strsep(&datablob, " \t"); | 195 | p = strsep(&datablob, " \t"); |
163 | if (!p) { | 196 | if (!p) { |
164 | pr_err("encrypted_key: insufficient parameters specified\n"); | 197 | pr_err("encrypted_key: insufficient parameters specified\n"); |
@@ -167,6 +200,7 @@ static int datablob_parse(char *datablob, const char **format, | |||
167 | 200 | ||
168 | key_format = match_token(p, key_format_tokens, args); | 201 | key_format = match_token(p, key_format_tokens, args); |
169 | switch (key_format) { | 202 | switch (key_format) { |
203 | case Opt_ecryptfs: | ||
170 | case Opt_default: | 204 | case Opt_default: |
171 | *format = p; | 205 | *format = p; |
172 | *master_desc = strsep(&datablob, " \t"); | 206 | *master_desc = strsep(&datablob, " \t"); |
@@ -601,6 +635,17 @@ static struct encrypted_key_payload *encrypted_key_alloc(struct key *key, | |||
601 | format_len = (!format) ? strlen(key_format_default) : strlen(format); | 635 | format_len = (!format) ? strlen(key_format_default) : strlen(format); |
602 | decrypted_datalen = dlen; | 636 | decrypted_datalen = dlen; |
603 | payload_datalen = decrypted_datalen; | 637 | payload_datalen = decrypted_datalen; |
638 | if (format && !strcmp(format, key_format_ecryptfs)) { | ||
639 | if (dlen != ECRYPTFS_MAX_KEY_BYTES) { | ||
640 | pr_err("encrypted_key: keylen for the ecryptfs format " | ||
641 | "must be equal to %d bytes\n", | ||
642 | ECRYPTFS_MAX_KEY_BYTES); | ||
643 | return ERR_PTR(-EINVAL); | ||
644 | } | ||
645 | decrypted_datalen = ECRYPTFS_MAX_KEY_BYTES; | ||
646 | payload_datalen = sizeof(struct ecryptfs_auth_tok); | ||
647 | } | ||
648 | |||
604 | encrypted_datalen = roundup(decrypted_datalen, blksize); | 649 | encrypted_datalen = roundup(decrypted_datalen, blksize); |
605 | 650 | ||
606 | datablob_len = format_len + 1 + strlen(master_desc) + 1 | 651 | datablob_len = format_len + 1 + strlen(master_desc) + 1 |
@@ -686,8 +731,14 @@ static void __ekey_init(struct encrypted_key_payload *epayload, | |||
686 | 731 | ||
687 | if (!format) | 732 | if (!format) |
688 | memcpy(epayload->format, key_format_default, format_len); | 733 | memcpy(epayload->format, key_format_default, format_len); |
689 | else | 734 | else { |
735 | if (!strcmp(format, key_format_ecryptfs)) | ||
736 | epayload->decrypted_data = | ||
737 | ecryptfs_get_auth_tok_key((struct ecryptfs_auth_tok *)epayload->payload_data); | ||
738 | |||
690 | memcpy(epayload->format, format, format_len); | 739 | memcpy(epayload->format, format, format_len); |
740 | } | ||
741 | |||
691 | memcpy(epayload->master_desc, master_desc, strlen(master_desc)); | 742 | memcpy(epayload->master_desc, master_desc, strlen(master_desc)); |
692 | memcpy(epayload->datalen, datalen, strlen(datalen)); | 743 | memcpy(epayload->datalen, datalen, strlen(datalen)); |
693 | } | 744 | } |
@@ -699,11 +750,21 @@ static void __ekey_init(struct encrypted_key_payload *epayload, | |||
699 | * itself. For an old key, decrypt the hex encoded data. | 750 | * itself. For an old key, decrypt the hex encoded data. |
700 | */ | 751 | */ |
701 | static int encrypted_init(struct encrypted_key_payload *epayload, | 752 | static int encrypted_init(struct encrypted_key_payload *epayload, |
702 | const char *format, const char *master_desc, | 753 | const char *key_desc, const char *format, |
703 | const char *datalen, const char *hex_encoded_iv) | 754 | const char *master_desc, const char *datalen, |
755 | const char *hex_encoded_iv) | ||
704 | { | 756 | { |
705 | int ret = 0; | 757 | int ret = 0; |
706 | 758 | ||
759 | if (format && !strcmp(format, key_format_ecryptfs)) { | ||
760 | ret = valid_ecryptfs_desc(key_desc); | ||
761 | if (ret < 0) | ||
762 | return ret; | ||
763 | |||
764 | ecryptfs_fill_auth_tok((struct ecryptfs_auth_tok *)epayload->payload_data, | ||
765 | key_desc); | ||
766 | } | ||
767 | |||
707 | __ekey_init(epayload, format, master_desc, datalen); | 768 | __ekey_init(epayload, format, master_desc, datalen); |
708 | if (!hex_encoded_iv) { | 769 | if (!hex_encoded_iv) { |
709 | get_random_bytes(epayload->iv, ivsize); | 770 | get_random_bytes(epayload->iv, ivsize); |
@@ -753,8 +814,8 @@ static int encrypted_instantiate(struct key *key, const void *data, | |||
753 | ret = PTR_ERR(epayload); | 814 | ret = PTR_ERR(epayload); |
754 | goto out; | 815 | goto out; |
755 | } | 816 | } |
756 | ret = encrypted_init(epayload, format, master_desc, decrypted_datalen, | 817 | ret = encrypted_init(epayload, key->description, format, master_desc, |
757 | hex_encoded_iv); | 818 | decrypted_datalen, hex_encoded_iv); |
758 | if (ret < 0) { | 819 | if (ret < 0) { |
759 | kfree(epayload); | 820 | kfree(epayload); |
760 | goto out; | 821 | goto out; |