Commit 1455c699 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt

Pull fscrypt updates from Eric Biggers:
 "Add an ioctl FS_IOC_GET_ENCRYPTION_NONCE which retrieves a file's
  encryption nonce.

  This makes it easier to write automated tests which verify that
  fscrypt is doing the encryption correctly"

* tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt:
  ubifs: wire up FS_IOC_GET_ENCRYPTION_NONCE
  f2fs: wire up FS_IOC_GET_ENCRYPTION_NONCE
  ext4: wire up FS_IOC_GET_ENCRYPTION_NONCE
  fscrypt: add FS_IOC_GET_ENCRYPTION_NONCE ioctl
parents 42595ce9 861261f2
...@@ -633,6 +633,17 @@ from a passphrase or other low-entropy user credential. ...@@ -633,6 +633,17 @@ from a passphrase or other low-entropy user credential.
FS_IOC_GET_ENCRYPTION_PWSALT is deprecated. Instead, prefer to FS_IOC_GET_ENCRYPTION_PWSALT is deprecated. Instead, prefer to
generate and manage any needed salt(s) in userspace. generate and manage any needed salt(s) in userspace.
Getting a file's encryption nonce
---------------------------------
Since Linux v5.7, the ioctl FS_IOC_GET_ENCRYPTION_NONCE is supported.
On encrypted files and directories it gets the inode's 16-byte nonce.
On unencrypted files and directories, it fails with ENODATA.
This ioctl can be useful for automated tests which verify that the
encryption is being done correctly. It is not needed for normal use
of fscrypt.
Adding keys Adding keys
----------- -----------
......
...@@ -76,6 +76,26 @@ static inline int fscrypt_context_size(const union fscrypt_context *ctx) ...@@ -76,6 +76,26 @@ static inline int fscrypt_context_size(const union fscrypt_context *ctx)
return 0; return 0;
} }
/* Check whether an fscrypt_context has a recognized version number and size */
static inline bool fscrypt_context_is_valid(const union 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 */
static inline const u8 *fscrypt_context_nonce(const union fscrypt_context *ctx)
{
switch (ctx->version) {
case FSCRYPT_CONTEXT_V1:
return ctx->v1.nonce;
case FSCRYPT_CONTEXT_V2:
return ctx->v2.nonce;
}
WARN_ON(1);
return NULL;
}
#undef fscrypt_policy #undef fscrypt_policy
union fscrypt_policy { union fscrypt_policy {
u8 version; u8 version;
......
...@@ -425,20 +425,8 @@ int fscrypt_get_encryption_info(struct inode *inode) ...@@ -425,20 +425,8 @@ int fscrypt_get_encryption_info(struct inode *inode)
goto out; goto out;
} }
switch (ctx.version) { memcpy(crypt_info->ci_nonce, fscrypt_context_nonce(&ctx),
case FSCRYPT_CONTEXT_V1: FS_KEY_DERIVATION_NONCE_SIZE);
memcpy(crypt_info->ci_nonce, ctx.v1.nonce,
FS_KEY_DERIVATION_NONCE_SIZE);
break;
case FSCRYPT_CONTEXT_V2:
memcpy(crypt_info->ci_nonce, ctx.v2.nonce,
FS_KEY_DERIVATION_NONCE_SIZE);
break;
default:
WARN_ON(1);
res = -EINVAL;
goto out;
}
if (!fscrypt_supported_policy(&crypt_info->ci_policy, inode)) { if (!fscrypt_supported_policy(&crypt_info->ci_policy, inode)) {
res = -EINVAL; res = -EINVAL;
......
...@@ -258,7 +258,7 @@ int fscrypt_policy_from_context(union fscrypt_policy *policy_u, ...@@ -258,7 +258,7 @@ int fscrypt_policy_from_context(union fscrypt_policy *policy_u,
{ {
memset(policy_u, 0, sizeof(*policy_u)); memset(policy_u, 0, sizeof(*policy_u));
if (ctx_size <= 0 || ctx_size != fscrypt_context_size(ctx_u)) if (!fscrypt_context_is_valid(ctx_u, ctx_size))
return -EINVAL; return -EINVAL;
switch (ctx_u->version) { switch (ctx_u->version) {
...@@ -481,6 +481,25 @@ int fscrypt_ioctl_get_policy_ex(struct file *filp, void __user *uarg) ...@@ -481,6 +481,25 @@ int fscrypt_ioctl_get_policy_ex(struct file *filp, void __user *uarg)
} }
EXPORT_SYMBOL_GPL(fscrypt_ioctl_get_policy_ex); EXPORT_SYMBOL_GPL(fscrypt_ioctl_get_policy_ex);
/* FS_IOC_GET_ENCRYPTION_NONCE: retrieve file's encryption nonce for testing */
int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg)
{
struct inode *inode = file_inode(filp);
union fscrypt_context ctx;
int ret;
ret = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx));
if (ret < 0)
return ret;
if (!fscrypt_context_is_valid(&ctx, ret))
return -EINVAL;
if (copy_to_user(arg, fscrypt_context_nonce(&ctx),
FS_KEY_DERIVATION_NONCE_SIZE))
return -EFAULT;
return 0;
}
EXPORT_SYMBOL_GPL(fscrypt_ioctl_get_nonce);
/** /**
* fscrypt_has_permitted_context() - is a file's encryption policy permitted * fscrypt_has_permitted_context() - is a file's encryption policy permitted
* within its directory? * within its directory?
......
...@@ -1210,6 +1210,11 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -1210,6 +1210,11 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
return -EOPNOTSUPP; return -EOPNOTSUPP;
return fscrypt_ioctl_get_key_status(filp, (void __user *)arg); return fscrypt_ioctl_get_key_status(filp, (void __user *)arg);
case FS_IOC_GET_ENCRYPTION_NONCE:
if (!ext4_has_feature_encrypt(sb))
return -EOPNOTSUPP;
return fscrypt_ioctl_get_nonce(filp, (void __user *)arg);
case EXT4_IOC_CLEAR_ES_CACHE: case EXT4_IOC_CLEAR_ES_CACHE:
{ {
if (!inode_owner_or_capable(inode)) if (!inode_owner_or_capable(inode))
...@@ -1370,6 +1375,7 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -1370,6 +1375,7 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case FS_IOC_REMOVE_ENCRYPTION_KEY: case FS_IOC_REMOVE_ENCRYPTION_KEY:
case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS: case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS:
case FS_IOC_GET_ENCRYPTION_KEY_STATUS: case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
case FS_IOC_GET_ENCRYPTION_NONCE:
case EXT4_IOC_SHUTDOWN: case EXT4_IOC_SHUTDOWN:
case FS_IOC_GETFSMAP: case FS_IOC_GETFSMAP:
case FS_IOC_ENABLE_VERITY: case FS_IOC_ENABLE_VERITY:
......
...@@ -2423,6 +2423,14 @@ static int f2fs_ioc_get_encryption_key_status(struct file *filp, ...@@ -2423,6 +2423,14 @@ static int f2fs_ioc_get_encryption_key_status(struct file *filp,
return fscrypt_ioctl_get_key_status(filp, (void __user *)arg); return fscrypt_ioctl_get_key_status(filp, (void __user *)arg);
} }
static int f2fs_ioc_get_encryption_nonce(struct file *filp, unsigned long arg)
{
if (!f2fs_sb_has_encrypt(F2FS_I_SB(file_inode(filp))))
return -EOPNOTSUPP;
return fscrypt_ioctl_get_nonce(filp, (void __user *)arg);
}
static int f2fs_ioc_gc(struct file *filp, unsigned long arg) static int f2fs_ioc_gc(struct file *filp, unsigned long arg)
{ {
struct inode *inode = file_inode(filp); struct inode *inode = file_inode(filp);
...@@ -3437,6 +3445,8 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -3437,6 +3445,8 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
return f2fs_ioc_remove_encryption_key_all_users(filp, arg); return f2fs_ioc_remove_encryption_key_all_users(filp, arg);
case FS_IOC_GET_ENCRYPTION_KEY_STATUS: case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
return f2fs_ioc_get_encryption_key_status(filp, arg); return f2fs_ioc_get_encryption_key_status(filp, arg);
case FS_IOC_GET_ENCRYPTION_NONCE:
return f2fs_ioc_get_encryption_nonce(filp, arg);
case F2FS_IOC_GARBAGE_COLLECT: case F2FS_IOC_GARBAGE_COLLECT:
return f2fs_ioc_gc(filp, arg); return f2fs_ioc_gc(filp, arg);
case F2FS_IOC_GARBAGE_COLLECT_RANGE: case F2FS_IOC_GARBAGE_COLLECT_RANGE:
...@@ -3611,6 +3621,7 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -3611,6 +3621,7 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case FS_IOC_REMOVE_ENCRYPTION_KEY: case FS_IOC_REMOVE_ENCRYPTION_KEY:
case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS: case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS:
case FS_IOC_GET_ENCRYPTION_KEY_STATUS: case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
case FS_IOC_GET_ENCRYPTION_NONCE:
case F2FS_IOC_GARBAGE_COLLECT: case F2FS_IOC_GARBAGE_COLLECT:
case F2FS_IOC_GARBAGE_COLLECT_RANGE: case F2FS_IOC_GARBAGE_COLLECT_RANGE:
case F2FS_IOC_WRITE_CHECKPOINT: case F2FS_IOC_WRITE_CHECKPOINT:
......
...@@ -208,6 +208,9 @@ long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -208,6 +208,9 @@ long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case FS_IOC_GET_ENCRYPTION_KEY_STATUS: case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
return fscrypt_ioctl_get_key_status(file, (void __user *)arg); return fscrypt_ioctl_get_key_status(file, (void __user *)arg);
case FS_IOC_GET_ENCRYPTION_NONCE:
return fscrypt_ioctl_get_nonce(file, (void __user *)arg);
default: default:
return -ENOTTY; return -ENOTTY;
} }
...@@ -230,6 +233,7 @@ long ubifs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -230,6 +233,7 @@ long ubifs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case FS_IOC_REMOVE_ENCRYPTION_KEY: case FS_IOC_REMOVE_ENCRYPTION_KEY:
case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS: case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS:
case FS_IOC_GET_ENCRYPTION_KEY_STATUS: case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
case FS_IOC_GET_ENCRYPTION_NONCE:
break; break;
default: default:
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
......
...@@ -139,6 +139,7 @@ extern void fscrypt_free_bounce_page(struct page *bounce_page); ...@@ -139,6 +139,7 @@ extern void fscrypt_free_bounce_page(struct page *bounce_page);
extern int fscrypt_ioctl_set_policy(struct file *, const void __user *); extern int fscrypt_ioctl_set_policy(struct file *, const void __user *);
extern int fscrypt_ioctl_get_policy(struct file *, void __user *); extern int fscrypt_ioctl_get_policy(struct file *, void __user *);
extern int fscrypt_ioctl_get_policy_ex(struct file *, void __user *); extern int fscrypt_ioctl_get_policy_ex(struct file *, void __user *);
extern int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg);
extern int fscrypt_has_permitted_context(struct inode *, struct inode *); extern int fscrypt_has_permitted_context(struct inode *, struct inode *);
extern int fscrypt_inherit_context(struct inode *, struct inode *, extern int fscrypt_inherit_context(struct inode *, struct inode *,
void *, bool); void *, bool);
...@@ -300,6 +301,11 @@ static inline int fscrypt_ioctl_get_policy_ex(struct file *filp, ...@@ -300,6 +301,11 @@ static inline int fscrypt_ioctl_get_policy_ex(struct file *filp,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static inline int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg)
{
return -EOPNOTSUPP;
}
static inline int fscrypt_has_permitted_context(struct inode *parent, static inline int fscrypt_has_permitted_context(struct inode *parent,
struct inode *child) struct inode *child)
{ {
......
...@@ -163,6 +163,7 @@ struct fscrypt_get_key_status_arg { ...@@ -163,6 +163,7 @@ struct fscrypt_get_key_status_arg {
#define FS_IOC_REMOVE_ENCRYPTION_KEY _IOWR('f', 24, struct fscrypt_remove_key_arg) #define FS_IOC_REMOVE_ENCRYPTION_KEY _IOWR('f', 24, struct fscrypt_remove_key_arg)
#define FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS _IOWR('f', 25, struct fscrypt_remove_key_arg) #define FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS _IOWR('f', 25, struct fscrypt_remove_key_arg)
#define FS_IOC_GET_ENCRYPTION_KEY_STATUS _IOWR('f', 26, struct fscrypt_get_key_status_arg) #define FS_IOC_GET_ENCRYPTION_KEY_STATUS _IOWR('f', 26, struct fscrypt_get_key_status_arg)
#define FS_IOC_GET_ENCRYPTION_NONCE _IOR('f', 27, __u8[16])
/**********************************************************************/ /**********************************************************************/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment