/*
* Copyright (C) 2010 IBM Corporation
* Copyright (C) 2010 Politecnico di Torino, Italy
* TORSEC group -- http://security.polito.it
*
* Authors:
* Mimi Zohar <zohar@us.ibm.com>
* Roberto Sassu <roberto.sassu@polito.it>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 2 of the License.
*
* See Documentation/security/keys-trusted-encrypted.txt
*/
#include <linux/uaccess.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/parser.h>
#include <linux/string.h>
#include <linux/err.h>
#include <keys/user-type.h>
#include <keys/trusted-type.h>
#include <keys/encrypted-type.h>
#include <linux/key-type.h>
#include <linux/random.h>
#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:";
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
struct sdesc {
struct shash_desc shash;
char ctx[];
};
static struct crypto_shash *hashalg;
static struct crypto_shash *hmacalg;
enum {
Opt_err = -1, Opt_new, Opt_load, Opt_update
};
enum {
Opt_error = -1, Opt_default, Opt_ecryptfs
};
static const match_table_t key_format_tokens = {
{Opt_default, "default"},
{Opt_ecryptfs, "ecryptfs"},
{Opt_error, NULL}
};
static const match_table_t key_tokens = {
{Opt_new, "new"},
{Opt_load, "load"},
{Opt_update, "update"},
{Opt_err, NULL}
};
static int aes_get_sizes(void)
{
struct crypto_blkcipher *tfm;
tfm = crypto_alloc_blkcipher(blkcipher_alg, 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(tfm)) {
pr_err("encrypted_key: failed to alloc_cipher (%ld)\n",
PTR_ERR(tfm));
return PTR_ERR(tfm);
}
ivsize = crypto_blkcipher_ivsize(tfm);
blksize = crypto_blkcipher_blocksize(tfm);
crypto_free_blkcipher(tfm);
return 0;
}
/*
* 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:"
* desc:= master-key description
*
* Verify that 'key-type' is valid and that 'desc' exists. On key update,
* only the master key description is permitted to change, not the key-type.
* The key-type remains constant.
*
* On success returns 0, otherwise -EINVAL.
*/
static int valid_master_desc(const char *new_desc, const char *orig_desc)
{
if (!memcmp(new_desc, KEY_TRUSTED_PREFIX, KEY_TRUSTED_PREFIX_LEN)) {
if (strlen(new_desc) == KEY_TRUSTED_PREFIX_LEN)
goto out;
if (orig_desc)
if (memcmp(new_desc, orig_desc, KEY_TRUSTED_PREFIX_LEN))
goto out;
} else if (!memcmp(new_desc, KEY_USER_PREFIX, KEY_USER_PREFIX_LEN)) {
if (strlen(new_desc) == KEY_USER_PREFIX_LEN)
goto out;
if (orig_desc)
if (memcmp(new_desc, orig_desc, KEY_USER_PREFIX_LEN))
goto out;
} else
goto out;
return 0;
out:
return -EINVAL;
}