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