2016-10-26 23:52:31 +00:00
package keysutil
2015-09-14 20:28:46 +00:00
import (
2016-08-30 20:29:09 +00:00
"bytes"
2015-09-14 20:28:46 +00:00
"crypto/aes"
"crypto/cipher"
2016-09-21 14:29:42 +00:00
"crypto/ecdsa"
"crypto/elliptic"
"crypto/hmac"
"crypto/rand"
2016-08-30 20:29:09 +00:00
"crypto/sha256"
2016-09-21 14:29:42 +00:00
"crypto/x509"
"encoding/asn1"
2015-09-14 20:28:46 +00:00
"encoding/base64"
"encoding/json"
2016-09-21 14:29:42 +00:00
"encoding/pem"
2016-01-15 19:02:51 +00:00
"fmt"
2016-08-30 20:29:09 +00:00
"io"
2016-09-21 14:29:42 +00:00
"math/big"
2015-09-14 20:28:46 +00:00
"strconv"
"strings"
"time"
2016-08-30 20:29:09 +00:00
"golang.org/x/crypto/hkdf"
2016-08-08 20:30:48 +00:00
uuid "github.com/hashicorp/go-uuid"
2016-07-28 19:19:27 +00:00
"github.com/hashicorp/vault/helper/errutil"
2016-07-06 16:25:40 +00:00
"github.com/hashicorp/vault/helper/jsonutil"
2015-09-14 20:28:46 +00:00
"github.com/hashicorp/vault/helper/kdf"
"github.com/hashicorp/vault/logical"
)
2016-09-21 14:29:42 +00:00
// Careful with iota; don't put anything before it in this const block because
// we need the default of zero to be the old-style KDF
2015-09-14 20:28:46 +00:00
const (
2016-10-26 23:52:31 +00:00
Kdf_hmac_sha256_counter = iota // built-in helper
Kdf_hkdf_sha256 // golang.org/x/crypto/hkdf
2015-09-14 20:28:46 +00:00
)
2016-09-21 14:29:42 +00:00
// Or this one...we need the default of zero to be the original AES256-GCM96
const (
2016-10-26 23:52:31 +00:00
KeyType_AES256_GCM96 = iota
KeyType_ECDSA_P256
2016-09-21 14:29:42 +00:00
)
const ErrTooOld = "ciphertext or signature version is disallowed by policy (too old)"
type ecdsaSignature struct {
R , S * big . Int
}
type KeyType int
func ( kt KeyType ) EncryptionSupported ( ) bool {
switch kt {
2016-10-26 23:52:31 +00:00
case KeyType_AES256_GCM96 :
2016-09-21 14:29:42 +00:00
return true
}
return false
}
func ( kt KeyType ) DecryptionSupported ( ) bool {
switch kt {
2016-10-26 23:52:31 +00:00
case KeyType_AES256_GCM96 :
2016-09-21 14:29:42 +00:00
return true
}
return false
}
func ( kt KeyType ) SigningSupported ( ) bool {
switch kt {
2016-10-26 23:52:31 +00:00
case KeyType_ECDSA_P256 :
2016-09-21 14:29:42 +00:00
return true
}
return false
}
func ( kt KeyType ) DerivationSupported ( ) bool {
switch kt {
2016-10-26 23:52:31 +00:00
case KeyType_AES256_GCM96 :
2016-09-21 14:29:42 +00:00
return true
}
return false
}
func ( kt KeyType ) String ( ) string {
switch kt {
2016-10-26 23:52:31 +00:00
case KeyType_AES256_GCM96 :
2016-09-21 14:29:42 +00:00
return "aes256-gcm96"
2016-10-26 23:52:31 +00:00
case KeyType_ECDSA_P256 :
2016-09-21 14:29:42 +00:00
return "ecdsa-p256"
}
return "[unknown]"
}
2016-08-30 20:29:09 +00:00
2016-10-26 23:52:31 +00:00
// KeyEntry stores the key and metadata
type KeyEntry struct {
2016-09-21 14:29:42 +00:00
AESKey [ ] byte ` json:"key" `
HMACKey [ ] byte ` json:"hmac_key" `
CreationTime int64 ` json:"creation_time" `
EC_X * big . Int ` json:"ec_x" `
EC_Y * big . Int ` json:"ec_y" `
EC_D * big . Int ` json:"ec_d" `
FormattedPublicKey string ` json:"public_key" `
2015-09-14 20:28:46 +00:00
}
2016-09-01 15:57:28 +00:00
// keyEntryMap is used to allow JSON marshal/unmarshal
2016-10-26 23:52:31 +00:00
type keyEntryMap map [ int ] KeyEntry
2015-09-14 20:28:46 +00:00
// MarshalJSON implements JSON marshaling
2016-09-01 15:57:28 +00:00
func ( kem keyEntryMap ) MarshalJSON ( ) ( [ ] byte , error ) {
2016-10-26 23:52:31 +00:00
intermediate := map [ string ] KeyEntry { }
2015-09-14 20:28:46 +00:00
for k , v := range kem {
intermediate [ strconv . Itoa ( k ) ] = v
}
return json . Marshal ( & intermediate )
}
// MarshalJSON implements JSON unmarshaling
2016-09-01 15:57:28 +00:00
func ( kem keyEntryMap ) UnmarshalJSON ( data [ ] byte ) error {
2016-10-26 23:52:31 +00:00
intermediate := map [ string ] KeyEntry { }
2016-07-06 16:25:40 +00:00
if err := jsonutil . DecodeJSON ( data , & intermediate ) ; err != nil {
2015-09-14 20:28:46 +00:00
return err
}
for k , v := range intermediate {
keyval , err := strconv . Atoi ( k )
if err != nil {
return err
}
kem [ keyval ] = v
}
return nil
}
// Policy is the struct used to store metadata
2016-10-26 23:52:31 +00:00
type Policy struct {
2016-09-21 14:29:42 +00:00
Name string ` json:"name" `
Key [ ] byte ` json:"key,omitempty" ` //DEPRECATED
Keys keyEntryMap ` json:"keys" `
2015-09-14 20:28:46 +00:00
2016-06-20 17:17:48 +00:00
// Derived keys MUST provide a context and the master underlying key is
// never used. If convergent encryption is true, the context will be used
// as the nonce as well.
2016-08-30 20:29:09 +00:00
Derived bool ` json:"derived" `
KDF int ` json:"kdf" `
ConvergentEncryption bool ` json:"convergent_encryption" `
2015-09-14 20:28:46 +00:00
2017-01-23 16:04:43 +00:00
// Whether the key is exportable
Exportable bool ` json:"exportable" `
2015-09-14 20:28:46 +00:00
// The minimum version of the key allowed to be used
// for decryption
MinDecryptionVersion int ` json:"min_decryption_version" `
2015-09-17 22:49:50 +00:00
2016-01-15 19:02:51 +00:00
// The latest key version in this policy
LatestVersion int ` json:"latest_version" `
2016-01-26 17:23:42 +00:00
// The latest key version in the archive. We never delete these, so this is
// a max.
2016-01-15 19:02:51 +00:00
ArchiveVersion int ` json:"archive_version" `
2015-09-17 22:49:50 +00:00
// Whether the key is allowed to be deleted
DeletionAllowed bool ` json:"deletion_allowed" `
2016-08-26 18:11:03 +00:00
// The version of the convergent nonce to use
ConvergentVersion int ` json:"convergent_version" `
2016-09-21 14:29:42 +00:00
// The type of key
Type KeyType ` json:"type" `
2015-09-14 20:28:46 +00:00
}
2016-01-26 17:23:42 +00:00
// ArchivedKeys stores old keys. This is used to keep the key loading time sane
// when there are huge numbers of rotations.
2016-09-01 15:57:28 +00:00
type archivedKeys struct {
2016-10-26 23:52:31 +00:00
Keys [ ] KeyEntry ` json:"keys" `
2016-01-15 19:02:51 +00:00
}
2016-10-26 23:52:31 +00:00
func ( p * Policy ) LoadArchive ( storage logical . Storage ) ( * archivedKeys , error ) {
2016-09-01 15:57:28 +00:00
archive := & archivedKeys { }
2016-01-15 19:02:51 +00:00
2016-01-27 17:02:32 +00:00
raw , err := storage . Get ( "archive/" + p . Name )
2016-01-15 19:02:51 +00:00
if err != nil {
return nil , err
}
if raw == nil {
2016-10-26 23:52:31 +00:00
archive . Keys = make ( [ ] KeyEntry , 0 )
2016-01-15 19:02:51 +00:00
return archive , nil
}
2016-07-06 16:25:40 +00:00
if err := jsonutil . DecodeJSON ( raw . Value , archive ) ; err != nil {
2016-01-15 19:02:51 +00:00
return nil , err
}
return archive , nil
}
2016-10-26 23:52:31 +00:00
func ( p * Policy ) storeArchive ( archive * archivedKeys , storage logical . Storage ) error {
2016-01-15 19:02:51 +00:00
// Encode the policy
buf , err := json . Marshal ( archive )
if err != nil {
return err
}
// Write the policy into storage
err = storage . Put ( & logical . StorageEntry {
2016-01-27 17:02:32 +00:00
Key : "archive/" + p . Name ,
2016-01-15 19:02:51 +00:00
Value : buf ,
} )
if err != nil {
return err
}
return nil
}
// handleArchiving manages the movement of keys to and from the policy archive.
// This should *ONLY* be called from Persist() since it assumes that the policy
// will be persisted afterwards.
2016-10-26 23:52:31 +00:00
func ( p * Policy ) handleArchiving ( storage logical . Storage ) error {
2016-09-01 15:57:28 +00:00
// We need to move keys that are no longer accessible to archivedKeys, and keys
2016-01-15 19:02:51 +00:00
// that now need to be accessible back here.
//
// For safety, because there isn't really a good reason to, we never delete
// keys from the archive even when we move them back.
2016-01-26 22:14:21 +00:00
// Check if we have the latest minimum version in the current set of keys
_ , keysContainsMinimum := p . Keys [ p . MinDecryptionVersion ]
2016-01-26 17:23:42 +00:00
// Sanity checks
switch {
case p . MinDecryptionVersion < 1 :
return fmt . Errorf ( "minimum decryption version of %d is less than 1" , p . MinDecryptionVersion )
case p . LatestVersion < 1 :
return fmt . Errorf ( "latest version of %d is less than 1" , p . LatestVersion )
2016-01-26 22:14:21 +00:00
case ! keysContainsMinimum && p . ArchiveVersion != p . LatestVersion :
return fmt . Errorf ( "need to move keys from archive but archive version not up-to-date" )
case p . ArchiveVersion > p . LatestVersion :
return fmt . Errorf ( "archive version of %d is greater than the latest version %d" ,
p . ArchiveVersion , p . LatestVersion )
2016-01-26 17:23:42 +00:00
case p . MinDecryptionVersion > p . LatestVersion :
return fmt . Errorf ( "minimum decryption version of %d is greater than the latest version %d" ,
p . MinDecryptionVersion , p . LatestVersion )
}
2016-10-26 23:52:31 +00:00
archive , err := p . LoadArchive ( storage )
2016-01-15 19:02:51 +00:00
if err != nil {
return err
}
2016-01-27 01:21:58 +00:00
if ! keysContainsMinimum {
// Need to move keys *from* archive
2016-01-15 19:02:51 +00:00
2016-01-27 01:21:58 +00:00
for i := p . MinDecryptionVersion ; i <= p . LatestVersion ; i ++ {
p . Keys [ i ] = archive . Keys [ i ]
2016-01-15 19:02:51 +00:00
}
2016-01-27 01:21:58 +00:00
return nil
}
2016-01-15 19:02:51 +00:00
2016-01-27 01:21:58 +00:00
// Need to move keys *to* archive
2016-01-15 19:02:51 +00:00
2016-01-27 01:21:58 +00:00
// We need a size that is equivalent to the latest version (number of keys)
// but adding one since slice numbering starts at 0 and we're indexing by
// key version
if len ( archive . Keys ) < p . LatestVersion + 1 {
// Increase the size of the archive slice
2016-10-26 23:52:31 +00:00
newKeys := make ( [ ] KeyEntry , p . LatestVersion + 1 )
2016-01-27 01:21:58 +00:00
copy ( newKeys , archive . Keys )
archive . Keys = newKeys
}
2016-01-15 19:02:51 +00:00
2016-01-27 01:21:58 +00:00
// We are storing all keys in the archive, so we ensure that it is up to
// date up to p.LatestVersion
for i := p . ArchiveVersion + 1 ; i <= p . LatestVersion ; i ++ {
archive . Keys [ i ] = p . Keys [ i ]
p . ArchiveVersion = i
}
err = p . storeArchive ( archive , storage )
if err != nil {
return err
}
// Perform deletion afterwards so that if there is an error saving we
// haven't messed with the current policy
for i := p . LatestVersion - len ( p . Keys ) + 1 ; i < p . MinDecryptionVersion ; i ++ {
delete ( p . Keys , i )
2016-01-15 19:02:51 +00:00
}
return nil
}
2016-10-26 23:52:31 +00:00
func ( p * Policy ) Persist ( storage logical . Storage ) error {
2016-01-26 17:23:42 +00:00
err := p . handleArchiving ( storage )
2016-01-15 19:02:51 +00:00
if err != nil {
return err
}
2015-09-14 20:28:46 +00:00
// Encode the policy
buf , err := p . Serialize ( )
if err != nil {
return err
}
// Write the policy into storage
err = storage . Put ( & logical . StorageEntry {
2016-01-26 17:23:42 +00:00
Key : "policy/" + p . Name ,
2015-09-14 20:28:46 +00:00
Value : buf ,
} )
if err != nil {
return err
}
return nil
}
2016-10-26 23:52:31 +00:00
func ( p * Policy ) Serialize ( ) ( [ ] byte , error ) {
2015-09-14 20:28:46 +00:00
return json . Marshal ( p )
}
2016-10-26 23:52:31 +00:00
func ( p * Policy ) NeedsUpgrade ( ) bool {
2016-04-26 15:39:19 +00:00
// Ensure we've moved from Key -> Keys
if p . Key != nil && len ( p . Key ) > 0 {
return true
}
2016-09-21 14:29:42 +00:00
// With archiving, past assumptions about the length of the keys map are no
// longer valid
2016-04-26 15:39:19 +00:00
if p . LatestVersion == 0 && len ( p . Keys ) != 0 {
return true
}
// We disallow setting the version to 0, since they start at 1 since moving
// to rotate-able keys, so update if it's set to 0
if p . MinDecryptionVersion == 0 {
return true
}
// On first load after an upgrade, copy keys to the archive
if p . ArchiveVersion == 0 {
return true
}
2016-08-26 18:11:03 +00:00
// Need to write the version
if p . ConvergentEncryption && p . ConvergentVersion == 0 {
return true
}
2016-09-21 15:10:57 +00:00
if p . Keys [ p . LatestVersion ] . HMACKey == nil || len ( p . Keys [ p . LatestVersion ] . HMACKey ) == 0 {
return true
}
2016-04-26 15:39:19 +00:00
return false
}
2016-10-26 23:52:31 +00:00
func ( p * Policy ) Upgrade ( storage logical . Storage ) error {
2016-04-26 15:39:19 +00:00
persistNeeded := false
// Ensure we've moved from Key -> Keys
if p . Key != nil && len ( p . Key ) > 0 {
2016-10-26 23:52:31 +00:00
p . MigrateKeyToKeysMap ( )
2016-04-26 15:39:19 +00:00
persistNeeded = true
}
2016-09-21 14:29:42 +00:00
// With archiving, past assumptions about the length of the keys map are no
// longer valid
2016-04-26 15:39:19 +00:00
if p . LatestVersion == 0 && len ( p . Keys ) != 0 {
p . LatestVersion = len ( p . Keys )
persistNeeded = true
}
// We disallow setting the version to 0, since they start at 1 since moving
// to rotate-able keys, so update if it's set to 0
if p . MinDecryptionVersion == 0 {
p . MinDecryptionVersion = 1
persistNeeded = true
}
// On first load after an upgrade, copy keys to the archive
if p . ArchiveVersion == 0 {
persistNeeded = true
}
2016-08-26 18:11:03 +00:00
if p . ConvergentEncryption && p . ConvergentVersion == 0 {
p . ConvergentVersion = 1
persistNeeded = true
}
2016-09-21 15:10:57 +00:00
if p . Keys [ p . LatestVersion ] . HMACKey == nil || len ( p . Keys [ p . LatestVersion ] . HMACKey ) == 0 {
entry := p . Keys [ p . LatestVersion ]
hmacKey , err := uuid . GenerateRandomBytes ( 32 )
if err != nil {
return err
}
entry . HMACKey = hmacKey
p . Keys [ p . LatestVersion ] = entry
persistNeeded = true
}
2016-04-26 15:39:19 +00:00
if persistNeeded {
err := p . Persist ( storage )
if err != nil {
return err
}
}
return nil
}
2016-08-30 20:29:09 +00:00
// DeriveKey is used to derive the encryption key that should be used depending
// on the policy. If derivation is disabled the raw key is used and no context
// is required, otherwise the KDF mode is used with the context to derive the
// proper key.
2016-10-26 23:52:31 +00:00
func ( p * Policy ) DeriveKey ( context [ ] byte , ver int ) ( [ ] byte , error ) {
2016-09-21 14:29:42 +00:00
if ! p . Type . DerivationSupported ( ) {
return nil , errutil . UserError { Err : fmt . Sprintf ( "derivation not supported for key type %v" , p . Type ) }
}
2016-01-15 19:02:51 +00:00
if p . Keys == nil || p . LatestVersion == 0 {
2016-07-28 19:19:27 +00:00
return nil , errutil . InternalError { Err : "unable to access the key; no key versions found" }
2015-09-14 20:28:46 +00:00
}
2016-01-15 19:02:51 +00:00
if ver <= 0 || ver > p . LatestVersion {
2016-07-28 19:19:27 +00:00
return nil , errutil . UserError { Err : "invalid key version" }
2015-09-14 20:28:46 +00:00
}
// Fast-path non-derived keys
if ! p . Derived {
2016-09-21 14:29:42 +00:00
return p . Keys [ ver ] . AESKey , nil
2015-09-14 20:28:46 +00:00
}
// Ensure a context is provided
if len ( context ) == 0 {
2016-07-28 19:19:27 +00:00
return nil , errutil . UserError { Err : "missing 'context' for key deriviation. The key was created using a derived key, which means additional, per-request information must be included in order to encrypt or decrypt information" }
2015-09-14 20:28:46 +00:00
}
2016-08-30 20:29:09 +00:00
switch p . KDF {
2016-10-26 23:52:31 +00:00
case Kdf_hmac_sha256_counter :
2015-09-14 20:28:46 +00:00
prf := kdf . HMACSHA256PRF
prfLen := kdf . HMACSHA256PRFLen
2016-09-21 14:29:42 +00:00
return kdf . CounterMode ( prf , prfLen , p . Keys [ ver ] . AESKey , context , 256 )
2016-10-26 23:52:31 +00:00
case Kdf_hkdf_sha256 :
2016-09-21 14:29:42 +00:00
reader := hkdf . New ( sha256 . New , p . Keys [ ver ] . AESKey , nil , context )
2016-08-30 20:29:09 +00:00
derBytes := bytes . NewBuffer ( nil )
derBytes . Grow ( 32 )
limReader := & io . LimitedReader {
R : reader ,
N : 32 ,
}
n , err := derBytes . ReadFrom ( limReader )
if err != nil {
return nil , errutil . InternalError { Err : fmt . Sprintf ( "error reading returned derived bytes: %v" , err ) }
}
if n != 32 {
return nil , errutil . InternalError { Err : fmt . Sprintf ( "unable to read enough derived bytes, needed 32, got %d" , n ) }
}
return derBytes . Bytes ( ) , nil
2015-09-14 20:28:46 +00:00
default :
2016-07-28 19:19:27 +00:00
return nil , errutil . InternalError { Err : "unsupported key derivation mode" }
2015-09-14 20:28:46 +00:00
}
}
2016-10-26 23:52:31 +00:00
func ( p * Policy ) Encrypt ( context , nonce [ ] byte , value string ) ( string , error ) {
2016-09-21 14:29:42 +00:00
if ! p . Type . EncryptionSupported ( ) {
return "" , errutil . UserError { Err : fmt . Sprintf ( "message encryption not supported for key type %v" , p . Type ) }
}
// Guard against a potentially invalid key type
switch p . Type {
2016-10-26 23:52:31 +00:00
case KeyType_AES256_GCM96 :
2016-09-21 14:29:42 +00:00
default :
return "" , errutil . InternalError { Err : fmt . Sprintf ( "unsupported key type %v" , p . Type ) }
}
2015-09-14 20:28:46 +00:00
// Decode the plaintext value
plaintext , err := base64 . StdEncoding . DecodeString ( value )
if err != nil {
2016-08-08 20:30:48 +00:00
return "" , errutil . UserError { Err : "failed to base64-decode plaintext" }
2015-09-14 20:28:46 +00:00
}
// Derive the key that should be used
2016-01-15 19:02:51 +00:00
key , err := p . DeriveKey ( context , p . LatestVersion )
2015-09-14 20:28:46 +00:00
if err != nil {
2016-07-11 21:37:46 +00:00
return "" , err
2015-09-14 20:28:46 +00:00
}
2016-09-21 14:29:42 +00:00
// Guard against a potentially invalid key type
switch p . Type {
2016-10-26 23:52:31 +00:00
case KeyType_AES256_GCM96 :
2015-09-14 20:28:46 +00:00
default :
2016-09-21 14:29:42 +00:00
return "" , errutil . InternalError { Err : fmt . Sprintf ( "unsupported key type %v" , p . Type ) }
2015-09-14 20:28:46 +00:00
}
// Setup the cipher
aesCipher , err := aes . NewCipher ( key )
if err != nil {
2016-07-28 19:19:27 +00:00
return "" , errutil . InternalError { Err : err . Error ( ) }
2015-09-14 20:28:46 +00:00
}
// Setup the GCM AEAD
gcm , err := cipher . NewGCM ( aesCipher )
if err != nil {
2016-07-28 19:19:27 +00:00
return "" , errutil . InternalError { Err : err . Error ( ) }
2015-09-14 20:28:46 +00:00
}
2016-06-20 17:17:48 +00:00
if p . ConvergentEncryption {
2016-09-21 14:29:42 +00:00
switch p . ConvergentVersion {
case 1 :
2016-08-26 18:11:03 +00:00
if len ( nonce ) != gcm . NonceSize ( ) {
return "" , errutil . UserError { Err : fmt . Sprintf ( "base64-decoded nonce must be %d bytes long when using convergent encryption with this key" , gcm . NonceSize ( ) ) }
}
2016-09-21 14:29:42 +00:00
default :
nonceHmac := hmac . New ( sha256 . New , context )
nonceHmac . Write ( plaintext )
nonceSum := nonceHmac . Sum ( nil )
nonce = nonceSum [ : gcm . NonceSize ( ) ]
2016-08-05 21:52:44 +00:00
}
2016-06-20 17:17:48 +00:00
} else {
2016-08-05 21:52:44 +00:00
// Compute random nonce
2016-08-08 21:00:59 +00:00
nonce , err = uuid . GenerateRandomBytes ( gcm . NonceSize ( ) )
2016-06-20 17:17:48 +00:00
if err != nil {
2016-07-28 19:19:27 +00:00
return "" , errutil . InternalError { Err : err . Error ( ) }
2016-06-20 17:17:48 +00:00
}
2015-09-14 20:28:46 +00:00
}
// Encrypt and tag with GCM
out := gcm . Seal ( nil , nonce , plaintext , nil )
// Place the encrypted data after the nonce
2016-08-05 21:52:44 +00:00
full := out
2016-08-26 21:01:56 +00:00
if ! p . ConvergentEncryption || p . ConvergentVersion > 1 {
2016-08-05 21:52:44 +00:00
full = append ( nonce , out ... )
}
2015-09-14 20:28:46 +00:00
// Convert to base64
encoded := base64 . StdEncoding . EncodeToString ( full )
// Prepend some information
2016-01-15 19:02:51 +00:00
encoded = "vault:v" + strconv . Itoa ( p . LatestVersion ) + ":" + encoded
2015-09-14 20:28:46 +00:00
return encoded , nil
}
2016-10-26 23:52:31 +00:00
func ( p * Policy ) Decrypt ( context , nonce [ ] byte , value string ) ( string , error ) {
2016-09-21 14:29:42 +00:00
if ! p . Type . DecryptionSupported ( ) {
return "" , errutil . UserError { Err : fmt . Sprintf ( "message decryption not supported for key type %v" , p . Type ) }
}
2015-09-14 20:28:46 +00:00
// Verify the prefix
if ! strings . HasPrefix ( value , "vault:v" ) {
2016-07-28 19:19:27 +00:00
return "" , errutil . UserError { Err : "invalid ciphertext: no prefix" }
2015-09-14 20:28:46 +00:00
}
2016-08-26 21:01:56 +00:00
if p . ConvergentEncryption && p . ConvergentVersion == 1 && ( nonce == nil || len ( nonce ) == 0 ) {
2016-08-05 21:52:44 +00:00
return "" , errutil . UserError { Err : "invalid convergent nonce supplied" }
}
2015-09-14 20:28:46 +00:00
splitVerCiphertext := strings . SplitN ( strings . TrimPrefix ( value , "vault:v" ) , ":" , 2 )
if len ( splitVerCiphertext ) != 2 {
2016-07-28 19:19:27 +00:00
return "" , errutil . UserError { Err : "invalid ciphertext: wrong number of fields" }
2015-09-14 20:28:46 +00:00
}
ver , err := strconv . Atoi ( splitVerCiphertext [ 0 ] )
if err != nil {
2016-07-28 19:19:27 +00:00
return "" , errutil . UserError { Err : "invalid ciphertext: version number could not be decoded" }
2015-09-14 20:28:46 +00:00
}
if ver == 0 {
2016-01-22 19:10:09 +00:00
// Compatibility mode with initial implementation, where keys start at
// zero
2015-09-14 20:28:46 +00:00
ver = 1
}
2016-04-21 20:32:06 +00:00
if ver > p . LatestVersion {
2016-07-28 19:19:27 +00:00
return "" , errutil . UserError { Err : "invalid ciphertext: version is too new" }
2016-04-21 20:32:06 +00:00
}
2015-09-14 20:28:46 +00:00
if p . MinDecryptionVersion > 0 && ver < p . MinDecryptionVersion {
2016-07-28 19:19:27 +00:00
return "" , errutil . UserError { Err : ErrTooOld }
2015-09-14 20:28:46 +00:00
}
// Derive the key that should be used
key , err := p . DeriveKey ( context , ver )
if err != nil {
return "" , err
}
2016-09-21 14:29:42 +00:00
// Guard against a potentially invalid key type
switch p . Type {
2016-10-26 23:52:31 +00:00
case KeyType_AES256_GCM96 :
2015-09-14 20:28:46 +00:00
default :
2016-09-21 14:29:42 +00:00
return "" , errutil . InternalError { Err : fmt . Sprintf ( "unsupported key type %v" , p . Type ) }
2015-09-14 20:28:46 +00:00
}
// Decode the base64
decoded , err := base64 . StdEncoding . DecodeString ( splitVerCiphertext [ 1 ] )
if err != nil {
2016-07-28 19:19:27 +00:00
return "" , errutil . UserError { Err : "invalid ciphertext: could not decode base64" }
2015-09-14 20:28:46 +00:00
}
// Setup the cipher
aesCipher , err := aes . NewCipher ( key )
if err != nil {
2016-07-28 19:19:27 +00:00
return "" , errutil . InternalError { Err : err . Error ( ) }
2015-09-14 20:28:46 +00:00
}
// Setup the GCM AEAD
gcm , err := cipher . NewGCM ( aesCipher )
if err != nil {
2016-07-28 19:19:27 +00:00
return "" , errutil . InternalError { Err : err . Error ( ) }
2015-09-14 20:28:46 +00:00
}
// Extract the nonce and ciphertext
2016-08-05 21:52:44 +00:00
var ciphertext [ ] byte
2016-08-26 21:01:56 +00:00
if p . ConvergentEncryption && p . ConvergentVersion < 2 {
2016-08-05 21:52:44 +00:00
ciphertext = decoded
} else {
nonce = decoded [ : gcm . NonceSize ( ) ]
ciphertext = decoded [ gcm . NonceSize ( ) : ]
}
2015-09-14 20:28:46 +00:00
// Verify and Decrypt
plain , err := gcm . Open ( nil , nonce , ciphertext , nil )
if err != nil {
2016-07-28 19:19:27 +00:00
return "" , errutil . UserError { Err : "invalid ciphertext: unable to decrypt" }
2015-09-14 20:28:46 +00:00
}
return base64 . StdEncoding . EncodeToString ( plain ) , nil
}
2016-10-26 23:52:31 +00:00
func ( p * Policy ) HMACKey ( version int ) ( [ ] byte , error ) {
2016-09-21 14:29:42 +00:00
if version < p . MinDecryptionVersion {
return nil , fmt . Errorf ( "key version disallowed by policy (minimum is %d)" , p . MinDecryptionVersion )
}
if version > p . LatestVersion {
return nil , fmt . Errorf ( "key version does not exist; latest key version is %d" , p . LatestVersion )
}
if p . Keys [ version ] . HMACKey == nil {
return nil , fmt . Errorf ( "no HMAC key exists for that key version" )
}
return p . Keys [ version ] . HMACKey , nil
}
2016-10-26 23:52:31 +00:00
func ( p * Policy ) Sign ( hashedInput [ ] byte ) ( string , error ) {
2016-09-21 14:29:42 +00:00
if ! p . Type . SigningSupported ( ) {
return "" , fmt . Errorf ( "message signing not supported for key type %v" , p . Type )
}
var sig [ ] byte
switch p . Type {
2016-10-26 23:52:31 +00:00
case KeyType_ECDSA_P256 :
2016-09-21 14:29:42 +00:00
keyParams := p . Keys [ p . LatestVersion ]
key := & ecdsa . PrivateKey {
PublicKey : ecdsa . PublicKey {
Curve : elliptic . P256 ( ) ,
X : keyParams . EC_X ,
Y : keyParams . EC_Y ,
} ,
D : keyParams . EC_D ,
}
r , s , err := ecdsa . Sign ( rand . Reader , key , hashedInput )
if err != nil {
return "" , err
}
marshaledSig , err := asn1 . Marshal ( ecdsaSignature {
R : r ,
S : s ,
} )
if err != nil {
return "" , err
}
sig = marshaledSig
default :
return "" , fmt . Errorf ( "unsupported key type %v" , p . Type )
}
// Convert to base64
encoded := base64 . StdEncoding . EncodeToString ( sig )
// Prepend some information
encoded = "vault:v" + strconv . Itoa ( p . LatestVersion ) + ":" + encoded
return encoded , nil
}
2016-10-26 23:52:31 +00:00
func ( p * Policy ) VerifySignature ( hashedInput [ ] byte , sig string ) ( bool , error ) {
2016-09-21 14:29:42 +00:00
if ! p . Type . SigningSupported ( ) {
return false , errutil . UserError { Err : fmt . Sprintf ( "message verification not supported for key type %v" , p . Type ) }
}
// Verify the prefix
if ! strings . HasPrefix ( sig , "vault:v" ) {
return false , errutil . UserError { Err : "invalid signature: no prefix" }
}
splitVerSig := strings . SplitN ( strings . TrimPrefix ( sig , "vault:v" ) , ":" , 2 )
if len ( splitVerSig ) != 2 {
return false , errutil . UserError { Err : "invalid signature: wrong number of fields" }
}
ver , err := strconv . Atoi ( splitVerSig [ 0 ] )
if err != nil {
return false , errutil . UserError { Err : "invalid signature: version number could not be decoded" }
}
if ver > p . LatestVersion {
return false , errutil . UserError { Err : "invalid signature: version is too new" }
}
if p . MinDecryptionVersion > 0 && ver < p . MinDecryptionVersion {
return false , errutil . UserError { Err : ErrTooOld }
}
switch p . Type {
2016-10-26 23:52:31 +00:00
case KeyType_ECDSA_P256 :
2016-09-21 14:29:42 +00:00
asn1Sig , err := base64 . StdEncoding . DecodeString ( splitVerSig [ 1 ] )
if err != nil {
return false , errutil . UserError { Err : "invalid base64 signature value" }
}
var ecdsaSig ecdsaSignature
rest , err := asn1 . Unmarshal ( asn1Sig , & ecdsaSig )
if err != nil {
return false , errutil . UserError { Err : "supplied signature is invalid" }
}
if rest != nil && len ( rest ) != 0 {
return false , errutil . UserError { Err : "supplied signature contains extra data" }
}
keyParams := p . Keys [ ver ]
key := & ecdsa . PublicKey {
Curve : elliptic . P256 ( ) ,
X : keyParams . EC_X ,
Y : keyParams . EC_Y ,
}
return ecdsa . Verify ( key , hashedInput , ecdsaSig . R , ecdsaSig . S ) , nil
default :
return false , errutil . InternalError { Err : fmt . Sprintf ( "unsupported key type %v" , p . Type ) }
}
return false , errutil . InternalError { Err : "no valid key type found" }
}
2016-10-26 23:52:31 +00:00
func ( p * Policy ) Rotate ( storage logical . Storage ) error {
2015-09-14 20:28:46 +00:00
if p . Keys == nil {
2016-01-27 01:21:58 +00:00
// This is an initial key rotation when generating a new policy. We
// don't need to call migrate here because if we've called getPolicy to
// get the policy in the first place it will have been run.
2016-09-01 15:57:28 +00:00
p . Keys = keyEntryMap { }
2015-09-14 20:28:46 +00:00
}
2016-09-21 14:29:42 +00:00
p . LatestVersion += 1
2016-10-26 23:52:31 +00:00
entry := KeyEntry {
2016-09-21 14:29:42 +00:00
CreationTime : time . Now ( ) . Unix ( ) ,
}
hmacKey , err := uuid . GenerateRandomBytes ( 32 )
2015-09-14 20:28:46 +00:00
if err != nil {
return err
}
2016-09-21 14:29:42 +00:00
entry . HMACKey = hmacKey
2016-01-15 19:02:51 +00:00
2016-09-21 14:29:42 +00:00
switch p . Type {
2016-10-26 23:52:31 +00:00
case KeyType_AES256_GCM96 :
2016-09-21 14:29:42 +00:00
// Generate a 256bit key
newKey , err := uuid . GenerateRandomBytes ( 32 )
if err != nil {
return err
}
entry . AESKey = newKey
2016-01-15 19:02:51 +00:00
2016-10-26 23:52:31 +00:00
case KeyType_ECDSA_P256 :
2016-09-21 14:29:42 +00:00
privKey , err := ecdsa . GenerateKey ( elliptic . P256 ( ) , rand . Reader )
if err != nil {
return err
}
entry . EC_D = privKey . D
entry . EC_X = privKey . X
entry . EC_Y = privKey . Y
derBytes , err := x509 . MarshalPKIXPublicKey ( privKey . Public ( ) )
if err != nil {
return fmt . Errorf ( "error marshaling public key: %s" , err )
}
pemBlock := & pem . Block {
Type : "PUBLIC KEY" ,
Bytes : derBytes ,
}
pemBytes := pem . EncodeToMemory ( pemBlock )
if pemBytes == nil || len ( pemBytes ) == 0 {
return fmt . Errorf ( "error PEM-encoding public key" )
}
entry . FormattedPublicKey = string ( pemBytes )
2015-09-14 20:28:46 +00:00
}
2016-09-21 14:29:42 +00:00
p . Keys [ p . LatestVersion ] = entry
2016-01-22 19:10:09 +00:00
// This ensures that with new key creations min decryption version is set
// to 1 rather than the int default of 0, since keys start at 1 (either
// fresh or after migration to the key map)
if p . MinDecryptionVersion == 0 {
p . MinDecryptionVersion = 1
}
2016-01-26 17:23:42 +00:00
return p . Persist ( storage )
2015-09-14 20:28:46 +00:00
}
2016-10-26 23:52:31 +00:00
func ( p * Policy ) MigrateKeyToKeysMap ( ) {
2016-09-01 15:57:28 +00:00
p . Keys = keyEntryMap {
2016-10-26 23:52:31 +00:00
1 : KeyEntry {
2016-09-21 14:29:42 +00:00
AESKey : p . Key ,
2015-09-14 20:28:46 +00:00
CreationTime : time . Now ( ) . Unix ( ) ,
} ,
}
p . Key = nil
}