diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-27 22:26:38 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-27 22:26:38 -0400 |
commit | 95b6886526bb510b8370b625a49bc0ab3b8ff10f (patch) | |
tree | 2862606224820d200be12d2092dcd26df1654b80 /security/keys | |
parent | 22712200e175e0df5c7f9edfe6c6bf5c94c23b83 (diff) | |
parent | 29412f0f6a19e34336368f13eab848091c343952 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6: (54 commits)
tpm_nsc: Fix bug when loading multiple TPM drivers
tpm: Move tpm_tis_reenable_interrupts out of CONFIG_PNP block
tpm: Fix compilation warning when CONFIG_PNP is not defined
TOMOYO: Update kernel-doc.
tpm: Fix a typo
tpm_tis: Probing function for Intel iTPM bug
tpm_tis: Fix the probing for interrupts
tpm_tis: Delay ACPI S3 suspend while the TPM is busy
tpm_tis: Re-enable interrupts upon (S3) resume
tpm: Fix display of data in pubek sysfs entry
tpm_tis: Add timeouts sysfs entry
tpm: Adjust interface timeouts if they are too small
tpm: Use interface timeouts returned from the TPM
tpm_tis: Introduce durations sysfs entry
tpm: Adjust the durations if they are too small
tpm: Use durations returned from TPM
TOMOYO: Enable conditional ACL.
TOMOYO: Allow using argv[]/envp[] of execve() as conditions.
TOMOYO: Allow using executable's realpath and symlink's target as conditions.
TOMOYO: Allow using owner/group etc. of file objects as conditions.
...
Fix up trivial conflict in security/tomoyo/realpath.c
Diffstat (limited to 'security/keys')
-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 | 251 | ||||
-rw-r--r-- | security/keys/request_key_auth.c | 2 |
5 files changed, 313 insertions, 53 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 b1cba5bf0a5e..e7eca9ec4c65 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 |
@@ -26,22 +29,27 @@ | |||
26 | #include <linux/rcupdate.h> | 29 | #include <linux/rcupdate.h> |
27 | #include <linux/scatterlist.h> | 30 | #include <linux/scatterlist.h> |
28 | #include <linux/crypto.h> | 31 | #include <linux/crypto.h> |
32 | #include <linux/ctype.h> | ||
29 | #include <crypto/hash.h> | 33 | #include <crypto/hash.h> |
30 | #include <crypto/sha.h> | 34 | #include <crypto/sha.h> |
31 | #include <crypto/aes.h> | 35 | #include <crypto/aes.h> |
32 | 36 | ||
33 | #include "encrypted.h" | 37 | #include "encrypted.h" |
38 | #include "ecryptfs_format.h" | ||
34 | 39 | ||
35 | static const char KEY_TRUSTED_PREFIX[] = "trusted:"; | 40 | static const char KEY_TRUSTED_PREFIX[] = "trusted:"; |
36 | static const char KEY_USER_PREFIX[] = "user:"; | 41 | static const char KEY_USER_PREFIX[] = "user:"; |
37 | static const char hash_alg[] = "sha256"; | 42 | static const char hash_alg[] = "sha256"; |
38 | static const char hmac_alg[] = "hmac(sha256)"; | 43 | static const char hmac_alg[] = "hmac(sha256)"; |
39 | static const char blkcipher_alg[] = "cbc(aes)"; | 44 | static const char blkcipher_alg[] = "cbc(aes)"; |
45 | static const char key_format_default[] = "default"; | ||
46 | static const char key_format_ecryptfs[] = "ecryptfs"; | ||
40 | static unsigned int ivsize; | 47 | static unsigned int ivsize; |
41 | static int blksize; | 48 | static int blksize; |
42 | 49 | ||
43 | #define KEY_TRUSTED_PREFIX_LEN (sizeof (KEY_TRUSTED_PREFIX) - 1) | 50 | #define KEY_TRUSTED_PREFIX_LEN (sizeof (KEY_TRUSTED_PREFIX) - 1) |
44 | #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 | ||
45 | #define HASH_SIZE SHA256_DIGEST_SIZE | 53 | #define HASH_SIZE SHA256_DIGEST_SIZE |
46 | #define MAX_DATA_SIZE 4096 | 54 | #define MAX_DATA_SIZE 4096 |
47 | #define MIN_DATA_SIZE 20 | 55 | #define MIN_DATA_SIZE 20 |
@@ -58,6 +66,16 @@ enum { | |||
58 | Opt_err = -1, Opt_new, Opt_load, Opt_update | 66 | Opt_err = -1, Opt_new, Opt_load, Opt_update |
59 | }; | 67 | }; |
60 | 68 | ||
69 | enum { | ||
70 | Opt_error = -1, Opt_default, Opt_ecryptfs | ||
71 | }; | ||
72 | |||
73 | static const match_table_t key_format_tokens = { | ||
74 | {Opt_default, "default"}, | ||
75 | {Opt_ecryptfs, "ecryptfs"}, | ||
76 | {Opt_error, NULL} | ||
77 | }; | ||
78 | |||
61 | static const match_table_t key_tokens = { | 79 | static const match_table_t key_tokens = { |
62 | {Opt_new, "new"}, | 80 | {Opt_new, "new"}, |
63 | {Opt_load, "load"}, | 81 | {Opt_load, "load"}, |
@@ -82,9 +100,37 @@ static int aes_get_sizes(void) | |||
82 | } | 100 | } |
83 | 101 | ||
84 | /* | 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 | /* | ||
85 | * 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 |
86 | * | 132 | * |
87 | * key-type:= "trusted:" | "encrypted:" | 133 | * key-type:= "trusted:" | "user:" |
88 | * desc:= master-key description | 134 | * desc:= master-key description |
89 | * | 135 | * |
90 | * Verify that 'key-type' is valid and that 'desc' exists. On key update, | 136 | * Verify that 'key-type' is valid and that 'desc' exists. On key update, |
@@ -118,8 +164,9 @@ out: | |||
118 | * datablob_parse - parse the keyctl data | 164 | * datablob_parse - parse the keyctl data |
119 | * | 165 | * |
120 | * datablob format: | 166 | * datablob format: |
121 | * new <master-key name> <decrypted data length> | 167 | * new [<format>] <master-key name> <decrypted data length> |
122 | * load <master-key name> <decrypted data length> <encrypted iv + data> | 168 | * load [<format>] <master-key name> <decrypted data length> |
169 | * <encrypted iv + data> | ||
123 | * update <new-master-key name> | 170 | * update <new-master-key name> |
124 | * | 171 | * |
125 | * Tokenizes a copy of the keyctl data, returning a pointer to each token, | 172 | * Tokenizes a copy of the keyctl data, returning a pointer to each token, |
@@ -127,52 +174,95 @@ out: | |||
127 | * | 174 | * |
128 | * On success returns 0, otherwise -EINVAL. | 175 | * On success returns 0, otherwise -EINVAL. |
129 | */ | 176 | */ |
130 | static int datablob_parse(char *datablob, char **master_desc, | 177 | static int datablob_parse(char *datablob, const char **format, |
131 | char **decrypted_datalen, char **hex_encoded_iv) | 178 | char **master_desc, char **decrypted_datalen, |
179 | char **hex_encoded_iv) | ||
132 | { | 180 | { |
133 | substring_t args[MAX_OPT_ARGS]; | 181 | substring_t args[MAX_OPT_ARGS]; |
134 | int ret = -EINVAL; | 182 | int ret = -EINVAL; |
135 | int key_cmd; | 183 | int key_cmd; |
136 | char *p; | 184 | int key_format; |
185 | char *p, *keyword; | ||
186 | |||
187 | keyword = strsep(&datablob, " \t"); | ||
188 | if (!keyword) { | ||
189 | pr_info("encrypted_key: insufficient parameters specified\n"); | ||
190 | return ret; | ||
191 | } | ||
192 | key_cmd = match_token(keyword, key_tokens, args); | ||
137 | 193 | ||
194 | /* Get optional format: default | ecryptfs */ | ||
138 | p = strsep(&datablob, " \t"); | 195 | p = strsep(&datablob, " \t"); |
139 | if (!p) | 196 | if (!p) { |
197 | pr_err("encrypted_key: insufficient parameters specified\n"); | ||
140 | return ret; | 198 | return ret; |
141 | key_cmd = match_token(p, key_tokens, args); | 199 | } |
142 | 200 | ||
143 | *master_desc = strsep(&datablob, " \t"); | 201 | key_format = match_token(p, key_format_tokens, args); |
144 | if (!*master_desc) | 202 | switch (key_format) { |
203 | case Opt_ecryptfs: | ||
204 | case Opt_default: | ||
205 | *format = p; | ||
206 | *master_desc = strsep(&datablob, " \t"); | ||
207 | break; | ||
208 | case Opt_error: | ||
209 | *master_desc = p; | ||
210 | break; | ||
211 | } | ||
212 | |||
213 | if (!*master_desc) { | ||
214 | pr_info("encrypted_key: master key parameter is missing\n"); | ||
145 | goto out; | 215 | goto out; |
216 | } | ||
146 | 217 | ||
147 | if (valid_master_desc(*master_desc, NULL) < 0) | 218 | if (valid_master_desc(*master_desc, NULL) < 0) { |
219 | pr_info("encrypted_key: master key parameter \'%s\' " | ||
220 | "is invalid\n", *master_desc); | ||
148 | goto out; | 221 | goto out; |
222 | } | ||
149 | 223 | ||
150 | if (decrypted_datalen) { | 224 | if (decrypted_datalen) { |
151 | *decrypted_datalen = strsep(&datablob, " \t"); | 225 | *decrypted_datalen = strsep(&datablob, " \t"); |
152 | if (!*decrypted_datalen) | 226 | if (!*decrypted_datalen) { |
227 | pr_info("encrypted_key: keylen parameter is missing\n"); | ||
153 | goto out; | 228 | goto out; |
229 | } | ||
154 | } | 230 | } |
155 | 231 | ||
156 | switch (key_cmd) { | 232 | switch (key_cmd) { |
157 | case Opt_new: | 233 | case Opt_new: |
158 | if (!decrypted_datalen) | 234 | if (!decrypted_datalen) { |
235 | pr_info("encrypted_key: keyword \'%s\' not allowed " | ||
236 | "when called from .update method\n", keyword); | ||
159 | break; | 237 | break; |
238 | } | ||
160 | ret = 0; | 239 | ret = 0; |
161 | break; | 240 | break; |
162 | case Opt_load: | 241 | case Opt_load: |
163 | if (!decrypted_datalen) | 242 | if (!decrypted_datalen) { |
243 | pr_info("encrypted_key: keyword \'%s\' not allowed " | ||
244 | "when called from .update method\n", keyword); | ||
164 | break; | 245 | break; |
246 | } | ||
165 | *hex_encoded_iv = strsep(&datablob, " \t"); | 247 | *hex_encoded_iv = strsep(&datablob, " \t"); |
166 | if (!*hex_encoded_iv) | 248 | if (!*hex_encoded_iv) { |
249 | pr_info("encrypted_key: hex blob is missing\n"); | ||
167 | break; | 250 | break; |
251 | } | ||
168 | ret = 0; | 252 | ret = 0; |
169 | break; | 253 | break; |
170 | case Opt_update: | 254 | case Opt_update: |
171 | if (decrypted_datalen) | 255 | if (decrypted_datalen) { |
256 | pr_info("encrypted_key: keyword \'%s\' not allowed " | ||
257 | "when called from .instantiate method\n", | ||
258 | keyword); | ||
172 | break; | 259 | break; |
260 | } | ||
173 | ret = 0; | 261 | ret = 0; |
174 | break; | 262 | break; |
175 | case Opt_err: | 263 | case Opt_err: |
264 | pr_info("encrypted_key: keyword \'%s\' not recognized\n", | ||
265 | keyword); | ||
176 | break; | 266 | break; |
177 | } | 267 | } |
178 | out: | 268 | out: |
@@ -197,8 +287,8 @@ static char *datablob_format(struct encrypted_key_payload *epayload, | |||
197 | ascii_buf[asciiblob_len] = '\0'; | 287 | ascii_buf[asciiblob_len] = '\0'; |
198 | 288 | ||
199 | /* copy datablob master_desc and datalen strings */ | 289 | /* copy datablob master_desc and datalen strings */ |
200 | len = sprintf(ascii_buf, "%s %s ", epayload->master_desc, | 290 | len = sprintf(ascii_buf, "%s %s %s ", epayload->format, |
201 | epayload->datalen); | 291 | epayload->master_desc, epayload->datalen); |
202 | 292 | ||
203 | /* convert the hex encoded iv, encrypted-data and HMAC to ascii */ | 293 | /* convert the hex encoded iv, encrypted-data and HMAC to ascii */ |
204 | bufp = &ascii_buf[len]; | 294 | bufp = &ascii_buf[len]; |
@@ -378,11 +468,13 @@ static struct key *request_master_key(struct encrypted_key_payload *epayload, | |||
378 | } else | 468 | } else |
379 | goto out; | 469 | goto out; |
380 | 470 | ||
381 | if (IS_ERR(mkey)) | 471 | if (IS_ERR(mkey)) { |
382 | pr_info("encrypted_key: key %s not found", | 472 | pr_info("encrypted_key: key %s not found", |
383 | epayload->master_desc); | 473 | epayload->master_desc); |
384 | if (mkey) | 474 | goto out; |
385 | dump_master_key(*master_key, *master_keylen); | 475 | } |
476 | |||
477 | dump_master_key(*master_key, *master_keylen); | ||
386 | out: | 478 | out: |
387 | return mkey; | 479 | return mkey; |
388 | } | 480 | } |
@@ -439,9 +531,9 @@ static int datablob_hmac_append(struct encrypted_key_payload *epayload, | |||
439 | if (ret < 0) | 531 | if (ret < 0) |
440 | goto out; | 532 | goto out; |
441 | 533 | ||
442 | digest = epayload->master_desc + epayload->datablob_len; | 534 | digest = epayload->format + epayload->datablob_len; |
443 | ret = calc_hmac(digest, derived_key, sizeof derived_key, | 535 | ret = calc_hmac(digest, derived_key, sizeof derived_key, |
444 | epayload->master_desc, epayload->datablob_len); | 536 | epayload->format, epayload->datablob_len); |
445 | if (!ret) | 537 | if (!ret) |
446 | dump_hmac(NULL, digest, HASH_SIZE); | 538 | dump_hmac(NULL, digest, HASH_SIZE); |
447 | out: | 539 | out: |
@@ -450,26 +542,35 @@ out: | |||
450 | 542 | ||
451 | /* verify HMAC before decrypting encrypted key */ | 543 | /* verify HMAC before decrypting encrypted key */ |
452 | static int datablob_hmac_verify(struct encrypted_key_payload *epayload, | 544 | static int datablob_hmac_verify(struct encrypted_key_payload *epayload, |
453 | const u8 *master_key, size_t master_keylen) | 545 | const u8 *format, const u8 *master_key, |
546 | size_t master_keylen) | ||
454 | { | 547 | { |
455 | u8 derived_key[HASH_SIZE]; | 548 | u8 derived_key[HASH_SIZE]; |
456 | u8 digest[HASH_SIZE]; | 549 | u8 digest[HASH_SIZE]; |
457 | int ret; | 550 | int ret; |
551 | char *p; | ||
552 | unsigned short len; | ||
458 | 553 | ||
459 | ret = get_derived_key(derived_key, AUTH_KEY, master_key, master_keylen); | 554 | ret = get_derived_key(derived_key, AUTH_KEY, master_key, master_keylen); |
460 | if (ret < 0) | 555 | if (ret < 0) |
461 | goto out; | 556 | goto out; |
462 | 557 | ||
463 | ret = calc_hmac(digest, derived_key, sizeof derived_key, | 558 | len = epayload->datablob_len; |
464 | epayload->master_desc, epayload->datablob_len); | 559 | if (!format) { |
560 | p = epayload->master_desc; | ||
561 | len -= strlen(epayload->format) + 1; | ||
562 | } else | ||
563 | p = epayload->format; | ||
564 | |||
565 | ret = calc_hmac(digest, derived_key, sizeof derived_key, p, len); | ||
465 | if (ret < 0) | 566 | if (ret < 0) |
466 | goto out; | 567 | goto out; |
467 | ret = memcmp(digest, epayload->master_desc + epayload->datablob_len, | 568 | ret = memcmp(digest, epayload->format + epayload->datablob_len, |
468 | sizeof digest); | 569 | sizeof digest); |
469 | if (ret) { | 570 | if (ret) { |
470 | ret = -EINVAL; | 571 | ret = -EINVAL; |
471 | dump_hmac("datablob", | 572 | dump_hmac("datablob", |
472 | epayload->master_desc + epayload->datablob_len, | 573 | epayload->format + epayload->datablob_len, |
473 | HASH_SIZE); | 574 | HASH_SIZE); |
474 | dump_hmac("calc", digest, HASH_SIZE); | 575 | dump_hmac("calc", digest, HASH_SIZE); |
475 | } | 576 | } |
@@ -514,13 +615,16 @@ out: | |||
514 | 615 | ||
515 | /* Allocate memory for decrypted key and datablob. */ | 616 | /* Allocate memory for decrypted key and datablob. */ |
516 | static struct encrypted_key_payload *encrypted_key_alloc(struct key *key, | 617 | static struct encrypted_key_payload *encrypted_key_alloc(struct key *key, |
618 | const char *format, | ||
517 | const char *master_desc, | 619 | const char *master_desc, |
518 | const char *datalen) | 620 | const char *datalen) |
519 | { | 621 | { |
520 | struct encrypted_key_payload *epayload = NULL; | 622 | struct encrypted_key_payload *epayload = NULL; |
521 | unsigned short datablob_len; | 623 | unsigned short datablob_len; |
522 | unsigned short decrypted_datalen; | 624 | unsigned short decrypted_datalen; |
625 | unsigned short payload_datalen; | ||
523 | unsigned int encrypted_datalen; | 626 | unsigned int encrypted_datalen; |
627 | unsigned int format_len; | ||
524 | long dlen; | 628 | long dlen; |
525 | int ret; | 629 | int ret; |
526 | 630 | ||
@@ -528,29 +632,43 @@ static struct encrypted_key_payload *encrypted_key_alloc(struct key *key, | |||
528 | if (ret < 0 || dlen < MIN_DATA_SIZE || dlen > MAX_DATA_SIZE) | 632 | if (ret < 0 || dlen < MIN_DATA_SIZE || dlen > MAX_DATA_SIZE) |
529 | return ERR_PTR(-EINVAL); | 633 | return ERR_PTR(-EINVAL); |
530 | 634 | ||
635 | format_len = (!format) ? strlen(key_format_default) : strlen(format); | ||
531 | decrypted_datalen = dlen; | 636 | decrypted_datalen = dlen; |
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 | |||
532 | encrypted_datalen = roundup(decrypted_datalen, blksize); | 649 | encrypted_datalen = roundup(decrypted_datalen, blksize); |
533 | 650 | ||
534 | datablob_len = strlen(master_desc) + 1 + strlen(datalen) + 1 | 651 | datablob_len = format_len + 1 + strlen(master_desc) + 1 |
535 | + ivsize + 1 + encrypted_datalen; | 652 | + strlen(datalen) + 1 + ivsize + 1 + encrypted_datalen; |
536 | 653 | ||
537 | ret = key_payload_reserve(key, decrypted_datalen + datablob_len | 654 | ret = key_payload_reserve(key, payload_datalen + datablob_len |
538 | + HASH_SIZE + 1); | 655 | + HASH_SIZE + 1); |
539 | if (ret < 0) | 656 | if (ret < 0) |
540 | return ERR_PTR(ret); | 657 | return ERR_PTR(ret); |
541 | 658 | ||
542 | epayload = kzalloc(sizeof(*epayload) + decrypted_datalen + | 659 | epayload = kzalloc(sizeof(*epayload) + payload_datalen + |
543 | datablob_len + HASH_SIZE + 1, GFP_KERNEL); | 660 | datablob_len + HASH_SIZE + 1, GFP_KERNEL); |
544 | if (!epayload) | 661 | if (!epayload) |
545 | return ERR_PTR(-ENOMEM); | 662 | return ERR_PTR(-ENOMEM); |
546 | 663 | ||
664 | epayload->payload_datalen = payload_datalen; | ||
547 | epayload->decrypted_datalen = decrypted_datalen; | 665 | epayload->decrypted_datalen = decrypted_datalen; |
548 | epayload->datablob_len = datablob_len; | 666 | epayload->datablob_len = datablob_len; |
549 | return epayload; | 667 | return epayload; |
550 | } | 668 | } |
551 | 669 | ||
552 | static int encrypted_key_decrypt(struct encrypted_key_payload *epayload, | 670 | static int encrypted_key_decrypt(struct encrypted_key_payload *epayload, |
553 | const char *hex_encoded_iv) | 671 | const char *format, const char *hex_encoded_iv) |
554 | { | 672 | { |
555 | struct key *mkey; | 673 | struct key *mkey; |
556 | u8 derived_key[HASH_SIZE]; | 674 | u8 derived_key[HASH_SIZE]; |
@@ -571,14 +689,14 @@ static int encrypted_key_decrypt(struct encrypted_key_payload *epayload, | |||
571 | hex2bin(epayload->iv, hex_encoded_iv, ivsize); | 689 | hex2bin(epayload->iv, hex_encoded_iv, ivsize); |
572 | hex2bin(epayload->encrypted_data, hex_encoded_data, encrypted_datalen); | 690 | hex2bin(epayload->encrypted_data, hex_encoded_data, encrypted_datalen); |
573 | 691 | ||
574 | hmac = epayload->master_desc + epayload->datablob_len; | 692 | hmac = epayload->format + epayload->datablob_len; |
575 | hex2bin(hmac, hex_encoded_data + (encrypted_datalen * 2), HASH_SIZE); | 693 | hex2bin(hmac, hex_encoded_data + (encrypted_datalen * 2), HASH_SIZE); |
576 | 694 | ||
577 | mkey = request_master_key(epayload, &master_key, &master_keylen); | 695 | mkey = request_master_key(epayload, &master_key, &master_keylen); |
578 | if (IS_ERR(mkey)) | 696 | if (IS_ERR(mkey)) |
579 | return PTR_ERR(mkey); | 697 | return PTR_ERR(mkey); |
580 | 698 | ||
581 | ret = datablob_hmac_verify(epayload, master_key, master_keylen); | 699 | ret = datablob_hmac_verify(epayload, format, master_key, master_keylen); |
582 | if (ret < 0) { | 700 | if (ret < 0) { |
583 | pr_err("encrypted_key: bad hmac (%d)\n", ret); | 701 | pr_err("encrypted_key: bad hmac (%d)\n", ret); |
584 | goto out; | 702 | goto out; |
@@ -598,13 +716,28 @@ out: | |||
598 | } | 716 | } |
599 | 717 | ||
600 | static void __ekey_init(struct encrypted_key_payload *epayload, | 718 | static void __ekey_init(struct encrypted_key_payload *epayload, |
601 | const char *master_desc, const char *datalen) | 719 | const char *format, const char *master_desc, |
720 | const char *datalen) | ||
602 | { | 721 | { |
603 | epayload->master_desc = epayload->decrypted_data | 722 | unsigned int format_len; |
604 | + epayload->decrypted_datalen; | 723 | |
724 | format_len = (!format) ? strlen(key_format_default) : strlen(format); | ||
725 | epayload->format = epayload->payload_data + epayload->payload_datalen; | ||
726 | epayload->master_desc = epayload->format + format_len + 1; | ||
605 | epayload->datalen = epayload->master_desc + strlen(master_desc) + 1; | 727 | epayload->datalen = epayload->master_desc + strlen(master_desc) + 1; |
606 | epayload->iv = epayload->datalen + strlen(datalen) + 1; | 728 | epayload->iv = epayload->datalen + strlen(datalen) + 1; |
607 | epayload->encrypted_data = epayload->iv + ivsize + 1; | 729 | epayload->encrypted_data = epayload->iv + ivsize + 1; |
730 | epayload->decrypted_data = epayload->payload_data; | ||
731 | |||
732 | if (!format) | ||
733 | memcpy(epayload->format, key_format_default, format_len); | ||
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 | |||
739 | memcpy(epayload->format, format, format_len); | ||
740 | } | ||
608 | 741 | ||
609 | memcpy(epayload->master_desc, master_desc, strlen(master_desc)); | 742 | memcpy(epayload->master_desc, master_desc, strlen(master_desc)); |
610 | memcpy(epayload->datalen, datalen, strlen(datalen)); | 743 | memcpy(epayload->datalen, datalen, strlen(datalen)); |
@@ -617,19 +750,29 @@ static void __ekey_init(struct encrypted_key_payload *epayload, | |||
617 | * itself. For an old key, decrypt the hex encoded data. | 750 | * itself. For an old key, decrypt the hex encoded data. |
618 | */ | 751 | */ |
619 | static int encrypted_init(struct encrypted_key_payload *epayload, | 752 | static int encrypted_init(struct encrypted_key_payload *epayload, |
753 | const char *key_desc, const char *format, | ||
620 | const char *master_desc, const char *datalen, | 754 | const char *master_desc, const char *datalen, |
621 | const char *hex_encoded_iv) | 755 | const char *hex_encoded_iv) |
622 | { | 756 | { |
623 | int ret = 0; | 757 | int ret = 0; |
624 | 758 | ||
625 | __ekey_init(epayload, master_desc, datalen); | 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 | |||
768 | __ekey_init(epayload, format, master_desc, datalen); | ||
626 | if (!hex_encoded_iv) { | 769 | if (!hex_encoded_iv) { |
627 | get_random_bytes(epayload->iv, ivsize); | 770 | get_random_bytes(epayload->iv, ivsize); |
628 | 771 | ||
629 | get_random_bytes(epayload->decrypted_data, | 772 | get_random_bytes(epayload->decrypted_data, |
630 | epayload->decrypted_datalen); | 773 | epayload->decrypted_datalen); |
631 | } else | 774 | } else |
632 | ret = encrypted_key_decrypt(epayload, hex_encoded_iv); | 775 | ret = encrypted_key_decrypt(epayload, format, hex_encoded_iv); |
633 | return ret; | 776 | return ret; |
634 | } | 777 | } |
635 | 778 | ||
@@ -646,6 +789,7 @@ static int encrypted_instantiate(struct key *key, const void *data, | |||
646 | { | 789 | { |
647 | struct encrypted_key_payload *epayload = NULL; | 790 | struct encrypted_key_payload *epayload = NULL; |
648 | char *datablob = NULL; | 791 | char *datablob = NULL; |
792 | const char *format = NULL; | ||
649 | char *master_desc = NULL; | 793 | char *master_desc = NULL; |
650 | char *decrypted_datalen = NULL; | 794 | char *decrypted_datalen = NULL; |
651 | char *hex_encoded_iv = NULL; | 795 | char *hex_encoded_iv = NULL; |
@@ -659,18 +803,19 @@ static int encrypted_instantiate(struct key *key, const void *data, | |||
659 | return -ENOMEM; | 803 | return -ENOMEM; |
660 | datablob[datalen] = 0; | 804 | datablob[datalen] = 0; |
661 | memcpy(datablob, data, datalen); | 805 | memcpy(datablob, data, datalen); |
662 | ret = datablob_parse(datablob, &master_desc, &decrypted_datalen, | 806 | ret = datablob_parse(datablob, &format, &master_desc, |
663 | &hex_encoded_iv); | 807 | &decrypted_datalen, &hex_encoded_iv); |
664 | if (ret < 0) | 808 | if (ret < 0) |
665 | goto out; | 809 | goto out; |
666 | 810 | ||
667 | epayload = encrypted_key_alloc(key, master_desc, decrypted_datalen); | 811 | epayload = encrypted_key_alloc(key, format, master_desc, |
812 | decrypted_datalen); | ||
668 | if (IS_ERR(epayload)) { | 813 | if (IS_ERR(epayload)) { |
669 | ret = PTR_ERR(epayload); | 814 | ret = PTR_ERR(epayload); |
670 | goto out; | 815 | goto out; |
671 | } | 816 | } |
672 | ret = encrypted_init(epayload, master_desc, decrypted_datalen, | 817 | ret = encrypted_init(epayload, key->description, format, master_desc, |
673 | hex_encoded_iv); | 818 | decrypted_datalen, hex_encoded_iv); |
674 | if (ret < 0) { | 819 | if (ret < 0) { |
675 | kfree(epayload); | 820 | kfree(epayload); |
676 | goto out; | 821 | goto out; |
@@ -706,6 +851,7 @@ static int encrypted_update(struct key *key, const void *data, size_t datalen) | |||
706 | struct encrypted_key_payload *new_epayload; | 851 | struct encrypted_key_payload *new_epayload; |
707 | char *buf; | 852 | char *buf; |
708 | char *new_master_desc = NULL; | 853 | char *new_master_desc = NULL; |
854 | const char *format = NULL; | ||
709 | int ret = 0; | 855 | int ret = 0; |
710 | 856 | ||
711 | if (datalen <= 0 || datalen > 32767 || !data) | 857 | if (datalen <= 0 || datalen > 32767 || !data) |
@@ -717,7 +863,7 @@ static int encrypted_update(struct key *key, const void *data, size_t datalen) | |||
717 | 863 | ||
718 | buf[datalen] = 0; | 864 | buf[datalen] = 0; |
719 | memcpy(buf, data, datalen); | 865 | memcpy(buf, data, datalen); |
720 | ret = datablob_parse(buf, &new_master_desc, NULL, NULL); | 866 | ret = datablob_parse(buf, &format, &new_master_desc, NULL, NULL); |
721 | if (ret < 0) | 867 | if (ret < 0) |
722 | goto out; | 868 | goto out; |
723 | 869 | ||
@@ -725,18 +871,19 @@ static int encrypted_update(struct key *key, const void *data, size_t datalen) | |||
725 | if (ret < 0) | 871 | if (ret < 0) |
726 | goto out; | 872 | goto out; |
727 | 873 | ||
728 | new_epayload = encrypted_key_alloc(key, new_master_desc, | 874 | new_epayload = encrypted_key_alloc(key, epayload->format, |
729 | epayload->datalen); | 875 | new_master_desc, epayload->datalen); |
730 | if (IS_ERR(new_epayload)) { | 876 | if (IS_ERR(new_epayload)) { |
731 | ret = PTR_ERR(new_epayload); | 877 | ret = PTR_ERR(new_epayload); |
732 | goto out; | 878 | goto out; |
733 | } | 879 | } |
734 | 880 | ||
735 | __ekey_init(new_epayload, new_master_desc, epayload->datalen); | 881 | __ekey_init(new_epayload, epayload->format, new_master_desc, |
882 | epayload->datalen); | ||
736 | 883 | ||
737 | memcpy(new_epayload->iv, epayload->iv, ivsize); | 884 | memcpy(new_epayload->iv, epayload->iv, ivsize); |
738 | memcpy(new_epayload->decrypted_data, epayload->decrypted_data, | 885 | memcpy(new_epayload->payload_data, epayload->payload_data, |
739 | epayload->decrypted_datalen); | 886 | epayload->payload_datalen); |
740 | 887 | ||
741 | rcu_assign_pointer(key->payload.data, new_epayload); | 888 | rcu_assign_pointer(key->payload.data, new_epayload); |
742 | call_rcu(&epayload->rcu, encrypted_rcu_free); | 889 | call_rcu(&epayload->rcu, encrypted_rcu_free); |
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c index 6cff37529b80..60d4e3f5e4bb 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c | |||
@@ -251,6 +251,8 @@ struct key *key_get_instantiation_authkey(key_serial_t target_id) | |||
251 | 251 | ||
252 | if (IS_ERR(authkey_ref)) { | 252 | if (IS_ERR(authkey_ref)) { |
253 | authkey = ERR_CAST(authkey_ref); | 253 | authkey = ERR_CAST(authkey_ref); |
254 | if (authkey == ERR_PTR(-EAGAIN)) | ||
255 | authkey = ERR_PTR(-ENOKEY); | ||
254 | goto error; | 256 | goto error; |
255 | } | 257 | } |
256 | 258 | ||