diff options
| author | Joe Richey joerichey@google.com <joerichey@google.com> | 2017-05-23 18:59:39 -0700 |
|---|---|---|
| committer | Joe Richey joerichey@google.com <joerichey@google.com> | 2017-05-31 12:45:50 -0700 |
| commit | 70ccdd078e71b36178acf87a88b6ebadf4011266 (patch) | |
| tree | e38f8afc95fecfc5b5e56fdd41b379e9f0651f3e /actions/callback.go | |
| parent | a14724d335a87c3f7a12f7f0837cfc01ec995b82 (diff) | |
actions: creating and unlocking protectors
This commit adds in the Protector struct to the actions package. This
struct represents an unlocked Protector. They can be created from a
context or they can be unlocked using some provided data. In either
case, the data is provided via a callback mechanism.
Change-Id: I066e965b8e8e0feeba61d9c0e4472dd08965cafb
Diffstat (limited to 'actions/callback.go')
| -rw-r--r-- | actions/callback.go | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/actions/callback.go b/actions/callback.go new file mode 100644 index 0000000..c1d2c8a --- /dev/null +++ b/actions/callback.go @@ -0,0 +1,101 @@ +/* + * callback.go - defines how the caller of an action function passes along a key + * to be used in this package. + * + * 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 actions + +import ( + "fscrypt/crypto" + "fscrypt/metadata" + "log" +) + +// ProtectorData is the information a caller will receive about a Protector +// before they have to return the corresponding key. This is currently a +// read-only view of metadata.ProtectorData. +type ProtectorData interface { + GetProtectorDescriptor() string + GetSource() metadata.SourceType + GetName() string + GetUid() int64 +} + +// KeyCallback is passed to a function that will require a key from the caller. +// For passphrase sources, the returned key should be a password. For raw +// sources, the returned key should be a standard cryptographic key. Consumers +// of the callback will wipe the provided key. If the callback returns an error, +// the function to which the callback is passed returns that error. Note that +// when using the key to unwrap a known key, the callback will be executed until +// the correct key is returned or an error is returned. +type KeyCallback func(data ProtectorData) (*crypto.Key, error) + +// getWrappingKey uses the provided callback to get the wrapping key +// corresponding to the ProtectorData. This runs the passphrase hash for +// passphrase sources or just relays the callback for raw sources. +func getWrappingKey(data *metadata.ProtectorData, callback KeyCallback) (*crypto.Key, error) { + // We don't need to go anything for raw keys + if data.Source == metadata.SourceType_raw_key { + return callback(data) + } + + // Run the passphrase hash for other sources. + passphrase, err := callback(data) + if err != nil { + return nil, err + } + defer passphrase.Wipe() + + log.Printf("running passphrase hash for protector %s", data.ProtectorDescriptor) + return crypto.PassphraseHash(passphrase, data.Salt, data.Costs) +} + +// unwrapProtectorKey uses the provided callback and protector data to return +// the unwrapped protector key. This will repeatedly use the callback to get the +// wrapping key until the correct key is returned or an error is returned. +func unwrapProtectorKey(data *metadata.ProtectorData, callback KeyCallback) (*crypto.Key, error) { + for { + wrappingKey, err := getWrappingKey(data, callback) + if err != nil { + return nil, err + } + + protectorKey, err := crypto.Unwrap(wrappingKey, data.WrappedKey) + wrappingKey.Wipe() + switch err { + case nil: + log.Printf("valid wrapping key for protector %s", data.ProtectorDescriptor) + return protectorKey, nil + case crypto.ErrBadAuth: + log.Printf("invalid wrapping key for protector %s", data.ProtectorDescriptor) + continue + default: + return nil, err + } + } +} + +// PolicyCallback is passed to a function that needs to unlock a policy. The +// callback is used so that the caller can specify which protector they wish to +// use to unlock a policy. The descriptor is the KeyDescriptor for the Policy, +// while for each Protector protecting the policy there is either an entry in +// protectors (if we were able to read the Protector's data). The PolicyCallback +// should either return a valid index into protectors corresponding to the +// desired protector, or an error. If the callback returns an error, the +// function to which the callback is passed returns that error. +type PolicyCallback func(descriptor string, protectors []ProtectorData) (int, error) |