From 2b25de6d445faefc28629603dd754aec9f744e60 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 15 Dec 2019 19:31:39 -0800 Subject: Metadata support for v2 encryption policies Linux v5.4 and later supports v2 encryption policies. These have several advantages over v1 encryption policies: - Their encryption keys can be added/removed to/from the filesystem by non-root users, thus gaining the benefits of the filesystem keyring while also retaining support for non-root use. - They use a more standard, secure, and flexible key derivation function. Because of this, some future kernel-level fscrypt features will be implemented for v2 policies only. - They prevent a denial-of-service attack where a user could associate the wrong key with another user's encrypted files. Prepare the fscrypt tool to support v2 encryption policies by: - Adding a policy_version field to the EncryptionOptions, i.e. to the config file and to the policy metadata files. - Using the kernel-specified algorithm to compute the key descriptor for v2 policies. - Handling setting and getting v2 policies. Actually adding/removing the keys for v2 policies to/from the kernel is left for the next patch. --- metadata/checks.go | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) (limited to 'metadata/checks.go') diff --git a/metadata/checks.go b/metadata/checks.go index 4fe4531..84fd208 100644 --- a/metadata/checks.go +++ b/metadata/checks.go @@ -119,7 +119,7 @@ func (p *ProtectorData) CheckValidity() error { if err := p.WrappedKey.CheckValidity(); err != nil { return errors.Wrap(err, "wrapped protector key") } - if err := util.CheckValidLength(DescriptorLen, len(p.ProtectorDescriptor)); err != nil { + if err := util.CheckValidLength(ProtectorDescriptorLen, len(p.ProtectorDescriptor)); err != nil { return errors.Wrap(err, "protector descriptor") } @@ -138,7 +138,17 @@ func (e *EncryptionOptions) CheckValidity() error { if err := e.Contents.CheckValidity(); err != nil { return errors.Wrap(err, "contents encryption mode") } - return errors.Wrap(e.Filenames.CheckValidity(), "filenames encryption mode") + if err := e.Filenames.CheckValidity(); err != nil { + return errors.Wrap(err, "filenames encryption mode") + } + // If PolicyVersion is unset, treat it as 1. + if e.PolicyVersion == 0 { + e.PolicyVersion = 1 + } + if e.PolicyVersion != 1 && e.PolicyVersion != 2 { + return errors.Errorf("policy version of %d is invalid", e.PolicyVersion) + } + return nil } // CheckValidity ensures the fields are valid and have the correct lengths. @@ -152,7 +162,7 @@ func (w *WrappedPolicyKey) CheckValidity() error { if err := util.CheckValidLength(PolicyKeyLen, len(w.WrappedKey.EncryptedKey)); err != nil { return errors.Wrap(err, "encrypted key") } - err := util.CheckValidLength(DescriptorLen, len(w.ProtectorDescriptor)) + err := util.CheckValidLength(ProtectorDescriptorLen, len(w.ProtectorDescriptor)) return errors.Wrap(err, "wrapping protector descriptor") } @@ -167,11 +177,26 @@ func (p *PolicyData) CheckValidity() error { return errors.Wrapf(err, "policy key slot %d", i) } } - if err := util.CheckValidLength(DescriptorLen, len(p.KeyDescriptor)); err != nil { + + if err := p.Options.CheckValidity(); err != nil { + return errors.Wrap(err, "policy options") + } + + var expectedLen int + switch p.Options.PolicyVersion { + case 1: + expectedLen = PolicyDescriptorLenV1 + case 2: + expectedLen = PolicyDescriptorLenV2 + default: + return errors.Errorf("policy version of %d is invalid", p.Options.PolicyVersion) + } + + if err := util.CheckValidLength(expectedLen, len(p.KeyDescriptor)); err != nil { return errors.Wrap(err, "policy key descriptor") } - return errors.Wrap(p.Options.CheckValidity(), "policy options") + return nil } // CheckValidity ensures the Config has all the necessary info for its Source. -- cgit v1.2.3