diff options
-rw-r--r-- | fs/ecryptfs/crypto.c | 12 | ||||
-rw-r--r-- | fs/ecryptfs/debug.c | 20 | ||||
-rw-r--r-- | fs/ecryptfs/ecryptfs_kernel.h | 17 | ||||
-rw-r--r-- | fs/ecryptfs/events.c | 92 | ||||
-rw-r--r-- | fs/ecryptfs/keystore.c | 17 | ||||
-rw-r--r-- | fs/ecryptfs/main.c | 18 | ||||
-rw-r--r-- | include/linux/ecryptfs.h | 22 | ||||
-rw-r--r-- | security/pfe/pfk.c | 42 |
8 files changed, 127 insertions, 113 deletions
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index b98b786b0e9d..cf0186fd9bfe 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -470,8 +470,6 @@ out: static void init_ecryption_parameters(bool *hw_crypt, bool *cipher_supported, struct ecryptfs_crypt_stat *crypt_stat) { - unsigned char final[2*ECRYPTFS_MAX_CIPHER_NAME_SIZE+1]; - if (!hw_crypt || !cipher_supported) return; @@ -480,9 +478,7 @@ static void init_ecryption_parameters(bool *hw_crypt, bool *cipher_supported, if (get_events() && get_events()->is_cipher_supported_cb) { *cipher_supported = - get_events()->is_cipher_supported_cb( - ecryptfs_get_full_cipher(crypt_stat->cipher, - crypt_stat->cipher_mode, final, sizeof(final))); + get_events()->is_cipher_supported_cb(crypt_stat); if (*cipher_supported) { /** @@ -809,12 +805,8 @@ static void ecryptfs_generate_new_key(struct ecryptfs_crypt_stat *crypt_stat) static int ecryptfs_generate_new_salt(struct ecryptfs_crypt_stat *crypt_stat) { size_t salt_size = 0; - unsigned char final[2*ECRYPTFS_MAX_CIPHER_NAME_SIZE+1]; - salt_size = ecryptfs_get_salt_size_for_cipher( - ecryptfs_get_full_cipher(crypt_stat->cipher, - crypt_stat->cipher_mode, - final, sizeof(final))); + salt_size = ecryptfs_get_salt_size_for_cipher(crypt_stat); if (0 == salt_size) return 0; diff --git a/fs/ecryptfs/debug.c b/fs/ecryptfs/debug.c index 1276764f3716..0556af1adfb7 100644 --- a/fs/ecryptfs/debug.c +++ b/fs/ecryptfs/debug.c @@ -119,9 +119,10 @@ void ecryptfs_dump_hex(char *data, int bytes) printk("\n"); } -void ecryptfs_dump_salt_hex(char *data, int key_size, char *cipher) +void ecryptfs_dump_salt_hex(char *data, int key_size, + const struct ecryptfs_crypt_stat *crypt_stat) { - size_t salt_size = ecryptfs_get_salt_size_for_cipher(cipher); + size_t salt_size = ecryptfs_get_salt_size_for_cipher(crypt_stat); if (0 == salt_size) return; @@ -132,3 +133,18 @@ void ecryptfs_dump_salt_hex(char *data, int key_size, char *cipher) ecryptfs_printk(KERN_DEBUG, "Decrypted session salt key:\n"); ecryptfs_dump_hex(data + key_size, salt_size); } + +void ecryptfs_dump_cipher(struct ecryptfs_crypt_stat *stat) +{ + if (!stat) + return; + + if (stat->cipher) + ecryptfs_printk(KERN_DEBUG, + "ecryptfs cipher is %s\n", stat->cipher); + + if (stat->cipher_mode) + ecryptfs_printk(KERN_DEBUG, "ecryptfs cipher mode is %s\n", + stat->cipher_mode); + +} diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index f5c96ed40805..89e7aa5f178a 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -624,7 +624,10 @@ int ecryptfs_encrypt_and_encode_filename( const char *name, size_t name_size); struct dentry *ecryptfs_lower_dentry(struct dentry *this_dentry); void ecryptfs_dump_hex(char *data, int bytes); -void ecryptfs_dump_salt_hex(char *data, int key_size, char *cipher); +void ecryptfs_dump_salt_hex(char *data, int key_size, + const struct ecryptfs_crypt_stat *crypt_stat); +extern void ecryptfs_dump_cipher(struct ecryptfs_crypt_stat *stat); + int virt_to_scatterlist(const void *addr, int size, struct scatterlist *sg, int sg_size); int ecryptfs_compute_root_iv(struct ecryptfs_crypt_stat *crypt_stat); @@ -779,16 +782,20 @@ void ecryptfs_freepage(struct page *page); struct ecryptfs_events *get_events(void); -size_t ecryptfs_get_salt_size_for_cipher(const char *cipher); +size_t ecryptfs_get_salt_size_for_cipher( + const struct ecryptfs_crypt_stat *crypt_stat); + +size_t ecryptfs_get_salt_size_for_cipher_mount( + const struct ecryptfs_mount_crypt_stat *mount_crypt_stat); size_t ecryptfs_get_key_size_to_enc_data( - struct ecryptfs_crypt_stat *crypt_stat); + const struct ecryptfs_crypt_stat *crypt_stat); size_t ecryptfs_get_key_size_to_store_key( - struct ecryptfs_crypt_stat *crypt_stat); + const struct ecryptfs_crypt_stat *crypt_stat); size_t ecryptfs_get_key_size_to_restore_key(size_t stored_key_size, - const char *cipher); + const struct ecryptfs_crypt_stat *crypt_stat); bool ecryptfs_check_space_for_salt(const size_t key_size, const size_t salt_size); diff --git a/fs/ecryptfs/events.c b/fs/ecryptfs/events.c index 043ea39c4901..12e26c683cf6 100644 --- a/fs/ecryptfs/events.c +++ b/fs/ecryptfs/events.c @@ -1,6 +1,6 @@ /** * eCryptfs: Linux filesystem encryption layer - * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -42,7 +42,7 @@ void ecryptfs_free_events(void) * The function returns a handle to be passed * to unregister function. */ -int ecryptfs_register_to_events(struct ecryptfs_events *ops) +int ecryptfs_register_to_events(const struct ecryptfs_events *ops) { int ret_value = 0; @@ -115,7 +115,7 @@ out: * The caller must pass ecryptfs data, which was received in one * of the callback invocations. */ -bool ecryptfs_is_page_in_metadata(void *data, pgoff_t offset) +bool ecryptfs_is_page_in_metadata(const void *data, pgoff_t offset) { struct ecryptfs_crypt_stat *stat = NULL; @@ -145,7 +145,7 @@ end: * Given two ecryptfs data, the function * decides whether they are equal. */ -inline bool ecryptfs_is_data_equal(void *data1, void *data2) +inline bool ecryptfs_is_data_equal(const void *data1, const void *data2) { /* pointer comparison*/ return data1 == data2; @@ -155,7 +155,7 @@ inline bool ecryptfs_is_data_equal(void *data1, void *data2) * Given ecryptfs data, the function * returns appropriate key size. */ -size_t ecryptfs_get_key_size(void *data) +size_t ecryptfs_get_key_size(const void *data) { struct ecryptfs_crypt_stat *stat = NULL; @@ -173,49 +173,67 @@ size_t ecryptfs_get_key_size(void *data) * * !!! crypt_stat cipher name and mode must be initialized */ -size_t ecryptfs_get_salt_size(void *data) +size_t ecryptfs_get_salt_size(const void *data) { - struct ecryptfs_crypt_stat *stat = NULL; - unsigned char final[2*ECRYPTFS_MAX_CIPHER_NAME_SIZE+1]; - if (!data) { ecryptfs_printk(KERN_ERR, "ecryptfs_get_salt_size: invalid data parameter\n"); return 0; } - stat = (struct ecryptfs_crypt_stat *)data; - return ecryptfs_get_salt_size_for_cipher( - ecryptfs_get_full_cipher(stat->cipher, - stat->cipher_mode, - final, sizeof(final))); + return ecryptfs_get_salt_size_for_cipher(data); } /** - * Given ecryptfs data, the function - * returns appropriate cipher. + * Given ecryptfs data and cipher string, the function + * returns true if provided cipher and the one in ecryptfs match. */ -const unsigned char *ecryptfs_get_cipher(void *data) +bool ecryptfs_cipher_match(const void *data, + const unsigned char *cipher, size_t cipher_size) { unsigned char final[2*ECRYPTFS_MAX_CIPHER_NAME_SIZE+1]; + const unsigned char *ecryptfs_cipher = NULL; struct ecryptfs_crypt_stat *stat = NULL; - if (!data) { + if (!data || !cipher) { ecryptfs_printk(KERN_ERR, "ecryptfs_get_cipher: invalid data parameter\n"); - return NULL; + return false; } + + if (!cipher_size || cipher_size > sizeof(final)) { + ecryptfs_printk(KERN_ERR, + "ecryptfs_get_cipher: cipher_size\n"); + return false; + } + stat = (struct ecryptfs_crypt_stat *)data; - return ecryptfs_get_full_cipher(stat->cipher, stat->cipher_mode, + ecryptfs_cipher = ecryptfs_get_full_cipher(stat->cipher, + stat->cipher_mode, final, sizeof(final)); + + if (!ecryptfs_cipher) { + ecryptfs_printk(KERN_ERR, + "ecryptfs_get_cipher: internal error while parsing cipher\n"); + return false; + } + + if (strcmp(ecryptfs_cipher, cipher)) { + if (ecryptfs_verbosity > 0) + ecryptfs_dump_cipher(stat); + + return false; + } + + return true; } /** * Given ecryptfs data, the function * returns file encryption key. */ -const unsigned char *ecryptfs_get_key(void *data) +const unsigned char *ecryptfs_get_key(const void *data) { struct ecryptfs_crypt_stat *stat = NULL; @@ -233,7 +251,7 @@ const unsigned char *ecryptfs_get_key(void *data) * Given ecryptfs data, the function * returns file encryption salt. */ -const unsigned char *ecryptfs_get_salt(void *data) +const unsigned char *ecryptfs_get_salt(const void *data) { struct ecryptfs_crypt_stat *stat = NULL; @@ -279,7 +297,7 @@ bool ecryptfs_check_space_for_salt(const size_t key_size, * or for all other general purposes */ size_t ecryptfs_get_key_size_to_enc_data( - struct ecryptfs_crypt_stat *crypt_stat) + const struct ecryptfs_crypt_stat *crypt_stat) { if (!crypt_stat) return 0; @@ -299,7 +317,7 @@ size_t ecryptfs_get_key_size_to_enc_data( * !!! crypt_stat cipher name and mode must be initialized */ size_t ecryptfs_get_key_size_to_store_key( - struct ecryptfs_crypt_stat *crypt_stat) + const struct ecryptfs_crypt_stat *crypt_stat) { size_t salt_size = 0; @@ -329,14 +347,14 @@ size_t ecryptfs_get_key_size_to_store_key( * !!! crypt_stat cipher name and mode must be initialized */ size_t ecryptfs_get_key_size_to_restore_key(size_t stored_key_size, - const char *cipher) + const struct ecryptfs_crypt_stat *crypt_stat) { size_t salt_size = 0; - if (!cipher) + if (!crypt_stat) return 0; - salt_size = ecryptfs_get_salt_size_for_cipher(cipher); + salt_size = ecryptfs_get_salt_size_for_cipher(crypt_stat); if (salt_size >= stored_key_size) { ecryptfs_printk(KERN_WARNING, @@ -350,12 +368,26 @@ size_t ecryptfs_get_key_size_to_restore_key(size_t stored_key_size, } /** - * Given cipher, the function returns appropriate salt size. + * Given crypt_stat, the function returns appropriate salt size. + */ +size_t ecryptfs_get_salt_size_for_cipher( + const struct ecryptfs_crypt_stat *crypt_stat) +{ + if (!get_events() || !(get_events()->get_salt_key_size_cb)) + return 0; + + return get_events()->get_salt_key_size_cb(crypt_stat); +} + +/** + * Given mount_crypt_stat, the function returns appropriate salt size. */ -size_t ecryptfs_get_salt_size_for_cipher(const char *cipher) +size_t ecryptfs_get_salt_size_for_cipher_mount( + const struct ecryptfs_mount_crypt_stat *crypt_stat) { if (!get_events() || !(get_events()->get_salt_key_size_cb)) return 0; - return get_events()->get_salt_key_size_cb(cipher); + return get_events()->get_salt_key_size_cb(crypt_stat); } + diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index 82b99c786abb..8319b776a461 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c @@ -1202,7 +1202,7 @@ decrypt_pki_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok, memcpy(crypt_stat->key, auth_tok->session_key.decrypted_key, auth_tok->session_key.decrypted_key_size); crypt_stat->key_size = ecryptfs_get_key_size_to_restore_key( - auth_tok->session_key.decrypted_key_size, full_cipher); + auth_tok->session_key.decrypted_key_size, crypt_stat); ecryptfs_parse_full_cipher(full_cipher, crypt_stat->cipher, crypt_stat->cipher_mode); @@ -1214,7 +1214,7 @@ decrypt_pki_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok, crypt_stat->key_size); ecryptfs_dump_salt_hex(crypt_stat->key, crypt_stat->key_size, - full_cipher); + crypt_stat); } out: kfree(msg); @@ -1487,7 +1487,7 @@ parse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat, crypt_stat->key_size = ecryptfs_get_key_size_to_restore_key( (*new_auth_tok)->session_key.encrypted_key_size, - full_cipher); + crypt_stat); } rc = ecryptfs_init_crypt_ctx(crypt_stat); @@ -1687,8 +1687,6 @@ static int decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok, struct ecryptfs_crypt_stat *crypt_stat) { - - unsigned char final[2*ECRYPTFS_MAX_CIPHER_NAME_SIZE+1]; struct scatterlist dst_sg[2]; struct scatterlist src_sg[2]; struct mutex *tfm_mutex; @@ -1762,9 +1760,7 @@ decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok, ecryptfs_dump_hex(crypt_stat->key, crypt_stat->key_size); ecryptfs_dump_salt_hex(crypt_stat->key, crypt_stat->key_size, - ecryptfs_get_full_cipher(crypt_stat->cipher, - crypt_stat->cipher_mode, - final, sizeof(final))); + crypt_stat); } out: return rc; @@ -2332,10 +2328,7 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes, ecryptfs_printk(KERN_DEBUG, "Encrypting [%zd] bytes of the key\n", crypt_stat->key_size); ecryptfs_printk(KERN_DEBUG, "Encrypting [%zd] bytes of the salt key\n", - ecryptfs_get_salt_size_for_cipher( - ecryptfs_get_full_cipher(crypt_stat->cipher, - crypt_stat->cipher_mode, - final, sizeof(final)))); + ecryptfs_get_salt_size_for_cipher(crypt_stat)); rc = crypto_blkcipher_encrypt(&desc, dst_sg, src_sg, (*key_rec).enc_key_size); mutex_unlock(tfm_mutex); diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 63298ba20478..489d213270f8 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -292,7 +292,6 @@ static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options, int cipher_key_bytes_set = 0; int fn_cipher_key_bytes; int fn_cipher_key_bytes_set = 0; - size_t salt_size = 0; struct ecryptfs_mount_crypt_stat *mount_crypt_stat = &sbi->mount_crypt_stat; substring_t args[MAX_OPT_ARGS]; @@ -447,22 +446,7 @@ static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options, strcpy(mount_crypt_stat->global_default_fn_cipher_name, mount_crypt_stat->global_default_cipher_name); - if (cipher_key_bytes_set) { - - salt_size = ecryptfs_get_salt_size_for_cipher( - ecryptfs_get_full_cipher( - mount_crypt_stat->global_default_cipher_name, - mount_crypt_stat->global_default_cipher_mode, - final, sizeof(final))); - - if (!ecryptfs_check_space_for_salt( - mount_crypt_stat->global_default_cipher_key_size, - salt_size)) { - ecryptfs_printk( - KERN_WARNING, - "eCryptfs internal error: no space for salt"); - } - } else + if (!cipher_key_bytes_set) mount_crypt_stat->global_default_cipher_key_size = 0; if ((mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) diff --git a/include/linux/ecryptfs.h b/include/linux/ecryptfs.h index 55433c6c603d..33d35ea4f937 100644 --- a/include/linux/ecryptfs.h +++ b/include/linux/ecryptfs.h @@ -119,7 +119,7 @@ struct ecryptfs_auth_tok { * such as ecryptfs_get_key_size(), ecryptfs_get_cipher() etc. */ struct ecryptfs_events { - bool (*is_cipher_supported_cb)(const char *cipher); + bool (*is_cipher_supported_cb)(const void *ecrytpfs_data); void (*open_cb)(struct inode *inode, void *ecrytpfs_data); void (*release_cb)(struct inode *inode); int (*encrypt_cb)(struct page *in_page, struct page *out_page, @@ -127,26 +127,28 @@ struct ecryptfs_events { int (*decrypt_cb)(struct page *in_page, struct page *out_page, struct inode *inode, unsigned long extent_offset); bool (*is_hw_crypt_cb)(void); - size_t (*get_salt_key_size_cb)(const char *cipher); + size_t (*get_salt_key_size_cb)(const void *ecrytpfs_data); }; -int ecryptfs_register_to_events(struct ecryptfs_events *ops); +int ecryptfs_register_to_events(const struct ecryptfs_events *ops); int ecryptfs_unregister_from_events(int user_handle); -const unsigned char *ecryptfs_get_key(void *ecrytpfs_data); +const unsigned char *ecryptfs_get_key(const void *ecrytpfs_data); -size_t ecryptfs_get_key_size(void *ecrytpfs_data); +size_t ecryptfs_get_key_size(const void *ecrytpfs_data); -const unsigned char *ecryptfs_get_salt(void *ecrytpfs_data); +const unsigned char *ecryptfs_get_salt(const void *ecrytpfs_data); -size_t ecryptfs_get_salt_size(void *ecrytpfs_data); +size_t ecryptfs_get_salt_size(const void *ecrytpfs_data); -const unsigned char *ecryptfs_get_cipher(void *ecrytpfs_data); +bool ecryptfs_cipher_match(const void *ecrytpfs_data, + const unsigned char *cipher, size_t cipher_size); -bool ecryptfs_is_page_in_metadata(void *ecrytpfs_data, pgoff_t offset); +bool ecryptfs_is_page_in_metadata(const void *ecrytpfs_data, pgoff_t offset); -bool ecryptfs_is_data_equal(void *ecrytpfs_data1, void *ecrytpfs_data2); +bool ecryptfs_is_data_equal(const void *ecrytpfs_data1, + const void *ecrytpfs_data2); #endif /* _LINUX_ECRYPTFS_H */ diff --git a/security/pfe/pfk.c b/security/pfe/pfk.c index 911012eeb570..23ea0b9d01b1 100644 --- a/security/pfe/pfk.c +++ b/security/pfe/pfk.c @@ -276,13 +276,13 @@ static int pfk_set_ecryptfs_data(struct inode *inode, void *ecryptfs_data) /** - * pfk_parse_cipher() - translate string cipher to enum - * @cipher: cipher in string as received from ecryptfs + * pfk_parse_cipher() - parse cipher from ecryptfs to enum + * @ecryptfs_data: ecrypfs data * @algo: pointer to store the output enum (can be null) * * return 0 in case of success, error otherwise (i.e not supported cipher) */ -static int pfk_parse_cipher(const unsigned char *cipher, +static int pfk_parse_cipher(const void *ecryptfs_data, enum ice_cryto_algo_mode *algo) { /* @@ -291,11 +291,12 @@ static int pfk_parse_cipher(const unsigned char *cipher, * be introduced */ - if (!cipher) - return -EPERM; + if (!ecryptfs_data) + return -EINVAL; - if (!strcmp(cipher, PFK_SUPPORTED_CIPHER) == 0) { - pr_debug("not supported alghoritm %s\n", cipher); + if (!ecryptfs_cipher_match(ecryptfs_data, + PFK_SUPPORTED_CIPHER, sizeof(PFK_SUPPORTED_CIPHER))) { + pr_debug("ecryptfs alghoritm is not supported by pfk\n"); return -EINVAL; } @@ -427,13 +428,6 @@ int pfk_load_key(const struct bio *bio, struct ice_crypto_setting *ice_setting) goto end; } - cipher = ecryptfs_get_cipher(ecryptfs_data); - if (!cipher) { - pr_err("could not parse key from ecryptfs\n"); - ret = -EINVAL; - goto end; - } - ret = pfk_parse_cipher(cipher, &algo_mode); if (ret != 0) { pr_debug("not supported cipher\n"); @@ -587,7 +581,6 @@ end: static void pfk_open_cb(struct inode *inode, void *ecryptfs_data) { size_t key_size; - const unsigned char *cipher = NULL; if (!pfk_is_ready()) return; @@ -603,13 +596,7 @@ static void pfk_open_cb(struct inode *inode, void *ecryptfs_data) return; } - cipher = ecryptfs_get_cipher(ecryptfs_data); - if (!cipher) { - pr_err("could not parse key from ecryptfs\n"); - return; - } - - if (0 != pfk_parse_cipher(cipher, NULL)) { + if (0 != pfk_parse_cipher(ecryptfs_data, NULL)) { pr_debug("open_cb: not supported cipher\n"); return; } @@ -677,20 +664,21 @@ static void pfk_release_cb(struct inode *inode) pfk_kc_remove_key_with_salt(key, key_size, salt, salt_size); + mutex_lock(&pfk_lock); pfk_set_ecryptfs_data(inode, NULL); mutex_unlock(&pfk_lock); } -static bool pfk_is_cipher_supported_cb(const char *cipher) +static bool pfk_is_cipher_supported_cb(const void *ecryptfs_data) { if (!pfk_is_ready()) return false; - if (!cipher) + if (!ecryptfs_data) return false; - return (pfk_parse_cipher(cipher, NULL)) == 0; + return (pfk_parse_cipher(ecryptfs_data, NULL)) == 0; } static bool pfk_is_hw_crypt_cb(void) @@ -701,12 +689,12 @@ static bool pfk_is_hw_crypt_cb(void) return true; } -static size_t pfk_get_salt_key_size_cb(const char *cipher) +static size_t pfk_get_salt_key_size_cb(const void *ecryptfs_data) { if (!pfk_is_ready()) return 0; - if (!pfk_is_cipher_supported_cb(cipher)) + if (!pfk_is_cipher_supported_cb(ecryptfs_data)) return 0; return PFK_SUPPORTED_SALT_SIZE; |