From db4349a46db63bdf7764bcb2256bc41869bafa41 Mon Sep 17 00:00:00 2001 From: Jarek Kowalski Date: Sun, 18 Jun 2017 12:28:01 -0700 Subject: [PATCH] changed HMAC secret used for policy ID items in vault --- cmd/kopia/command_vault_show.go | 2 +- snapshot/manager.go | 22 ++++++++++++++-------- snapshot/policy.go | 1 + vault/vault.go | 23 +++++++---------------- 4 files changed, 23 insertions(+), 25 deletions(-) diff --git a/cmd/kopia/command_vault_show.go b/cmd/kopia/command_vault_show.go index 05c3ffd0f..4b7f99114 100644 --- a/cmd/kopia/command_vault_show.go +++ b/cmd/kopia/command_vault_show.go @@ -9,7 +9,7 @@ ) var ( - vaultShowCommand = vaultCommands.Command("show", "Show contents of a vault item") + vaultShowCommand = vaultCommands.Command("show", "Show contents of a vault item").Alias("cat") vaultShowID = vaultShowCommand.Arg("id", "ID of the vault item to show").String() vaultShowJSON = vaultShowCommand.Flag("json", "Pretty-print JSON").Short('j').Bool() vaultShowNoNewLine = vaultShowCommand.Flag("nonewline", "Do not emit newline").Short('n').Bool() diff --git a/snapshot/manager.go b/snapshot/manager.go index 71e3859a2..e81dcd6e4 100644 --- a/snapshot/manager.go +++ b/snapshot/manager.go @@ -28,7 +28,9 @@ // Manager manages filesystem snapshots. type Manager struct { - vault *vault.Vault + vault *vault.Vault + snapshotIDSecret []byte + policyIDSecret []byte } // ListSources lists all snapshot sources. @@ -64,7 +66,7 @@ func (m *Manager) ListSources() ([]*SourceInfo, error) { // ListSnapshots lists all snapshots for a given source. func (m *Manager) ListSnapshots(si *SourceInfo, limit int) ([]*Manifest, error) { - names, err := m.vault.List(backupPrefix+si.HashString(m.vault.UniqueID()), limit) + names, err := m.vault.List(backupPrefix+si.HashString(m.snapshotIDSecret), limit) if err != nil { return nil, err } @@ -92,7 +94,7 @@ func (m *Manager) SaveSnapshot(manifest *Manifest) (string, error) { uniqueID := make([]byte, 8) rand.Read(uniqueID) ts := math.MaxInt64 - manifest.StartTime.UnixNano() - manifestID := fmt.Sprintf("%v%v.%08x.%x", backupPrefix, manifest.Source.HashString(m.vault.UniqueID()), ts, uniqueID) + manifestID := fmt.Sprintf("%v%v.%08x.%x", backupPrefix, manifest.Source.HashString(m.snapshotIDSecret), ts, uniqueID) b, err := json.Marshal(manifest) if err != nil { @@ -146,7 +148,7 @@ func (m *Manager) ListSnapshotManifests(src *SourceInfo, limit int) ([]string, e var prefix string if src != nil { - prefix = src.HashString(m.vault.UniqueID()) + prefix = src.HashString(m.snapshotIDSecret) } return m.vault.List(backupPrefix+prefix, limit) @@ -225,7 +227,7 @@ func cloneSourceInfo(si SourceInfo) *SourceInfo { // SavePolicy persists the given snapshot policy. func (m *Manager) SavePolicy(p *Policy) error { - itemID := fmt.Sprintf("%v%v", policyPrefix, p.Source.HashString(m.vault.UniqueID())) + itemID := fmt.Sprintf("%v%v", policyPrefix, p.Source.HashString(m.policyIDSecret)) b, err := json.Marshal(p) if err != nil { @@ -237,7 +239,7 @@ func (m *Manager) SavePolicy(p *Policy) error { // RemovePolicy removes the policy for a given source func (m *Manager) RemovePolicy(src *SourceInfo) error { - itemID := fmt.Sprintf("%v%v", policyPrefix, src.HashString(m.vault.UniqueID())) + itemID := fmt.Sprintf("%v%v", policyPrefix, src.HashString(m.policyIDSecret)) return m.vault.Remove(itemID) } @@ -245,7 +247,7 @@ func (m *Manager) RemovePolicy(src *SourceInfo) error { // GetPolicy retrieves the Policy for a given source, if defined. // Returns ErrPolicyNotFound if policy not defined. func (m *Manager) GetPolicy(src *SourceInfo) (*Policy, error) { - itemID := fmt.Sprintf("%v%v", policyPrefix, src.HashString(m.vault.UniqueID())) + itemID := fmt.Sprintf("%v%v", policyPrefix, src.HashString(m.policyIDSecret)) return m.getPolicyItem(itemID) } @@ -309,5 +311,9 @@ func (m *Manager) ListPolicies() ([]*Policy, error) { // NewManager creates new snapshot manager for a given connection. func NewManager(conn *kopia.Connection) *Manager { - return &Manager{conn.Vault} + return &Manager{ + conn.Vault, + conn.Vault.DeriveKey([]byte("snapshot-id"), 32), + conn.Vault.DeriveKey([]byte("policyID-id"), 32), + } } diff --git a/snapshot/policy.go b/snapshot/policy.go index fbf297707..262392b52 100644 --- a/snapshot/policy.go +++ b/snapshot/policy.go @@ -21,6 +21,7 @@ type ExpirationPolicy struct { KeepDaily: intPtr(7), KeepWeekly: intPtr(4), KeepMonthly: intPtr(4), + KeepAnnual: intPtr(0), } // FilesPolicy describes files to be uploaded when taking snapshots diff --git a/vault/vault.go b/vault/vault.go index 10f1d75a0..3abafebd8 100644 --- a/vault/vault.go +++ b/vault/vault.go @@ -55,11 +55,6 @@ type Vault struct { authData []byte // additional data to authenticate } -// UniqueID returns the unique identifier of the vault. -func (v *Vault) UniqueID() []byte { - return v.format.UniqueID -} - // Put saves the specified content in a vault under a specified name. func (v *Vault) Put(itemID string, content []byte) error { if err := checkReservedName(itemID); err != nil { @@ -111,10 +106,12 @@ func (v *Vault) decryptBlock(content []byte) ([]byte, error) { return content, nil } -func (v *Vault) deriveKey(purpose []byte, key []byte) error { +// DeriveKey computes a key for a specific purpose and length using HKDF based on the master key. +func (v *Vault) DeriveKey(purpose []byte, length int) []byte { + key := make([]byte, length) k := hkdf.New(sha256.New, v.masterKey, v.format.UniqueID, purpose) - _, err := io.ReadFull(k, key) - return err + io.ReadFull(k, key) + return key } // Get returns the contents of a specified vault item. @@ -383,14 +380,8 @@ func (v *Vault) initCrypto() error { case "NONE": // do nothing return nil case "AES256_GCM": - aesKey := make([]byte, 32) - if err := v.deriveKey(purposeAESKey, aesKey); err != nil { - return fmt.Errorf("cannot derive key: %v", err) - } - v.authData = make([]byte, 32) - if err := v.deriveKey(purposeAuthData, v.authData); err != nil { - return fmt.Errorf("cannot derive auth data: %v", err) - } + aesKey := v.DeriveKey(purposeAESKey, 32) + v.authData = v.DeriveKey(purposeAuthData, 32) blk, err := aes.NewCipher(aesKey) if err != nil {