SSL fscrypt_private.h
Interaktion und PortierbarkeitC
/* SPDX-License-Identifier: GPL-2.0 */ /* * fscrypt_private.h * * Copyright (C) 2015, Google, Inc. * * Originally written by Michael Halcrow, Ildar Muslukhov, and Uday Savagaonkar. * Heavily modified since then.
*/
/* * Minimum size of an fscrypt master key. Note: a longer key will be required * if ciphers with a 256-bit security strength are used. This is just the * absolute minimum, which applies when only 128-bit encryption is used.
*/ #define FSCRYPT_MIN_KEY_SIZE 16
/* Maximum size of a raw fscrypt master key */ #define FSCRYPT_MAX_RAW_KEY_SIZE 64
/* Maximum size of a hardware-wrapped fscrypt master key */ #define FSCRYPT_MAX_HW_WRAPPED_KEY_SIZE BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE
/* Maximum size of an fscrypt master key across both key types */ #define FSCRYPT_MAX_ANY_KEY_SIZE \
MAX(FSCRYPT_MAX_RAW_KEY_SIZE, FSCRYPT_MAX_HW_WRAPPED_KEY_SIZE)
/* * FSCRYPT_MAX_KEY_SIZE is defined in the UAPI header, but the addition of * hardware-wrapped keys has made it misleading as it's only for raw keys. * Don't use it in kernel code; use one of the above constants instead.
*/ #undef FSCRYPT_MAX_KEY_SIZE
/* * This mask is passed as the third argument to the crypto_alloc_*() functions * to prevent fscrypt from using the Crypto API drivers for non-inline crypto * engines. Those drivers have been problematic for fscrypt. fscrypt users * have reported hangs and even incorrect en/decryption with these drivers. * Since going to the driver, off CPU, and back again is really slow, such * drivers can be over 50 times slower than the CPU-based code for fscrypt's * workload. Even on platforms that lack AES instructions on the CPU, using the * offloads has been shown to be slower, even staying with AES. (Of course, * Adiantum is faster still, and is the recommended option on such platforms...) * * Note that fscrypt also supports inline crypto engines. Those don't use the * Crypto API and work much better than the old-style (non-inline) engines.
*/ #define FSCRYPT_CRYPTOAPI_MASK \
(CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY | \
CRYPTO_ALG_KERN_DRIVER_ONLY)
/* * fscrypt_context - the encryption context of an inode * * This is the on-disk equivalent of an fscrypt_policy, stored alongside each * encrypted file usually in a hidden extended attribute. It contains the * fields from the fscrypt_policy, in order to identify the encryption algorithm * and key with which the file is encrypted. It also contains a nonce that was * randomly generated by fscrypt itself; this is used as KDF input or as a tweak * to cause different files to be encrypted differently.
*/ union fscrypt_context {
u8 version; struct fscrypt_context_v1 v1; struct fscrypt_context_v2 v2;
};
/* * Return the size expected for the given fscrypt_context based on its version * number, or 0 if the context version is unrecognized.
*/ staticinlineint fscrypt_context_size(constunion fscrypt_context *ctx)
{ switch (ctx->version) { case FSCRYPT_CONTEXT_V1:
BUILD_BUG_ON(sizeof(ctx->v1) != 28); returnsizeof(ctx->v1); case FSCRYPT_CONTEXT_V2:
BUILD_BUG_ON(sizeof(ctx->v2) != 40); returnsizeof(ctx->v2);
} return 0;
}
/* Check whether an fscrypt_context has a recognized version number and size */ staticinlinebool fscrypt_context_is_valid(constunion fscrypt_context *ctx, int ctx_size)
{ return ctx_size >= 1 && ctx_size == fscrypt_context_size(ctx);
}
/* Retrieve the context's nonce, assuming the context was already validated */ staticinlineconst u8 *fscrypt_context_nonce(constunion fscrypt_context *ctx)
{ switch (ctx->version) { case FSCRYPT_CONTEXT_V1: return ctx->v1.nonce; case FSCRYPT_CONTEXT_V2: return ctx->v2.nonce;
}
WARN_ON_ONCE(1); return NULL;
}
/* * Return the size expected for the given fscrypt_policy based on its version * number, or 0 if the policy version is unrecognized.
*/ staticinlineint fscrypt_policy_size(constunion fscrypt_policy *policy)
{ switch (policy->version) { case FSCRYPT_POLICY_V1: returnsizeof(policy->v1); case FSCRYPT_POLICY_V2: returnsizeof(policy->v2);
} return 0;
}
/* Return the contents encryption mode of a valid encryption policy */ staticinline u8
fscrypt_policy_contents_mode(constunion fscrypt_policy *policy)
{ switch (policy->version) { case FSCRYPT_POLICY_V1: return policy->v1.contents_encryption_mode; case FSCRYPT_POLICY_V2: return policy->v2.contents_encryption_mode;
}
BUG();
}
/* Return the filenames encryption mode of a valid encryption policy */ staticinline u8
fscrypt_policy_fnames_mode(constunion fscrypt_policy *policy)
{ switch (policy->version) { case FSCRYPT_POLICY_V1: return policy->v1.filenames_encryption_mode; case FSCRYPT_POLICY_V2: return policy->v2.filenames_encryption_mode;
}
BUG();
}
/* Return the flags (FSCRYPT_POLICY_FLAG*) of a valid encryption policy */ staticinline u8
fscrypt_policy_flags(constunion fscrypt_policy *policy)
{ switch (policy->version) { case FSCRYPT_POLICY_V1: return policy->v1.flags; case FSCRYPT_POLICY_V2: return policy->v2.flags;
}
BUG();
}
/* * For encrypted symlinks, the ciphertext length is stored at the beginning * of the string in little-endian format.
*/ struct fscrypt_symlink_data {
__le16 len; char encrypted_path[];
} __packed;
/** * struct fscrypt_prepared_key - a key prepared for actual encryption/decryption * @tfm: crypto API transform object * @blk_key: key for blk-crypto * * Normally only one of the fields will be non-NULL.
*/ struct fscrypt_prepared_key { struct crypto_sync_skcipher *tfm; #ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT struct blk_crypto_key *blk_key; #endif
};
/* * fscrypt_inode_info - the "encryption key" for an inode * * When an encrypted file's key is made available, an instance of this struct is * allocated and stored in ->i_crypt_info. Once created, it remains until the * inode is evicted.
*/ struct fscrypt_inode_info {
/* The key in a form prepared for actual encryption/decryption */ struct fscrypt_prepared_key ci_enc_key;
/* True if ci_enc_key should be freed when this struct is freed */
u8 ci_owns_key : 1;
#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT /* * True if this inode will use inline encryption (blk-crypto) instead of * the traditional filesystem-layer encryption.
*/
u8 ci_inlinecrypt : 1; #endif
/* True if ci_dirhash_key is initialized */
u8 ci_dirhash_key_initialized : 1;
/* * log2 of the data unit size (granularity of contents encryption) of * this file. This is computable from ci_policy and ci_inode but is * cached here for efficiency. Only used for regular files.
*/
u8 ci_data_unit_bits;
/* Cached value: log2 of number of data units per FS block */
u8 ci_data_units_per_block_bits;
/* Hashed inode number. Only set for IV_INO_LBLK_32 */
u32 ci_hashed_ino;
/* * Encryption mode used for this inode. It corresponds to either the * contents or filenames encryption mode, depending on the inode type.
*/ struct fscrypt_mode *ci_mode;
/* Back-pointer to the inode */ struct inode *ci_inode;
/* * The master key with which this inode was unlocked (decrypted). This * will be NULL if the master key was found in a process-subscribed * keyring rather than in the filesystem-level keyring.
*/ struct fscrypt_master_key *ci_master_key;
/* * Link in list of inodes that were unlocked with the master key. * Only used when ->ci_master_key is set.
*/ struct list_head ci_master_key_link;
/* * If non-NULL, then encryption is done using the master key directly * and ci_enc_key will equal ci_direct_key->dk_key.
*/ struct fscrypt_direct_key *ci_direct_key;
/* * This inode's hash key for filenames. This is a 128-bit SipHash-2-4 * key. This is only set for directories that use a keyed dirhash over * the plaintext filenames -- currently just casefolded directories.
*/
siphash_key_t ci_dirhash_key;
/* The encryption policy used by this inode */ union fscrypt_policy ci_policy;
/* This inode's nonce, copied from the fscrypt_context */
u8 ci_nonce[FSCRYPT_FILE_NONCE_SIZE];
};
/* * Return the number of bits used by the maximum file data unit index that is * possible on the given filesystem, using the given log2 data unit size.
*/ staticinlineint
fscrypt_max_file_dun_bits(conststruct super_block *sb, int du_bits)
{ return fls64(sb->s_maxbytes - 1) - du_bits;
}
int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key, unsignedint master_key_size);
/* * The list of contexts in which fscrypt uses HKDF. These values are used as * the first byte of the HKDF application-specific info string to guarantee that * info strings are never repeated between contexts. This ensures that all HKDF * outputs are unique and cryptographically isolated, i.e. knowledge of one * output doesn't reveal another.
*/ #define HKDF_CONTEXT_KEY_IDENTIFIER_FOR_RAW_KEY 1 /* info=<empty> */ #define HKDF_CONTEXT_PER_FILE_ENC_KEY 2 /* info=file_nonce */ #define HKDF_CONTEXT_DIRECT_KEY 3 /* info=mode_num */ #define HKDF_CONTEXT_IV_INO_LBLK_64_KEY 4 /* info=mode_num||fs_uuid */ #define HKDF_CONTEXT_DIRHASH_KEY 5 /* info=file_nonce */ #define HKDF_CONTEXT_IV_INO_LBLK_32_KEY 6 /* info=mode_num||fs_uuid */ #define HKDF_CONTEXT_INODE_HASH_KEY 7 /* info=<empty> */ #define HKDF_CONTEXT_KEY_IDENTIFIER_FOR_HW_WRAPPED_KEY \
8 /* info=<empty> */
/* * Check whether the crypto transform or blk-crypto key has been allocated in * @prep_key, depending on which encryption implementation the file will use.
*/ staticinlinebool
fscrypt_is_key_prepared(struct fscrypt_prepared_key *prep_key, conststruct fscrypt_inode_info *ci)
{ /* * The two smp_load_acquire()'s here pair with the smp_store_release()'s * in fscrypt_prepare_inline_crypt_key() and fscrypt_prepare_key(). * I.e., in some cases (namely, if this prep_key is a per-mode * encryption key) another task can publish blk_key or tfm concurrently, * executing a RELEASE barrier. We need to use smp_load_acquire() here * to safely ACQUIRE the memory the other task published.
*/ if (fscrypt_using_inline_encryption(ci)) return smp_load_acquire(&prep_key->blk_key) != NULL; return smp_load_acquire(&prep_key->tfm) != NULL;
}
/* * fscrypt_master_key_secret - secret key material of an in-use master key
*/ struct fscrypt_master_key_secret {
/* * The KDF with which subkeys of this key can be derived. * * For v1 policy keys, this isn't applicable and won't be set. * Otherwise, this KDF will be keyed by this master key if * ->is_hw_wrapped=false, or by the "software secret" that hardware * derived from this master key if ->is_hw_wrapped=true.
*/ struct fscrypt_hkdf hkdf;
/* * True if this key is a hardware-wrapped key; false if this key is a * raw key (i.e. a "software key"). For v1 policy keys this will always * be false, as v1 policy support is a legacy feature which doesn't * support newer functionality such as hardware-wrapped keys.
*/ bool is_hw_wrapped;
/* * Size of the key in bytes. This remains set even if ->bytes was * zeroized due to no longer being needed. I.e. we still remember the * size of the key even if we don't need to remember the key itself.
*/
u32 size;
/* * The bytes of the key, when still needed. This can be either a raw * key or a hardware-wrapped key, as indicated by ->is_hw_wrapped. In * the case of a raw, v2 policy key, there is no need to remember the * actual key separately from ->hkdf so this field will be zeroized as * soon as ->hkdf is initialized.
*/
u8 bytes[FSCRYPT_MAX_ANY_KEY_SIZE];
} __randomize_layout;
/* * fscrypt_master_key - an in-use master key * * This represents a master encryption key which has been added to the * filesystem. There are three high-level states that a key can be in: * * FSCRYPT_KEY_STATUS_PRESENT * Key is fully usable; it can be used to unlock inodes that are encrypted * with it (this includes being able to create new inodes). ->mk_present * indicates whether the key is in this state. ->mk_secret exists, the key * is in the keyring, and ->mk_active_refs > 0 due to ->mk_present. * * FSCRYPT_KEY_STATUS_INCOMPLETELY_REMOVED * Removal of this key has been initiated, but some inodes that were * unlocked with it are still in-use. Like ABSENT, ->mk_secret is wiped, * and the key can no longer be used to unlock inodes. Unlike ABSENT, the * key is still in the keyring; ->mk_decrypted_inodes is nonempty; and * ->mk_active_refs > 0, being equal to the size of ->mk_decrypted_inodes. * * This state transitions to ABSENT if ->mk_decrypted_inodes becomes empty, * or to PRESENT if FS_IOC_ADD_ENCRYPTION_KEY is called again for this key. * * FSCRYPT_KEY_STATUS_ABSENT * Key is fully removed. The key is no longer in the keyring, * ->mk_decrypted_inodes is empty, ->mk_active_refs == 0, ->mk_secret is * wiped, and the key can no longer be used to unlock inodes.
*/ struct fscrypt_master_key {
/* * Link in ->s_master_keys->key_hashtable. * Only valid if ->mk_active_refs > 0.
*/ struct hlist_node mk_node;
/* Semaphore that protects ->mk_secret, ->mk_users, and ->mk_present */ struct rw_semaphore mk_sem;
/* * Active and structural reference counts. An active ref guarantees * that the struct continues to exist, continues to be in the keyring * ->s_master_keys, and that any embedded subkeys (e.g. * ->mk_direct_keys) that have been prepared continue to exist. * A structural ref only guarantees that the struct continues to exist. * * There is one active ref associated with ->mk_present being true, and * one active ref for each inode in ->mk_decrypted_inodes. * * There is one structural ref associated with the active refcount being * nonzero. Finding a key in the keyring also takes a structural ref, * which is then held temporarily while the key is operated on.
*/
refcount_t mk_active_refs;
refcount_t mk_struct_refs;
struct rcu_head mk_rcu_head;
/* * The secret key material. Wiped as soon as it is no longer needed; * for details, see the fscrypt_master_key struct comment. * * Locking: protected by ->mk_sem.
*/ struct fscrypt_master_key_secret mk_secret;
/* * For v1 policy keys: an arbitrary key descriptor which was assigned by * userspace (->descriptor). * * For v2 policy keys: a cryptographic hash of this key (->identifier).
*/ struct fscrypt_key_specifier mk_spec;
/* * Keyring which contains a key of type 'key_type_fscrypt_user' for each * user who has added this key. Normally each key will be added by just * one user, but it's possible that multiple users share a key, and in * that case we need to keep track of those users so that one user can't * remove the key before the others want it removed too. * * This is NULL for v1 policy keys; those can only be added by root. * * Locking: protected by ->mk_sem. (We don't just rely on the keyrings * subsystem semaphore ->mk_users->sem, as we need support for atomic * search+insert along with proper synchronization with other fields.)
*/ struct key *mk_users;
/* * List of inodes that were unlocked using this key. This allows the * inodes to be evicted efficiently if the key is removed.
*/ struct list_head mk_decrypted_inodes;
spinlock_t mk_decrypted_inodes_lock;
/* * Per-mode encryption keys for the various types of encryption policies * that use them. Allocated and derived on-demand.
*/ struct fscrypt_prepared_key mk_direct_keys[FSCRYPT_MODE_MAX + 1]; struct fscrypt_prepared_key mk_iv_ino_lblk_64_keys[FSCRYPT_MODE_MAX + 1]; struct fscrypt_prepared_key mk_iv_ino_lblk_32_keys[FSCRYPT_MODE_MAX + 1];
/* Hash key for inode numbers. Initialized only when needed. */
siphash_key_t mk_ino_hash_key; bool mk_ino_hash_key_initialized;
/* * Whether this key is in the "present" state, i.e. fully usable. For * details, see the fscrypt_master_key struct comment. * * Locking: protected by ->mk_sem, but can be read locklessly using * READ_ONCE(). Writers must use WRITE_ONCE() when concurrent readers * are possible.
*/ bool mk_present;
} __randomize_layout;
staticinlineconstchar *master_key_spec_type( conststruct fscrypt_key_specifier *spec)
{ switch (spec->type) { case FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR: return"descriptor"; case FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER: return"identifier";
} return"[unknown]";
}
staticinlineint master_key_spec_len(conststruct fscrypt_key_specifier *spec)
{ switch (spec->type) { case FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR: return FSCRYPT_KEY_DESCRIPTOR_SIZE; case FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER: return FSCRYPT_KEY_IDENTIFIER_SIZE;
} return 0;
}
int fscrypt_get_test_dummy_key_identifier(
u8 key_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]);
int fscrypt_add_test_dummy_key(struct super_block *sb, struct fscrypt_key_specifier *key_spec);
int fscrypt_verify_key_added(struct super_block *sb, const u8 identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]);
int __init fscrypt_init_keyring(void);
/* keysetup.c */
struct fscrypt_mode { constchar *friendly_name; constchar *cipher_str; int keysize; /* key size in bytes */ int security_strength; /* security strength in bytes */ int ivsize; /* IV size in bytes */ int logged_cryptoapi_impl; int logged_blk_crypto_native; int logged_blk_crypto_fallback; enum blk_crypto_mode_num blk_crypto_mode;
};
externstruct fscrypt_mode fscrypt_modes[];
int fscrypt_prepare_key(struct fscrypt_prepared_key *prep_key, const u8 *raw_key, conststruct fscrypt_inode_info *ci);
int fscrypt_get_encryption_info(struct inode *inode, bool allow_unsupported);
/** * fscrypt_require_key() - require an inode's encryption key * @inode: the inode we need the key for * * If the inode is encrypted, set up its encryption key if not already done. * Then require that the key be present and return -ENOKEY otherwise. * * No locks are needed, and the key will live as long as the struct inode --- so * it won't go away from under you. * * Return: 0 on success, -ENOKEY if the key is missing, or another -errno code * if a problem occurred while setting up the encryption key.
*/ staticinlineint fscrypt_require_key(struct inode *inode)
{ if (IS_ENCRYPTED(inode)) { int err = fscrypt_get_encryption_info(inode, false);
if (err) return err; if (!fscrypt_has_encryption_key(inode)) return -ENOKEY;
} return 0;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.