From 400dfb7bb5f680f8d9ee996eb966e9162dd78a6e Mon Sep 17 00:00:00 2001 From: Andy Doan Date: Thu, 25 Jun 2020 20:35:05 -0500 Subject: [PATCH 1/2] ecdsa: Add support for ECDH1-DERIVE method This method can be used to help do ecies encryption. Signed-off-by: Andy Doan --- ecdsa.go | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/ecdsa.go b/ecdsa.go index c094232..d12643e 100644 --- a/ecdsa.go +++ b/ecdsa.go @@ -290,6 +290,53 @@ func (c *Context) GenerateECDSAKeyPairWithAttributes(public, private AttributeSe return k, err } +// Perform CKM_ECDH1_DERIVE function with the given public key. +// +// This implementation set the derivation parameters to CKD_NULL and therefore +// does not support ANSI X9.63 key ECDH derivation. +func (c *Context) ECDH1Derive(pk Signer, pubkey *ecdsa.PublicKey) ([]byte, error) { + ecpk, ok := pk.(*pkcs11PrivateKeyECDSA) + if !ok { + return nil, errors.New("Private key is not ECDSA") + } + + template := []*pkcs11.Attribute{ + pkcs11.NewAttribute(pkcs11.CKA_TOKEN, false), + pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_SECRET_KEY), + pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_GENERIC_SECRET), + pkcs11.NewAttribute(pkcs11.CKA_SENSITIVE, false), + pkcs11.NewAttribute(pkcs11.CKA_EXTRACTABLE, true), + pkcs11.NewAttribute(pkcs11.CKA_ENCRYPT, true), + pkcs11.NewAttribute(pkcs11.CKA_DECRYPT, true), + pkcs11.NewAttribute(pkcs11.CKA_WRAP, true), + pkcs11.NewAttribute(pkcs11.CKA_UNWRAP, true), + pkcs11.NewAttribute(pkcs11.CKA_VALUE_LEN, (pubkey.Curve.Params().BitSize+7)/8), + } + params := pkcs11.ECDH1DeriveParams{KDF: pkcs11.CKD_NULL, PublicKeyData: elliptic.Marshal(pubkey.Curve, pubkey.X, pubkey.Y)} + mech := []*pkcs11.Mechanism{ + pkcs11.NewMechanism(pkcs11.CKM_ECDH1_DERIVE, ¶ms), + } + + var buf []byte + err := c.withSession(func(session *pkcs11Session) error { + handle, err := session.ctx.DeriveKey(session.handle, mech, ecpk.handle, template) + if err != nil { + return err + } + + template = []*pkcs11.Attribute{ + pkcs11.NewAttribute(pkcs11.CKA_VALUE, nil), + } + attr, err := session.ctx.GetAttributeValue(session.handle, handle, template) + if err != nil { + return err + } + buf = attr[0].Value + return nil + }) + return buf, err +} + // Sign signs a message using an ECDSA key. // // This completes the implemention of crypto.Signer for pkcs11PrivateKeyECDSA. From ff32260f12899c9b7fab5fa37468fb593cd19871 Mon Sep 17 00:00:00 2001 From: Andy Doan Date: Tue, 21 Jul 2020 15:16:01 -0500 Subject: [PATCH 2/2] ecdsa: Add test for ECDH1Derive Signed-off-by: Andy Doan --- ecdsa.go | 1 + ecdsa_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/ecdsa.go b/ecdsa.go index d12643e..ae93045 100644 --- a/ecdsa.go +++ b/ecdsa.go @@ -261,6 +261,7 @@ func (c *Context) GenerateECDSAKeyPairWithAttributes(public, private AttributeSe pkcs11.NewAttribute(pkcs11.CKA_SIGN, true), pkcs11.NewAttribute(pkcs11.CKA_SENSITIVE, true), pkcs11.NewAttribute(pkcs11.CKA_EXTRACTABLE, false), + pkcs11.NewAttribute(pkcs11.CKA_DERIVE, true), }) mech := []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_ECDSA_KEY_PAIR_GEN, nil)} diff --git a/ecdsa_test.go b/ecdsa_test.go index 43407e3..905ff32 100644 --- a/ecdsa_test.go +++ b/ecdsa_test.go @@ -150,3 +150,28 @@ func TestEcdsaRequiredArgs(t *testing.T) { _, err = ctx.GenerateECDSAKeyPairWithLabel(val, nil, elliptic.P224()) require.Error(t, err) } + +func TestEcdsaECDH1Derive(t *testing.T) { + ctx, err := ConfigureFromFile("config") + require.NoError(t, err) + + defer func() { + require.NoError(t, ctx.Close()) + }() + + key1, err := ctx.GenerateECDSAKeyPair(randomBytes(), elliptic.P256()) + require.NoError(t, err) + require.NotNil(t, key1) + defer key1.Delete() + + key2, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + require.NoError(t, err) + + d1, err := ctx.ECDH1Derive(key1, key2.Public().(crypto.PublicKey).(*ecdsa.PublicKey)) + require.NoError(t, err) + + pub := key1.Public().(crypto.PublicKey).(*ecdsa.PublicKey) + d2, _ := pub.Curve.ScalarMult(pub.X, pub.Y, key2.D.Bytes()) + + require.Equal(t, d1, d2.Bytes()) +}