421 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			421 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Go
		
	
	
	
| package pkcs11helpers
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"crypto"
 | |
| 	"crypto/ecdsa"
 | |
| 	"crypto/elliptic"
 | |
| 	"crypto/rand"
 | |
| 	"crypto/rsa"
 | |
| 	"crypto/sha256"
 | |
| 	"encoding/asn1"
 | |
| 	"errors"
 | |
| 	"math/big"
 | |
| 	"strings"
 | |
| 	"testing"
 | |
| 
 | |
| 	"github.com/letsencrypt/boulder/test"
 | |
| 	"github.com/miekg/pkcs11"
 | |
| )
 | |
| 
 | |
| func TestGetECDSAPublicKey(t *testing.T) {
 | |
| 	ctx := &MockCtx{}
 | |
| 	s := &Session{ctx, 0}
 | |
| 
 | |
| 	// test attribute retrieval failing
 | |
| 	ctx.GetAttributeValueFunc = func(pkcs11.SessionHandle, pkcs11.ObjectHandle, []*pkcs11.Attribute) ([]*pkcs11.Attribute, error) {
 | |
| 		return nil, errors.New("yup")
 | |
| 	}
 | |
| 	_, err := s.GetECDSAPublicKey(0)
 | |
| 	test.AssertError(t, err, "ecPub didn't fail on GetAttributeValue error")
 | |
| 
 | |
| 	// test we fail to construct key with missing params and point
 | |
| 	ctx.GetAttributeValueFunc = func(pkcs11.SessionHandle, pkcs11.ObjectHandle, []*pkcs11.Attribute) ([]*pkcs11.Attribute, error) {
 | |
| 		return []*pkcs11.Attribute{}, nil
 | |
| 	}
 | |
| 	_, err = s.GetECDSAPublicKey(0)
 | |
| 	test.AssertError(t, err, "ecPub didn't fail with empty attribute list")
 | |
| 
 | |
| 	// test we fail to construct key with unknown curve
 | |
| 	ctx.GetAttributeValueFunc = func(pkcs11.SessionHandle, pkcs11.ObjectHandle, []*pkcs11.Attribute) ([]*pkcs11.Attribute, error) {
 | |
| 		return []*pkcs11.Attribute{
 | |
| 			pkcs11.NewAttribute(pkcs11.CKA_EC_PARAMS, []byte{1, 2, 3}),
 | |
| 		}, nil
 | |
| 	}
 | |
| 	_, err = s.GetECDSAPublicKey(0)
 | |
| 	test.AssertError(t, err, "ecPub didn't fail with unknown curve")
 | |
| 
 | |
| 	// test we fail to construct key with invalid EC point (invalid encoding)
 | |
| 	ctx.GetAttributeValueFunc = func(pkcs11.SessionHandle, pkcs11.ObjectHandle, []*pkcs11.Attribute) ([]*pkcs11.Attribute, error) {
 | |
| 		return []*pkcs11.Attribute{
 | |
| 			pkcs11.NewAttribute(pkcs11.CKA_EC_PARAMS, []byte{6, 8, 42, 134, 72, 206, 61, 3, 1, 7}),
 | |
| 			pkcs11.NewAttribute(pkcs11.CKA_EC_POINT, []byte{255}),
 | |
| 		}, nil
 | |
| 	}
 | |
| 	_, err = s.GetECDSAPublicKey(0)
 | |
| 	test.AssertError(t, err, "ecPub didn't fail with invalid EC point (invalid encoding)")
 | |
| 
 | |
| 	// test we fail to construct key with invalid EC point (empty octet string)
 | |
| 	ctx.GetAttributeValueFunc = func(pkcs11.SessionHandle, pkcs11.ObjectHandle, []*pkcs11.Attribute) ([]*pkcs11.Attribute, error) {
 | |
| 		return []*pkcs11.Attribute{
 | |
| 			pkcs11.NewAttribute(pkcs11.CKA_EC_PARAMS, []byte{6, 8, 42, 134, 72, 206, 61, 3, 1, 7}),
 | |
| 			pkcs11.NewAttribute(pkcs11.CKA_EC_POINT, []byte{4, 0}),
 | |
| 		}, nil
 | |
| 	}
 | |
| 	_, err = s.GetECDSAPublicKey(0)
 | |
| 	test.AssertError(t, err, "ecPub didn't fail with invalid EC point (empty octet string)")
 | |
| 
 | |
| 	// test we fail to construct key with invalid EC point (octet string, invalid contents)
 | |
| 	ctx.GetAttributeValueFunc = func(pkcs11.SessionHandle, pkcs11.ObjectHandle, []*pkcs11.Attribute) ([]*pkcs11.Attribute, error) {
 | |
| 		return []*pkcs11.Attribute{
 | |
| 			pkcs11.NewAttribute(pkcs11.CKA_EC_PARAMS, []byte{6, 8, 42, 134, 72, 206, 61, 3, 1, 7}),
 | |
| 			pkcs11.NewAttribute(pkcs11.CKA_EC_POINT, []byte{4, 4, 4, 1, 2, 3}),
 | |
| 		}, nil
 | |
| 	}
 | |
| 	_, err = s.GetECDSAPublicKey(0)
 | |
| 	test.AssertError(t, err, "ecPub didn't fail with invalid EC point (octet string, invalid contents)")
 | |
| 
 | |
| 	// test we don't fail with the correct attributes (traditional encoding)
 | |
| 	ctx.GetAttributeValueFunc = func(pkcs11.SessionHandle, pkcs11.ObjectHandle, []*pkcs11.Attribute) ([]*pkcs11.Attribute, error) {
 | |
| 		return []*pkcs11.Attribute{
 | |
| 			pkcs11.NewAttribute(pkcs11.CKA_EC_PARAMS, []byte{6, 5, 43, 129, 4, 0, 33}),
 | |
| 			pkcs11.NewAttribute(pkcs11.CKA_EC_POINT, []byte{4, 217, 225, 246, 210, 153, 134, 246, 104, 95, 79, 122, 206, 135, 241, 37, 114, 199, 87, 56, 167, 83, 56, 136, 174, 6, 145, 97, 239, 221, 49, 67, 148, 13, 126, 65, 90, 208, 195, 193, 171, 105, 40, 98, 132, 124, 30, 189, 215, 197, 178, 226, 166, 238, 240, 57, 215}),
 | |
| 		}, nil
 | |
| 	}
 | |
| 	_, err = s.GetECDSAPublicKey(0)
 | |
| 	test.AssertNotError(t, err, "ecPub failed with valid attributes (traditional encoding)")
 | |
| 
 | |
| 	// test we don't fail with the correct attributes (non-traditional encoding)
 | |
| 	ctx.GetAttributeValueFunc = func(pkcs11.SessionHandle, pkcs11.ObjectHandle, []*pkcs11.Attribute) ([]*pkcs11.Attribute, error) {
 | |
| 		return []*pkcs11.Attribute{
 | |
| 			pkcs11.NewAttribute(pkcs11.CKA_EC_PARAMS, []byte{6, 5, 43, 129, 4, 0, 33}),
 | |
| 			pkcs11.NewAttribute(pkcs11.CKA_EC_POINT, []byte{4, 57, 4, 217, 225, 246, 210, 153, 134, 246, 104, 95, 79, 122, 206, 135, 241, 37, 114, 199, 87, 56, 167, 83, 56, 136, 174, 6, 145, 97, 239, 221, 49, 67, 148, 13, 126, 65, 90, 208, 195, 193, 171, 105, 40, 98, 132, 124, 30, 189, 215, 197, 178, 226, 166, 238, 240, 57, 215}),
 | |
| 		}, nil
 | |
| 	}
 | |
| 	_, err = s.GetECDSAPublicKey(0)
 | |
| 	test.AssertNotError(t, err, "ecPub failed with valid attributes (non-traditional encoding)")
 | |
| }
 | |
| 
 | |
| func TestRSAPublicKey(t *testing.T) {
 | |
| 	ctx := &MockCtx{}
 | |
| 	s := &Session{ctx, 0}
 | |
| 
 | |
| 	// test attribute retrieval failing
 | |
| 	ctx.GetAttributeValueFunc = func(pkcs11.SessionHandle, pkcs11.ObjectHandle, []*pkcs11.Attribute) ([]*pkcs11.Attribute, error) {
 | |
| 		return nil, errors.New("yup")
 | |
| 	}
 | |
| 	_, err := s.GetRSAPublicKey(0)
 | |
| 	test.AssertError(t, err, "rsaPub didn't fail on GetAttributeValue error")
 | |
| 
 | |
| 	// test we fail to construct key with missing modulus and exp
 | |
| 	ctx.GetAttributeValueFunc = func(pkcs11.SessionHandle, pkcs11.ObjectHandle, []*pkcs11.Attribute) ([]*pkcs11.Attribute, error) {
 | |
| 		return []*pkcs11.Attribute{}, nil
 | |
| 	}
 | |
| 	_, err = s.GetRSAPublicKey(0)
 | |
| 	test.AssertError(t, err, "rsaPub didn't fail with empty attribute list")
 | |
| 
 | |
| 	// test we don't fail with the correct attributes
 | |
| 	ctx.GetAttributeValueFunc = func(pkcs11.SessionHandle, pkcs11.ObjectHandle, []*pkcs11.Attribute) ([]*pkcs11.Attribute, error) {
 | |
| 		return []*pkcs11.Attribute{
 | |
| 			pkcs11.NewAttribute(pkcs11.CKA_PUBLIC_EXPONENT, []byte{1, 0, 1}),
 | |
| 			pkcs11.NewAttribute(pkcs11.CKA_MODULUS, []byte{255}),
 | |
| 		}, nil
 | |
| 	}
 | |
| 	_, err = s.GetRSAPublicKey(0)
 | |
| 	test.AssertNotError(t, err, "rsaPub failed with valid attributes")
 | |
| }
 | |
| 
 | |
| func findObjectsInitOK(pkcs11.SessionHandle, []*pkcs11.Attribute) error {
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func findObjectsOK(pkcs11.SessionHandle, int) ([]pkcs11.ObjectHandle, bool, error) {
 | |
| 	return []pkcs11.ObjectHandle{1}, false, nil
 | |
| }
 | |
| 
 | |
| func findObjectsFinalOK(pkcs11.SessionHandle) error {
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func newMock() *MockCtx {
 | |
| 	return &MockCtx{
 | |
| 		FindObjectsInitFunc:  findObjectsInitOK,
 | |
| 		FindObjectsFunc:      findObjectsOK,
 | |
| 		FindObjectsFinalFunc: findObjectsFinalOK,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func newSessionWithMock() (*Session, *MockCtx) {
 | |
| 	ctx := newMock()
 | |
| 	return &Session{ctx, 0}, ctx
 | |
| }
 | |
| 
 | |
| func TestFindObjectFailsOnFailedInit(t *testing.T) {
 | |
| 	ctx := MockCtx{}
 | |
| 	ctx.FindObjectsFinalFunc = findObjectsFinalOK
 | |
| 	ctx.FindObjectsFunc = func(pkcs11.SessionHandle, int) ([]pkcs11.ObjectHandle, bool, error) {
 | |
| 		return []pkcs11.ObjectHandle{1}, false, nil
 | |
| 	}
 | |
| 
 | |
| 	// test FindObject fails when FindObjectsInit fails
 | |
| 	ctx.FindObjectsInitFunc = func(pkcs11.SessionHandle, []*pkcs11.Attribute) error {
 | |
| 		return errors.New("broken")
 | |
| 	}
 | |
| 	s := &Session{ctx, 0}
 | |
| 	_, err := s.FindObject(nil)
 | |
| 	test.AssertError(t, err, "FindObject didn't fail when FindObjectsInit failed")
 | |
| }
 | |
| 
 | |
| func TestFindObjectFailsOnFailedFindObjects(t *testing.T) {
 | |
| 	ctx := MockCtx{}
 | |
| 	ctx.FindObjectsInitFunc = findObjectsInitOK
 | |
| 	ctx.FindObjectsFinalFunc = findObjectsFinalOK
 | |
| 
 | |
| 	// test FindObject fails when FindObjects fails
 | |
| 	ctx.FindObjectsFunc = func(pkcs11.SessionHandle, int) ([]pkcs11.ObjectHandle, bool, error) {
 | |
| 		return nil, false, errors.New("broken")
 | |
| 	}
 | |
| 	s := &Session{ctx, 0}
 | |
| 	_, err := s.FindObject(nil)
 | |
| 	test.AssertError(t, err, "FindObject didn't fail when FindObjects failed")
 | |
| }
 | |
| 
 | |
| func TestFindObjectFailsOnNoHandles(t *testing.T) {
 | |
| 	ctx := MockCtx{}
 | |
| 	ctx.FindObjectsInitFunc = findObjectsInitOK
 | |
| 	ctx.FindObjectsFinalFunc = findObjectsFinalOK
 | |
| 
 | |
| 	// test FindObject fails when no handles are returned
 | |
| 	ctx.FindObjectsFunc = func(pkcs11.SessionHandle, int) ([]pkcs11.ObjectHandle, bool, error) {
 | |
| 		return []pkcs11.ObjectHandle{}, false, nil
 | |
| 	}
 | |
| 	s := &Session{ctx, 0}
 | |
| 	_, err := s.FindObject(nil)
 | |
| 	test.AssertEquals(t, err, ErrNoObject)
 | |
| }
 | |
| 
 | |
| func TestFindObjectFailsOnMultipleHandles(t *testing.T) {
 | |
| 	ctx := MockCtx{}
 | |
| 	ctx.FindObjectsInitFunc = findObjectsInitOK
 | |
| 	ctx.FindObjectsFinalFunc = findObjectsFinalOK
 | |
| 
 | |
| 	// test FindObject fails when multiple handles are returned
 | |
| 	ctx.FindObjectsFunc = func(pkcs11.SessionHandle, int) ([]pkcs11.ObjectHandle, bool, error) {
 | |
| 		return []pkcs11.ObjectHandle{1, 2, 3}, false, nil
 | |
| 	}
 | |
| 	s := &Session{ctx, 0}
 | |
| 	_, err := s.FindObject(nil)
 | |
| 	test.AssertError(t, err, "FindObject didn't fail when FindObjects returns multiple handles")
 | |
| 	test.Assert(t, strings.HasPrefix(err.Error(), "too many objects"), "FindObject failed with wrong error")
 | |
| }
 | |
| 
 | |
| func TestFindObjectFailsOnFinalizeFailure(t *testing.T) {
 | |
| 	ctx := MockCtx{}
 | |
| 	ctx.FindObjectsInitFunc = findObjectsInitOK
 | |
| 
 | |
| 	// test FindObject fails when FindObjectsFinal fails
 | |
| 	ctx.FindObjectsFunc = func(pkcs11.SessionHandle, int) ([]pkcs11.ObjectHandle, bool, error) {
 | |
| 		return []pkcs11.ObjectHandle{1}, false, nil
 | |
| 	}
 | |
| 	ctx.FindObjectsFinalFunc = func(pkcs11.SessionHandle) error {
 | |
| 		return errors.New("broken")
 | |
| 	}
 | |
| 	s := &Session{ctx, 0}
 | |
| 	_, err := s.FindObject(nil)
 | |
| 	test.AssertError(t, err, "FindObject didn't fail when FindObjectsFinal fails")
 | |
| }
 | |
| 
 | |
| func TestFindObjectSucceeds(t *testing.T) {
 | |
| 	ctx := MockCtx{}
 | |
| 	ctx.FindObjectsInitFunc = findObjectsInitOK
 | |
| 	ctx.FindObjectsFinalFunc = findObjectsFinalOK
 | |
| 	ctx.FindObjectsFunc = func(pkcs11.SessionHandle, int) ([]pkcs11.ObjectHandle, bool, error) {
 | |
| 		return []pkcs11.ObjectHandle{1}, false, nil
 | |
| 	}
 | |
| 	s := &Session{ctx, 0}
 | |
| 
 | |
| 	// test FindObject works
 | |
| 	handle, err := s.FindObject(nil)
 | |
| 	test.AssertNotError(t, err, "FindObject failed when everything worked as expected")
 | |
| 	test.AssertEquals(t, handle, pkcs11.ObjectHandle(1))
 | |
| }
 | |
| 
 | |
| func TestX509Signer(t *testing.T) {
 | |
| 	ctx := MockCtx{}
 | |
| 
 | |
| 	// test that x509Signer.Sign properly converts the PKCS#11 format signature to
 | |
| 	// the RFC 5480 format signature
 | |
| 	ctx.SignInitFunc = func(pkcs11.SessionHandle, []*pkcs11.Mechanism, pkcs11.ObjectHandle) error {
 | |
| 		return nil
 | |
| 	}
 | |
| 	tk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
 | |
| 	test.AssertNotError(t, err, "Failed to generate test key")
 | |
| 	ctx.SignFunc = func(_ pkcs11.SessionHandle, digest []byte) ([]byte, error) {
 | |
| 		r, s, err := ecdsa.Sign(rand.Reader, tk, digest[:])
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		rBytes := r.Bytes()
 | |
| 		sBytes := s.Bytes()
 | |
| 		// http://docs.oasis-open.org/pkcs11/pkcs11-curr/v2.40/os/pkcs11-curr-v2.40-os.html
 | |
| 		// Section 2.3.1: EC Signatures
 | |
| 		// "If r and s have different octet length, the shorter of both must be padded with
 | |
| 		// leading zero octets such that both have the same octet length."
 | |
| 		switch {
 | |
| 		case len(rBytes) < len(sBytes):
 | |
| 			padding := make([]byte, len(sBytes)-len(rBytes))
 | |
| 			rBytes = append(padding, rBytes...)
 | |
| 		case len(rBytes) > len(sBytes):
 | |
| 			padding := make([]byte, len(rBytes)-len(sBytes))
 | |
| 			sBytes = append(padding, sBytes...)
 | |
| 		}
 | |
| 		return append(rBytes, sBytes...), nil
 | |
| 	}
 | |
| 	digest := sha256.Sum256([]byte("hello"))
 | |
| 	s := &Session{ctx, 0}
 | |
| 	signer := &x509Signer{session: s, keyType: ECDSAKey, pub: tk.Public()}
 | |
| 	signature, err := signer.Sign(nil, digest[:], crypto.SHA256)
 | |
| 	test.AssertNotError(t, err, "x509Signer.Sign failed")
 | |
| 
 | |
| 	var rfcFormat struct {
 | |
| 		R, S *big.Int
 | |
| 	}
 | |
| 	rest, err := asn1.Unmarshal(signature, &rfcFormat)
 | |
| 	test.AssertNotError(t, err, "asn1.Unmarshal failed trying to parse signature")
 | |
| 	test.Assert(t, len(rest) == 0, "Signature had trailing garbage")
 | |
| 	verified := ecdsa.Verify(&tk.PublicKey, digest[:], rfcFormat.R, rfcFormat.S)
 | |
| 	test.Assert(t, verified, "Failed to verify RFC format signature")
 | |
| 	// For the sake of coverage
 | |
| 	test.AssertEquals(t, signer.Public(), tk.Public())
 | |
| }
 | |
| 
 | |
| func TestGetKeyWhenLabelIsWrong(t *testing.T) {
 | |
| 	s, ctx := newSessionWithMock()
 | |
| 	pubKey := &rsa.PublicKey{N: big.NewInt(1), E: 1}
 | |
| 	rightLabel := "label"
 | |
| 	var objectsToReturn []pkcs11.ObjectHandle
 | |
| 
 | |
| 	ctx.FindObjectsInitFunc = func(_ pkcs11.SessionHandle, attr []*pkcs11.Attribute) error {
 | |
| 		objectsToReturn = []pkcs11.ObjectHandle{1}
 | |
| 		for _, a := range attr {
 | |
| 			if a.Type == pkcs11.CKA_LABEL && !bytes.Equal(a.Value, []byte(rightLabel)) {
 | |
| 				objectsToReturn = nil
 | |
| 			}
 | |
| 		}
 | |
| 		return nil
 | |
| 	}
 | |
| 	ctx.FindObjectsFunc = func(_ pkcs11.SessionHandle, _ int) ([]pkcs11.ObjectHandle, bool, error) {
 | |
| 		return objectsToReturn, false, nil
 | |
| 	}
 | |
| 	ctx.FindObjectsFinalFunc = func(_ pkcs11.SessionHandle) error {
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	_, err := s.NewSigner("wrong-label", pubKey)
 | |
| 	test.AssertError(t, err, "newSigner didn't fail when label was a mismatch for public key")
 | |
| 	expected := "no objects found matching provided template"
 | |
| 	if !strings.Contains(err.Error(), expected) {
 | |
| 		t.Errorf("expected error to contain %q but it was %q", expected, err)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestGetKeyWhenGetAttributeValueFails(t *testing.T) {
 | |
| 	s, ctx := newSessionWithMock()
 | |
| 	pubKey := &rsa.PublicKey{N: big.NewInt(1), E: 1}
 | |
| 
 | |
| 	// test newSigner fails when GetAttributeValue fails
 | |
| 	ctx.GetAttributeValueFunc = func(pkcs11.SessionHandle, pkcs11.ObjectHandle, []*pkcs11.Attribute) ([]*pkcs11.Attribute, error) {
 | |
| 		return nil, errors.New("broken")
 | |
| 	}
 | |
| 	_, err := s.NewSigner("label", pubKey)
 | |
| 	test.AssertError(t, err, "newSigner didn't fail when GetAttributeValue for private key type failed")
 | |
| }
 | |
| 
 | |
| func TestGetKeyWhenGetAttributeValueReturnsNone(t *testing.T) {
 | |
| 	s, ctx := newSessionWithMock()
 | |
| 	pubKey := &rsa.PublicKey{N: big.NewInt(1), E: 1}
 | |
| 
 | |
| 	ctx.GetAttributeValueFunc = func(pkcs11.SessionHandle, pkcs11.ObjectHandle, []*pkcs11.Attribute) ([]*pkcs11.Attribute, error) {
 | |
| 		return nil, errors.New("broken")
 | |
| 	}
 | |
| 	// test newSigner fails when GetAttributeValue returns no attributes
 | |
| 	ctx.GetAttributeValueFunc = func(pkcs11.SessionHandle, pkcs11.ObjectHandle, []*pkcs11.Attribute) ([]*pkcs11.Attribute, error) {
 | |
| 		return nil, nil
 | |
| 	}
 | |
| 	_, err := s.NewSigner("label", pubKey)
 | |
| 	test.AssertError(t, err, "newSigner didn't fail when GetAttributeValue for private key type returned no attributes")
 | |
| }
 | |
| 
 | |
| func TestGetKeyWhenFindObjectForPublicKeyFails(t *testing.T) {
 | |
| 	s, ctx := newSessionWithMock()
 | |
| 	pubKey := &rsa.PublicKey{N: big.NewInt(1), E: 1}
 | |
| 
 | |
| 	// test newSigner fails when FindObject for public key
 | |
| 	ctx.GetAttributeValueFunc = func(pkcs11.SessionHandle, pkcs11.ObjectHandle, []*pkcs11.Attribute) ([]*pkcs11.Attribute, error) {
 | |
| 		return []*pkcs11.Attribute{pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_EC)}, nil
 | |
| 	}
 | |
| 	ctx.FindObjectsInitFunc = func(_ pkcs11.SessionHandle, tmpl []*pkcs11.Attribute) error {
 | |
| 		if bytes.Equal(tmpl[0].Value, []byte{2, 0, 0, 0, 0, 0, 0, 0}) {
 | |
| 			return errors.New("broken")
 | |
| 		}
 | |
| 		return nil
 | |
| 	}
 | |
| 	_, err := s.NewSigner("label", pubKey)
 | |
| 	test.AssertError(t, err, "newSigner didn't fail when FindObject for public key handle failed")
 | |
| }
 | |
| 
 | |
| func TestGetKeyWhenFindObjectForPrivateKeyReturnsUnknownType(t *testing.T) {
 | |
| 	s, ctx := newSessionWithMock()
 | |
| 	pubKey := &rsa.PublicKey{N: big.NewInt(1), E: 1}
 | |
| 
 | |
| 	// test newSigner fails when FindObject for private key returns unknown CKA_KEY_TYPE
 | |
| 	ctx.FindObjectsInitFunc = func(_ pkcs11.SessionHandle, tmpl []*pkcs11.Attribute) error {
 | |
| 		return nil
 | |
| 	}
 | |
| 	ctx.GetAttributeValueFunc = func(pkcs11.SessionHandle, pkcs11.ObjectHandle, []*pkcs11.Attribute) ([]*pkcs11.Attribute, error) {
 | |
| 		return []*pkcs11.Attribute{pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, []byte{2, 0, 0, 0, 0, 0, 0, 0})}, nil
 | |
| 	}
 | |
| 	_, err := s.NewSigner("label", pubKey)
 | |
| 	test.AssertError(t, err, "newSigner didn't fail when GetAttributeValue for private key returned unknown key type")
 | |
| }
 | |
| 
 | |
| func TestGetKeyWhenFindObjectForPrivateKeyFails(t *testing.T) {
 | |
| 	s, ctx := newSessionWithMock()
 | |
| 	pubKey := &rsa.PublicKey{N: big.NewInt(1), E: 1}
 | |
| 
 | |
| 	// test newSigner fails when FindObject for private key fails
 | |
| 	ctx.GetAttributeValueFunc = func(pkcs11.SessionHandle, pkcs11.ObjectHandle, []*pkcs11.Attribute) ([]*pkcs11.Attribute, error) {
 | |
| 		return []*pkcs11.Attribute{pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, []byte{0, 0, 0, 0, 0, 0, 0, 0})}, nil
 | |
| 	}
 | |
| 	_, err := s.NewSigner("label", pubKey)
 | |
| 	test.AssertError(t, err, "newSigner didn't fail when GetRSAPublicKey fails")
 | |
| 
 | |
| 	// test newSigner fails when GetECDSAPublicKey fails
 | |
| 	ctx.GetAttributeValueFunc = func(pkcs11.SessionHandle, pkcs11.ObjectHandle, []*pkcs11.Attribute) ([]*pkcs11.Attribute, error) {
 | |
| 		return []*pkcs11.Attribute{pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, []byte{3, 0, 0, 0, 0, 0, 0, 0})}, nil
 | |
| 	}
 | |
| 	_, err = s.NewSigner("label", pubKey)
 | |
| 	test.AssertError(t, err, "newSigner didn't fail when GetECDSAPublicKey fails")
 | |
| }
 | |
| 
 | |
| func TestGetKeySucceeds(t *testing.T) {
 | |
| 	s, ctx := newSessionWithMock()
 | |
| 	pubKey := &rsa.PublicKey{N: big.NewInt(1), E: 1}
 | |
| 
 | |
| 	// test newSigner works when everything... works
 | |
| 	ctx.GetAttributeValueFunc = func(_ pkcs11.SessionHandle, _ pkcs11.ObjectHandle, attrs []*pkcs11.Attribute) ([]*pkcs11.Attribute, error) {
 | |
| 		var returns []*pkcs11.Attribute
 | |
| 		for _, attr := range attrs {
 | |
| 			switch attr.Type {
 | |
| 			case pkcs11.CKA_ID:
 | |
| 				returns = append(returns, pkcs11.NewAttribute(pkcs11.CKA_ID, []byte{99}))
 | |
| 			default:
 | |
| 				return nil, errors.New("GetAttributeValue got unexpected attribute type")
 | |
| 			}
 | |
| 		}
 | |
| 		return returns, nil
 | |
| 	}
 | |
| 	_, err := s.NewSigner("label", pubKey)
 | |
| 	test.AssertNotError(t, err, "newSigner failed when everything worked properly")
 | |
| }
 |