github.com/letsencrypt/boulder@v0.20251208.0/cmd/ceremony/ecdsa_test.go (about)

     1  package main
     2  
     3  import (
     4  	"crypto/ecdsa"
     5  	"crypto/elliptic"
     6  	"crypto/rand"
     7  	"errors"
     8  	"testing"
     9  
    10  	"github.com/letsencrypt/boulder/pkcs11helpers"
    11  	"github.com/letsencrypt/boulder/test"
    12  	"github.com/miekg/pkcs11"
    13  )
    14  
    15  func TestECPub(t *testing.T) {
    16  	s, ctx := pkcs11helpers.NewSessionWithMock()
    17  
    18  	// test we fail when pkcs11helpers.GetECDSAPublicKey fails
    19  	ctx.GetAttributeValueFunc = func(pkcs11.SessionHandle, pkcs11.ObjectHandle, []*pkcs11.Attribute) ([]*pkcs11.Attribute, error) {
    20  		return nil, errors.New("bad!")
    21  	}
    22  	_, err := ecPub(s, 0, elliptic.P256())
    23  	test.AssertError(t, err, "ecPub didn't fail with non-matching curve")
    24  	test.AssertEquals(t, err.Error(), "Failed to retrieve key attributes: bad!")
    25  
    26  	// test we fail to construct key with non-matching curve
    27  	ctx.GetAttributeValueFunc = func(pkcs11.SessionHandle, pkcs11.ObjectHandle, []*pkcs11.Attribute) ([]*pkcs11.Attribute, error) {
    28  		return []*pkcs11.Attribute{
    29  			pkcs11.NewAttribute(pkcs11.CKA_EC_PARAMS, []byte{6, 5, 43, 129, 4, 0, 33}),
    30  			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}),
    31  		}, nil
    32  	}
    33  	_, err = ecPub(s, 0, elliptic.P256())
    34  	test.AssertError(t, err, "ecPub didn't fail with non-matching curve")
    35  }
    36  
    37  func TestECGenerate(t *testing.T) {
    38  	ctx := pkcs11helpers.MockCtx{}
    39  	s := &pkcs11helpers.Session{Module: &ctx, Session: 0}
    40  	ctx.GenerateRandomFunc = func(pkcs11.SessionHandle, int) ([]byte, error) {
    41  		return []byte{1, 2, 3}, nil
    42  	}
    43  	priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
    44  	test.AssertNotError(t, err, "Failed to generate a ECDSA test key")
    45  
    46  	// Test ecGenerate fails with unknown curve
    47  	_, _, err = ecGenerate(s, "", "bad-curve")
    48  	test.AssertError(t, err, "ecGenerate accepted unknown curve")
    49  
    50  	// Test ecGenerate fails when GenerateKeyPair fails
    51  	ctx.GenerateKeyPairFunc = func(pkcs11.SessionHandle, []*pkcs11.Mechanism, []*pkcs11.Attribute, []*pkcs11.Attribute) (pkcs11.ObjectHandle, pkcs11.ObjectHandle, error) {
    52  		return 0, 0, errors.New("bad")
    53  	}
    54  	_, _, err = ecGenerate(s, "", "P-256")
    55  	test.AssertError(t, err, "ecGenerate didn't fail on GenerateKeyPair error")
    56  
    57  	// Test ecGenerate fails when ecPub fails
    58  	ctx.GenerateKeyPairFunc = func(pkcs11.SessionHandle, []*pkcs11.Mechanism, []*pkcs11.Attribute, []*pkcs11.Attribute) (pkcs11.ObjectHandle, pkcs11.ObjectHandle, error) {
    59  		return 0, 0, nil
    60  	}
    61  	ctx.GetAttributeValueFunc = func(pkcs11.SessionHandle, pkcs11.ObjectHandle, []*pkcs11.Attribute) ([]*pkcs11.Attribute, error) {
    62  		return nil, errors.New("bad")
    63  	}
    64  	_, _, err = ecGenerate(s, "", "P-256")
    65  	test.AssertError(t, err, "ecGenerate didn't fail on ecPub error")
    66  
    67  	// Test ecGenerate fails when ecVerify fails
    68  	ctx.GetAttributeValueFunc = func(pkcs11.SessionHandle, pkcs11.ObjectHandle, []*pkcs11.Attribute) ([]*pkcs11.Attribute, error) {
    69  		return []*pkcs11.Attribute{
    70  			pkcs11.NewAttribute(pkcs11.CKA_EC_PARAMS, []byte{6, 8, 42, 134, 72, 206, 61, 3, 1, 7}),
    71  			pkcs11.NewAttribute(pkcs11.CKA_EC_POINT, elliptic.Marshal(elliptic.P256(), priv.X, priv.Y)),
    72  		}, nil
    73  	}
    74  	ctx.GenerateRandomFunc = func(pkcs11.SessionHandle, int) ([]byte, error) {
    75  		return nil, errors.New("yup")
    76  	}
    77  	_, _, err = ecGenerate(s, "", "P-256")
    78  	test.AssertError(t, err, "ecGenerate didn't fail on ecVerify error")
    79  
    80  	// Test ecGenerate doesn't fail when everything works
    81  	ctx.SignInitFunc = func(pkcs11.SessionHandle, []*pkcs11.Mechanism, pkcs11.ObjectHandle) error {
    82  		return nil
    83  	}
    84  	ctx.GenerateRandomFunc = func(pkcs11.SessionHandle, int) ([]byte, error) {
    85  		return []byte{1, 2, 3}, nil
    86  	}
    87  	ctx.SignFunc = func(_ pkcs11.SessionHandle, msg []byte) ([]byte, error) {
    88  		return ecPKCS11Sign(priv, msg)
    89  	}
    90  	_, _, err = ecGenerate(s, "", "P-256")
    91  	test.AssertNotError(t, err, "ecGenerate didn't succeed when everything worked as expected")
    92  }
    93  
    94  func ecPKCS11Sign(priv *ecdsa.PrivateKey, msg []byte) ([]byte, error) {
    95  	r, s, err := ecdsa.Sign(rand.Reader, priv, msg[:])
    96  	if err != nil {
    97  		return nil, err
    98  	}
    99  	rBytes := r.Bytes()
   100  	sBytes := s.Bytes()
   101  	// http://docs.oasis-open.org/pkcs11/pkcs11-curr/v2.40/os/pkcs11-curr-v2.40-os.html
   102  	// Section 2.3.1: EC Signatures
   103  	// "If r and s have different octet length, the shorter of both must be padded with
   104  	// leading zero octets such that both have the same octet length."
   105  	switch {
   106  	case len(rBytes) < len(sBytes):
   107  		padding := make([]byte, len(sBytes)-len(rBytes))
   108  		rBytes = append(padding, rBytes...)
   109  	case len(rBytes) > len(sBytes):
   110  		padding := make([]byte, len(rBytes)-len(sBytes))
   111  		sBytes = append(padding, sBytes...)
   112  	}
   113  	return append(rBytes, sBytes...), nil
   114  }