github.com/opentofu/opentofu@v1.7.1/internal/encryption/keyprovider/pbkdf2/config.go (about) 1 // Copyright (c) The OpenTofu Authors 2 // SPDX-License-Identifier: MPL-2.0 3 // Copyright (c) 2023 HashiCorp, Inc. 4 // SPDX-License-Identifier: MPL-2.0 5 6 package pbkdf2 7 8 import ( 9 "fmt" 10 "hash" 11 "io" 12 13 "github.com/opentofu/opentofu/internal/encryption/keyprovider" 14 ) 15 16 // HashFunction is a provider of a hash.Hash. 17 type HashFunction func() hash.Hash 18 19 // HashFunctionName describes a hash function to use for PBKDF2 hash generation. While you could theoretically supply 20 // your own from outside the package, please don't do that. Include your hash function in this package. (Thanks Go for 21 // the lack of visibility constraints.) 22 type HashFunctionName string 23 24 // Validate checks if the specified hash function name is valid. 25 func (h HashFunctionName) Validate() error { 26 if h == "" { 27 return &keyprovider.ErrInvalidConfiguration{Message: "please specify a hash function"} 28 } 29 if _, ok := hashFunctions[h]; !ok { 30 return &keyprovider.ErrInvalidConfiguration{Message: fmt.Sprintf("invalid hash function name: %s", h)} 31 } 32 return nil 33 } 34 35 // Function returns the underlying hash function for the name. 36 func (h HashFunctionName) Function() HashFunction { 37 return hashFunctions[h] 38 } 39 40 type Config struct { 41 // Set by the descriptor. 42 randomSource io.Reader 43 44 Passphrase string `hcl:"passphrase"` 45 KeyLength int `hcl:"key_length,optional"` 46 Iterations int `hcl:"iterations,optional"` 47 HashFunction HashFunctionName `hcl:"hash_function,optional"` 48 SaltLength int `hcl:"salt_length,optional"` 49 } 50 51 // WithPassphrase adds the passphrase and returns the same config for chaining. 52 func (c *Config) WithPassphrase(passphrase string) *Config { 53 c.Passphrase = passphrase 54 return c 55 } 56 57 // WithKeyLength sets the key length and returns the same config for chaining 58 func (c *Config) WithKeyLength(length int) *Config { 59 c.KeyLength = length 60 return c 61 } 62 63 // WithIterations sets the iterations and returns the same config for chaining 64 func (c *Config) WithIterations(iterations int) *Config { 65 c.Iterations = iterations 66 return c 67 } 68 69 // WithSaltLength sets the salt length and returns the same config for chaining 70 func (c *Config) WithSaltLength(length int) *Config { 71 c.SaltLength = length 72 return c 73 } 74 75 // WithHashFunction sets the hash function and returns the same config for chaining 76 func (c *Config) WithHashFunction(hashFunction HashFunctionName) *Config { 77 c.HashFunction = hashFunction 78 return c 79 } 80 81 func (c *Config) Build() (keyprovider.KeyProvider, keyprovider.KeyMeta, error) { 82 if c.randomSource == nil { 83 return nil, nil, &keyprovider.ErrInvalidConfiguration{ 84 Message: "missing randomness source (please don't initialize the Config struct directly, use the descriptor)", 85 } 86 } 87 88 if c.Passphrase == "" { 89 return nil, nil, &keyprovider.ErrInvalidConfiguration{ 90 Message: "no passphrase provided", 91 } 92 } 93 94 if len(c.Passphrase) < MinimumPassphraseLength { 95 return nil, nil, &keyprovider.ErrInvalidConfiguration{ 96 Message: fmt.Sprintf("passphrase is too short (minimum %d characters)", MinimumPassphraseLength), 97 } 98 } 99 100 if c.KeyLength <= 0 { 101 return nil, nil, &keyprovider.ErrInvalidConfiguration{ 102 Message: "the key length must be larger than zero", 103 } 104 } 105 106 if c.Iterations <= 0 { 107 return nil, nil, &keyprovider.ErrInvalidConfiguration{ 108 Message: "the number of iterations must be larger than zero", 109 } 110 } 111 if c.Iterations < MinimumIterations { 112 return nil, nil, &keyprovider.ErrInvalidConfiguration{ 113 Message: fmt.Sprintf("the number of iterations is dangerously low (<%d), refusing to generate key", MinimumIterations), 114 } 115 } 116 117 if c.SaltLength <= 0 { 118 return nil, nil, &keyprovider.ErrInvalidConfiguration{ 119 Message: "the salt length must be larger than zero", 120 } 121 } 122 123 if err := c.HashFunction.Validate(); err != nil { 124 return nil, nil, &keyprovider.ErrInvalidConfiguration{ 125 Cause: err, 126 } 127 } 128 129 return &pbkdf2KeyProvider{*c}, new(Metadata), nil 130 }