Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.2-rc3 215 lines 6.4 kB view raw
1/* 2 * linux/fs/ext4/crypto_policy.c 3 * 4 * Copyright (C) 2015, Google, Inc. 5 * 6 * This contains encryption policy functions for ext4 7 * 8 * Written by Michael Halcrow, 2015. 9 */ 10 11#include <linux/random.h> 12#include <linux/string.h> 13#include <linux/types.h> 14 15#include "ext4.h" 16#include "xattr.h" 17 18static int ext4_inode_has_encryption_context(struct inode *inode) 19{ 20 int res = ext4_xattr_get(inode, EXT4_XATTR_INDEX_ENCRYPTION, 21 EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, NULL, 0); 22 return (res > 0); 23} 24 25/* 26 * check whether the policy is consistent with the encryption context 27 * for the inode 28 */ 29static int ext4_is_encryption_context_consistent_with_policy( 30 struct inode *inode, const struct ext4_encryption_policy *policy) 31{ 32 struct ext4_encryption_context ctx; 33 int res = ext4_xattr_get(inode, EXT4_XATTR_INDEX_ENCRYPTION, 34 EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, &ctx, 35 sizeof(ctx)); 36 if (res != sizeof(ctx)) 37 return 0; 38 return (memcmp(ctx.master_key_descriptor, policy->master_key_descriptor, 39 EXT4_KEY_DESCRIPTOR_SIZE) == 0 && 40 (ctx.flags == 41 policy->flags) && 42 (ctx.contents_encryption_mode == 43 policy->contents_encryption_mode) && 44 (ctx.filenames_encryption_mode == 45 policy->filenames_encryption_mode)); 46} 47 48static int ext4_create_encryption_context_from_policy( 49 struct inode *inode, const struct ext4_encryption_policy *policy) 50{ 51 struct ext4_encryption_context ctx; 52 int res = 0; 53 54 res = ext4_convert_inline_data(inode); 55 if (res) 56 return res; 57 58 ctx.format = EXT4_ENCRYPTION_CONTEXT_FORMAT_V1; 59 memcpy(ctx.master_key_descriptor, policy->master_key_descriptor, 60 EXT4_KEY_DESCRIPTOR_SIZE); 61 if (!ext4_valid_contents_enc_mode(policy->contents_encryption_mode)) { 62 printk(KERN_WARNING 63 "%s: Invalid contents encryption mode %d\n", __func__, 64 policy->contents_encryption_mode); 65 return -EINVAL; 66 } 67 if (!ext4_valid_filenames_enc_mode(policy->filenames_encryption_mode)) { 68 printk(KERN_WARNING 69 "%s: Invalid filenames encryption mode %d\n", __func__, 70 policy->filenames_encryption_mode); 71 return -EINVAL; 72 } 73 if (policy->flags & ~EXT4_POLICY_FLAGS_VALID) 74 return -EINVAL; 75 ctx.contents_encryption_mode = policy->contents_encryption_mode; 76 ctx.filenames_encryption_mode = policy->filenames_encryption_mode; 77 ctx.flags = policy->flags; 78 BUILD_BUG_ON(sizeof(ctx.nonce) != EXT4_KEY_DERIVATION_NONCE_SIZE); 79 get_random_bytes(ctx.nonce, EXT4_KEY_DERIVATION_NONCE_SIZE); 80 81 res = ext4_xattr_set(inode, EXT4_XATTR_INDEX_ENCRYPTION, 82 EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, &ctx, 83 sizeof(ctx), 0); 84 if (!res) 85 ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT); 86 return res; 87} 88 89int ext4_process_policy(const struct ext4_encryption_policy *policy, 90 struct inode *inode) 91{ 92 if (policy->version != 0) 93 return -EINVAL; 94 95 if (!ext4_inode_has_encryption_context(inode)) { 96 if (!S_ISDIR(inode->i_mode)) 97 return -EINVAL; 98 if (!ext4_empty_dir(inode)) 99 return -ENOTEMPTY; 100 return ext4_create_encryption_context_from_policy(inode, 101 policy); 102 } 103 104 if (ext4_is_encryption_context_consistent_with_policy(inode, policy)) 105 return 0; 106 107 printk(KERN_WARNING "%s: Policy inconsistent with encryption context\n", 108 __func__); 109 return -EINVAL; 110} 111 112int ext4_get_policy(struct inode *inode, struct ext4_encryption_policy *policy) 113{ 114 struct ext4_encryption_context ctx; 115 116 int res = ext4_xattr_get(inode, EXT4_XATTR_INDEX_ENCRYPTION, 117 EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, 118 &ctx, sizeof(ctx)); 119 if (res != sizeof(ctx)) 120 return -ENOENT; 121 if (ctx.format != EXT4_ENCRYPTION_CONTEXT_FORMAT_V1) 122 return -EINVAL; 123 policy->version = 0; 124 policy->contents_encryption_mode = ctx.contents_encryption_mode; 125 policy->filenames_encryption_mode = ctx.filenames_encryption_mode; 126 policy->flags = ctx.flags; 127 memcpy(&policy->master_key_descriptor, ctx.master_key_descriptor, 128 EXT4_KEY_DESCRIPTOR_SIZE); 129 return 0; 130} 131 132int ext4_is_child_context_consistent_with_parent(struct inode *parent, 133 struct inode *child) 134{ 135 struct ext4_crypt_info *parent_ci, *child_ci; 136 int res; 137 138 if ((parent == NULL) || (child == NULL)) { 139 pr_err("parent %p child %p\n", parent, child); 140 BUG_ON(1); 141 } 142 /* no restrictions if the parent directory is not encrypted */ 143 if (!ext4_encrypted_inode(parent)) 144 return 1; 145 /* if the child directory is not encrypted, this is always a problem */ 146 if (!ext4_encrypted_inode(child)) 147 return 0; 148 res = ext4_get_encryption_info(parent); 149 if (res) 150 return 0; 151 res = ext4_get_encryption_info(child); 152 if (res) 153 return 0; 154 parent_ci = EXT4_I(parent)->i_crypt_info; 155 child_ci = EXT4_I(child)->i_crypt_info; 156 if (!parent_ci && !child_ci) 157 return 1; 158 if (!parent_ci || !child_ci) 159 return 0; 160 161 return (memcmp(parent_ci->ci_master_key, 162 child_ci->ci_master_key, 163 EXT4_KEY_DESCRIPTOR_SIZE) == 0 && 164 (parent_ci->ci_data_mode == child_ci->ci_data_mode) && 165 (parent_ci->ci_filename_mode == child_ci->ci_filename_mode) && 166 (parent_ci->ci_flags == child_ci->ci_flags)); 167} 168 169/** 170 * ext4_inherit_context() - Sets a child context from its parent 171 * @parent: Parent inode from which the context is inherited. 172 * @child: Child inode that inherits the context from @parent. 173 * 174 * Return: Zero on success, non-zero otherwise 175 */ 176int ext4_inherit_context(struct inode *parent, struct inode *child) 177{ 178 struct ext4_encryption_context ctx; 179 struct ext4_crypt_info *ci; 180 int res; 181 182 res = ext4_get_encryption_info(parent); 183 if (res < 0) 184 return res; 185 ci = EXT4_I(parent)->i_crypt_info; 186 if (ci == NULL) 187 return -ENOKEY; 188 189 ctx.format = EXT4_ENCRYPTION_CONTEXT_FORMAT_V1; 190 if (DUMMY_ENCRYPTION_ENABLED(EXT4_SB(parent->i_sb))) { 191 ctx.contents_encryption_mode = EXT4_ENCRYPTION_MODE_AES_256_XTS; 192 ctx.filenames_encryption_mode = 193 EXT4_ENCRYPTION_MODE_AES_256_CTS; 194 ctx.flags = 0; 195 memset(ctx.master_key_descriptor, 0x42, 196 EXT4_KEY_DESCRIPTOR_SIZE); 197 res = 0; 198 } else { 199 ctx.contents_encryption_mode = ci->ci_data_mode; 200 ctx.filenames_encryption_mode = ci->ci_filename_mode; 201 ctx.flags = ci->ci_flags; 202 memcpy(ctx.master_key_descriptor, ci->ci_master_key, 203 EXT4_KEY_DESCRIPTOR_SIZE); 204 } 205 get_random_bytes(ctx.nonce, EXT4_KEY_DERIVATION_NONCE_SIZE); 206 res = ext4_xattr_set(child, EXT4_XATTR_INDEX_ENCRYPTION, 207 EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, &ctx, 208 sizeof(ctx), 0); 209 if (!res) { 210 ext4_set_inode_flag(child, EXT4_INODE_ENCRYPT); 211 ext4_clear_inode_state(child, EXT4_STATE_MAY_INLINE_DATA); 212 res = ext4_get_encryption_info(child); 213 } 214 return res; 215}