1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 20b81d077SJaegeuk Kim /* 30b81d077SJaegeuk Kim * Encryption policy functions for per-file encryption support. 40b81d077SJaegeuk Kim * 50b81d077SJaegeuk Kim * Copyright (C) 2015, Google, Inc. 60b81d077SJaegeuk Kim * Copyright (C) 2015, Motorola Mobility. 70b81d077SJaegeuk Kim * 85dae460cSEric Biggers * Originally written by Michael Halcrow, 2015. 90b81d077SJaegeuk Kim * Modified by Jaegeuk Kim, 2015. 105dae460cSEric Biggers * Modified by Eric Biggers, 2019 for v2 policy support. 110b81d077SJaegeuk Kim */ 120b81d077SJaegeuk Kim 130b81d077SJaegeuk Kim #include <linux/random.h> 14ed318a6cSEric Biggers #include <linux/seq_file.h> 150b81d077SJaegeuk Kim #include <linux/string.h> 16ba63f23dSEric Biggers #include <linux/mount.h> 17cc4e0df0STheodore Ts'o #include "fscrypt_private.h" 180b81d077SJaegeuk Kim 195dae460cSEric Biggers /** 20d2fe9754SEric Biggers * fscrypt_policies_equal() - check whether two encryption policies are the same 21d2fe9754SEric Biggers * @policy1: the first policy 22d2fe9754SEric Biggers * @policy2: the second policy 235dae460cSEric Biggers * 245dae460cSEric Biggers * Return: %true if equal, else %false 250b81d077SJaegeuk Kim */ 265dae460cSEric Biggers bool fscrypt_policies_equal(const union fscrypt_policy *policy1, 275dae460cSEric Biggers const union fscrypt_policy *policy2) 280b81d077SJaegeuk Kim { 295dae460cSEric Biggers if (policy1->version != policy2->version) 305dae460cSEric Biggers return false; 315dae460cSEric Biggers 325dae460cSEric Biggers return !memcmp(policy1, policy2, fscrypt_policy_size(policy1)); 330b81d077SJaegeuk Kim } 340b81d077SJaegeuk Kim 35ef5b18b0SEric Biggers static bool fscrypt_valid_enc_modes(u32 contents_mode, u32 filenames_mode) 36ef5b18b0SEric Biggers { 37ef5b18b0SEric Biggers if (contents_mode == FSCRYPT_MODE_AES_256_XTS && 38ef5b18b0SEric Biggers filenames_mode == FSCRYPT_MODE_AES_256_CTS) 39ef5b18b0SEric Biggers return true; 40ef5b18b0SEric Biggers 41ef5b18b0SEric Biggers if (contents_mode == FSCRYPT_MODE_AES_128_CBC && 42ef5b18b0SEric Biggers filenames_mode == FSCRYPT_MODE_AES_128_CTS) 43ef5b18b0SEric Biggers return true; 44ef5b18b0SEric Biggers 45ef5b18b0SEric Biggers if (contents_mode == FSCRYPT_MODE_ADIANTUM && 46ef5b18b0SEric Biggers filenames_mode == FSCRYPT_MODE_ADIANTUM) 47ef5b18b0SEric Biggers return true; 48ef5b18b0SEric Biggers 49ef5b18b0SEric Biggers return false; 50ef5b18b0SEric Biggers } 51ef5b18b0SEric Biggers 5285af90e5SEric Biggers static bool supported_direct_key_modes(const struct inode *inode, 5385af90e5SEric Biggers u32 contents_mode, u32 filenames_mode) 5485af90e5SEric Biggers { 5585af90e5SEric Biggers const struct fscrypt_mode *mode; 5685af90e5SEric Biggers 5785af90e5SEric Biggers if (contents_mode != filenames_mode) { 5885af90e5SEric Biggers fscrypt_warn(inode, 5985af90e5SEric Biggers "Direct key flag not allowed with different contents and filenames modes"); 6085af90e5SEric Biggers return false; 6185af90e5SEric Biggers } 6285af90e5SEric Biggers mode = &fscrypt_modes[contents_mode]; 6385af90e5SEric Biggers 6485af90e5SEric Biggers if (mode->ivsize < offsetofend(union fscrypt_iv, nonce)) { 6585af90e5SEric Biggers fscrypt_warn(inode, "Direct key flag not allowed with %s", 6685af90e5SEric Biggers mode->friendly_name); 6785af90e5SEric Biggers return false; 6885af90e5SEric Biggers } 6985af90e5SEric Biggers return true; 7085af90e5SEric Biggers } 7185af90e5SEric Biggers 72e3b1078bSEric Biggers static bool supported_iv_ino_lblk_policy(const struct fscrypt_policy_v2 *policy, 73e3b1078bSEric Biggers const struct inode *inode, 74e3b1078bSEric Biggers const char *type, 75e3b1078bSEric Biggers int max_ino_bits, int max_lblk_bits) 76b103fb76SEric Biggers { 77b103fb76SEric Biggers struct super_block *sb = inode->i_sb; 78b103fb76SEric Biggers int ino_bits = 64, lblk_bits = 64; 79b103fb76SEric Biggers 80b103fb76SEric Biggers /* 81f000223cSEric Biggers * IV_INO_LBLK_* exist only because of hardware limitations, and 82f000223cSEric Biggers * currently the only known use case for them involves AES-256-XTS. 83f000223cSEric Biggers * That's also all we test currently. For these reasons, for now only 84f000223cSEric Biggers * allow AES-256-XTS here. This can be relaxed later if a use case for 85f000223cSEric Biggers * IV_INO_LBLK_* with other encryption modes arises. 86f000223cSEric Biggers */ 87f000223cSEric Biggers if (policy->contents_encryption_mode != FSCRYPT_MODE_AES_256_XTS) { 88f000223cSEric Biggers fscrypt_warn(inode, 89f000223cSEric Biggers "Can't use %s policy with contents mode other than AES-256-XTS", 90f000223cSEric Biggers type); 91f000223cSEric Biggers return false; 92f000223cSEric Biggers } 93f000223cSEric Biggers 94f000223cSEric Biggers /* 95b103fb76SEric Biggers * It's unsafe to include inode numbers in the IVs if the filesystem can 96b103fb76SEric Biggers * potentially renumber inodes, e.g. via filesystem shrinking. 97b103fb76SEric Biggers */ 98b103fb76SEric Biggers if (!sb->s_cop->has_stable_inodes || 99b103fb76SEric Biggers !sb->s_cop->has_stable_inodes(sb)) { 100b103fb76SEric Biggers fscrypt_warn(inode, 101e3b1078bSEric Biggers "Can't use %s policy on filesystem '%s' because it doesn't have stable inode numbers", 102e3b1078bSEric Biggers type, sb->s_id); 103b103fb76SEric Biggers return false; 104b103fb76SEric Biggers } 105b103fb76SEric Biggers if (sb->s_cop->get_ino_and_lblk_bits) 106b103fb76SEric Biggers sb->s_cop->get_ino_and_lblk_bits(sb, &ino_bits, &lblk_bits); 107e3b1078bSEric Biggers if (ino_bits > max_ino_bits) { 108b103fb76SEric Biggers fscrypt_warn(inode, 109e3b1078bSEric Biggers "Can't use %s policy on filesystem '%s' because its inode numbers are too long", 110e3b1078bSEric Biggers type, sb->s_id); 111e3b1078bSEric Biggers return false; 112e3b1078bSEric Biggers } 113e3b1078bSEric Biggers if (lblk_bits > max_lblk_bits) { 114e3b1078bSEric Biggers fscrypt_warn(inode, 115e3b1078bSEric Biggers "Can't use %s policy on filesystem '%s' because its block numbers are too long", 116e3b1078bSEric Biggers type, sb->s_id); 117b103fb76SEric Biggers return false; 118b103fb76SEric Biggers } 119b103fb76SEric Biggers return true; 120b103fb76SEric Biggers } 121b103fb76SEric Biggers 122393a24a7SEric Biggers static bool fscrypt_supported_v1_policy(const struct fscrypt_policy_v1 *policy, 1235dae460cSEric Biggers const struct inode *inode) 1240b81d077SJaegeuk Kim { 125b7e7cf7aSDaniel Walter if (!fscrypt_valid_enc_modes(policy->contents_encryption_mode, 1265dae460cSEric Biggers policy->filenames_encryption_mode)) { 1275dae460cSEric Biggers fscrypt_warn(inode, 1285dae460cSEric Biggers "Unsupported encryption modes (contents %d, filenames %d)", 1295dae460cSEric Biggers policy->contents_encryption_mode, 1305dae460cSEric Biggers policy->filenames_encryption_mode); 1315dae460cSEric Biggers return false; 1325dae460cSEric Biggers } 1335dae460cSEric Biggers 134b103fb76SEric Biggers if (policy->flags & ~(FSCRYPT_POLICY_FLAGS_PAD_MASK | 135b103fb76SEric Biggers FSCRYPT_POLICY_FLAG_DIRECT_KEY)) { 136393a24a7SEric Biggers fscrypt_warn(inode, "Unsupported encryption flags (0x%02x)", 1375dae460cSEric Biggers policy->flags); 1385dae460cSEric Biggers return false; 1395dae460cSEric Biggers } 1405dae460cSEric Biggers 14185af90e5SEric Biggers if ((policy->flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) && 14285af90e5SEric Biggers !supported_direct_key_modes(inode, policy->contents_encryption_mode, 14385af90e5SEric Biggers policy->filenames_encryption_mode)) 14485af90e5SEric Biggers return false; 14585af90e5SEric Biggers 1466e1918cfSDaniel Rosenberg if (IS_CASEFOLDED(inode)) { 1476e1918cfSDaniel Rosenberg /* With v1, there's no way to derive dirhash keys. */ 1486e1918cfSDaniel Rosenberg fscrypt_warn(inode, 1496e1918cfSDaniel Rosenberg "v1 policies can't be used on casefolded directories"); 1506e1918cfSDaniel Rosenberg return false; 1516e1918cfSDaniel Rosenberg } 1526e1918cfSDaniel Rosenberg 1535dae460cSEric Biggers return true; 1545dae460cSEric Biggers } 1555dae460cSEric Biggers 156393a24a7SEric Biggers static bool fscrypt_supported_v2_policy(const struct fscrypt_policy_v2 *policy, 157393a24a7SEric Biggers const struct inode *inode) 158393a24a7SEric Biggers { 159e3b1078bSEric Biggers int count = 0; 160e3b1078bSEric Biggers 1615dae460cSEric Biggers if (!fscrypt_valid_enc_modes(policy->contents_encryption_mode, 1625dae460cSEric Biggers policy->filenames_encryption_mode)) { 1635dae460cSEric Biggers fscrypt_warn(inode, 1645dae460cSEric Biggers "Unsupported encryption modes (contents %d, filenames %d)", 1655dae460cSEric Biggers policy->contents_encryption_mode, 1665dae460cSEric Biggers policy->filenames_encryption_mode); 1675dae460cSEric Biggers return false; 1685dae460cSEric Biggers } 1695dae460cSEric Biggers 1705dae460cSEric Biggers if (policy->flags & ~FSCRYPT_POLICY_FLAGS_VALID) { 171393a24a7SEric Biggers fscrypt_warn(inode, "Unsupported encryption flags (0x%02x)", 1725dae460cSEric Biggers policy->flags); 1735dae460cSEric Biggers return false; 1745dae460cSEric Biggers } 1755dae460cSEric Biggers 176e3b1078bSEric Biggers count += !!(policy->flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY); 177e3b1078bSEric Biggers count += !!(policy->flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64); 178e3b1078bSEric Biggers count += !!(policy->flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32); 179e3b1078bSEric Biggers if (count > 1) { 180e3b1078bSEric Biggers fscrypt_warn(inode, "Mutually exclusive encryption flags (0x%02x)", 181e3b1078bSEric Biggers policy->flags); 182e3b1078bSEric Biggers return false; 183e3b1078bSEric Biggers } 184e3b1078bSEric Biggers 18585af90e5SEric Biggers if ((policy->flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) && 18685af90e5SEric Biggers !supported_direct_key_modes(inode, policy->contents_encryption_mode, 18785af90e5SEric Biggers policy->filenames_encryption_mode)) 18885af90e5SEric Biggers return false; 18985af90e5SEric Biggers 190b103fb76SEric Biggers if ((policy->flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) && 191e3b1078bSEric Biggers !supported_iv_ino_lblk_policy(policy, inode, "IV_INO_LBLK_64", 192e3b1078bSEric Biggers 32, 32)) 193e3b1078bSEric Biggers return false; 194e3b1078bSEric Biggers 195e3b1078bSEric Biggers if ((policy->flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32) && 196e3b1078bSEric Biggers /* This uses hashed inode numbers, so ino_bits doesn't matter. */ 197e3b1078bSEric Biggers !supported_iv_ino_lblk_policy(policy, inode, "IV_INO_LBLK_32", 198e3b1078bSEric Biggers INT_MAX, 32)) 199b103fb76SEric Biggers return false; 200b103fb76SEric Biggers 201393a24a7SEric Biggers if (memchr_inv(policy->__reserved, 0, sizeof(policy->__reserved))) { 202393a24a7SEric Biggers fscrypt_warn(inode, "Reserved bits set in encryption policy"); 2035dae460cSEric Biggers return false; 2045dae460cSEric Biggers } 2055dae460cSEric Biggers 2065dae460cSEric Biggers return true; 2075dae460cSEric Biggers } 208393a24a7SEric Biggers 209393a24a7SEric Biggers /** 210d2fe9754SEric Biggers * fscrypt_supported_policy() - check whether an encryption policy is supported 211d2fe9754SEric Biggers * @policy_u: the encryption policy 212d2fe9754SEric Biggers * @inode: the inode on which the policy will be used 213393a24a7SEric Biggers * 214393a24a7SEric Biggers * Given an encryption policy, check whether all its encryption modes and other 215393a24a7SEric Biggers * settings are supported by this kernel on the given inode. (But we don't 216393a24a7SEric Biggers * currently don't check for crypto API support here, so attempting to use an 217393a24a7SEric Biggers * algorithm not configured into the crypto API will still fail later.) 218393a24a7SEric Biggers * 219393a24a7SEric Biggers * Return: %true if supported, else %false 220393a24a7SEric Biggers */ 221393a24a7SEric Biggers bool fscrypt_supported_policy(const union fscrypt_policy *policy_u, 222393a24a7SEric Biggers const struct inode *inode) 223393a24a7SEric Biggers { 224393a24a7SEric Biggers switch (policy_u->version) { 225393a24a7SEric Biggers case FSCRYPT_POLICY_V1: 226393a24a7SEric Biggers return fscrypt_supported_v1_policy(&policy_u->v1, inode); 227393a24a7SEric Biggers case FSCRYPT_POLICY_V2: 228393a24a7SEric Biggers return fscrypt_supported_v2_policy(&policy_u->v2, inode); 2295dae460cSEric Biggers } 2305dae460cSEric Biggers return false; 2315dae460cSEric Biggers } 2325dae460cSEric Biggers 2335dae460cSEric Biggers /** 234d2fe9754SEric Biggers * fscrypt_new_context_from_policy() - create a new fscrypt_context from 235d2fe9754SEric Biggers * an fscrypt_policy 236d2fe9754SEric Biggers * @ctx_u: output context 237d2fe9754SEric Biggers * @policy_u: input policy 2385dae460cSEric Biggers * 2395dae460cSEric Biggers * Create an fscrypt_context for an inode that is being assigned the given 2405dae460cSEric Biggers * encryption policy. A new nonce is randomly generated. 2415dae460cSEric Biggers * 2425dae460cSEric Biggers * Return: the size of the new context in bytes. 2435dae460cSEric Biggers */ 2445dae460cSEric Biggers static int fscrypt_new_context_from_policy(union fscrypt_context *ctx_u, 2455dae460cSEric Biggers const union fscrypt_policy *policy_u) 2465dae460cSEric Biggers { 2475dae460cSEric Biggers memset(ctx_u, 0, sizeof(*ctx_u)); 2485dae460cSEric Biggers 2495dae460cSEric Biggers switch (policy_u->version) { 2505dae460cSEric Biggers case FSCRYPT_POLICY_V1: { 2515dae460cSEric Biggers const struct fscrypt_policy_v1 *policy = &policy_u->v1; 2525dae460cSEric Biggers struct fscrypt_context_v1 *ctx = &ctx_u->v1; 2535dae460cSEric Biggers 2545dae460cSEric Biggers ctx->version = FSCRYPT_CONTEXT_V1; 2555dae460cSEric Biggers ctx->contents_encryption_mode = 2565dae460cSEric Biggers policy->contents_encryption_mode; 2575dae460cSEric Biggers ctx->filenames_encryption_mode = 2585dae460cSEric Biggers policy->filenames_encryption_mode; 2595dae460cSEric Biggers ctx->flags = policy->flags; 2605dae460cSEric Biggers memcpy(ctx->master_key_descriptor, 2615dae460cSEric Biggers policy->master_key_descriptor, 2625dae460cSEric Biggers sizeof(ctx->master_key_descriptor)); 2635dae460cSEric Biggers get_random_bytes(ctx->nonce, sizeof(ctx->nonce)); 2645dae460cSEric Biggers return sizeof(*ctx); 2655dae460cSEric Biggers } 2665dae460cSEric Biggers case FSCRYPT_POLICY_V2: { 2675dae460cSEric Biggers const struct fscrypt_policy_v2 *policy = &policy_u->v2; 2685dae460cSEric Biggers struct fscrypt_context_v2 *ctx = &ctx_u->v2; 2695dae460cSEric Biggers 2705dae460cSEric Biggers ctx->version = FSCRYPT_CONTEXT_V2; 2715dae460cSEric Biggers ctx->contents_encryption_mode = 2725dae460cSEric Biggers policy->contents_encryption_mode; 2735dae460cSEric Biggers ctx->filenames_encryption_mode = 2745dae460cSEric Biggers policy->filenames_encryption_mode; 2755dae460cSEric Biggers ctx->flags = policy->flags; 2765dae460cSEric Biggers memcpy(ctx->master_key_identifier, 2775dae460cSEric Biggers policy->master_key_identifier, 2785dae460cSEric Biggers sizeof(ctx->master_key_identifier)); 2795dae460cSEric Biggers get_random_bytes(ctx->nonce, sizeof(ctx->nonce)); 2805dae460cSEric Biggers return sizeof(*ctx); 2815dae460cSEric Biggers } 2825dae460cSEric Biggers } 2835dae460cSEric Biggers BUG(); 2845dae460cSEric Biggers } 2855dae460cSEric Biggers 2865dae460cSEric Biggers /** 287d2fe9754SEric Biggers * fscrypt_policy_from_context() - convert an fscrypt_context to 288d2fe9754SEric Biggers * an fscrypt_policy 289d2fe9754SEric Biggers * @policy_u: output policy 290d2fe9754SEric Biggers * @ctx_u: input context 291d2fe9754SEric Biggers * @ctx_size: size of input context in bytes 2925dae460cSEric Biggers * 2935dae460cSEric Biggers * Given an fscrypt_context, build the corresponding fscrypt_policy. 2945dae460cSEric Biggers * 2955dae460cSEric Biggers * Return: 0 on success, or -EINVAL if the fscrypt_context has an unrecognized 2965dae460cSEric Biggers * version number or size. 2975dae460cSEric Biggers * 2985dae460cSEric Biggers * This does *not* validate the settings within the policy itself, e.g. the 2995dae460cSEric Biggers * modes, flags, and reserved bits. Use fscrypt_supported_policy() for that. 3005dae460cSEric Biggers */ 3015dae460cSEric Biggers int fscrypt_policy_from_context(union fscrypt_policy *policy_u, 3025dae460cSEric Biggers const union fscrypt_context *ctx_u, 3035dae460cSEric Biggers int ctx_size) 3045dae460cSEric Biggers { 3055dae460cSEric Biggers memset(policy_u, 0, sizeof(*policy_u)); 3065dae460cSEric Biggers 307e98ad464SEric Biggers if (!fscrypt_context_is_valid(ctx_u, ctx_size)) 3080b81d077SJaegeuk Kim return -EINVAL; 3090b81d077SJaegeuk Kim 3105dae460cSEric Biggers switch (ctx_u->version) { 3115dae460cSEric Biggers case FSCRYPT_CONTEXT_V1: { 3125dae460cSEric Biggers const struct fscrypt_context_v1 *ctx = &ctx_u->v1; 3135dae460cSEric Biggers struct fscrypt_policy_v1 *policy = &policy_u->v1; 3145dae460cSEric Biggers 3155dae460cSEric Biggers policy->version = FSCRYPT_POLICY_V1; 3165dae460cSEric Biggers policy->contents_encryption_mode = 3175dae460cSEric Biggers ctx->contents_encryption_mode; 3185dae460cSEric Biggers policy->filenames_encryption_mode = 3195dae460cSEric Biggers ctx->filenames_encryption_mode; 3205dae460cSEric Biggers policy->flags = ctx->flags; 3215dae460cSEric Biggers memcpy(policy->master_key_descriptor, 3225dae460cSEric Biggers ctx->master_key_descriptor, 3235dae460cSEric Biggers sizeof(policy->master_key_descriptor)); 3245dae460cSEric Biggers return 0; 3255dae460cSEric Biggers } 3265dae460cSEric Biggers case FSCRYPT_CONTEXT_V2: { 3275dae460cSEric Biggers const struct fscrypt_context_v2 *ctx = &ctx_u->v2; 3285dae460cSEric Biggers struct fscrypt_policy_v2 *policy = &policy_u->v2; 3295dae460cSEric Biggers 3305dae460cSEric Biggers policy->version = FSCRYPT_POLICY_V2; 3315dae460cSEric Biggers policy->contents_encryption_mode = 3325dae460cSEric Biggers ctx->contents_encryption_mode; 3335dae460cSEric Biggers policy->filenames_encryption_mode = 3345dae460cSEric Biggers ctx->filenames_encryption_mode; 3355dae460cSEric Biggers policy->flags = ctx->flags; 3365dae460cSEric Biggers memcpy(policy->__reserved, ctx->__reserved, 3375dae460cSEric Biggers sizeof(policy->__reserved)); 3385dae460cSEric Biggers memcpy(policy->master_key_identifier, 3395dae460cSEric Biggers ctx->master_key_identifier, 3405dae460cSEric Biggers sizeof(policy->master_key_identifier)); 3415dae460cSEric Biggers return 0; 3425dae460cSEric Biggers } 3435dae460cSEric Biggers } 3445dae460cSEric Biggers /* unreachable */ 3455dae460cSEric Biggers return -EINVAL; 3465dae460cSEric Biggers } 3475dae460cSEric Biggers 3485dae460cSEric Biggers /* Retrieve an inode's encryption policy */ 3495dae460cSEric Biggers static int fscrypt_get_policy(struct inode *inode, union fscrypt_policy *policy) 3505dae460cSEric Biggers { 3515dae460cSEric Biggers const struct fscrypt_info *ci; 3525dae460cSEric Biggers union fscrypt_context ctx; 3535dae460cSEric Biggers int ret; 3545dae460cSEric Biggers 3555dae460cSEric Biggers ci = READ_ONCE(inode->i_crypt_info); 3565dae460cSEric Biggers if (ci) { 3575dae460cSEric Biggers /* key available, use the cached policy */ 3585dae460cSEric Biggers *policy = ci->ci_policy; 3595dae460cSEric Biggers return 0; 3605dae460cSEric Biggers } 3615dae460cSEric Biggers 3625dae460cSEric Biggers if (!IS_ENCRYPTED(inode)) 3635dae460cSEric Biggers return -ENODATA; 3645dae460cSEric Biggers 3655dae460cSEric Biggers ret = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx)); 3665dae460cSEric Biggers if (ret < 0) 3675dae460cSEric Biggers return (ret == -ERANGE) ? -EINVAL : ret; 3685dae460cSEric Biggers 3695dae460cSEric Biggers return fscrypt_policy_from_context(policy, &ctx, ret); 3705dae460cSEric Biggers } 3715dae460cSEric Biggers 3725dae460cSEric Biggers static int set_encryption_policy(struct inode *inode, 3735dae460cSEric Biggers const union fscrypt_policy *policy) 3745dae460cSEric Biggers { 3755dae460cSEric Biggers union fscrypt_context ctx; 3765dae460cSEric Biggers int ctxsize; 3775ab7189aSEric Biggers int err; 3785dae460cSEric Biggers 3795dae460cSEric Biggers if (!fscrypt_supported_policy(policy, inode)) 3800b81d077SJaegeuk Kim return -EINVAL; 3810b81d077SJaegeuk Kim 3825ab7189aSEric Biggers switch (policy->version) { 3835ab7189aSEric Biggers case FSCRYPT_POLICY_V1: 3845dae460cSEric Biggers /* 3855dae460cSEric Biggers * The original encryption policy version provided no way of 3865dae460cSEric Biggers * verifying that the correct master key was supplied, which was 3875dae460cSEric Biggers * insecure in scenarios where multiple users have access to the 3885dae460cSEric Biggers * same encrypted files (even just read-only access). The new 3895dae460cSEric Biggers * encryption policy version fixes this and also implies use of 3905dae460cSEric Biggers * an improved key derivation function and allows non-root users 3915dae460cSEric Biggers * to securely remove keys. So as long as compatibility with 3925dae460cSEric Biggers * old kernels isn't required, it is recommended to use the new 3935dae460cSEric Biggers * policy version for all new encrypted directories. 3945dae460cSEric Biggers */ 3955dae460cSEric Biggers pr_warn_once("%s (pid %d) is setting deprecated v1 encryption policy; recommend upgrading to v2.\n", 3965dae460cSEric Biggers current->comm, current->pid); 3975ab7189aSEric Biggers break; 3985ab7189aSEric Biggers case FSCRYPT_POLICY_V2: 3995ab7189aSEric Biggers err = fscrypt_verify_key_added(inode->i_sb, 4005ab7189aSEric Biggers policy->v2.master_key_identifier); 4015ab7189aSEric Biggers if (err) 4025ab7189aSEric Biggers return err; 403e3b1078bSEric Biggers if (policy->v2.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32) 404e3b1078bSEric Biggers pr_warn_once("%s (pid %d) is setting an IV_INO_LBLK_32 encryption policy. This should only be used if there are certain hardware limitations.\n", 405e3b1078bSEric Biggers current->comm, current->pid); 4065ab7189aSEric Biggers break; 4075ab7189aSEric Biggers default: 4085ab7189aSEric Biggers WARN_ON(1); 4095ab7189aSEric Biggers return -EINVAL; 4105dae460cSEric Biggers } 4110b81d077SJaegeuk Kim 4125dae460cSEric Biggers ctxsize = fscrypt_new_context_from_policy(&ctx, policy); 4135dae460cSEric Biggers 4145dae460cSEric Biggers return inode->i_sb->s_cop->set_context(inode, &ctx, ctxsize, NULL); 4150b81d077SJaegeuk Kim } 4160b81d077SJaegeuk Kim 417db717d8eSEric Biggers int fscrypt_ioctl_set_policy(struct file *filp, const void __user *arg) 4180b81d077SJaegeuk Kim { 4195dae460cSEric Biggers union fscrypt_policy policy; 4205dae460cSEric Biggers union fscrypt_policy existing_policy; 421ba63f23dSEric Biggers struct inode *inode = file_inode(filp); 4225dae460cSEric Biggers u8 version; 4235dae460cSEric Biggers int size; 424ba63f23dSEric Biggers int ret; 425ba63f23dSEric Biggers 4265dae460cSEric Biggers if (get_user(policy.version, (const u8 __user *)arg)) 427db717d8eSEric Biggers return -EFAULT; 428db717d8eSEric Biggers 4295dae460cSEric Biggers size = fscrypt_policy_size(&policy); 4305dae460cSEric Biggers if (size <= 0) 4315dae460cSEric Biggers return -EINVAL; 4325dae460cSEric Biggers 4335dae460cSEric Biggers /* 4345dae460cSEric Biggers * We should just copy the remaining 'size - 1' bytes here, but a 4355dae460cSEric Biggers * bizarre bug in gcc 7 and earlier (fixed by gcc r255731) causes gcc to 4365dae460cSEric Biggers * think that size can be 0 here (despite the check above!) *and* that 4375dae460cSEric Biggers * it's a compile-time constant. Thus it would think copy_from_user() 4385dae460cSEric Biggers * is passed compile-time constant ULONG_MAX, causing the compile-time 4395dae460cSEric Biggers * buffer overflow check to fail, breaking the build. This only occurred 4405dae460cSEric Biggers * when building an i386 kernel with -Os and branch profiling enabled. 4415dae460cSEric Biggers * 4425dae460cSEric Biggers * Work around it by just copying the first byte again... 4435dae460cSEric Biggers */ 4445dae460cSEric Biggers version = policy.version; 4455dae460cSEric Biggers if (copy_from_user(&policy, arg, size)) 4465dae460cSEric Biggers return -EFAULT; 4475dae460cSEric Biggers policy.version = version; 4485dae460cSEric Biggers 449163ae1c6SEric Biggers if (!inode_owner_or_capable(inode)) 450163ae1c6SEric Biggers return -EACCES; 451163ae1c6SEric Biggers 452ba63f23dSEric Biggers ret = mnt_want_write_file(filp); 453ba63f23dSEric Biggers if (ret) 454ba63f23dSEric Biggers return ret; 455ba63f23dSEric Biggers 4568906a822SEric Biggers inode_lock(inode); 4578906a822SEric Biggers 4585dae460cSEric Biggers ret = fscrypt_get_policy(inode, &existing_policy); 459efee590eSEric Biggers if (ret == -ENODATA) { 460002ced4bSEric Biggers if (!S_ISDIR(inode->i_mode)) 461dffd0cfaSEric Biggers ret = -ENOTDIR; 4625858bdadSHongjie Fang else if (IS_DEADDIR(inode)) 4635858bdadSHongjie Fang ret = -ENOENT; 464ba63f23dSEric Biggers else if (!inode->i_sb->s_cop->empty_dir(inode)) 465ba63f23dSEric Biggers ret = -ENOTEMPTY; 466ba63f23dSEric Biggers else 4675dae460cSEric Biggers ret = set_encryption_policy(inode, &policy); 4685dae460cSEric Biggers } else if (ret == -EINVAL || 4695dae460cSEric Biggers (ret == 0 && !fscrypt_policies_equal(&policy, 4705dae460cSEric Biggers &existing_policy))) { 471efee590eSEric Biggers /* The file already uses a different encryption policy. */ 4728488cd96SEric Biggers ret = -EEXIST; 4730b81d077SJaegeuk Kim } 4740b81d077SJaegeuk Kim 4758906a822SEric Biggers inode_unlock(inode); 4768906a822SEric Biggers 477ba63f23dSEric Biggers mnt_drop_write_file(filp); 478ba63f23dSEric Biggers return ret; 4790b81d077SJaegeuk Kim } 480db717d8eSEric Biggers EXPORT_SYMBOL(fscrypt_ioctl_set_policy); 4810b81d077SJaegeuk Kim 4825dae460cSEric Biggers /* Original ioctl version; can only get the original policy version */ 483db717d8eSEric Biggers int fscrypt_ioctl_get_policy(struct file *filp, void __user *arg) 4840b81d077SJaegeuk Kim { 4855dae460cSEric Biggers union fscrypt_policy policy; 4865dae460cSEric Biggers int err; 4870b81d077SJaegeuk Kim 4885dae460cSEric Biggers err = fscrypt_get_policy(file_inode(filp), &policy); 4895dae460cSEric Biggers if (err) 4905dae460cSEric Biggers return err; 4910b81d077SJaegeuk Kim 4925dae460cSEric Biggers if (policy.version != FSCRYPT_POLICY_V1) 4930b81d077SJaegeuk Kim return -EINVAL; 4940b81d077SJaegeuk Kim 4955dae460cSEric Biggers if (copy_to_user(arg, &policy, sizeof(policy.v1))) 496db717d8eSEric Biggers return -EFAULT; 4970b81d077SJaegeuk Kim return 0; 4980b81d077SJaegeuk Kim } 499db717d8eSEric Biggers EXPORT_SYMBOL(fscrypt_ioctl_get_policy); 5000b81d077SJaegeuk Kim 5015dae460cSEric Biggers /* Extended ioctl version; can get policies of any version */ 5025dae460cSEric Biggers int fscrypt_ioctl_get_policy_ex(struct file *filp, void __user *uarg) 5035dae460cSEric Biggers { 5045dae460cSEric Biggers struct fscrypt_get_policy_ex_arg arg; 5055dae460cSEric Biggers union fscrypt_policy *policy = (union fscrypt_policy *)&arg.policy; 5065dae460cSEric Biggers size_t policy_size; 5075dae460cSEric Biggers int err; 5085dae460cSEric Biggers 5095dae460cSEric Biggers /* arg is policy_size, then policy */ 5105dae460cSEric Biggers BUILD_BUG_ON(offsetof(typeof(arg), policy_size) != 0); 5115dae460cSEric Biggers BUILD_BUG_ON(offsetofend(typeof(arg), policy_size) != 5125dae460cSEric Biggers offsetof(typeof(arg), policy)); 5135dae460cSEric Biggers BUILD_BUG_ON(sizeof(arg.policy) != sizeof(*policy)); 5145dae460cSEric Biggers 5155dae460cSEric Biggers err = fscrypt_get_policy(file_inode(filp), policy); 5165dae460cSEric Biggers if (err) 5175dae460cSEric Biggers return err; 5185dae460cSEric Biggers policy_size = fscrypt_policy_size(policy); 5195dae460cSEric Biggers 5205dae460cSEric Biggers if (copy_from_user(&arg, uarg, sizeof(arg.policy_size))) 5215dae460cSEric Biggers return -EFAULT; 5225dae460cSEric Biggers 5235dae460cSEric Biggers if (policy_size > arg.policy_size) 5245dae460cSEric Biggers return -EOVERFLOW; 5255dae460cSEric Biggers arg.policy_size = policy_size; 5265dae460cSEric Biggers 5275dae460cSEric Biggers if (copy_to_user(uarg, &arg, sizeof(arg.policy_size) + policy_size)) 5285dae460cSEric Biggers return -EFAULT; 5295dae460cSEric Biggers return 0; 5305dae460cSEric Biggers } 5315dae460cSEric Biggers EXPORT_SYMBOL_GPL(fscrypt_ioctl_get_policy_ex); 5325dae460cSEric Biggers 533e98ad464SEric Biggers /* FS_IOC_GET_ENCRYPTION_NONCE: retrieve file's encryption nonce for testing */ 534e98ad464SEric Biggers int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg) 535e98ad464SEric Biggers { 536e98ad464SEric Biggers struct inode *inode = file_inode(filp); 537e98ad464SEric Biggers union fscrypt_context ctx; 538e98ad464SEric Biggers int ret; 539e98ad464SEric Biggers 540e98ad464SEric Biggers ret = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx)); 541e98ad464SEric Biggers if (ret < 0) 542e98ad464SEric Biggers return ret; 543e98ad464SEric Biggers if (!fscrypt_context_is_valid(&ctx, ret)) 544e98ad464SEric Biggers return -EINVAL; 545e98ad464SEric Biggers if (copy_to_user(arg, fscrypt_context_nonce(&ctx), 5461d6217a4SEric Biggers FSCRYPT_FILE_NONCE_SIZE)) 547e98ad464SEric Biggers return -EFAULT; 548e98ad464SEric Biggers return 0; 549e98ad464SEric Biggers } 550e98ad464SEric Biggers EXPORT_SYMBOL_GPL(fscrypt_ioctl_get_nonce); 551e98ad464SEric Biggers 552272f98f6SEric Biggers /** 553272f98f6SEric Biggers * fscrypt_has_permitted_context() - is a file's encryption policy permitted 554272f98f6SEric Biggers * within its directory? 555272f98f6SEric Biggers * 556272f98f6SEric Biggers * @parent: inode for parent directory 557272f98f6SEric Biggers * @child: inode for file being looked up, opened, or linked into @parent 558272f98f6SEric Biggers * 559272f98f6SEric Biggers * Filesystems must call this before permitting access to an inode in a 560272f98f6SEric Biggers * situation where the parent directory is encrypted (either before allowing 561272f98f6SEric Biggers * ->lookup() to succeed, or for a regular file before allowing it to be opened) 562272f98f6SEric Biggers * and before any operation that involves linking an inode into an encrypted 563272f98f6SEric Biggers * directory, including link, rename, and cross rename. It enforces the 564272f98f6SEric Biggers * constraint that within a given encrypted directory tree, all files use the 565272f98f6SEric Biggers * same encryption policy. The pre-access check is needed to detect potentially 566272f98f6SEric Biggers * malicious offline violations of this constraint, while the link and rename 567272f98f6SEric Biggers * checks are needed to prevent online violations of this constraint. 568272f98f6SEric Biggers * 569f5e55e77SEric Biggers * Return: 1 if permitted, 0 if forbidden. 570272f98f6SEric Biggers */ 5710b81d077SJaegeuk Kim int fscrypt_has_permitted_context(struct inode *parent, struct inode *child) 5720b81d077SJaegeuk Kim { 5735dae460cSEric Biggers union fscrypt_policy parent_policy, child_policy; 5745dae460cSEric Biggers int err; 5750b81d077SJaegeuk Kim 57642d97eb0SEric Biggers /* No restrictions on file types which are never encrypted */ 57742d97eb0SEric Biggers if (!S_ISREG(child->i_mode) && !S_ISDIR(child->i_mode) && 57842d97eb0SEric Biggers !S_ISLNK(child->i_mode)) 57942d97eb0SEric Biggers return 1; 58042d97eb0SEric Biggers 581272f98f6SEric Biggers /* No restrictions if the parent directory is unencrypted */ 582e0428a26SEric Biggers if (!IS_ENCRYPTED(parent)) 5830b81d077SJaegeuk Kim return 1; 584272f98f6SEric Biggers 585272f98f6SEric Biggers /* Encrypted directories must not contain unencrypted files */ 586e0428a26SEric Biggers if (!IS_ENCRYPTED(child)) 5870b81d077SJaegeuk Kim return 0; 588272f98f6SEric Biggers 589272f98f6SEric Biggers /* 590272f98f6SEric Biggers * Both parent and child are encrypted, so verify they use the same 591272f98f6SEric Biggers * encryption policy. Compare the fscrypt_info structs if the keys are 592272f98f6SEric Biggers * available, otherwise retrieve and compare the fscrypt_contexts. 593272f98f6SEric Biggers * 594272f98f6SEric Biggers * Note that the fscrypt_context retrieval will be required frequently 595272f98f6SEric Biggers * when accessing an encrypted directory tree without the key. 596272f98f6SEric Biggers * Performance-wise this is not a big deal because we already don't 597272f98f6SEric Biggers * really optimize for file access without the key (to the extent that 598272f98f6SEric Biggers * such access is even possible), given that any attempted access 599272f98f6SEric Biggers * already causes a fscrypt_context retrieval and keyring search. 600272f98f6SEric Biggers * 601272f98f6SEric Biggers * In any case, if an unexpected error occurs, fall back to "forbidden". 602272f98f6SEric Biggers */ 603272f98f6SEric Biggers 6045dae460cSEric Biggers err = fscrypt_get_encryption_info(parent); 6055dae460cSEric Biggers if (err) 6060b81d077SJaegeuk Kim return 0; 6075dae460cSEric Biggers err = fscrypt_get_encryption_info(child); 6085dae460cSEric Biggers if (err) 609272f98f6SEric Biggers return 0; 610272f98f6SEric Biggers 6115dae460cSEric Biggers err = fscrypt_get_policy(parent, &parent_policy); 6125dae460cSEric Biggers if (err) 613272f98f6SEric Biggers return 0; 614272f98f6SEric Biggers 6155dae460cSEric Biggers err = fscrypt_get_policy(child, &child_policy); 6165dae460cSEric Biggers if (err) 6175dae460cSEric Biggers return 0; 6185dae460cSEric Biggers 6195dae460cSEric Biggers return fscrypt_policies_equal(&parent_policy, &child_policy); 6200b81d077SJaegeuk Kim } 6210b81d077SJaegeuk Kim EXPORT_SYMBOL(fscrypt_has_permitted_context); 6220b81d077SJaegeuk Kim 6230b81d077SJaegeuk Kim /** 6240b81d077SJaegeuk Kim * fscrypt_inherit_context() - Sets a child context from its parent 6250b81d077SJaegeuk Kim * @parent: Parent inode from which the context is inherited. 6260b81d077SJaegeuk Kim * @child: Child inode that inherits the context from @parent. 6270b81d077SJaegeuk Kim * @fs_data: private data given by FS. 6285bbdcbbbSTheodore Ts'o * @preload: preload child i_crypt_info if true 6290b81d077SJaegeuk Kim * 6305bbdcbbbSTheodore Ts'o * Return: 0 on success, -errno on failure 6310b81d077SJaegeuk Kim */ 6320b81d077SJaegeuk Kim int fscrypt_inherit_context(struct inode *parent, struct inode *child, 6330b81d077SJaegeuk Kim void *fs_data, bool preload) 6340b81d077SJaegeuk Kim { 6355dae460cSEric Biggers union fscrypt_context ctx; 6365dae460cSEric Biggers int ctxsize; 6370b81d077SJaegeuk Kim struct fscrypt_info *ci; 6380b81d077SJaegeuk Kim int res; 6390b81d077SJaegeuk Kim 6400b81d077SJaegeuk Kim res = fscrypt_get_encryption_info(parent); 6410b81d077SJaegeuk Kim if (res < 0) 6420b81d077SJaegeuk Kim return res; 6430b81d077SJaegeuk Kim 644e37a784dSEric Biggers ci = READ_ONCE(parent->i_crypt_info); 6450b81d077SJaegeuk Kim if (ci == NULL) 6460b81d077SJaegeuk Kim return -ENOKEY; 6470b81d077SJaegeuk Kim 6485dae460cSEric Biggers ctxsize = fscrypt_new_context_from_policy(&ctx, &ci->ci_policy); 6495dae460cSEric Biggers 650af65207cSTahsin Erdogan BUILD_BUG_ON(sizeof(ctx) != FSCRYPT_SET_CONTEXT_MAX_SIZE); 6515dae460cSEric Biggers res = parent->i_sb->s_cop->set_context(child, &ctx, ctxsize, fs_data); 6520b81d077SJaegeuk Kim if (res) 6530b81d077SJaegeuk Kim return res; 6540b81d077SJaegeuk Kim return preload ? fscrypt_get_encryption_info(child): 0; 6550b81d077SJaegeuk Kim } 6560b81d077SJaegeuk Kim EXPORT_SYMBOL(fscrypt_inherit_context); 657ed318a6cSEric Biggers 658ed318a6cSEric Biggers /** 659ed318a6cSEric Biggers * fscrypt_set_test_dummy_encryption() - handle '-o test_dummy_encryption' 660ed318a6cSEric Biggers * @sb: the filesystem on which test_dummy_encryption is being specified 661ed318a6cSEric Biggers * @arg: the argument to the test_dummy_encryption option. 662ed318a6cSEric Biggers * If no argument was specified, then @arg->from == NULL. 663ed318a6cSEric Biggers * @dummy_ctx: the filesystem's current dummy context (input/output, see below) 664ed318a6cSEric Biggers * 665ed318a6cSEric Biggers * Handle the test_dummy_encryption mount option by creating a dummy encryption 666ed318a6cSEric Biggers * context, saving it in @dummy_ctx, and adding the corresponding dummy 667ed318a6cSEric Biggers * encryption key to the filesystem. If the @dummy_ctx is already set, then 668ed318a6cSEric Biggers * instead validate that it matches @arg. Don't support changing it via 669ed318a6cSEric Biggers * remount, as that is difficult to do safely. 670ed318a6cSEric Biggers * 671ed318a6cSEric Biggers * The reason we use an fscrypt_context rather than an fscrypt_policy is because 672ed318a6cSEric Biggers * we mustn't generate a new nonce each time we access a dummy-encrypted 673ed318a6cSEric Biggers * directory, as that would change the way filenames are encrypted. 674ed318a6cSEric Biggers * 675ed318a6cSEric Biggers * Return: 0 on success (dummy context set, or the same context is already set); 676ed318a6cSEric Biggers * -EEXIST if a different dummy context is already set; 677ed318a6cSEric Biggers * or another -errno value. 678ed318a6cSEric Biggers */ 679ed318a6cSEric Biggers int fscrypt_set_test_dummy_encryption(struct super_block *sb, 680ed318a6cSEric Biggers const substring_t *arg, 681ed318a6cSEric Biggers struct fscrypt_dummy_context *dummy_ctx) 682ed318a6cSEric Biggers { 6830ca2ddb0SEric Biggers const char *argstr = "v2"; 684ed318a6cSEric Biggers const char *argstr_to_free = NULL; 685ed318a6cSEric Biggers struct fscrypt_key_specifier key_spec = { 0 }; 686ed318a6cSEric Biggers int version; 687ed318a6cSEric Biggers union fscrypt_context *ctx = NULL; 688ed318a6cSEric Biggers int err; 689ed318a6cSEric Biggers 690ed318a6cSEric Biggers if (arg->from) { 691ed318a6cSEric Biggers argstr = argstr_to_free = match_strdup(arg); 692ed318a6cSEric Biggers if (!argstr) 693ed318a6cSEric Biggers return -ENOMEM; 694ed318a6cSEric Biggers } 695ed318a6cSEric Biggers 696ed318a6cSEric Biggers if (!strcmp(argstr, "v1")) { 697ed318a6cSEric Biggers version = FSCRYPT_CONTEXT_V1; 698ed318a6cSEric Biggers key_spec.type = FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR; 699ed318a6cSEric Biggers memset(key_spec.u.descriptor, 0x42, 700ed318a6cSEric Biggers FSCRYPT_KEY_DESCRIPTOR_SIZE); 701ed318a6cSEric Biggers } else if (!strcmp(argstr, "v2")) { 702ed318a6cSEric Biggers version = FSCRYPT_CONTEXT_V2; 703ed318a6cSEric Biggers key_spec.type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER; 704ed318a6cSEric Biggers /* key_spec.u.identifier gets filled in when adding the key */ 705ed318a6cSEric Biggers } else { 706ed318a6cSEric Biggers err = -EINVAL; 707ed318a6cSEric Biggers goto out; 708ed318a6cSEric Biggers } 709ed318a6cSEric Biggers 710ed318a6cSEric Biggers if (dummy_ctx->ctx) { 711ed318a6cSEric Biggers /* 712ed318a6cSEric Biggers * Note: if we ever make test_dummy_encryption support 713ed318a6cSEric Biggers * specifying other encryption settings, such as the encryption 714ed318a6cSEric Biggers * modes, we'll need to compare those settings here. 715ed318a6cSEric Biggers */ 716ed318a6cSEric Biggers if (dummy_ctx->ctx->version == version) 717ed318a6cSEric Biggers err = 0; 718ed318a6cSEric Biggers else 719ed318a6cSEric Biggers err = -EEXIST; 720ed318a6cSEric Biggers goto out; 721ed318a6cSEric Biggers } 722ed318a6cSEric Biggers 723ed318a6cSEric Biggers ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 724ed318a6cSEric Biggers if (!ctx) { 725ed318a6cSEric Biggers err = -ENOMEM; 726ed318a6cSEric Biggers goto out; 727ed318a6cSEric Biggers } 728ed318a6cSEric Biggers 729ed318a6cSEric Biggers err = fscrypt_add_test_dummy_key(sb, &key_spec); 730ed318a6cSEric Biggers if (err) 731ed318a6cSEric Biggers goto out; 732ed318a6cSEric Biggers 733ed318a6cSEric Biggers ctx->version = version; 734ed318a6cSEric Biggers switch (ctx->version) { 735ed318a6cSEric Biggers case FSCRYPT_CONTEXT_V1: 736ed318a6cSEric Biggers ctx->v1.contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS; 737ed318a6cSEric Biggers ctx->v1.filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS; 738ed318a6cSEric Biggers memcpy(ctx->v1.master_key_descriptor, key_spec.u.descriptor, 739ed318a6cSEric Biggers FSCRYPT_KEY_DESCRIPTOR_SIZE); 740ed318a6cSEric Biggers break; 741ed318a6cSEric Biggers case FSCRYPT_CONTEXT_V2: 742ed318a6cSEric Biggers ctx->v2.contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS; 743ed318a6cSEric Biggers ctx->v2.filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS; 744ed318a6cSEric Biggers memcpy(ctx->v2.master_key_identifier, key_spec.u.identifier, 745ed318a6cSEric Biggers FSCRYPT_KEY_IDENTIFIER_SIZE); 746ed318a6cSEric Biggers break; 747ed318a6cSEric Biggers default: 748ed318a6cSEric Biggers WARN_ON(1); 749ed318a6cSEric Biggers err = -EINVAL; 750ed318a6cSEric Biggers goto out; 751ed318a6cSEric Biggers } 752ed318a6cSEric Biggers dummy_ctx->ctx = ctx; 753ed318a6cSEric Biggers ctx = NULL; 754ed318a6cSEric Biggers err = 0; 755ed318a6cSEric Biggers out: 756ed318a6cSEric Biggers kfree(ctx); 757ed318a6cSEric Biggers kfree(argstr_to_free); 758ed318a6cSEric Biggers return err; 759ed318a6cSEric Biggers } 760ed318a6cSEric Biggers EXPORT_SYMBOL_GPL(fscrypt_set_test_dummy_encryption); 761ed318a6cSEric Biggers 762ed318a6cSEric Biggers /** 763ed318a6cSEric Biggers * fscrypt_show_test_dummy_encryption() - show '-o test_dummy_encryption' 764ed318a6cSEric Biggers * @seq: the seq_file to print the option to 765ed318a6cSEric Biggers * @sep: the separator character to use 766ed318a6cSEric Biggers * @sb: the filesystem whose options are being shown 767ed318a6cSEric Biggers * 768ed318a6cSEric Biggers * Show the test_dummy_encryption mount option, if it was specified. 769ed318a6cSEric Biggers * This is mainly used for /proc/mounts. 770ed318a6cSEric Biggers */ 771ed318a6cSEric Biggers void fscrypt_show_test_dummy_encryption(struct seq_file *seq, char sep, 772ed318a6cSEric Biggers struct super_block *sb) 773ed318a6cSEric Biggers { 774ed318a6cSEric Biggers const union fscrypt_context *ctx = fscrypt_get_dummy_context(sb); 775ed318a6cSEric Biggers 776ed318a6cSEric Biggers if (!ctx) 777ed318a6cSEric Biggers return; 778ed318a6cSEric Biggers seq_printf(seq, "%ctest_dummy_encryption=v%d", sep, ctx->version); 779ed318a6cSEric Biggers } 780ed318a6cSEric Biggers EXPORT_SYMBOL_GPL(fscrypt_show_test_dummy_encryption); 781