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)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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 ------
 | 
			
		||||
// 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
 | 
			
		||||
| 
						 | 
				
			
			@ -966,3 +1055,27 @@ func (s *StubCtx) Sign(sh pkcs11.SessionHandle, message []byte) ([]byte, error)
 | 
			
		|||
	}
 | 
			
		||||
	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