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

fscrypto/f2fs: allow fs-specific key prefix for fs encryption

This patch allows fscrypto to handle a second key prefix given by filesystem.
The main reason is to provide backward compatibility, since previously f2fs
used "f2fs:" as a crypto prefix instead of "fscrypt:".
Later, ext4 should also provide key_prefix() to give "ext4:".

One concern decribed by Ted would be kinda double check overhead of prefixes.
In x86, for example, validate_user_key consumes 8 ms after boot-up, which turns
out derive_key_aes() consumed most of the time to load specific crypto module.
After such the cold miss, it shows almost zero latencies, which treats as a
negligible overhead.
Note that request_key() detects wrong prefix in prior to derive_key_aes() even.

Cc: Ted Tso <tytso@mit.edu>
Cc: stable@vger.kernel.org # v4.6
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>

+98 -44
+76 -44
fs/crypto/keyinfo.c
··· 78 78 return res; 79 79 } 80 80 81 + static int validate_user_key(struct fscrypt_info *crypt_info, 82 + struct fscrypt_context *ctx, u8 *raw_key, 83 + u8 *prefix, int prefix_size) 84 + { 85 + u8 *full_key_descriptor; 86 + struct key *keyring_key; 87 + struct fscrypt_key *master_key; 88 + const struct user_key_payload *ukp; 89 + int full_key_len = prefix_size + (FS_KEY_DESCRIPTOR_SIZE * 2) + 1; 90 + int res; 91 + 92 + full_key_descriptor = kmalloc(full_key_len, GFP_NOFS); 93 + if (!full_key_descriptor) 94 + return -ENOMEM; 95 + 96 + memcpy(full_key_descriptor, prefix, prefix_size); 97 + sprintf(full_key_descriptor + prefix_size, 98 + "%*phN", FS_KEY_DESCRIPTOR_SIZE, 99 + ctx->master_key_descriptor); 100 + full_key_descriptor[full_key_len - 1] = '\0'; 101 + keyring_key = request_key(&key_type_logon, full_key_descriptor, NULL); 102 + kfree(full_key_descriptor); 103 + if (IS_ERR(keyring_key)) 104 + return PTR_ERR(keyring_key); 105 + 106 + if (keyring_key->type != &key_type_logon) { 107 + printk_once(KERN_WARNING 108 + "%s: key type must be logon\n", __func__); 109 + res = -ENOKEY; 110 + goto out; 111 + } 112 + down_read(&keyring_key->sem); 113 + ukp = user_key_payload(keyring_key); 114 + if (ukp->datalen != sizeof(struct fscrypt_key)) { 115 + res = -EINVAL; 116 + up_read(&keyring_key->sem); 117 + goto out; 118 + } 119 + master_key = (struct fscrypt_key *)ukp->data; 120 + BUILD_BUG_ON(FS_AES_128_ECB_KEY_SIZE != FS_KEY_DERIVATION_NONCE_SIZE); 121 + 122 + if (master_key->size != FS_AES_256_XTS_KEY_SIZE) { 123 + printk_once(KERN_WARNING 124 + "%s: key size incorrect: %d\n", 125 + __func__, master_key->size); 126 + res = -ENOKEY; 127 + up_read(&keyring_key->sem); 128 + goto out; 129 + } 130 + res = derive_key_aes(ctx->nonce, master_key->raw, raw_key); 131 + up_read(&keyring_key->sem); 132 + if (res) 133 + goto out; 134 + 135 + crypt_info->ci_keyring_key = keyring_key; 136 + return 0; 137 + out: 138 + key_put(keyring_key); 139 + return res; 140 + } 141 + 81 142 static void put_crypt_info(struct fscrypt_info *ci) 82 143 { 83 144 if (!ci) ··· 152 91 int get_crypt_info(struct inode *inode) 153 92 { 154 93 struct fscrypt_info *crypt_info; 155 - u8 full_key_descriptor[FS_KEY_DESC_PREFIX_SIZE + 156 - (FS_KEY_DESCRIPTOR_SIZE * 2) + 1]; 157 - struct key *keyring_key = NULL; 158 - struct fscrypt_key *master_key; 159 94 struct fscrypt_context ctx; 160 - const struct user_key_payload *ukp; 161 95 struct crypto_skcipher *ctfm; 162 96 const char *cipher_str; 163 97 u8 raw_key[FS_MAX_KEY_SIZE]; ··· 223 167 memset(raw_key, 0x42, FS_AES_256_XTS_KEY_SIZE); 224 168 goto got_key; 225 169 } 226 - memcpy(full_key_descriptor, FS_KEY_DESC_PREFIX, 227 - FS_KEY_DESC_PREFIX_SIZE); 228 - sprintf(full_key_descriptor + FS_KEY_DESC_PREFIX_SIZE, 229 - "%*phN", FS_KEY_DESCRIPTOR_SIZE, 230 - ctx.master_key_descriptor); 231 - full_key_descriptor[FS_KEY_DESC_PREFIX_SIZE + 232 - (2 * FS_KEY_DESCRIPTOR_SIZE)] = '\0'; 233 - keyring_key = request_key(&key_type_logon, full_key_descriptor, NULL); 234 - if (IS_ERR(keyring_key)) { 235 - res = PTR_ERR(keyring_key); 236 - keyring_key = NULL; 237 - goto out; 238 - } 239 - crypt_info->ci_keyring_key = keyring_key; 240 - if (keyring_key->type != &key_type_logon) { 241 - printk_once(KERN_WARNING 242 - "%s: key type must be logon\n", __func__); 243 - res = -ENOKEY; 244 - goto out; 245 - } 246 - down_read(&keyring_key->sem); 247 - ukp = user_key_payload(keyring_key); 248 - if (ukp->datalen != sizeof(struct fscrypt_key)) { 249 - res = -EINVAL; 250 - up_read(&keyring_key->sem); 251 - goto out; 252 - } 253 - master_key = (struct fscrypt_key *)ukp->data; 254 - BUILD_BUG_ON(FS_AES_128_ECB_KEY_SIZE != FS_KEY_DERIVATION_NONCE_SIZE); 255 170 256 - if (master_key->size != FS_AES_256_XTS_KEY_SIZE) { 257 - printk_once(KERN_WARNING 258 - "%s: key size incorrect: %d\n", 259 - __func__, master_key->size); 260 - res = -ENOKEY; 261 - up_read(&keyring_key->sem); 171 + res = validate_user_key(crypt_info, &ctx, raw_key, 172 + FS_KEY_DESC_PREFIX, FS_KEY_DESC_PREFIX_SIZE); 173 + if (res && inode->i_sb->s_cop->key_prefix) { 174 + u8 *prefix = NULL; 175 + int prefix_size, res2; 176 + 177 + prefix_size = inode->i_sb->s_cop->key_prefix(inode, &prefix); 178 + res2 = validate_user_key(crypt_info, &ctx, raw_key, 179 + prefix, prefix_size); 180 + if (res2) { 181 + if (res2 == -ENOKEY) 182 + res = -ENOKEY; 183 + goto out; 184 + } 185 + } else if (res) { 262 186 goto out; 263 187 } 264 - res = derive_key_aes(ctx.nonce, master_key->raw, raw_key); 265 - up_read(&keyring_key->sem); 266 - if (res) 267 - goto out; 268 188 got_key: 269 189 ctfm = crypto_alloc_skcipher(cipher_str, 0, 0); 270 190 if (!ctfm || IS_ERR(ctfm)) {
+8
fs/f2fs/f2fs.h
··· 711 711 MAX_TIME, 712 712 }; 713 713 714 + #ifdef CONFIG_F2FS_FS_ENCRYPTION 715 + #define F2FS_KEY_DESC_PREFIX "f2fs:" 716 + #define F2FS_KEY_DESC_PREFIX_SIZE 5 717 + #endif 714 718 struct f2fs_sb_info { 715 719 struct super_block *sb; /* pointer to VFS super block */ 716 720 struct proc_dir_entry *s_proc; /* proc entry */ ··· 722 718 int valid_super_block; /* valid super block no */ 723 719 int s_flag; /* flags for sbi */ 724 720 721 + #ifdef CONFIG_F2FS_FS_ENCRYPTION 722 + u8 key_prefix[F2FS_KEY_DESC_PREFIX_SIZE]; 723 + u8 key_prefix_size; 724 + #endif 725 725 /* for node-related operations */ 726 726 struct f2fs_nm_info *nm_info; /* node manager */ 727 727 struct inode *node_inode; /* cache node blocks */
+13
fs/f2fs/super.c
··· 964 964 ctx, len, NULL); 965 965 } 966 966 967 + static int f2fs_key_prefix(struct inode *inode, u8 **key) 968 + { 969 + *key = F2FS_I_SB(inode)->key_prefix; 970 + return F2FS_I_SB(inode)->key_prefix_size; 971 + } 972 + 967 973 static int f2fs_set_context(struct inode *inode, const void *ctx, size_t len, 968 974 void *fs_data) 969 975 { ··· 986 980 987 981 static struct fscrypt_operations f2fs_cryptops = { 988 982 .get_context = f2fs_get_context, 983 + .key_prefix = f2fs_key_prefix, 989 984 .set_context = f2fs_set_context, 990 985 .is_encrypted = f2fs_encrypted_inode, 991 986 .empty_dir = f2fs_empty_dir, ··· 1312 1305 1313 1306 INIT_LIST_HEAD(&sbi->s_list); 1314 1307 mutex_init(&sbi->umount_mutex); 1308 + 1309 + #ifdef CONFIG_F2FS_FS_ENCRYPTION 1310 + memcpy(sbi->key_prefix, F2FS_KEY_DESC_PREFIX, 1311 + F2FS_KEY_DESC_PREFIX_SIZE); 1312 + sbi->key_prefix_size = F2FS_KEY_DESC_PREFIX_SIZE; 1313 + #endif 1315 1314 } 1316 1315 1317 1316 /*
+1
include/linux/fscrypto.h
··· 175 175 */ 176 176 struct fscrypt_operations { 177 177 int (*get_context)(struct inode *, void *, size_t); 178 + int (*key_prefix)(struct inode *, u8 **); 178 179 int (*prepare_context)(struct inode *); 179 180 int (*set_context)(struct inode *, const void *, size_t, void *); 180 181 int (*dummy_context)(struct inode *);