1package vault 2 3import ( 4 "context" 5 "crypto/aes" 6 "crypto/cipher" 7 "crypto/rand" 8 "crypto/subtle" 9 "encoding/binary" 10 "errors" 11 "fmt" 12 "io" 13 "strings" 14 "sync" 15 "time" 16 17 "github.com/armon/go-metrics" 18 "github.com/hashicorp/errwrap" 19 "github.com/hashicorp/vault/sdk/helper/jsonutil" 20 "github.com/hashicorp/vault/sdk/helper/strutil" 21 "github.com/hashicorp/vault/sdk/logical" 22 "github.com/hashicorp/vault/sdk/physical" 23 "go.uber.org/atomic" 24) 25 26const ( 27 // initialKeyTerm is the hard coded initial key term. This is 28 // used only for values that are not encrypted with the keyring. 29 initialKeyTerm = 1 30 31 // termSize the number of bytes used for the key term. 32 termSize = 4 33) 34 35// Versions of the AESGCM storage methodology 36const ( 37 AESGCMVersion1 = 0x1 38 AESGCMVersion2 = 0x2 39) 40 41// barrierInit is the JSON encoded value stored 42type barrierInit struct { 43 Version int // Version is the current format version 44 Key []byte // Key is the primary encryption key 45} 46 47// Validate AESGCMBarrier satisfies SecurityBarrier interface 48var _ SecurityBarrier = &AESGCMBarrier{} 49 50// AESGCMBarrier is a SecurityBarrier implementation that uses the AES 51// cipher core and the Galois Counter Mode block mode. It defaults to 52// the golang NONCE default value of 12 and a key size of 256 53// bit. AES-GCM is high performance, and provides both confidentiality 54// and integrity. 55type AESGCMBarrier struct { 56 backend physical.Backend 57 58 l sync.RWMutex 59 sealed bool 60 61 // keyring is used to maintain all of the encryption keys, including 62 // the active key used for encryption, but also prior keys to allow 63 // decryption of keys encrypted under previous terms. 64 keyring *Keyring 65 66 // cache is used to reduce the number of AEAD constructions we do 67 cache map[uint32]cipher.AEAD 68 cacheLock sync.RWMutex 69 70 // currentAESGCMVersionByte is prefixed to a message to allow for 71 // future versioning of barrier implementations. It's var instead 72 // of const to allow for testing 73 currentAESGCMVersionByte byte 74 75 initialized atomic.Bool 76} 77 78// NewAESGCMBarrier is used to construct a new barrier that uses 79// the provided physical backend for storage. 80func NewAESGCMBarrier(physical physical.Backend) (*AESGCMBarrier, error) { 81 b := &AESGCMBarrier{ 82 backend: physical, 83 sealed: true, 84 cache: make(map[uint32]cipher.AEAD), 85 currentAESGCMVersionByte: byte(AESGCMVersion2), 86 } 87 return b, nil 88} 89 90// Initialized checks if the barrier has been initialized 91// and has a master key set. 92func (b *AESGCMBarrier) Initialized(ctx context.Context) (bool, error) { 93 if b.initialized.Load() { 94 return true, nil 95 } 96 97 // Read the keyring file 98 keys, err := b.backend.List(ctx, keyringPrefix) 99 if err != nil { 100 return false, errwrap.Wrapf("failed to check for initialization: {{err}}", err) 101 } 102 if strutil.StrListContains(keys, "keyring") { 103 b.initialized.Store(true) 104 return true, nil 105 } 106 107 // Fallback, check for the old sentinel file 108 out, err := b.backend.Get(ctx, barrierInitPath) 109 if err != nil { 110 return false, errwrap.Wrapf("failed to check for initialization: {{err}}", err) 111 } 112 b.initialized.Store(out != nil) 113 return out != nil, nil 114} 115 116// Initialize works only if the barrier has not been initialized 117// and makes use of the given master key. 118func (b *AESGCMBarrier) Initialize(ctx context.Context, key, sealKey []byte, reader io.Reader) error { 119 // Verify the key size 120 min, max := b.KeyLength() 121 if len(key) < min || len(key) > max { 122 return fmt.Errorf("key size must be %d or %d", min, max) 123 } 124 125 // Check if already initialized 126 if alreadyInit, err := b.Initialized(ctx); err != nil { 127 return err 128 } else if alreadyInit { 129 return ErrBarrierAlreadyInit 130 } 131 132 // Generate encryption key 133 encrypt, err := b.GenerateKey(reader) 134 if err != nil { 135 return errwrap.Wrapf("failed to generate encryption key: {{err}}", err) 136 } 137 138 // Create a new keyring, install the keys 139 keyring := NewKeyring() 140 keyring = keyring.SetMasterKey(key) 141 keyring, err = keyring.AddKey(&Key{ 142 Term: 1, 143 Version: 1, 144 Value: encrypt, 145 }) 146 if err != nil { 147 return errwrap.Wrapf("failed to create keyring: {{err}}", err) 148 } 149 150 err = b.persistKeyring(ctx, keyring) 151 if err != nil { 152 return err 153 } 154 155 if len(sealKey) > 0 { 156 primary, err := b.aeadFromKey(encrypt) 157 if err != nil { 158 return err 159 } 160 161 err = b.putInternal(ctx, 1, primary, &logical.StorageEntry{ 162 Key: shamirKekPath, 163 Value: sealKey, 164 }) 165 if err != nil { 166 return errwrap.Wrapf("failed to store new seal key: {{err}}", err) 167 } 168 } 169 170 return nil 171} 172 173// persistKeyring is used to write out the keyring using the 174// master key to encrypt it. 175func (b *AESGCMBarrier) persistKeyring(ctx context.Context, keyring *Keyring) error { 176 // Create the keyring entry 177 keyringBuf, err := keyring.Serialize() 178 defer memzero(keyringBuf) 179 if err != nil { 180 return errwrap.Wrapf("failed to serialize keyring: {{err}}", err) 181 } 182 183 // Create the AES-GCM 184 gcm, err := b.aeadFromKey(keyring.MasterKey()) 185 if err != nil { 186 return err 187 } 188 189 // Encrypt the barrier init value 190 value, err := b.encrypt(keyringPath, initialKeyTerm, gcm, keyringBuf) 191 if err != nil { 192 return err 193 } 194 195 // Create the keyring physical entry 196 pe := &physical.Entry{ 197 Key: keyringPath, 198 Value: value, 199 } 200 if err := b.backend.Put(ctx, pe); err != nil { 201 return errwrap.Wrapf("failed to persist keyring: {{err}}", err) 202 } 203 204 // Serialize the master key value 205 key := &Key{ 206 Term: 1, 207 Version: 1, 208 Value: keyring.MasterKey(), 209 } 210 keyBuf, err := key.Serialize() 211 defer memzero(keyBuf) 212 if err != nil { 213 return errwrap.Wrapf("failed to serialize master key: {{err}}", err) 214 } 215 216 // Encrypt the master key 217 activeKey := keyring.ActiveKey() 218 aead, err := b.aeadFromKey(activeKey.Value) 219 if err != nil { 220 return err 221 } 222 value, err = b.encrypt(masterKeyPath, activeKey.Term, aead, keyBuf) 223 if err != nil { 224 return err 225 } 226 227 // Update the masterKeyPath for standby instances 228 pe = &physical.Entry{ 229 Key: masterKeyPath, 230 Value: value, 231 } 232 if err := b.backend.Put(ctx, pe); err != nil { 233 return errwrap.Wrapf("failed to persist master key: {{err}}", err) 234 } 235 return nil 236} 237 238// GenerateKey is used to generate a new key 239func (b *AESGCMBarrier) GenerateKey(reader io.Reader) ([]byte, error) { 240 // Generate a 256bit key 241 buf := make([]byte, 2*aes.BlockSize) 242 _, err := reader.Read(buf) 243 244 return buf, err 245} 246 247// KeyLength is used to sanity check a key 248func (b *AESGCMBarrier) KeyLength() (int, int) { 249 return aes.BlockSize, 2 * aes.BlockSize 250} 251 252// Sealed checks if the barrier has been unlocked yet. The Barrier 253// is not expected to be able to perform any CRUD until it is unsealed. 254func (b *AESGCMBarrier) Sealed() (bool, error) { 255 b.l.RLock() 256 sealed := b.sealed 257 b.l.RUnlock() 258 return sealed, nil 259} 260 261// VerifyMaster is used to check if the given key matches the master key 262func (b *AESGCMBarrier) VerifyMaster(key []byte) error { 263 b.l.RLock() 264 defer b.l.RUnlock() 265 if b.sealed { 266 return ErrBarrierSealed 267 } 268 if subtle.ConstantTimeCompare(key, b.keyring.MasterKey()) != 1 { 269 return ErrBarrierInvalidKey 270 } 271 return nil 272} 273 274// ReloadKeyring is used to re-read the underlying keyring. 275// This is used for HA deployments to ensure the latest keyring 276// is present in the leader. 277func (b *AESGCMBarrier) ReloadKeyring(ctx context.Context) error { 278 b.l.Lock() 279 defer b.l.Unlock() 280 281 // Create the AES-GCM 282 gcm, err := b.aeadFromKey(b.keyring.MasterKey()) 283 if err != nil { 284 return err 285 } 286 287 // Read in the keyring 288 out, err := b.backend.Get(ctx, keyringPath) 289 if err != nil { 290 return errwrap.Wrapf("failed to check for keyring: {{err}}", err) 291 } 292 293 // Ensure that the keyring exists. This should never happen, 294 // and indicates something really bad has happened. 295 if out == nil { 296 return errors.New("keyring unexpectedly missing") 297 } 298 299 // Verify the term is always just one 300 term := binary.BigEndian.Uint32(out.Value[:4]) 301 if term != initialKeyTerm { 302 return errors.New("term mis-match") 303 } 304 305 // Decrypt the barrier init key 306 plain, err := b.decrypt(keyringPath, gcm, out.Value) 307 defer memzero(plain) 308 if err != nil { 309 if strings.Contains(err.Error(), "message authentication failed") { 310 return ErrBarrierInvalidKey 311 } 312 return err 313 } 314 315 // Recover the keyring 316 keyring, err := DeserializeKeyring(plain) 317 if err != nil { 318 return errwrap.Wrapf("keyring deserialization failed: {{err}}", err) 319 } 320 321 // Setup the keyring and finish 322 b.cache = make(map[uint32]cipher.AEAD) 323 b.keyring = keyring 324 return nil 325} 326 327// ReloadMasterKey is used to re-read the underlying masterkey. 328// This is used for HA deployments to ensure the latest master key 329// is available for keyring reloading. 330func (b *AESGCMBarrier) ReloadMasterKey(ctx context.Context) error { 331 // Read the masterKeyPath upgrade 332 out, err := b.Get(ctx, masterKeyPath) 333 if err != nil { 334 return errwrap.Wrapf("failed to read master key path: {{err}}", err) 335 } 336 337 // The masterKeyPath could be missing (backwards incompatible), 338 // we can ignore this and attempt to make progress with the current 339 // master key. 340 if out == nil { 341 return nil 342 } 343 344 // Grab write lock and refetch 345 b.l.Lock() 346 defer b.l.Unlock() 347 348 out, err = b.lockSwitchedGet(ctx, masterKeyPath, false) 349 if err != nil { 350 return errwrap.Wrapf("failed to read master key path: {{err}}", err) 351 } 352 353 if out == nil { 354 return nil 355 } 356 357 // Deserialize the master key 358 key, err := DeserializeKey(out.Value) 359 memzero(out.Value) 360 if err != nil { 361 return errwrap.Wrapf("failed to deserialize key: {{err}}", err) 362 } 363 364 // Check if the master key is the same 365 if subtle.ConstantTimeCompare(b.keyring.MasterKey(), key.Value) == 1 { 366 return nil 367 } 368 369 // Update the master key 370 oldKeyring := b.keyring 371 b.keyring = b.keyring.SetMasterKey(key.Value) 372 oldKeyring.Zeroize(false) 373 return nil 374} 375 376// Unseal is used to provide the master key which permits the barrier 377// to be unsealed. If the key is not correct, the barrier remains sealed. 378func (b *AESGCMBarrier) Unseal(ctx context.Context, key []byte) error { 379 b.l.Lock() 380 defer b.l.Unlock() 381 382 // Do nothing if already unsealed 383 if !b.sealed { 384 return nil 385 } 386 387 // Create the AES-GCM 388 gcm, err := b.aeadFromKey(key) 389 if err != nil { 390 return err 391 } 392 393 // Read in the keyring 394 out, err := b.backend.Get(ctx, keyringPath) 395 if err != nil { 396 return errwrap.Wrapf("failed to check for keyring: {{err}}", err) 397 } 398 if out != nil { 399 // Verify the term is always just one 400 term := binary.BigEndian.Uint32(out.Value[:4]) 401 if term != initialKeyTerm { 402 return errors.New("term mis-match") 403 } 404 405 // Decrypt the barrier init key 406 plain, err := b.decrypt(keyringPath, gcm, out.Value) 407 defer memzero(plain) 408 if err != nil { 409 if strings.Contains(err.Error(), "message authentication failed") { 410 return ErrBarrierInvalidKey 411 } 412 return err 413 } 414 415 // Recover the keyring 416 keyring, err := DeserializeKeyring(plain) 417 if err != nil { 418 return errwrap.Wrapf("keyring deserialization failed: {{err}}", err) 419 } 420 421 // Setup the keyring and finish 422 b.keyring = keyring 423 b.sealed = false 424 return nil 425 } 426 427 // Read the barrier initialization key 428 out, err = b.backend.Get(ctx, barrierInitPath) 429 if err != nil { 430 return errwrap.Wrapf("failed to check for initialization: {{err}}", err) 431 } 432 if out == nil { 433 return ErrBarrierNotInit 434 } 435 436 // Verify the term is always just one 437 term := binary.BigEndian.Uint32(out.Value[:4]) 438 if term != initialKeyTerm { 439 return errors.New("term mis-match") 440 } 441 442 // Decrypt the barrier init key 443 plain, err := b.decrypt(barrierInitPath, gcm, out.Value) 444 if err != nil { 445 if strings.Contains(err.Error(), "message authentication failed") { 446 return ErrBarrierInvalidKey 447 } 448 return err 449 } 450 defer memzero(plain) 451 452 // Unmarshal the barrier init 453 var init barrierInit 454 if err := jsonutil.DecodeJSON(plain, &init); err != nil { 455 return fmt.Errorf("failed to unmarshal barrier init file") 456 } 457 458 // Setup a new keyring, this is for backwards compatibility 459 keyringNew := NewKeyring() 460 keyring := keyringNew.SetMasterKey(key) 461 462 // AddKey reuses the master, so we are only zeroizing after this call 463 defer keyringNew.Zeroize(false) 464 465 keyring, err = keyring.AddKey(&Key{ 466 Term: 1, 467 Version: 1, 468 Value: init.Key, 469 }) 470 if err != nil { 471 return errwrap.Wrapf("failed to create keyring: {{err}}", err) 472 } 473 if err := b.persistKeyring(ctx, keyring); err != nil { 474 return err 475 } 476 477 // Delete the old barrier entry 478 if err := b.backend.Delete(ctx, barrierInitPath); err != nil { 479 return errwrap.Wrapf("failed to delete barrier init file: {{err}}", err) 480 } 481 482 // Set the vault as unsealed 483 b.keyring = keyring 484 b.sealed = false 485 return nil 486} 487 488// Seal is used to re-seal the barrier. This requires the barrier to 489// be unsealed again to perform any further operations. 490func (b *AESGCMBarrier) Seal() error { 491 b.l.Lock() 492 defer b.l.Unlock() 493 494 // Remove the primary key, and seal the vault 495 b.cache = make(map[uint32]cipher.AEAD) 496 b.keyring.Zeroize(true) 497 b.keyring = nil 498 b.sealed = true 499 return nil 500} 501 502// Rotate is used to create a new encryption key. All future writes 503// should use the new key, while old values should still be decryptable. 504func (b *AESGCMBarrier) Rotate(ctx context.Context, reader io.Reader) (uint32, error) { 505 b.l.Lock() 506 defer b.l.Unlock() 507 if b.sealed { 508 return 0, ErrBarrierSealed 509 } 510 511 // Generate a new key 512 encrypt, err := b.GenerateKey(reader) 513 if err != nil { 514 return 0, errwrap.Wrapf("failed to generate encryption key: {{err}}", err) 515 } 516 517 // Get the next term 518 term := b.keyring.ActiveTerm() 519 newTerm := term + 1 520 521 // Add a new encryption key 522 newKeyring, err := b.keyring.AddKey(&Key{ 523 Term: newTerm, 524 Version: 1, 525 Value: encrypt, 526 }) 527 if err != nil { 528 return 0, errwrap.Wrapf("failed to add new encryption key: {{err}}", err) 529 } 530 531 // Persist the new keyring 532 if err := b.persistKeyring(ctx, newKeyring); err != nil { 533 return 0, err 534 } 535 536 // Swap the keyrings 537 b.keyring = newKeyring 538 return newTerm, nil 539} 540 541// CreateUpgrade creates an upgrade path key to the given term from the previous term 542func (b *AESGCMBarrier) CreateUpgrade(ctx context.Context, term uint32) error { 543 b.l.RLock() 544 if b.sealed { 545 b.l.RUnlock() 546 return ErrBarrierSealed 547 } 548 549 // Get the key for this term 550 termKey := b.keyring.TermKey(term) 551 buf, err := termKey.Serialize() 552 defer memzero(buf) 553 if err != nil { 554 b.l.RUnlock() 555 return err 556 } 557 558 // Get the AEAD for the previous term 559 prevTerm := term - 1 560 primary, err := b.aeadForTerm(prevTerm) 561 if err != nil { 562 b.l.RUnlock() 563 return err 564 } 565 566 key := fmt.Sprintf("%s%d", keyringUpgradePrefix, prevTerm) 567 value, err := b.encrypt(key, prevTerm, primary, buf) 568 b.l.RUnlock() 569 if err != nil { 570 return err 571 } 572 // Create upgrade key 573 pe := &physical.Entry{ 574 Key: key, 575 Value: value, 576 } 577 return b.backend.Put(ctx, pe) 578} 579 580// DestroyUpgrade destroys the upgrade path key to the given term 581func (b *AESGCMBarrier) DestroyUpgrade(ctx context.Context, term uint32) error { 582 path := fmt.Sprintf("%s%d", keyringUpgradePrefix, term-1) 583 return b.Delete(ctx, path) 584} 585 586// CheckUpgrade looks for an upgrade to the current term and installs it 587func (b *AESGCMBarrier) CheckUpgrade(ctx context.Context) (bool, uint32, error) { 588 b.l.RLock() 589 if b.sealed { 590 b.l.RUnlock() 591 return false, 0, ErrBarrierSealed 592 } 593 594 // Get the current term 595 activeTerm := b.keyring.ActiveTerm() 596 597 // Check for an upgrade key 598 upgrade := fmt.Sprintf("%s%d", keyringUpgradePrefix, activeTerm) 599 entry, err := b.lockSwitchedGet(ctx, upgrade, false) 600 if err != nil { 601 b.l.RUnlock() 602 return false, 0, err 603 } 604 605 // Nothing to do if no upgrade 606 if entry == nil { 607 b.l.RUnlock() 608 return false, 0, nil 609 } 610 611 // Upgrade from read lock to write lock 612 b.l.RUnlock() 613 b.l.Lock() 614 defer b.l.Unlock() 615 616 // Validate base cases and refetch values again 617 618 if b.sealed { 619 return false, 0, ErrBarrierSealed 620 } 621 622 activeTerm = b.keyring.ActiveTerm() 623 624 upgrade = fmt.Sprintf("%s%d", keyringUpgradePrefix, activeTerm) 625 entry, err = b.lockSwitchedGet(ctx, upgrade, false) 626 if err != nil { 627 return false, 0, err 628 } 629 630 if entry == nil { 631 return false, 0, nil 632 } 633 634 // Deserialize the key 635 key, err := DeserializeKey(entry.Value) 636 memzero(entry.Value) 637 if err != nil { 638 return false, 0, err 639 } 640 641 // Update the keyring 642 newKeyring, err := b.keyring.AddKey(key) 643 if err != nil { 644 return false, 0, errwrap.Wrapf("failed to add new encryption key: {{err}}", err) 645 } 646 b.keyring = newKeyring 647 648 // Done! 649 return true, key.Term, nil 650} 651 652// ActiveKeyInfo is used to inform details about the active key 653func (b *AESGCMBarrier) ActiveKeyInfo() (*KeyInfo, error) { 654 b.l.RLock() 655 defer b.l.RUnlock() 656 if b.sealed { 657 return nil, ErrBarrierSealed 658 } 659 660 // Determine the key install time 661 term := b.keyring.ActiveTerm() 662 key := b.keyring.TermKey(term) 663 664 // Return the key info 665 info := &KeyInfo{ 666 Term: int(term), 667 InstallTime: key.InstallTime, 668 } 669 return info, nil 670} 671 672// Rekey is used to change the master key used to protect the keyring 673func (b *AESGCMBarrier) Rekey(ctx context.Context, key []byte) error { 674 b.l.Lock() 675 defer b.l.Unlock() 676 677 newKeyring, err := b.updateMasterKeyCommon(key) 678 if err != nil { 679 return err 680 } 681 682 // Persist the new keyring 683 if err := b.persistKeyring(ctx, newKeyring); err != nil { 684 return err 685 } 686 687 // Swap the keyrings 688 oldKeyring := b.keyring 689 b.keyring = newKeyring 690 oldKeyring.Zeroize(false) 691 return nil 692} 693 694// SetMasterKey updates the keyring's in-memory master key but does not persist 695// anything to storage 696func (b *AESGCMBarrier) SetMasterKey(key []byte) error { 697 b.l.Lock() 698 defer b.l.Unlock() 699 700 newKeyring, err := b.updateMasterKeyCommon(key) 701 if err != nil { 702 return err 703 } 704 705 // Swap the keyrings 706 oldKeyring := b.keyring 707 b.keyring = newKeyring 708 oldKeyring.Zeroize(false) 709 return nil 710} 711 712// Performs common tasks related to updating the master key; note that the lock 713// must be held before calling this function 714func (b *AESGCMBarrier) updateMasterKeyCommon(key []byte) (*Keyring, error) { 715 if b.sealed { 716 return nil, ErrBarrierSealed 717 } 718 719 // Verify the key size 720 min, max := b.KeyLength() 721 if len(key) < min || len(key) > max { 722 return nil, fmt.Errorf("key size must be %d or %d", min, max) 723 } 724 725 return b.keyring.SetMasterKey(key), nil 726} 727 728// Put is used to insert or update an entry 729func (b *AESGCMBarrier) Put(ctx context.Context, entry *logical.StorageEntry) error { 730 defer metrics.MeasureSince([]string{"barrier", "put"}, time.Now()) 731 b.l.RLock() 732 if b.sealed { 733 b.l.RUnlock() 734 return ErrBarrierSealed 735 } 736 737 term := b.keyring.ActiveTerm() 738 primary, err := b.aeadForTerm(term) 739 b.l.RUnlock() 740 if err != nil { 741 return err 742 } 743 744 return b.putInternal(ctx, term, primary, entry) 745} 746 747func (b *AESGCMBarrier) putInternal(ctx context.Context, term uint32, primary cipher.AEAD, entry *logical.StorageEntry) error { 748 value, err := b.encrypt(entry.Key, term, primary, entry.Value) 749 if err != nil { 750 return err 751 } 752 pe := &physical.Entry{ 753 Key: entry.Key, 754 Value: value, 755 SealWrap: entry.SealWrap, 756 } 757 return b.backend.Put(ctx, pe) 758} 759 760// Get is used to fetch an entry 761func (b *AESGCMBarrier) Get(ctx context.Context, key string) (*logical.StorageEntry, error) { 762 return b.lockSwitchedGet(ctx, key, true) 763} 764 765func (b *AESGCMBarrier) lockSwitchedGet(ctx context.Context, key string, getLock bool) (*logical.StorageEntry, error) { 766 defer metrics.MeasureSince([]string{"barrier", "get"}, time.Now()) 767 if getLock { 768 b.l.RLock() 769 } 770 if b.sealed { 771 if getLock { 772 b.l.RUnlock() 773 } 774 return nil, ErrBarrierSealed 775 } 776 777 // Read the key from the backend 778 pe, err := b.backend.Get(ctx, key) 779 if err != nil { 780 if getLock { 781 b.l.RUnlock() 782 } 783 return nil, err 784 } else if pe == nil { 785 if getLock { 786 b.l.RUnlock() 787 } 788 return nil, nil 789 } 790 791 if len(pe.Value) < 4 { 792 if getLock { 793 b.l.RUnlock() 794 } 795 return nil, errors.New("invalid value") 796 } 797 798 // Verify the term 799 term := binary.BigEndian.Uint32(pe.Value[:4]) 800 801 // Get the GCM by term 802 // It is expensive to do this first but it is not a 803 // normal case that this won't match 804 gcm, err := b.aeadForTerm(term) 805 if getLock { 806 b.l.RUnlock() 807 } 808 if err != nil { 809 return nil, err 810 } 811 if gcm == nil { 812 return nil, fmt.Errorf("no decryption key available for term %d", term) 813 } 814 815 // Decrypt the ciphertext 816 plain, err := b.decrypt(key, gcm, pe.Value) 817 if err != nil { 818 return nil, errwrap.Wrapf("decryption failed: {{err}}", err) 819 } 820 821 // Wrap in a logical entry 822 entry := &logical.StorageEntry{ 823 Key: key, 824 Value: plain, 825 SealWrap: pe.SealWrap, 826 } 827 return entry, nil 828} 829 830// Delete is used to permanently delete an entry 831func (b *AESGCMBarrier) Delete(ctx context.Context, key string) error { 832 defer metrics.MeasureSince([]string{"barrier", "delete"}, time.Now()) 833 b.l.RLock() 834 sealed := b.sealed 835 b.l.RUnlock() 836 if sealed { 837 return ErrBarrierSealed 838 } 839 840 return b.backend.Delete(ctx, key) 841} 842 843// List is used ot list all the keys under a given 844// prefix, up to the next prefix. 845func (b *AESGCMBarrier) List(ctx context.Context, prefix string) ([]string, error) { 846 defer metrics.MeasureSince([]string{"barrier", "list"}, time.Now()) 847 b.l.RLock() 848 sealed := b.sealed 849 b.l.RUnlock() 850 if sealed { 851 return nil, ErrBarrierSealed 852 } 853 854 return b.backend.List(ctx, prefix) 855} 856 857// aeadForTerm returns the AES-GCM AEAD for the given term 858func (b *AESGCMBarrier) aeadForTerm(term uint32) (cipher.AEAD, error) { 859 // Check for the keyring 860 keyring := b.keyring 861 if keyring == nil { 862 return nil, nil 863 } 864 865 // Check the cache for the aead 866 b.cacheLock.RLock() 867 aead, ok := b.cache[term] 868 b.cacheLock.RUnlock() 869 if ok { 870 return aead, nil 871 } 872 873 // Read the underlying key 874 key := keyring.TermKey(term) 875 if key == nil { 876 return nil, nil 877 } 878 879 // Create a new aead 880 aead, err := b.aeadFromKey(key.Value) 881 if err != nil { 882 return nil, err 883 } 884 885 // Update the cache 886 b.cacheLock.Lock() 887 b.cache[term] = aead 888 b.cacheLock.Unlock() 889 return aead, nil 890} 891 892// aeadFromKey returns an AES-GCM AEAD using the given key. 893func (b *AESGCMBarrier) aeadFromKey(key []byte) (cipher.AEAD, error) { 894 // Create the AES cipher 895 aesCipher, err := aes.NewCipher(key) 896 if err != nil { 897 return nil, errwrap.Wrapf("failed to create cipher: {{err}}", err) 898 } 899 900 // Create the GCM mode AEAD 901 gcm, err := cipher.NewGCM(aesCipher) 902 if err != nil { 903 return nil, fmt.Errorf("failed to initialize GCM mode") 904 } 905 return gcm, nil 906} 907 908// encrypt is used to encrypt a value 909func (b *AESGCMBarrier) encrypt(path string, term uint32, gcm cipher.AEAD, plain []byte) ([]byte, error) { 910 // Allocate the output buffer with room for tern, version byte, 911 // nonce, GCM tag and the plaintext 912 capacity := termSize + 1 + gcm.NonceSize() + gcm.Overhead() + len(plain) 913 size := termSize + 1 + gcm.NonceSize() 914 out := make([]byte, size, capacity) 915 916 // Set the key term 917 binary.BigEndian.PutUint32(out[:4], term) 918 919 // Set the version byte 920 out[4] = b.currentAESGCMVersionByte 921 922 // Generate a random nonce 923 nonce := out[5 : 5+gcm.NonceSize()] 924 n, err := rand.Read(nonce) 925 if err != nil { 926 return nil, err 927 } 928 if n != len(nonce) { 929 return nil, errors.New("unable to read enough random bytes to fill gcm nonce") 930 } 931 932 // Seal the output 933 switch b.currentAESGCMVersionByte { 934 case AESGCMVersion1: 935 out = gcm.Seal(out, nonce, plain, nil) 936 case AESGCMVersion2: 937 aad := []byte(nil) 938 if path != "" { 939 aad = []byte(path) 940 } 941 out = gcm.Seal(out, nonce, plain, aad) 942 default: 943 panic("Unknown AESGCM version") 944 } 945 946 return out, nil 947} 948 949// decrypt is used to decrypt a value using the keyring 950func (b *AESGCMBarrier) decrypt(path string, gcm cipher.AEAD, cipher []byte) ([]byte, error) { 951 // Capture the parts 952 nonce := cipher[5 : 5+gcm.NonceSize()] 953 raw := cipher[5+gcm.NonceSize():] 954 out := make([]byte, 0, len(raw)-gcm.NonceSize()) 955 956 // Attempt to open 957 switch cipher[4] { 958 case AESGCMVersion1: 959 return gcm.Open(out, nonce, raw, nil) 960 case AESGCMVersion2: 961 aad := []byte(nil) 962 if path != "" { 963 aad = []byte(path) 964 } 965 return gcm.Open(out, nonce, raw, aad) 966 default: 967 return nil, fmt.Errorf("version bytes mis-match") 968 } 969} 970 971// Encrypt is used to encrypt in-memory for the BarrierEncryptor interface 972func (b *AESGCMBarrier) Encrypt(ctx context.Context, key string, plaintext []byte) ([]byte, error) { 973 b.l.RLock() 974 if b.sealed { 975 b.l.RUnlock() 976 return nil, ErrBarrierSealed 977 } 978 979 term := b.keyring.ActiveTerm() 980 primary, err := b.aeadForTerm(term) 981 b.l.RUnlock() 982 if err != nil { 983 return nil, err 984 } 985 986 ciphertext, err := b.encrypt(key, term, primary, plaintext) 987 if err != nil { 988 return nil, err 989 } 990 return ciphertext, nil 991} 992 993// Decrypt is used to decrypt in-memory for the BarrierEncryptor interface 994func (b *AESGCMBarrier) Decrypt(ctx context.Context, key string, ciphertext []byte) ([]byte, error) { 995 b.l.RLock() 996 if b.sealed { 997 b.l.RUnlock() 998 return nil, ErrBarrierSealed 999 } 1000 1001 // Verify the term 1002 term := binary.BigEndian.Uint32(ciphertext[:4]) 1003 1004 // Get the GCM by term 1005 // It is expensive to do this first but it is not a 1006 // normal case that this won't match 1007 gcm, err := b.aeadForTerm(term) 1008 b.l.RUnlock() 1009 if err != nil { 1010 return nil, err 1011 } 1012 if gcm == nil { 1013 return nil, fmt.Errorf("no decryption key available for term %d", term) 1014 } 1015 1016 // Decrypt the ciphertext 1017 plain, err := b.decrypt(key, gcm, ciphertext) 1018 if err != nil { 1019 return nil, errwrap.Wrapf("decryption failed: {{err}}", err) 1020 } 1021 1022 return plain, nil 1023} 1024 1025func (b *AESGCMBarrier) Keyring() (*Keyring, error) { 1026 b.l.RLock() 1027 defer b.l.RUnlock() 1028 if b.sealed { 1029 return nil, ErrBarrierSealed 1030 } 1031 1032 return b.keyring.Clone(), nil 1033} 1034