Check for existing objects before generating a key. (#4981)

We only expect to want one key per slot/token.

Refactor key_test somewhat to split up cases, and add a new test case.
This commit is contained in:
Jacob Hoffman-Andrews 2020-07-23 16:55:43 -07:00 committed by GitHub
parent 91ba1730dc
commit 62eae60711
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 62 additions and 20 deletions

View File

@ -54,9 +54,13 @@ type keyInfo struct {
}
func generateKey(ctx pkcs11helpers.PKCtx, session pkcs11.SessionHandle, label string, outputPath string, config keyGenConfig) (*keyInfo, error) {
_, err := pkcs11helpers.FindObject(ctx, session, []*pkcs11.Attribute{})
if err != pkcs11helpers.ErrNoObject {
return nil, fmt.Errorf("expected no objects in slot for key storage. got error: %s", err)
}
var pubKey crypto.PublicKey
var keyID []byte
var err error
switch config.Type {
case "rsa":
pubKey, keyID, err = rsaGenerate(ctx, session, label, config.RSAModLength, rsaExp)

View File

@ -12,6 +12,7 @@ import (
"math/big"
"os"
"path"
"strings"
"testing"
"github.com/letsencrypt/boulder/pkcs11helpers"
@ -19,30 +20,43 @@ import (
"github.com/miekg/pkcs11"
)
func TestGenerateKey(t *testing.T) {
tmp, err := ioutil.TempDir("", "ceremony-testing")
func setupCtx() pkcs11helpers.MockCtx {
return pkcs11helpers.MockCtx{
GenerateKeyPairFunc: func(pkcs11.SessionHandle, []*pkcs11.Mechanism, []*pkcs11.Attribute, []*pkcs11.Attribute) (pkcs11.ObjectHandle, pkcs11.ObjectHandle, error) {
return 0, 0, nil
},
SignInitFunc: func(pkcs11.SessionHandle, []*pkcs11.Mechanism, pkcs11.ObjectHandle) error {
return nil
},
GenerateRandomFunc: func(pkcs11.SessionHandle, int) ([]byte, error) {
return []byte{1, 2, 3}, nil
},
FindObjectsInitFunc: func(pkcs11.SessionHandle, []*pkcs11.Attribute) error {
return nil
},
FindObjectsFunc: func(pkcs11.SessionHandle, int) ([]pkcs11.ObjectHandle, bool, error) {
return nil, false, nil
},
FindObjectsFinalFunc: func(pkcs11.SessionHandle) error {
return nil
},
}
}
func TestGenerateKeyRSA(t *testing.T) {
tmp, err := ioutil.TempDir("", "ceremony-testing-rsa")
test.AssertNotError(t, err, "Failed to create temporary directory")
defer os.RemoveAll(tmp)
// RSA
ctx := pkcs11helpers.MockCtx{}
ctx := setupCtx()
rsaPriv, err := rsa.GenerateKey(rand.Reader, 1024)
test.AssertNotError(t, err, "Failed to generate a test RSA key")
ctx.GenerateKeyPairFunc = func(pkcs11.SessionHandle, []*pkcs11.Mechanism, []*pkcs11.Attribute, []*pkcs11.Attribute) (pkcs11.ObjectHandle, pkcs11.ObjectHandle, error) {
return 0, 0, nil
}
ctx.GetAttributeValueFunc = func(pkcs11.SessionHandle, pkcs11.ObjectHandle, []*pkcs11.Attribute) ([]*pkcs11.Attribute, error) {
return []*pkcs11.Attribute{
pkcs11.NewAttribute(pkcs11.CKA_PUBLIC_EXPONENT, big.NewInt(int64(rsaPriv.E)).Bytes()),
pkcs11.NewAttribute(pkcs11.CKA_MODULUS, rsaPriv.N.Bytes()),
}, nil
}
ctx.SignInitFunc = func(pkcs11.SessionHandle, []*pkcs11.Mechanism, pkcs11.ObjectHandle) error {
return nil
}
ctx.GenerateRandomFunc = func(pkcs11.SessionHandle, int) ([]byte, error) {
return []byte{1, 2, 3}, nil
}
ctx.SignFunc = func(_ pkcs11.SessionHandle, msg []byte) ([]byte, error) {
// Chop of the hash identifier and feed back into rsa.SignPKCS1v15
return rsa.SignPKCS1v15(rand.Reader, rsaPriv, crypto.SHA256, msg[19:])
@ -59,8 +73,14 @@ func TestGenerateKey(t *testing.T) {
diskKey, err := x509.ParsePKIXPublicKey(block.Bytes)
test.AssertNotError(t, err, "Failed to parse disk key")
test.AssertDeepEquals(t, diskKey, keyInfo.key)
}
// EC
func TestGenerateKeyEC(t *testing.T) {
tmp, err := ioutil.TempDir("", "ceremony-testing-ec")
test.AssertNotError(t, err, "Failed to create temporary directory")
defer os.RemoveAll(tmp)
ctx := setupCtx()
ecPriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
test.AssertNotError(t, err, "Failed to generate a ECDSA test key")
ctx.GetAttributeValueFunc = func(pkcs11.SessionHandle, pkcs11.ObjectHandle, []*pkcs11.Attribute) ([]*pkcs11.Attribute, error) {
@ -72,16 +92,34 @@ func TestGenerateKey(t *testing.T) {
ctx.SignFunc = func(_ pkcs11.SessionHandle, msg []byte) ([]byte, error) {
return ecPKCS11Sign(ecPriv, msg)
}
keyPath = path.Join(tmp, "test-ecdsa-key.pem")
keyInfo, err = generateKey(ctx, 0, "", keyPath, keyGenConfig{
keyPath := path.Join(tmp, "test-ecdsa-key.pem")
keyInfo, err := generateKey(ctx, 0, "", keyPath, keyGenConfig{
Type: "ecdsa",
ECDSACurve: "P-256",
})
test.AssertNotError(t, err, "Failed to generate ECDSA key")
diskKeyBytes, err = ioutil.ReadFile(keyPath)
diskKeyBytes, err := ioutil.ReadFile(keyPath)
test.AssertNotError(t, err, "Failed to load key from disk")
block, _ = pem.Decode(diskKeyBytes)
diskKey, err = x509.ParsePKIXPublicKey(block.Bytes)
block, _ := pem.Decode(diskKeyBytes)
diskKey, err := x509.ParsePKIXPublicKey(block.Bytes)
test.AssertNotError(t, err, "Failed to parse disk key")
test.AssertDeepEquals(t, diskKey, keyInfo.key)
}
func TestGenerateKeySlotHasSomething(t *testing.T) {
tmp, err := ioutil.TempDir("", "ceremony-testing-slot-has-something")
test.AssertNotError(t, err, "Failed to create temporary directory")
defer os.RemoveAll(tmp)
ctx := setupCtx()
ctx.FindObjectsFunc = func(pkcs11.SessionHandle, int) ([]pkcs11.ObjectHandle, bool, error) {
return []pkcs11.ObjectHandle{1}, false, nil
}
keyPath := path.Join(tmp, "should-not-exist.pem")
_, err = generateKey(ctx, 0, "", keyPath, keyGenConfig{
Type: "ecdsa",
ECDSACurve: "P-256",
})
test.AssertError(t, err, "expected failure for a slot with an object already in it")
test.Assert(t, strings.HasPrefix(err.Error(), "expected no objects"), "wrong error")
}