aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys/encrypted.c
diff options
context:
space:
mode:
authorRoberto Sassu <roberto.sassu@polito.it>2011-06-27 13:45:44 +0200
committerMimi Zohar <zohar@linux.vnet.ibm.com>2011-06-27 09:11:17 -0400
commit79a73d188726b473ca3bf483244bc96096831905 (patch)
tree787ba050c91981cae2524b1e95e415424b067e64 /security/keys/encrypted.c
parenteCryptfs: export global eCryptfs definitions to include/linux/ecryptfs.h (diff)
downloadlinux-dev-79a73d188726b473ca3bf483244bc96096831905.tar.xz
linux-dev-79a73d188726b473ca3bf483244bc96096831905.zip
encrypted-keys: add ecryptfs format support
The 'encrypted' key type defines its own payload format which contains a symmetric key randomly generated that cannot be used directly to mount an eCryptfs filesystem, because it expects an authentication token structure. This patch introduces the new format 'ecryptfs' that allows to store an authentication token structure inside the encrypted key payload containing a randomly generated symmetric key, as the same for the format 'default'. More details about the usage of encrypted keys with the eCryptfs filesystem can be found in the file 'Documentation/keys-ecryptfs.txt'. Signed-off-by: Roberto Sassu <roberto.sassu@polito.it> Acked-by: Gianluca Ramunno <ramunno@polito.it> Acked-by: Tyler Hicks <tyhicks@linux.vnet.ibm.com> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
Diffstat (limited to 'security/keys/encrypted.c')
-rw-r--r--security/keys/encrypted.c75
1 files changed, 68 insertions, 7 deletions
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 @@
#include <linux/rcupdate.h>
#include <linux/scatterlist.h>
#include <linux/crypto.h>
+#include <linux/ctype.h>
#include <crypto/hash.h>
#include <crypto/sha.h>
#include <crypto/aes.h>
#include "encrypted.h"
+#include "ecryptfs_format.h"
static const char KEY_TRUSTED_PREFIX[] = "trusted:";
static const char KEY_USER_PREFIX[] = "user:";
@@ -41,11 +43,13 @@ static const char hash_alg[] = "sha256";
static const char hmac_alg[] = "hmac(sha256)";
static const char blkcipher_alg[] = "cbc(aes)";
static const char key_format_default[] = "default";
+static const char key_format_ecryptfs[] = "ecryptfs";
static unsigned int ivsize;
static int blksize;
#define KEY_TRUSTED_PREFIX_LEN (sizeof (KEY_TRUSTED_PREFIX) - 1)
#define KEY_USER_PREFIX_LEN (sizeof (KEY_USER_PREFIX) - 1)
+#define KEY_ECRYPTFS_DESC_LEN 16
#define HASH_SIZE SHA256_DIGEST_SIZE
#define MAX_DATA_SIZE 4096
#define MIN_DATA_SIZE 20
@@ -63,11 +67,12 @@ enum {
};
enum {
- Opt_error = -1, Opt_default
+ Opt_error = -1, Opt_default, Opt_ecryptfs
};
static const match_table_t key_format_tokens = {
{Opt_default, "default"},
+ {Opt_ecryptfs, "ecryptfs"},
{Opt_error, NULL}
};
@@ -95,6 +100,34 @@ static int aes_get_sizes(void)
}
/*
+ * valid_ecryptfs_desc - verify the description of a new/loaded encrypted key
+ *
+ * The description of a encrypted key with format 'ecryptfs' must contain
+ * exactly 16 hexadecimal characters.
+ *
+ */
+static int valid_ecryptfs_desc(const char *ecryptfs_desc)
+{
+ int i;
+
+ if (strlen(ecryptfs_desc) != KEY_ECRYPTFS_DESC_LEN) {
+ pr_err("encrypted_key: key description must be %d hexadecimal "
+ "characters long\n", KEY_ECRYPTFS_DESC_LEN);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < KEY_ECRYPTFS_DESC_LEN; i++) {
+ if (!isxdigit(ecryptfs_desc[i])) {
+ pr_err("encrypted_key: key description must contain "
+ "only hexadecimal characters\n");
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+/*
* valid_master_desc - verify the 'key-type:desc' of a new/updated master-key
*
* key-type:= "trusted:" | "user:"
@@ -158,7 +191,7 @@ static int datablob_parse(char *datablob, const char **format,
}
key_cmd = match_token(keyword, key_tokens, args);
- /* Get optional format: default */
+ /* Get optional format: default | ecryptfs */
p = strsep(&datablob, " \t");
if (!p) {
pr_err("encrypted_key: insufficient parameters specified\n");
@@ -167,6 +200,7 @@ static int datablob_parse(char *datablob, const char **format,
key_format = match_token(p, key_format_tokens, args);
switch (key_format) {
+ case Opt_ecryptfs:
case Opt_default:
*format = p;
*master_desc = strsep(&datablob, " \t");
@@ -601,6 +635,17 @@ static struct encrypted_key_payload *encrypted_key_alloc(struct key *key,
format_len = (!format) ? strlen(key_format_default) : strlen(format);
decrypted_datalen = dlen;
payload_datalen = decrypted_datalen;
+ if (format && !strcmp(format, key_format_ecryptfs)) {
+ if (dlen != ECRYPTFS_MAX_KEY_BYTES) {
+ pr_err("encrypted_key: keylen for the ecryptfs format "
+ "must be equal to %d bytes\n",
+ ECRYPTFS_MAX_KEY_BYTES);
+ return ERR_PTR(-EINVAL);
+ }
+ decrypted_datalen = ECRYPTFS_MAX_KEY_BYTES;
+ payload_datalen = sizeof(struct ecryptfs_auth_tok);
+ }
+
encrypted_datalen = roundup(decrypted_datalen, blksize);
datablob_len = format_len + 1 + strlen(master_desc) + 1
@@ -686,8 +731,14 @@ static void __ekey_init(struct encrypted_key_payload *epayload,
if (!format)
memcpy(epayload->format, key_format_default, format_len);
- else
+ else {
+ if (!strcmp(format, key_format_ecryptfs))
+ epayload->decrypted_data =
+ ecryptfs_get_auth_tok_key((struct ecryptfs_auth_tok *)epayload->payload_data);
+
memcpy(epayload->format, format, format_len);
+ }
+
memcpy(epayload->master_desc, master_desc, strlen(master_desc));
memcpy(epayload->datalen, datalen, strlen(datalen));
}
@@ -699,11 +750,21 @@ static void __ekey_init(struct encrypted_key_payload *epayload,
* itself. For an old key, decrypt the hex encoded data.
*/
static int encrypted_init(struct encrypted_key_payload *epayload,
- const char *format, const char *master_desc,
- const char *datalen, const char *hex_encoded_iv)
+ const char *key_desc, const char *format,
+ const char *master_desc, const char *datalen,
+ const char *hex_encoded_iv)
{
int ret = 0;
+ if (format && !strcmp(format, key_format_ecryptfs)) {
+ ret = valid_ecryptfs_desc(key_desc);
+ if (ret < 0)
+ return ret;
+
+ ecryptfs_fill_auth_tok((struct ecryptfs_auth_tok *)epayload->payload_data,
+ key_desc);
+ }
+
__ekey_init(epayload, format, master_desc, datalen);
if (!hex_encoded_iv) {
get_random_bytes(epayload->iv, ivsize);
@@ -753,8 +814,8 @@ static int encrypted_instantiate(struct key *key, const void *data,
ret = PTR_ERR(epayload);
goto out;
}
- ret = encrypted_init(epayload, format, master_desc, decrypted_datalen,
- hex_encoded_iv);
+ ret = encrypted_init(epayload, key->description, format, master_desc,
+ decrypted_datalen, hex_encoded_iv);
if (ret < 0) {
kfree(epayload);
goto out;