Skip to content

Commit cd3bc04

Browse files
yaeltzurmimizohar
authored andcommitted
KEYS: encrypted: Instantiate key with user-provided decrypted data
For availability and performance reasons master keys often need to be released outside of a Key Management Service (KMS) to clients. It would be beneficial to provide a mechanism where the wrapping/unwrapping of data encryption keys (DEKs) is not dependent on a remote call at runtime yet security is not (or only minimally) compromised. Master keys could be securely stored in the Kernel and be used to wrap/unwrap keys from Userspace. The encrypted.c class supports instantiation of encrypted keys with either an already-encrypted key material, or by generating new key material based on random numbers. This patch defines a new datablob format: [<format>] <master-key name> <decrypted data length> <decrypted data> that allows to inject and encrypt user-provided decrypted data. The decrypted data must be hex-ascii encoded. Signed-off-by: Yael Tzur <yaelt@google.com> Reviewed-by: Mimi Zohar <zohar@linux.ibm.com> Reviewed-by: Sumit Garg <sumit.garg@linaro.org> Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org> Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
1 parent 8c54135 commit cd3bc04

3 files changed

Lines changed: 86 additions & 29 deletions

File tree

Documentation/security/keys/trusted-encrypted.rst

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,13 @@ Encrypted Keys
107107
--------------
108108

109109
Encrypted keys do not depend on a trust source, and are faster, as they use AES
110-
for encryption/decryption. New keys are created from kernel-generated random
111-
numbers, and are encrypted/decrypted using a specified ‘master’ key. The
112-
‘master’ key can either be a trusted-key or user-key type. The main disadvantage
113-
of encrypted keys is that if they are not rooted in a trusted key, they are only
114-
as secure as the user key encrypting them. The master user key should therefore
115-
be loaded in as secure a way as possible, preferably early in boot.
110+
for encryption/decryption. New keys are created either from kernel-generated
111+
random numbers or user-provided decrypted data, and are encrypted/decrypted
112+
using a specified ‘master’ key. The ‘master’ key can either be a trusted-key or
113+
user-key type. The main disadvantage of encrypted keys is that if they are not
114+
rooted in a trusted key, they are only as secure as the user key encrypting
115+
them. The master user key should therefore be loaded in as secure a way as
116+
possible, preferably early in boot.
116117

117118

118119
Usage
@@ -199,6 +200,8 @@ Usage::
199200

200201
keyctl add encrypted name "new [format] key-type:master-key-name keylen"
201202
ring
203+
keyctl add encrypted name "new [format] key-type:master-key-name keylen
204+
decrypted-data" ring
202205
keyctl add encrypted name "load hex_blob" ring
203206
keyctl update keyid "update key-type:master-key-name"
204207

@@ -303,6 +306,16 @@ Load an encrypted key "evm" from saved blob::
303306
82dbbc55be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e0
304307
24717c64 5972dcb82ab2dde83376d82b2e3c09ffc
305308

309+
Instantiate an encrypted key "evm" using user-provided decrypted data::
310+
311+
$ keyctl add encrypted evm "new default user:kmk 32 `cat evm_decrypted_data.blob`" @u
312+
794890253
313+
314+
$ keyctl print 794890253
315+
default user:kmk 32 2375725ad57798846a9bbd240de8906f006e66c03af53b1b382d
316+
bbc55be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e0247
317+
17c64 5972dcb82ab2dde83376d82b2e3c09ffc
318+
306319
Other uses for trusted and encrypted keys, such as for disk and file encryption
307320
are anticipated. In particular the new format 'ecryptfs' has been defined
308321
in order to use encrypted keys to mount an eCryptfs filesystem. More details

security/keys/Kconfig

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,21 @@ config ENCRYPTED_KEYS
9898
select CRYPTO_RNG
9999
help
100100
This option provides support for create/encrypting/decrypting keys
101-
in the kernel. Encrypted keys are kernel generated random numbers,
102-
which are encrypted/decrypted with a 'master' symmetric key. The
103-
'master' key can be either a trusted-key or user-key type.
104-
Userspace only ever sees/stores encrypted blobs.
101+
in the kernel. Encrypted keys are instantiated using kernel
102+
generated random numbers or provided decrypted data, and are
103+
encrypted/decrypted with a 'master' symmetric key. The 'master'
104+
key can be either a trusted-key or user-key type. Only encrypted
105+
blobs are ever output to Userspace.
106+
107+
If you are unsure as to whether this is required, answer N.
108+
109+
config USER_DECRYPTED_DATA
110+
bool "Allow encrypted keys with user decrypted data"
111+
depends on ENCRYPTED_KEYS
112+
help
113+
This option provides support for instantiating encrypted keys using
114+
user-provided decrypted data. The decrypted data must be hex-ascii
115+
encoded.
105116

106117
If you are unsure as to whether this is required, answer N.
107118

security/keys/encrypted-keys/encrypted.c

Lines changed: 52 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@ static const match_table_t key_tokens = {
7878
{Opt_err, NULL}
7979
};
8080

81+
static bool user_decrypted_data = IS_ENABLED(CONFIG_USER_DECRYPTED_DATA);
82+
module_param(user_decrypted_data, bool, 0);
83+
MODULE_PARM_DESC(user_decrypted_data,
84+
"Allow instantiation of encrypted keys using provided decrypted data");
85+
8186
static int aes_get_sizes(void)
8287
{
8388
struct crypto_skcipher *tfm;
@@ -158,7 +163,7 @@ static int valid_master_desc(const char *new_desc, const char *orig_desc)
158163
* datablob_parse - parse the keyctl data
159164
*
160165
* datablob format:
161-
* new [<format>] <master-key name> <decrypted data length>
166+
* new [<format>] <master-key name> <decrypted data length> [<decrypted data>]
162167
* load [<format>] <master-key name> <decrypted data length>
163168
* <encrypted iv + data>
164169
* update <new-master-key name>
@@ -170,7 +175,7 @@ static int valid_master_desc(const char *new_desc, const char *orig_desc)
170175
*/
171176
static int datablob_parse(char *datablob, const char **format,
172177
char **master_desc, char **decrypted_datalen,
173-
char **hex_encoded_iv)
178+
char **hex_encoded_iv, char **decrypted_data)
174179
{
175180
substring_t args[MAX_OPT_ARGS];
176181
int ret = -EINVAL;
@@ -231,6 +236,7 @@ static int datablob_parse(char *datablob, const char **format,
231236
"when called from .update method\n", keyword);
232237
break;
233238
}
239+
*decrypted_data = strsep(&datablob, " \t");
234240
ret = 0;
235241
break;
236242
case Opt_load:
@@ -595,7 +601,8 @@ static int derived_key_decrypt(struct encrypted_key_payload *epayload,
595601
static struct encrypted_key_payload *encrypted_key_alloc(struct key *key,
596602
const char *format,
597603
const char *master_desc,
598-
const char *datalen)
604+
const char *datalen,
605+
const char *decrypted_data)
599606
{
600607
struct encrypted_key_payload *epayload = NULL;
601608
unsigned short datablob_len;
@@ -604,6 +611,7 @@ static struct encrypted_key_payload *encrypted_key_alloc(struct key *key,
604611
unsigned int encrypted_datalen;
605612
unsigned int format_len;
606613
long dlen;
614+
int i;
607615
int ret;
608616

609617
ret = kstrtol(datalen, 10, &dlen);
@@ -613,6 +621,24 @@ static struct encrypted_key_payload *encrypted_key_alloc(struct key *key,
613621
format_len = (!format) ? strlen(key_format_default) : strlen(format);
614622
decrypted_datalen = dlen;
615623
payload_datalen = decrypted_datalen;
624+
625+
if (decrypted_data) {
626+
if (!user_decrypted_data) {
627+
pr_err("encrypted key: instantiation of keys using provided decrypted data is disabled since CONFIG_USER_DECRYPTED_DATA is set to false\n");
628+
return ERR_PTR(-EINVAL);
629+
}
630+
if (strlen(decrypted_data) != decrypted_datalen) {
631+
pr_err("encrypted key: decrypted data provided does not match decrypted data length provided\n");
632+
return ERR_PTR(-EINVAL);
633+
}
634+
for (i = 0; i < strlen(decrypted_data); i++) {
635+
if (!isxdigit(decrypted_data[i])) {
636+
pr_err("encrypted key: decrypted data provided must contain only hexadecimal characters\n");
637+
return ERR_PTR(-EINVAL);
638+
}
639+
}
640+
}
641+
616642
if (format) {
617643
if (!strcmp(format, key_format_ecryptfs)) {
618644
if (dlen != ECRYPTFS_MAX_KEY_BYTES) {
@@ -740,13 +766,14 @@ static void __ekey_init(struct encrypted_key_payload *epayload,
740766
/*
741767
* encrypted_init - initialize an encrypted key
742768
*
743-
* For a new key, use a random number for both the iv and data
744-
* itself. For an old key, decrypt the hex encoded data.
769+
* For a new key, use either a random number or user-provided decrypted data in
770+
* case it is provided. A random number is used for the iv in both cases. For
771+
* an old key, decrypt the hex encoded data.
745772
*/
746773
static int encrypted_init(struct encrypted_key_payload *epayload,
747774
const char *key_desc, const char *format,
748775
const char *master_desc, const char *datalen,
749-
const char *hex_encoded_iv)
776+
const char *hex_encoded_iv, const char *decrypted_data)
750777
{
751778
int ret = 0;
752779

@@ -760,21 +787,26 @@ static int encrypted_init(struct encrypted_key_payload *epayload,
760787
}
761788

762789
__ekey_init(epayload, format, master_desc, datalen);
763-
if (!hex_encoded_iv) {
764-
get_random_bytes(epayload->iv, ivsize);
765-
766-
get_random_bytes(epayload->decrypted_data,
767-
epayload->decrypted_datalen);
768-
} else
790+
if (hex_encoded_iv) {
769791
ret = encrypted_key_decrypt(epayload, format, hex_encoded_iv);
792+
} else if (decrypted_data) {
793+
get_random_bytes(epayload->iv, ivsize);
794+
memcpy(epayload->decrypted_data, decrypted_data,
795+
epayload->decrypted_datalen);
796+
} else {
797+
get_random_bytes(epayload->iv, ivsize);
798+
get_random_bytes(epayload->decrypted_data, epayload->decrypted_datalen);
799+
}
770800
return ret;
771801
}
772802

773803
/*
774804
* encrypted_instantiate - instantiate an encrypted key
775805
*
776-
* Decrypt an existing encrypted datablob or create a new encrypted key
777-
* based on a kernel random number.
806+
* Instantiates the key:
807+
* - by decrypting an existing encrypted datablob, or
808+
* - by creating a new encrypted key based on a kernel random number, or
809+
* - using provided decrypted data.
778810
*
779811
* On success, return 0. Otherwise return errno.
780812
*/
@@ -787,6 +819,7 @@ static int encrypted_instantiate(struct key *key,
787819
char *master_desc = NULL;
788820
char *decrypted_datalen = NULL;
789821
char *hex_encoded_iv = NULL;
822+
char *decrypted_data = NULL;
790823
size_t datalen = prep->datalen;
791824
int ret;
792825

@@ -799,18 +832,18 @@ static int encrypted_instantiate(struct key *key,
799832
datablob[datalen] = 0;
800833
memcpy(datablob, prep->data, datalen);
801834
ret = datablob_parse(datablob, &format, &master_desc,
802-
&decrypted_datalen, &hex_encoded_iv);
835+
&decrypted_datalen, &hex_encoded_iv, &decrypted_data);
803836
if (ret < 0)
804837
goto out;
805838

806839
epayload = encrypted_key_alloc(key, format, master_desc,
807-
decrypted_datalen);
840+
decrypted_datalen, decrypted_data);
808841
if (IS_ERR(epayload)) {
809842
ret = PTR_ERR(epayload);
810843
goto out;
811844
}
812845
ret = encrypted_init(epayload, key->description, format, master_desc,
813-
decrypted_datalen, hex_encoded_iv);
846+
decrypted_datalen, hex_encoded_iv, decrypted_data);
814847
if (ret < 0) {
815848
kfree_sensitive(epayload);
816849
goto out;
@@ -860,7 +893,7 @@ static int encrypted_update(struct key *key, struct key_preparsed_payload *prep)
860893

861894
buf[datalen] = 0;
862895
memcpy(buf, prep->data, datalen);
863-
ret = datablob_parse(buf, &format, &new_master_desc, NULL, NULL);
896+
ret = datablob_parse(buf, &format, &new_master_desc, NULL, NULL, NULL);
864897
if (ret < 0)
865898
goto out;
866899

@@ -869,7 +902,7 @@ static int encrypted_update(struct key *key, struct key_preparsed_payload *prep)
869902
goto out;
870903

871904
new_epayload = encrypted_key_alloc(key, epayload->format,
872-
new_master_desc, epayload->datalen);
905+
new_master_desc, epayload->datalen, NULL);
873906
if (IS_ERR(new_epayload)) {
874907
ret = PTR_ERR(new_epayload);
875908
goto out;

0 commit comments

Comments
 (0)