mirror of https://github.com/docker/docs.git
Add tests for verifying signatures before returning a signature.
Signed-off-by: Ying Li <ying.li@docker.com> Signed-off-by: David Lawrence <david.lawrence@docker.com> Signed-off-by: Ying Li <ying.li@docker.com> (github: endophage)
This commit is contained in:
parent
4b7fefd5ef
commit
96bfaac05f
|
|
@ -790,6 +790,95 @@ func TestYubiSignCleansUpOnError(t *testing.T) {
|
||||||
[]string{"Logout"}, false)
|
[]string{"Logout"}, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If Sign gives us an invalid signature, we retry until successful up to
|
||||||
|
// a maximum of 5 times.
|
||||||
|
func TestYubiRetrySignUntilSuccess(t *testing.T) {
|
||||||
|
if !YubikeyAccessible() {
|
||||||
|
t.Skip("Must have Yubikey access.")
|
||||||
|
}
|
||||||
|
clearAllKeys(t)
|
||||||
|
|
||||||
|
SetYubikeyKeyMode(KeymodeNone)
|
||||||
|
defer func() {
|
||||||
|
SetYubikeyKeyMode(KeymodeTouch | KeymodePinOnce)
|
||||||
|
}()
|
||||||
|
|
||||||
|
store, err := NewYubiKeyStore(trustmanager.NewKeyMemoryStore(ret), ret)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
key, err := testAddKey(t, store)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
message := []byte("Hello there")
|
||||||
|
goodSig, err := key.Sign(rand.Reader, message, nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
privKey, _, err := store.GetKey(key.ID())
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
yubiPrivateKey, ok := privKey.(*YubiPrivateKey)
|
||||||
|
assert.True(t, ok)
|
||||||
|
|
||||||
|
badSigner := &SignInvalidSigCtx{
|
||||||
|
Ctx: *pkcs11.New(pkcs11Lib),
|
||||||
|
goodSig: goodSig,
|
||||||
|
failNum: 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
yubiPrivateKey.setLibLoader(func(string) IPKCS11Ctx { return badSigner })
|
||||||
|
|
||||||
|
sig, err := yubiPrivateKey.Sign(rand.Reader, message, nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
// because the SignInvalidSigCtx returns the good signature, we can just
|
||||||
|
// deep equal instead of verifying
|
||||||
|
assert.True(t, reflect.DeepEqual(goodSig, sig))
|
||||||
|
assert.Equal(t, 3, badSigner.signCalls)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If Sign gives us an invalid signature, we retry until up to a maximum of 5
|
||||||
|
// times, and if it's still invalid, fail.
|
||||||
|
func TestYubiRetrySign5TimesAndFail(t *testing.T) {
|
||||||
|
if !YubikeyAccessible() {
|
||||||
|
t.Skip("Must have Yubikey access.")
|
||||||
|
}
|
||||||
|
clearAllKeys(t)
|
||||||
|
|
||||||
|
SetYubikeyKeyMode(KeymodeNone)
|
||||||
|
defer func() {
|
||||||
|
SetYubikeyKeyMode(KeymodeTouch | KeymodePinOnce)
|
||||||
|
}()
|
||||||
|
|
||||||
|
store, err := NewYubiKeyStore(trustmanager.NewKeyMemoryStore(ret), ret)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
key, err := testAddKey(t, store)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
message := []byte("Hello there")
|
||||||
|
goodSig, err := key.Sign(rand.Reader, message, nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
privKey, _, err := store.GetKey(key.ID())
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
yubiPrivateKey, ok := privKey.(*YubiPrivateKey)
|
||||||
|
assert.True(t, ok)
|
||||||
|
|
||||||
|
badSigner := &SignInvalidSigCtx{
|
||||||
|
Ctx: *pkcs11.New(pkcs11Lib),
|
||||||
|
goodSig: goodSig,
|
||||||
|
failNum: 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
yubiPrivateKey.setLibLoader(func(string) IPKCS11Ctx { return badSigner })
|
||||||
|
|
||||||
|
_, err = yubiPrivateKey.Sign(rand.Reader, message, nil)
|
||||||
|
assert.Error(t, err)
|
||||||
|
// because the SignInvalidSigCtx returns the good signature, we can just
|
||||||
|
// deep equal instead of verifying
|
||||||
|
assert.Equal(t, 5, badSigner.signCalls)
|
||||||
|
}
|
||||||
|
|
||||||
// ----- Stubbed pkcs11 for testing error conditions ------
|
// ----- Stubbed pkcs11 for testing error conditions ------
|
||||||
// This is just a passthrough to the underlying pkcs11 library, with optional
|
// This is just a passthrough to the underlying pkcs11 library, with optional
|
||||||
// error injection. This is to ensure that if errors occur during the process
|
// error injection. This is to ensure that if errors occur during the process
|
||||||
|
|
@ -966,3 +1055,27 @@ func (s *StubCtx) Sign(sh pkcs11.SessionHandle, message []byte) ([]byte, error)
|
||||||
}
|
}
|
||||||
return sig, sigErr
|
return sig, sigErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// a different stub Ctx object in which Sign returns an invalid signature some
|
||||||
|
// number of times
|
||||||
|
type SignInvalidSigCtx struct {
|
||||||
|
pkcs11.Ctx
|
||||||
|
|
||||||
|
// Signature verification is to mitigate against hardware failure while
|
||||||
|
// signing - which might occur during testing. So to prevent spurious
|
||||||
|
// errors, return a real known good signature in the success case.
|
||||||
|
goodSig []byte
|
||||||
|
|
||||||
|
failNum int // number of calls to fail before succeeding
|
||||||
|
signCalls int // number of calls to Sign so far
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SignInvalidSigCtx) Sign(sh pkcs11.SessionHandle, message []byte) ([]byte, error) {
|
||||||
|
s.signCalls++
|
||||||
|
s.Ctx.Sign(sh, message) // clear out the SignInit
|
||||||
|
|
||||||
|
if s.signCalls > s.failNum {
|
||||||
|
return s.goodSig, nil
|
||||||
|
}
|
||||||
|
return []byte("12345"), nil
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue