aboutsummaryrefslogtreecommitdiff
path: root/metadata/checks.go
diff options
context:
space:
mode:
Diffstat (limited to 'metadata/checks.go')
-rw-r--r--metadata/checks.go71
1 files changed, 58 insertions, 13 deletions
diff --git a/metadata/checks.go b/metadata/checks.go
index 4fe4531..d7dea41 100644
--- a/metadata/checks.go
+++ b/metadata/checks.go
@@ -20,8 +20,11 @@
package metadata
import (
- "github.com/golang/protobuf/proto"
+ "log"
+ "math"
+
"github.com/pkg/errors"
+ "google.golang.org/protobuf/proto"
"github.com/google/fscrypt/util"
)
@@ -57,20 +60,37 @@ func (s SourceType) CheckValidity() error {
return nil
}
+// MaxParallelism is the maximum allowed value for HashingCosts.Parallelism.
+const MaxParallelism = math.MaxUint8
+
// CheckValidity ensures the hash costs will be accepted by Argon2.
func (h *HashingCosts) CheckValidity() error {
if h == nil {
return errNotInitialized
}
- if h.Time <= 0 {
- return errors.Errorf("time=%d is not positive", h.Time)
+
+ minP := int64(1)
+ p := uint8(h.Parallelism)
+ if h.Parallelism < minP || h.Parallelism > MaxParallelism {
+ if h.TruncationFixed || p == 0 {
+ return errors.Errorf("parallelism cost %d is not in range [%d, %d]",
+ h.Parallelism, minP, MaxParallelism)
+ }
+ // Previously we unconditionally casted costs.Parallelism to a uint8,
+ // so we replicate this behavior for backwards compatibility.
+ log.Printf("WARNING: Truncating parallelism cost of %d to %d", h.Parallelism, p)
}
- if h.Parallelism <= 0 {
- return errors.Errorf("parallelism=%d is not positive", h.Parallelism)
+
+ minT := int64(1)
+ maxT := int64(math.MaxUint32)
+ if h.Time < minT || h.Time > maxT {
+ return errors.Errorf("time cost %d is not in range [%d, %d]", h.Time, minT, maxT)
}
- minMemory := 8 * h.Parallelism
- if h.Memory < minMemory {
- return errors.Errorf("memory=%d is less than minimum (%d)", h.Memory, minMemory)
+
+ minM := 8 * int64(p)
+ maxM := int64(math.MaxUint32)
+ if h.Memory < minM || h.Memory > maxM {
+ return errors.Errorf("memory cost %d KiB is not in range [%d, %d]", h.Memory, minM, maxM)
}
return nil
}
@@ -119,7 +139,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 +158,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 +182,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 +197,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.