aboutsummaryrefslogtreecommitdiff
path: root/metadata/checks.go
diff options
context:
space:
mode:
Diffstat (limited to 'metadata/checks.go')
-rw-r--r--metadata/checks.go197
1 files changed, 197 insertions, 0 deletions
diff --git a/metadata/checks.go b/metadata/checks.go
new file mode 100644
index 0000000..5d0ce59
--- /dev/null
+++ b/metadata/checks.go
@@ -0,0 +1,197 @@
+/*
+ * checks.go - Some sanity check methods for our metadata structures
+ *
+ * Copyright 2017 Google Inc.
+ * Author: Joe Richey (joerichey@google.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package metadata
+
+import (
+ "log"
+
+ "github.com/golang/protobuf/proto"
+
+ "fscrypt/util"
+)
+
+// Metadata is the interface to all of the protobuf structures that can be
+// checked with the IsValid method.
+type Metadata interface {
+ IsValid() bool
+ proto.Message
+}
+
+// checkValidLength returns true if expected == actual, otherwise it logs an
+// InvalidLengthError.
+func checkValidLength(name string, expected int, actual int) bool {
+ if expected != actual {
+ log.Print(util.InvalidLengthError(name, expected, actual))
+ return false
+ }
+ return true
+}
+
+// IsValid ensures the mode has a name and isn't empty.
+func (m EncryptionOptions_Mode) IsValid() bool {
+ if m.String() == "" {
+ log.Print("Encryption mode cannot be the empty string")
+ return false
+ }
+ if m == EncryptionOptions_default {
+ log.Print("Encryption mode must be set to a non-default value")
+ return false
+ }
+ return true
+}
+
+// IsValid ensures the source has a name and isn't empty.
+func (s SourceType) IsValid() bool {
+ if s.String() == "" {
+ log.Print("SourceType cannot be the empty string")
+ return false
+ }
+ if s == SourceType_default {
+ log.Print("SourceType must be set to a non-default value")
+ return false
+ }
+ return true
+}
+
+// IsValid ensures the hash costs will be accepted by Argon2.
+func (h *HashingCosts) IsValid() bool {
+ if h == nil {
+ log.Print("HashingCosts not initialized")
+ return false
+ }
+ if h.Time == 0 {
+ log.Print("Hashing time cost not initialized")
+ return false
+ }
+ if h.Parallelism == 0 {
+ log.Print("Hashing parallelism cost not initialized")
+ return false
+ }
+ minMemory := 8 * h.Parallelism
+ if h.Memory < minMemory {
+ log.Printf("Hashing memory cost must be at least %d", minMemory)
+ return false
+ }
+ return true
+}
+
+// IsValid ensures our buffers are the correct length (or just exist).
+func (w *WrappedKeyData) IsValid() bool {
+ if w == nil {
+ log.Print("WrappedKeyData not initialized")
+ return false
+ }
+ if len(w.EncryptedKey) == 0 {
+ log.Print("EncryptedKey not initialized")
+ return false
+ }
+ return checkValidLength("IV", IVLen, len(w.IV)) &&
+ checkValidLength("HMAC", HMACLen, len(w.Hmac))
+}
+
+// IsValid ensures our ProtectorData has the correct fields for its source.
+func (p *ProtectorData) IsValid() bool {
+ if p == nil {
+ log.Print("ProtectorData not initialized")
+ return false
+ }
+
+ // Source specific checks
+ switch p.Source {
+ case SourceType_pam_passphrase:
+ if p.Uid < 0 {
+ log.Print("The UID should never be negative")
+ return false
+ }
+ fallthrough
+ case SourceType_custom_passphrase:
+ if !p.Costs.IsValid() || !checkValidLength("Salt", SaltLen, len(p.Salt)) {
+ return false
+ }
+ }
+
+ // Generic checks
+ return p.Source.IsValid() &&
+ p.WrappedKey.IsValid() &&
+ checkValidLength("EncryptedKey", InternalKeyLen, len(p.WrappedKey.EncryptedKey)) &&
+ checkValidLength("ProtectorDescriptor", DescriptorLen, len(p.ProtectorDescriptor))
+
+}
+
+// IsValid ensures each of the options is valid.
+func (e *EncryptionOptions) IsValid() bool {
+ if e == nil {
+ log.Print("EncryptionOptions not initialized")
+ return false
+ }
+ if _, ok := util.Index(e.Padding, paddingArray); !ok {
+ log.Printf("Padding of %d is invalid", e.Padding)
+ return false
+ }
+
+ return e.Contents.IsValid() && e.Filenames.IsValid()
+}
+
+// IsValid ensures the fields are valid and have the correct lengths.
+func (w *WrappedPolicyKey) IsValid() bool {
+ if w == nil {
+ log.Print("WrappedPolicyKey not initialized")
+ return false
+ }
+ return w.WrappedKey.IsValid() &&
+ checkValidLength("EncryptedKey", PolicyKeyLen, len(w.WrappedKey.EncryptedKey)) &&
+ checkValidLength("ProtectorDescriptor", DescriptorLen, len(w.ProtectorDescriptor))
+}
+
+// IsValid ensures the fields and each wrapped key are valid.
+func (p *PolicyData) IsValid() bool {
+ if p == nil {
+ log.Print("PolicyData not initialized")
+ return false
+ }
+ // Check each wrapped key
+ for _, w := range p.WrappedPolicyKeys {
+ if !w.IsValid() {
+ return false
+ }
+ }
+ return p.Options.IsValid() &&
+ checkValidLength("KeyDescriptor", DescriptorLen, len(p.KeyDescriptor))
+}
+
+// IsValid ensures the Config has all the necessary info for its Source.
+func (c *Config) IsValid() bool {
+ // General checks
+ if c == nil {
+ log.Print("Config not initialized")
+ return false
+ }
+ if !c.Source.IsValid() || !c.Options.IsValid() {
+ return false
+ }
+
+ // Source specific checks
+ switch c.Source {
+ case SourceType_pam_passphrase, SourceType_custom_passphrase:
+ return c.HashCosts.IsValid()
+ default:
+ return true
+ }
+}