integrity-v5.18
-----BEGIN PGP SIGNATURE----- iIoEABYIADIWIQQdXVVFGN5XqKr1Hj7LwZzRsCrn5QUCYji6mxQcem9oYXJAbGlu dXguaWJtLmNvbQAKCRDLwZzRsCrn5bbvAQDB0uFJXS+FutMZSdfoXdvoV36piSyV KNEo+sM0Ie0FTQEAtHnMZbIB2Tc5szJXaxgDbr6XbRKW4aaJonkvnYF93QQ= =ZuAU -----END PGP SIGNATURE----- Merge tag 'integrity-v5.18' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity Pull integrity subsystem updates from Mimi Zohar: "Except for extending the 'encrypted' key type to support user provided data, the rest is code cleanup, __setup() usage bug fix, and a trivial change" * tag 'integrity-v5.18' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity: MAINTAINERS: add missing security/integrity/platform_certs EVM: fix the evm= __setup handler return value KEYS: encrypted: Instantiate key with user-provided decrypted data ima: define ima_max_digest_data struct without a flexible array variable ima: rename IMA_ACTION_FLAGS to IMA_NONACTION_FLAGS ima: Return error code obtained from securityfs functions MAINTAINERS: add missing "security/integrity" directory ima: Fix trivial typos in the comments
This commit is contained in:
Коммит
7f313ff0ac
|
@ -107,12 +107,13 @@ Encrypted Keys
|
|||
--------------
|
||||
|
||||
Encrypted keys do not depend on a trust source, and are faster, as they use AES
|
||||
for encryption/decryption. New keys are created from kernel-generated random
|
||||
numbers, and are encrypted/decrypted using a specified ‘master’ key. The
|
||||
‘master’ key can either be a trusted-key or user-key type. The main disadvantage
|
||||
of encrypted keys is that if they are not rooted in a trusted key, they are only
|
||||
as secure as the user key encrypting them. The master user key should therefore
|
||||
be loaded in as secure a way as possible, preferably early in boot.
|
||||
for encryption/decryption. New keys are created either from kernel-generated
|
||||
random numbers or user-provided decrypted data, and are encrypted/decrypted
|
||||
using a specified ‘master’ key. The ‘master’ key can either be a trusted-key or
|
||||
user-key type. The main disadvantage of encrypted keys is that if they are not
|
||||
rooted in a trusted key, they are only as secure as the user key encrypting
|
||||
them. The master user key should therefore be loaded in as secure a way as
|
||||
possible, preferably early in boot.
|
||||
|
||||
|
||||
Usage
|
||||
|
@ -199,6 +200,8 @@ Usage::
|
|||
|
||||
keyctl add encrypted name "new [format] key-type:master-key-name keylen"
|
||||
ring
|
||||
keyctl add encrypted name "new [format] key-type:master-key-name keylen
|
||||
decrypted-data" ring
|
||||
keyctl add encrypted name "load hex_blob" ring
|
||||
keyctl update keyid "update key-type:master-key-name"
|
||||
|
||||
|
@ -303,6 +306,16 @@ Load an encrypted key "evm" from saved blob::
|
|||
82dbbc55be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e0
|
||||
24717c64 5972dcb82ab2dde83376d82b2e3c09ffc
|
||||
|
||||
Instantiate an encrypted key "evm" using user-provided decrypted data::
|
||||
|
||||
$ keyctl add encrypted evm "new default user:kmk 32 `cat evm_decrypted_data.blob`" @u
|
||||
794890253
|
||||
|
||||
$ keyctl print 794890253
|
||||
default user:kmk 32 2375725ad57798846a9bbd240de8906f006e66c03af53b1b382d
|
||||
bbc55be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e0247
|
||||
17c64 5972dcb82ab2dde83376d82b2e3c09ffc
|
||||
|
||||
Other uses for trusted and encrypted keys, such as for disk and file encryption
|
||||
are anticipated. In particular the new format 'ecryptfs' has been defined
|
||||
in order to use encrypted keys to mount an eCryptfs filesystem. More details
|
||||
|
|
11
MAINTAINERS
11
MAINTAINERS
|
@ -7280,7 +7280,9 @@ Extended Verification Module (EVM)
|
|||
M: Mimi Zohar <zohar@linux.ibm.com>
|
||||
L: linux-integrity@vger.kernel.org
|
||||
S: Supported
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity.git
|
||||
F: security/integrity/evm/
|
||||
F: security/integrity/
|
||||
|
||||
EXTENSIBLE FIRMWARE INTERFACE (EFI)
|
||||
M: Ard Biesheuvel <ardb@kernel.org>
|
||||
|
@ -9537,6 +9539,7 @@ L: linux-integrity@vger.kernel.org
|
|||
S: Supported
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity.git
|
||||
F: security/integrity/ima/
|
||||
F: security/integrity/
|
||||
|
||||
INTEL 810/815 FRAMEBUFFER DRIVER
|
||||
M: Antonino Daplas <adaplas@gmail.com>
|
||||
|
@ -10675,6 +10678,14 @@ F: include/linux/keyctl.h
|
|||
F: include/uapi/linux/keyctl.h
|
||||
F: security/keys/
|
||||
|
||||
KEYS/KEYRINGS_INTEGRITY
|
||||
M: Jarkko Sakkinen <jarkko@kernel.org>
|
||||
M: Mimi Zohar <zohar@linux.ibm.com>
|
||||
L: linux-integrity@vger.kernel.org
|
||||
L: keyrings@vger.kernel.org
|
||||
S: Supported
|
||||
F: security/integrity/platform_certs
|
||||
|
||||
KFENCE
|
||||
M: Alexander Potapenko <glider@google.com>
|
||||
M: Marco Elver <elver@google.com>
|
||||
|
|
|
@ -86,7 +86,7 @@ static int __init evm_set_fixmode(char *str)
|
|||
else
|
||||
pr_err("invalid \"%s\" mode", str);
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
__setup("evm=", evm_set_fixmode);
|
||||
|
||||
|
|
|
@ -217,14 +217,11 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
|
|||
const char *audit_cause = "failed";
|
||||
struct inode *inode = file_inode(file);
|
||||
const char *filename = file->f_path.dentry->d_name.name;
|
||||
struct ima_max_digest_data hash;
|
||||
int result = 0;
|
||||
int length;
|
||||
void *tmpbuf;
|
||||
u64 i_version;
|
||||
struct {
|
||||
struct ima_digest_data hdr;
|
||||
char digest[IMA_MAX_DIGEST_SIZE];
|
||||
} hash;
|
||||
|
||||
/*
|
||||
* Always collect the modsig, because IMA might have already collected
|
||||
|
@ -238,9 +235,10 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
|
|||
goto out;
|
||||
|
||||
/*
|
||||
* Dectecting file change is based on i_version. On filesystems
|
||||
* which do not support i_version, support is limited to an initial
|
||||
* measurement/appraisal/audit.
|
||||
* Detecting file change is based on i_version. On filesystems
|
||||
* which do not support i_version, support was originally limited
|
||||
* to an initial measurement/appraisal/audit, but was modified to
|
||||
* assume the file changed.
|
||||
*/
|
||||
i_version = inode_query_iversion(inode);
|
||||
hash.hdr.algo = algo;
|
||||
|
|
|
@ -452,47 +452,61 @@ static const struct file_operations ima_measure_policy_ops = {
|
|||
|
||||
int __init ima_fs_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ima_dir = securityfs_create_dir("ima", integrity_dir);
|
||||
if (IS_ERR(ima_dir))
|
||||
return -1;
|
||||
return PTR_ERR(ima_dir);
|
||||
|
||||
ima_symlink = securityfs_create_symlink("ima", NULL, "integrity/ima",
|
||||
NULL);
|
||||
if (IS_ERR(ima_symlink))
|
||||
if (IS_ERR(ima_symlink)) {
|
||||
ret = PTR_ERR(ima_symlink);
|
||||
goto out;
|
||||
}
|
||||
|
||||
binary_runtime_measurements =
|
||||
securityfs_create_file("binary_runtime_measurements",
|
||||
S_IRUSR | S_IRGRP, ima_dir, NULL,
|
||||
&ima_measurements_ops);
|
||||
if (IS_ERR(binary_runtime_measurements))
|
||||
if (IS_ERR(binary_runtime_measurements)) {
|
||||
ret = PTR_ERR(binary_runtime_measurements);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ascii_runtime_measurements =
|
||||
securityfs_create_file("ascii_runtime_measurements",
|
||||
S_IRUSR | S_IRGRP, ima_dir, NULL,
|
||||
&ima_ascii_measurements_ops);
|
||||
if (IS_ERR(ascii_runtime_measurements))
|
||||
if (IS_ERR(ascii_runtime_measurements)) {
|
||||
ret = PTR_ERR(ascii_runtime_measurements);
|
||||
goto out;
|
||||
}
|
||||
|
||||
runtime_measurements_count =
|
||||
securityfs_create_file("runtime_measurements_count",
|
||||
S_IRUSR | S_IRGRP, ima_dir, NULL,
|
||||
&ima_measurements_count_ops);
|
||||
if (IS_ERR(runtime_measurements_count))
|
||||
if (IS_ERR(runtime_measurements_count)) {
|
||||
ret = PTR_ERR(runtime_measurements_count);
|
||||
goto out;
|
||||
}
|
||||
|
||||
violations =
|
||||
securityfs_create_file("violations", S_IRUSR | S_IRGRP,
|
||||
ima_dir, NULL, &ima_htable_violations_ops);
|
||||
if (IS_ERR(violations))
|
||||
if (IS_ERR(violations)) {
|
||||
ret = PTR_ERR(violations);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ima_policy = securityfs_create_file("policy", POLICY_FILE_FLAGS,
|
||||
ima_dir, NULL,
|
||||
&ima_measure_policy_ops);
|
||||
if (IS_ERR(ima_policy))
|
||||
if (IS_ERR(ima_policy)) {
|
||||
ret = PTR_ERR(ima_policy);
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
out:
|
||||
|
@ -503,5 +517,6 @@ out:
|
|||
securityfs_remove(binary_runtime_measurements);
|
||||
securityfs_remove(ima_symlink);
|
||||
securityfs_remove(ima_dir);
|
||||
return -1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -47,12 +47,9 @@ static int __init ima_add_boot_aggregate(void)
|
|||
struct integrity_iint_cache tmp_iint, *iint = &tmp_iint;
|
||||
struct ima_event_data event_data = { .iint = iint,
|
||||
.filename = boot_aggregate_name };
|
||||
struct ima_max_digest_data hash;
|
||||
int result = -ENOMEM;
|
||||
int violation = 0;
|
||||
struct {
|
||||
struct ima_digest_data hdr;
|
||||
char digest[TPM_MAX_DIGEST_SIZE];
|
||||
} hash;
|
||||
|
||||
memset(iint, 0, sizeof(*iint));
|
||||
memset(&hash, 0, sizeof(hash));
|
||||
|
|
|
@ -263,7 +263,7 @@ static int process_measurement(struct file *file, const struct cred *cred,
|
|||
/* reset appraisal flags if ima_inode_post_setattr was called */
|
||||
iint->flags &= ~(IMA_APPRAISE | IMA_APPRAISED |
|
||||
IMA_APPRAISE_SUBMASK | IMA_APPRAISED_SUBMASK |
|
||||
IMA_ACTION_FLAGS);
|
||||
IMA_NONACTION_FLAGS);
|
||||
|
||||
/*
|
||||
* Re-evaulate the file if either the xattr has changed or the
|
||||
|
@ -764,7 +764,7 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
|
|||
* call to ima_post_load_data().
|
||||
*
|
||||
* Callers of this LSM hook can not measure, appraise, or audit the
|
||||
* data provided by userspace. Enforce policy rules requring a file
|
||||
* data provided by userspace. Enforce policy rules requiring a file
|
||||
* signature (eg. kexec'ed kernel image).
|
||||
*
|
||||
* For permission return 0, otherwise return -EACCES.
|
||||
|
@ -874,10 +874,7 @@ int process_buffer_measurement(struct user_namespace *mnt_userns,
|
|||
.buf = buf,
|
||||
.buf_len = size};
|
||||
struct ima_template_desc *template;
|
||||
struct {
|
||||
struct ima_digest_data hdr;
|
||||
char digest[IMA_MAX_DIGEST_SIZE];
|
||||
} hash = {};
|
||||
struct ima_max_digest_data hash;
|
||||
char digest_hash[IMA_MAX_DIGEST_SIZE];
|
||||
int digest_hash_len = hash_digest_size[ima_hash_algo];
|
||||
int violation = 0;
|
||||
|
|
|
@ -428,7 +428,7 @@ static int ima_lsm_update_rule(struct ima_rule_entry *entry)
|
|||
/*
|
||||
* ima_lsm_copy_rule() shallow copied all references, except for the
|
||||
* LSM references, from entry to nentry so we only want to free the LSM
|
||||
* references and the entry itself. All other memory refrences will now
|
||||
* references and the entry itself. All other memory references will now
|
||||
* be owned by nentry.
|
||||
*/
|
||||
ima_lsm_free_rule(entry);
|
||||
|
@ -711,7 +711,7 @@ int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode,
|
|||
func, mask, func_data))
|
||||
continue;
|
||||
|
||||
action |= entry->flags & IMA_ACTION_FLAGS;
|
||||
action |= entry->flags & IMA_NONACTION_FLAGS;
|
||||
|
||||
action |= entry->action & IMA_DO_MASK;
|
||||
if (entry->action & IMA_APPRAISE) {
|
||||
|
|
|
@ -272,7 +272,7 @@ static int ima_eventdigest_init_common(const u8 *digest, u32 digestsize,
|
|||
* digest formats:
|
||||
* - DATA_FMT_DIGEST: digest
|
||||
* - DATA_FMT_DIGEST_WITH_ALGO: [<hash algo>] + ':' + '\0' + digest,
|
||||
* where <hash algo> is provided if the hash algoritm is not
|
||||
* where <hash algo> is provided if the hash algorithm is not
|
||||
* SHA1 or MD5
|
||||
*/
|
||||
u8 buffer[CRYPTO_MAX_ALG_NAME + 2 + IMA_MAX_DIGEST_SIZE] = { 0 };
|
||||
|
@ -307,10 +307,7 @@ static int ima_eventdigest_init_common(const u8 *digest, u32 digestsize,
|
|||
int ima_eventdigest_init(struct ima_event_data *event_data,
|
||||
struct ima_field_data *field_data)
|
||||
{
|
||||
struct {
|
||||
struct ima_digest_data hdr;
|
||||
char digest[IMA_MAX_DIGEST_SIZE];
|
||||
} hash;
|
||||
struct ima_max_digest_data hash;
|
||||
u8 *cur_digest = NULL;
|
||||
u32 cur_digestsize = 0;
|
||||
struct inode *inode;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/types.h>
|
||||
#include <linux/integrity.h>
|
||||
#include <crypto/sha1.h>
|
||||
#include <crypto/hash.h>
|
||||
#include <linux/key.h>
|
||||
#include <linux/audit.h>
|
||||
|
||||
|
@ -30,8 +31,8 @@
|
|||
#define IMA_HASH 0x00000100
|
||||
#define IMA_HASHED 0x00000200
|
||||
|
||||
/* iint cache flags */
|
||||
#define IMA_ACTION_FLAGS 0xff000000
|
||||
/* iint policy rule cache flags */
|
||||
#define IMA_NONACTION_FLAGS 0xff000000
|
||||
#define IMA_DIGSIG_REQUIRED 0x01000000
|
||||
#define IMA_PERMIT_DIRECTIO 0x02000000
|
||||
#define IMA_NEW_FILE 0x04000000
|
||||
|
@ -110,6 +111,15 @@ struct ima_digest_data {
|
|||
u8 digest[];
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* Instead of wrapping the ima_digest_data struct inside a local structure
|
||||
* with the maximum hash size, define ima_max_digest_data struct.
|
||||
*/
|
||||
struct ima_max_digest_data {
|
||||
struct ima_digest_data hdr;
|
||||
u8 digest[HASH_MAX_DIGESTSIZE];
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* signature format v2 - for using with asymmetric keys
|
||||
*/
|
||||
|
|
|
@ -98,10 +98,21 @@ config ENCRYPTED_KEYS
|
|||
select CRYPTO_RNG
|
||||
help
|
||||
This option provides support for create/encrypting/decrypting keys
|
||||
in the kernel. Encrypted keys are kernel generated random numbers,
|
||||
which are encrypted/decrypted with a 'master' symmetric key. The
|
||||
'master' key can be either a trusted-key or user-key type.
|
||||
Userspace only ever sees/stores encrypted blobs.
|
||||
in the kernel. Encrypted keys are instantiated using kernel
|
||||
generated random numbers or provided decrypted data, and are
|
||||
encrypted/decrypted with a 'master' symmetric key. The 'master'
|
||||
key can be either a trusted-key or user-key type. Only encrypted
|
||||
blobs are ever output to Userspace.
|
||||
|
||||
If you are unsure as to whether this is required, answer N.
|
||||
|
||||
config USER_DECRYPTED_DATA
|
||||
bool "Allow encrypted keys with user decrypted data"
|
||||
depends on ENCRYPTED_KEYS
|
||||
help
|
||||
This option provides support for instantiating encrypted keys using
|
||||
user-provided decrypted data. The decrypted data must be hex-ascii
|
||||
encoded.
|
||||
|
||||
If you are unsure as to whether this is required, answer N.
|
||||
|
||||
|
|
|
@ -78,6 +78,11 @@ static const match_table_t key_tokens = {
|
|||
{Opt_err, NULL}
|
||||
};
|
||||
|
||||
static bool user_decrypted_data = IS_ENABLED(CONFIG_USER_DECRYPTED_DATA);
|
||||
module_param(user_decrypted_data, bool, 0);
|
||||
MODULE_PARM_DESC(user_decrypted_data,
|
||||
"Allow instantiation of encrypted keys using provided decrypted data");
|
||||
|
||||
static int aes_get_sizes(void)
|
||||
{
|
||||
struct crypto_skcipher *tfm;
|
||||
|
@ -158,7 +163,7 @@ static int valid_master_desc(const char *new_desc, const char *orig_desc)
|
|||
* datablob_parse - parse the keyctl data
|
||||
*
|
||||
* datablob format:
|
||||
* new [<format>] <master-key name> <decrypted data length>
|
||||
* new [<format>] <master-key name> <decrypted data length> [<decrypted data>]
|
||||
* load [<format>] <master-key name> <decrypted data length>
|
||||
* <encrypted iv + data>
|
||||
* update <new-master-key name>
|
||||
|
@ -170,7 +175,7 @@ static int valid_master_desc(const char *new_desc, const char *orig_desc)
|
|||
*/
|
||||
static int datablob_parse(char *datablob, const char **format,
|
||||
char **master_desc, char **decrypted_datalen,
|
||||
char **hex_encoded_iv)
|
||||
char **hex_encoded_iv, char **decrypted_data)
|
||||
{
|
||||
substring_t args[MAX_OPT_ARGS];
|
||||
int ret = -EINVAL;
|
||||
|
@ -231,6 +236,7 @@ static int datablob_parse(char *datablob, const char **format,
|
|||
"when called from .update method\n", keyword);
|
||||
break;
|
||||
}
|
||||
*decrypted_data = strsep(&datablob, " \t");
|
||||
ret = 0;
|
||||
break;
|
||||
case Opt_load:
|
||||
|
@ -595,7 +601,8 @@ out:
|
|||
static struct encrypted_key_payload *encrypted_key_alloc(struct key *key,
|
||||
const char *format,
|
||||
const char *master_desc,
|
||||
const char *datalen)
|
||||
const char *datalen,
|
||||
const char *decrypted_data)
|
||||
{
|
||||
struct encrypted_key_payload *epayload = NULL;
|
||||
unsigned short datablob_len;
|
||||
|
@ -604,6 +611,7 @@ static struct encrypted_key_payload *encrypted_key_alloc(struct key *key,
|
|||
unsigned int encrypted_datalen;
|
||||
unsigned int format_len;
|
||||
long dlen;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
ret = kstrtol(datalen, 10, &dlen);
|
||||
|
@ -613,6 +621,24 @@ 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 (decrypted_data) {
|
||||
if (!user_decrypted_data) {
|
||||
pr_err("encrypted key: instantiation of keys using provided decrypted data is disabled since CONFIG_USER_DECRYPTED_DATA is set to false\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
if (strlen(decrypted_data) != decrypted_datalen) {
|
||||
pr_err("encrypted key: decrypted data provided does not match decrypted data length provided\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
for (i = 0; i < strlen(decrypted_data); i++) {
|
||||
if (!isxdigit(decrypted_data[i])) {
|
||||
pr_err("encrypted key: decrypted data provided must contain only hexadecimal characters\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (format) {
|
||||
if (!strcmp(format, key_format_ecryptfs)) {
|
||||
if (dlen != ECRYPTFS_MAX_KEY_BYTES) {
|
||||
|
@ -740,13 +766,14 @@ static void __ekey_init(struct encrypted_key_payload *epayload,
|
|||
/*
|
||||
* encrypted_init - initialize an encrypted key
|
||||
*
|
||||
* For a new key, use a random number for both the iv and data
|
||||
* itself. For an old key, decrypt the hex encoded data.
|
||||
* For a new key, use either a random number or user-provided decrypted data in
|
||||
* case it is provided. A random number is used for the iv in both cases. For
|
||||
* an old key, decrypt the hex encoded data.
|
||||
*/
|
||||
static int encrypted_init(struct encrypted_key_payload *epayload,
|
||||
const char *key_desc, const char *format,
|
||||
const char *master_desc, const char *datalen,
|
||||
const char *hex_encoded_iv)
|
||||
const char *hex_encoded_iv, const char *decrypted_data)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
|
@ -760,21 +787,26 @@ static int encrypted_init(struct encrypted_key_payload *epayload,
|
|||
}
|
||||
|
||||
__ekey_init(epayload, format, master_desc, datalen);
|
||||
if (!hex_encoded_iv) {
|
||||
get_random_bytes(epayload->iv, ivsize);
|
||||
|
||||
get_random_bytes(epayload->decrypted_data,
|
||||
epayload->decrypted_datalen);
|
||||
} else
|
||||
if (hex_encoded_iv) {
|
||||
ret = encrypted_key_decrypt(epayload, format, hex_encoded_iv);
|
||||
} else if (decrypted_data) {
|
||||
get_random_bytes(epayload->iv, ivsize);
|
||||
memcpy(epayload->decrypted_data, decrypted_data,
|
||||
epayload->decrypted_datalen);
|
||||
} else {
|
||||
get_random_bytes(epayload->iv, ivsize);
|
||||
get_random_bytes(epayload->decrypted_data, epayload->decrypted_datalen);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* encrypted_instantiate - instantiate an encrypted key
|
||||
*
|
||||
* Decrypt an existing encrypted datablob or create a new encrypted key
|
||||
* based on a kernel random number.
|
||||
* Instantiates the key:
|
||||
* - by decrypting an existing encrypted datablob, or
|
||||
* - by creating a new encrypted key based on a kernel random number, or
|
||||
* - using provided decrypted data.
|
||||
*
|
||||
* On success, return 0. Otherwise return errno.
|
||||
*/
|
||||
|
@ -787,6 +819,7 @@ static int encrypted_instantiate(struct key *key,
|
|||
char *master_desc = NULL;
|
||||
char *decrypted_datalen = NULL;
|
||||
char *hex_encoded_iv = NULL;
|
||||
char *decrypted_data = NULL;
|
||||
size_t datalen = prep->datalen;
|
||||
int ret;
|
||||
|
||||
|
@ -799,18 +832,18 @@ static int encrypted_instantiate(struct key *key,
|
|||
datablob[datalen] = 0;
|
||||
memcpy(datablob, prep->data, datalen);
|
||||
ret = datablob_parse(datablob, &format, &master_desc,
|
||||
&decrypted_datalen, &hex_encoded_iv);
|
||||
&decrypted_datalen, &hex_encoded_iv, &decrypted_data);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
epayload = encrypted_key_alloc(key, format, master_desc,
|
||||
decrypted_datalen);
|
||||
decrypted_datalen, decrypted_data);
|
||||
if (IS_ERR(epayload)) {
|
||||
ret = PTR_ERR(epayload);
|
||||
goto out;
|
||||
}
|
||||
ret = encrypted_init(epayload, key->description, format, master_desc,
|
||||
decrypted_datalen, hex_encoded_iv);
|
||||
decrypted_datalen, hex_encoded_iv, decrypted_data);
|
||||
if (ret < 0) {
|
||||
kfree_sensitive(epayload);
|
||||
goto out;
|
||||
|
@ -860,7 +893,7 @@ static int encrypted_update(struct key *key, struct key_preparsed_payload *prep)
|
|||
|
||||
buf[datalen] = 0;
|
||||
memcpy(buf, prep->data, datalen);
|
||||
ret = datablob_parse(buf, &format, &new_master_desc, NULL, NULL);
|
||||
ret = datablob_parse(buf, &format, &new_master_desc, NULL, NULL, NULL);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
|
@ -869,7 +902,7 @@ static int encrypted_update(struct key *key, struct key_preparsed_payload *prep)
|
|||
goto out;
|
||||
|
||||
new_epayload = encrypted_key_alloc(key, epayload->format,
|
||||
new_master_desc, epayload->datalen);
|
||||
new_master_desc, epayload->datalen, NULL);
|
||||
if (IS_ERR(new_epayload)) {
|
||||
ret = PTR_ERR(new_epayload);
|
||||
goto out;
|
||||
|
|
Загрузка…
Ссылка в новой задаче