waddrmgr/manager: guard access to newSecretKey

This commit places a mutex around calls to newSecretKey,
since the inner function needs to be swapped out
during testing. Prior to this change, the race
detector would panic since the mutation was
unprotected.
This commit is contained in:
Conner Fromknecht 2018-08-31 16:27:04 -07:00
parent 7b84dc25a6
commit ba58d5357f
No known key found for this signature in database
GPG key ID: E7D737B67FA592C7

View file

@ -174,15 +174,46 @@ type unlockDeriveInfo struct {
index uint32
}
// SecretKeyGenerator is the function signature of a method that can generate
// secret keys for the address manager.
type SecretKeyGenerator func(
passphrase *[]byte, config *ScryptOptions) (*snacl.SecretKey, error)
// defaultNewSecretKey returns a new secret key. See newSecretKey.
func defaultNewSecretKey(passphrase *[]byte, config *ScryptOptions) (*snacl.SecretKey, error) {
func defaultNewSecretKey(passphrase *[]byte,
config *ScryptOptions) (*snacl.SecretKey, error) {
return snacl.NewSecretKey(passphrase, config.N, config.R, config.P)
}
// newSecretKey is used as a way to replace the new secret key generation
// function used so tests can provide a version that fails for testing error
// paths.
var newSecretKey = defaultNewSecretKey
var (
// secretKeyGen is the inner method that is executed when calling
// newSecretKey.
secretKeyGen = defaultNewSecretKey
// secretKeyGenMtx protects access to secretKeyGen, so that it can be
// replaced in testing.
secretKeyGenMtx sync.RWMutex
)
// SetSecretKeyGen replaces the existing secret key generator, and returns the
// previous generator.
func SetSecretKeyGen(keyGen SecretKeyGenerator) SecretKeyGenerator {
secretKeyGenMtx.Lock()
oldKeyGen := secretKeyGen
secretKeyGen = keyGen
secretKeyGenMtx.Unlock()
return oldKeyGen
}
// newSecretKey generates a new secret key using the active secretKeyGen.
func newSecretKey(passphrase *[]byte,
config *ScryptOptions) (*snacl.SecretKey, error) {
secretKeyGenMtx.RLock()
defer secretKeyGenMtx.RUnlock()
return secretKeyGen(passphrase, config)
}
// EncryptorDecryptor provides an abstraction on top of snacl.CryptoKey so that
// our tests can use dependency injection to force the behaviour they need.