From c7e7c541e2d0cd8647ed0f19849c277268acfe3f Mon Sep 17 00:00:00 2001 From: Andy Doan Date: Fri, 26 Jun 2020 10:45:03 -0500 Subject: [PATCH 1/7] pkcs11: Stub out where this will happen Signed-off-by: Andy Doan --- internal/app.go | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/internal/app.go b/internal/app.go index 8dd624e..4307d5b 100644 --- a/internal/app.go +++ b/internal/app.go @@ -56,10 +56,11 @@ func tomlAssertVal(tree *toml.Tree, key string, allowed []string) string { return val } -func createClient(sota *toml.Tree) (*http.Client, CryptoHandler) { - _ = tomlAssertVal(sota, "tls.ca_source", []string{"file"}) - _ = tomlAssertVal(sota, "tls.pkey_source", []string{"file"}) - _ = tomlAssertVal(sota, "tls.cert_source", []string{"file"}) +func createClientPkcs11(sota *toml.Tree) (*http.Client, CryptoHandler) { + panic("TODO") +} + +func createClientLocal(sota *toml.Tree) (*http.Client, CryptoHandler) { certFile := tomlGet(sota, "import.tls_clientcert_path") keyFile := tomlGet(sota, "import.tls_pkey_path") caFile := tomlGet(sota, "import.tls_cacert_path") @@ -89,6 +90,16 @@ func createClient(sota *toml.Tree) (*http.Client, CryptoHandler) { panic("Unsupported private key") } +func createClient(sota *toml.Tree) (*http.Client, CryptoHandler) { + _ = tomlAssertVal(sota, "tls.ca_source", []string{"file"}) + source := tomlAssertVal(sota, "tls.pkey_source", []string{"file", "pkcs11"}) + _ = tomlAssertVal(sota, "tls.cert_source", []string{source}) + if source == "file" { + return createClientLocal(sota) + } + return createClientPkcs11(sota) +} + func NewApp(sota_config, secrets_dir string, testing bool) (*App, error) { sota, err := toml.LoadFile(filepath.Join(sota_config, "sota.toml")) if err != nil { From e7033fbb8ff18b61e8e8bf87367b4254e9bcee32 Mon Sep 17 00:00:00 2001 From: Andy Doan Date: Fri, 26 Jun 2020 12:02:18 -0500 Subject: [PATCH 2/7] Start of pkcs11 support This lets us connect to the device-gateway via TLS Signed-off-by: Andy Doan --- go.mod | 1 + go.sum | 6 +++++ internal/app.go | 66 +++++++++++++++++++++++++++++++++++++++++++++-- internal/ecies.go | 7 ++++- 4 files changed, 77 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4de4596..ffbf273 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/foundriesio/fioconfig go 1.13 require ( + github.com/ThalesIgnite/crypto11 v1.2.1 github.com/ethereum/go-ethereum v1.9.11 github.com/pelletier/go-toml v1.8.0 github.com/urfave/cli/v2 v2.2.0 diff --git a/go.sum b/go.sum index 4378381..2a1c41a 100644 --- a/go.sum +++ b/go.sum @@ -15,6 +15,7 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.5/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/ThalesIgnite/crypto11 v1.2.1/go.mod h1:vmlYtalkn8uCp3eStRZ0r7Sslmf1jAtL8De0PIyqPks= github.com/VictoriaMetrics/fastcache v1.5.3/go.mod h1:+jv9Ckb+za/P1ZRg/sulP5Ni1v49daAVERr0H3CuscE= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -79,6 +80,8 @@ github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXT github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/pkcs11 v1.0.3-0.20190429190417-a667d056470f h1:eVB9ELsoq5ouItQBr5Tj334bhPJG/MX+m7rTchmzVUQ= +github.com/miekg/pkcs11 v1.0.3-0.20190429190417-a667d056470f/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= @@ -93,6 +96,7 @@ github.com/pelletier/go-toml v1.8.0 h1:Keo9qb7iRJs2voHvunFtuuYFsbWeOBh8/P9v/kVMF github.com/pelletier/go-toml v1.8.0/go.mod h1:D6yutnOGMveHEPV7VQOuvI/gXY61bv+9bAOTRnLElKs= github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -117,6 +121,8 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA= +github.com/thales-e-security/pool v0.0.1 h1:1eJJNN2K/mAzwfr546brAiQVa3UaRC0gGENsHM8veS8= +github.com/thales-e-security/pool v0.0.1/go.mod h1:qtpMm2+thHtqhLzTwgDBj/OuNnMpupY8mv0Phz0gjhU= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= diff --git a/internal/app.go b/internal/app.go index 4307d5b..afa6896 100644 --- a/internal/app.go +++ b/internal/app.go @@ -15,6 +15,7 @@ import ( "path/filepath" "time" + "github.com/ThalesIgnite/crypto11" toml "github.com/pelletier/go-toml" ) @@ -56,8 +57,69 @@ func tomlAssertVal(tree *toml.Tree, key string, allowed []string) string { return val } +// sota.toml has slot id's as "01". We need to turn that into []byte{1} +func idToBytes(id string) []byte { + bytes := []byte(id) + start := -1 + for idx, char := range bytes { + bytes[idx] = char - byte('0') + if bytes[idx] != 0 && start == -1 { + start = idx + } + } + //strip off leading 0's + return bytes[start:] +} + func createClientPkcs11(sota *toml.Tree) (*http.Client, CryptoHandler) { - panic("TODO") + module := tomlGet(sota, "p11.module") + pin := tomlGet(sota, "p11.pass") + pkeyId := tomlGet(sota, "p11.tls_pkey_id") + certId := tomlGet(sota, "p11.tls_clientcert_id") + caFile := tomlGet(sota, "import.tls_cacert_path") + + cfg := crypto11.Config{ + Path: module, + TokenLabel: "aktualizr", + Pin: pin, + } + + ctx, err := crypto11.Configure(&cfg) + if err != nil { + log.Fatal(err) + } + + privKey, err := ctx.FindKeyPair(idToBytes(pkeyId), nil) + if err != nil { + log.Fatal(err) + } + cert, err := ctx.FindCertificate(idToBytes(certId), nil, nil) + if err != nil { + log.Fatal(err) + } + if cert == nil || privKey == nil { + log.Fatal("Unable to load pkcs11 client cert and/or private key") + } + + caCert, err := ioutil.ReadFile(caFile) + if err != nil { + log.Fatal(err) + } + caCertPool := x509.NewCertPool() + caCertPool.AppendCertsFromPEM(caCert) + + tlsConfig := &tls.Config{ + Certificates: []tls.Certificate{ + tls.Certificate{ + Certificate: [][]byte{cert.Raw}, + PrivateKey: privKey, + }, + }, + RootCAs: caCertPool, + } + transport := &http.Transport{TLSClientConfig: tlsConfig} + client := &http.Client{Timeout: time.Second * 30, Transport: transport} + return client, NewEciesPkcs11Handler(privKey) } func createClientLocal(sota *toml.Tree) (*http.Client, CryptoHandler) { @@ -84,7 +146,7 @@ func createClientLocal(sota *toml.Tree) (*http.Client, CryptoHandler) { transport := &http.Transport{TLSClientConfig: tlsConfig} client := &http.Client{Timeout: time.Second * 30, Transport: transport} - if handler := NewEciesHandler(cert.PrivateKey); handler != nil { + if handler := NewEciesLocalHandler(cert.PrivateKey); handler != nil { return client, handler } panic("Unsupported private key") diff --git a/internal/ecies.go b/internal/ecies.go index 3b89ec7..62c72f8 100644 --- a/internal/ecies.go +++ b/internal/ecies.go @@ -6,6 +6,7 @@ import ( "encoding/base64" "fmt" + "github.com/ThalesIgnite/crypto11" "github.com/ethereum/go-ethereum/crypto/ecies" ) @@ -13,7 +14,7 @@ type EciesCrypto struct { PrivKey *ecies.PrivateKey } -func NewEciesHandler(privKey crypto.PrivateKey) CryptoHandler { +func NewEciesLocalHandler(privKey crypto.PrivateKey) CryptoHandler { if ec, ok := privKey.(*ecdsa.PrivateKey); ok { return &EciesCrypto{ecies.ImportECDSA(ec)} } @@ -31,3 +32,7 @@ func (ec *EciesCrypto) Decrypt(value string) ([]byte, error) { } return decrypted, nil } + +func NewEciesPkcs11Handler(privKey crypto11.Signer) CryptoHandler { + panic("NOT IMPLEMENTED") +} From 46a5b4c9be1f03d1749dfd389cba9327bf9e6a3b Mon Sep 17 00:00:00 2001 From: Andy Doan Date: Fri, 26 Jun 2020 13:21:47 -0500 Subject: [PATCH 3/7] Pull in ecies implementation from ethereum We are going to update this in a way that probably can't be merged upstream. This was copied from: https://github.com/ethereum/go-ethereum/blob/02cea2330d6b4822b43a7fbaeacc12ddc8e8b1db/crypto/ecies/ecies.go Signed-off-by: Andy Doan --- internal/ecies_ethereum.go | 323 ++++++++++++++++++++++++++++++ internal/ecies_params_ethereum.go | 137 +++++++++++++ 2 files changed, 460 insertions(+) create mode 100644 internal/ecies_ethereum.go create mode 100644 internal/ecies_params_ethereum.go diff --git a/internal/ecies_ethereum.go b/internal/ecies_ethereum.go new file mode 100644 index 0000000..d01cb25 --- /dev/null +++ b/internal/ecies_ethereum.go @@ -0,0 +1,323 @@ +// Copyright (c) 2013 Kyle Isom +// Copyright (c) 2012 The Go Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This is forked from: +// https://github.com/ethereum/go-ethereum/blob/02cea2330d6b4822b43a7fbaeacc12ddc8e8b1db/crypto/ecies/ecies.go +// to work with both local private keys and pcks11 based keys + + +package ecies + +import ( + "crypto/cipher" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/hmac" + "crypto/subtle" + "encoding/binary" + "fmt" + "hash" + "io" + "math/big" +) + +var ( + ErrImport = fmt.Errorf("ecies: failed to import key") + ErrInvalidCurve = fmt.Errorf("ecies: invalid elliptic curve") + ErrInvalidPublicKey = fmt.Errorf("ecies: invalid public key") + ErrSharedKeyIsPointAtInfinity = fmt.Errorf("ecies: shared key is point at infinity") + ErrSharedKeyTooBig = fmt.Errorf("ecies: shared key params are too big") +) + +// PublicKey is a representation of an elliptic curve public key. +type PublicKey struct { + X *big.Int + Y *big.Int + elliptic.Curve + Params *ECIESParams +} + +// Export an ECIES public key as an ECDSA public key. +func (pub *PublicKey) ExportECDSA() *ecdsa.PublicKey { + return &ecdsa.PublicKey{Curve: pub.Curve, X: pub.X, Y: pub.Y} +} + +// Import an ECDSA public key as an ECIES public key. +func ImportECDSAPublic(pub *ecdsa.PublicKey) *PublicKey { + return &PublicKey{ + X: pub.X, + Y: pub.Y, + Curve: pub.Curve, + Params: ParamsFromCurve(pub.Curve), + } +} + +// PrivateKey is a representation of an elliptic curve private key. +type PrivateKey struct { + PublicKey + D *big.Int +} + +// Export an ECIES private key as an ECDSA private key. +func (prv *PrivateKey) ExportECDSA() *ecdsa.PrivateKey { + pub := &prv.PublicKey + pubECDSA := pub.ExportECDSA() + return &ecdsa.PrivateKey{PublicKey: *pubECDSA, D: prv.D} +} + +// Import an ECDSA private key as an ECIES private key. +func ImportECDSA(prv *ecdsa.PrivateKey) *PrivateKey { + pub := ImportECDSAPublic(&prv.PublicKey) + return &PrivateKey{*pub, prv.D} +} + +// Generate an elliptic curve public / private keypair. If params is nil, +// the recommended default parameters for the key will be chosen. +func GenerateKey(rand io.Reader, curve elliptic.Curve, params *ECIESParams) (prv *PrivateKey, err error) { + pb, x, y, err := elliptic.GenerateKey(curve, rand) + if err != nil { + return + } + prv = new(PrivateKey) + prv.PublicKey.X = x + prv.PublicKey.Y = y + prv.PublicKey.Curve = curve + prv.D = new(big.Int).SetBytes(pb) + if params == nil { + params = ParamsFromCurve(curve) + } + prv.PublicKey.Params = params + return +} + +// MaxSharedKeyLength returns the maximum length of the shared key the +// public key can produce. +func MaxSharedKeyLength(pub *PublicKey) int { + return (pub.Curve.Params().BitSize + 7) / 8 +} + +// ECDH key agreement method used to establish secret keys for encryption. +func (prv *PrivateKey) GenerateShared(pub *PublicKey, skLen, macLen int) (sk []byte, err error) { + if prv.PublicKey.Curve != pub.Curve { + return nil, ErrInvalidCurve + } + if skLen+macLen > MaxSharedKeyLength(pub) { + return nil, ErrSharedKeyTooBig + } + + x, _ := pub.Curve.ScalarMult(pub.X, pub.Y, prv.D.Bytes()) + if x == nil { + return nil, ErrSharedKeyIsPointAtInfinity + } + + sk = make([]byte, skLen+macLen) + skBytes := x.Bytes() + copy(sk[len(sk)-len(skBytes):], skBytes) + return sk, nil +} + +var ( + ErrSharedTooLong = fmt.Errorf("ecies: shared secret is too long") + ErrInvalidMessage = fmt.Errorf("ecies: invalid message") +) + +// NIST SP 800-56 Concatenation Key Derivation Function (see section 5.8.1). +func concatKDF(hash hash.Hash, z, s1 []byte, kdLen int) []byte { + counterBytes := make([]byte, 4) + k := make([]byte, 0, roundup(kdLen, hash.Size())) + for counter := uint32(1); len(k) < kdLen; counter++ { + binary.BigEndian.PutUint32(counterBytes, counter) + hash.Reset() + hash.Write(counterBytes) + hash.Write(z) + hash.Write(s1) + k = hash.Sum(k) + } + return k[:kdLen] +} + +// roundup rounds size up to the next multiple of blocksize. +func roundup(size, blocksize int) int { + return size + blocksize - (size % blocksize) +} + +// deriveKeys creates the encryption and MAC keys using concatKDF. +func deriveKeys(hash hash.Hash, z, s1 []byte, keyLen int) (Ke, Km []byte) { + K := concatKDF(hash, z, s1, 2*keyLen) + Ke = K[:keyLen] + Km = K[keyLen:] + hash.Reset() + hash.Write(Km) + Km = hash.Sum(Km[:0]) + return Ke, Km +} + +// messageTag computes the MAC of a message (called the tag) as per +// SEC 1, 3.5. +func messageTag(hash func() hash.Hash, km, msg, shared []byte) []byte { + mac := hmac.New(hash, km) + mac.Write(msg) + mac.Write(shared) + tag := mac.Sum(nil) + return tag +} + +// Generate an initialisation vector for CTR mode. +func generateIV(params *ECIESParams, rand io.Reader) (iv []byte, err error) { + iv = make([]byte, params.BlockSize) + _, err = io.ReadFull(rand, iv) + return +} + +// symEncrypt carries out CTR encryption using the block cipher specified in the +func symEncrypt(rand io.Reader, params *ECIESParams, key, m []byte) (ct []byte, err error) { + c, err := params.Cipher(key) + if err != nil { + return + } + + iv, err := generateIV(params, rand) + if err != nil { + return + } + ctr := cipher.NewCTR(c, iv) + + ct = make([]byte, len(m)+params.BlockSize) + copy(ct, iv) + ctr.XORKeyStream(ct[params.BlockSize:], m) + return +} + +// symDecrypt carries out CTR decryption using the block cipher specified in +// the parameters +func symDecrypt(params *ECIESParams, key, ct []byte) (m []byte, err error) { + c, err := params.Cipher(key) + if err != nil { + return + } + + ctr := cipher.NewCTR(c, ct[:params.BlockSize]) + + m = make([]byte, len(ct)-params.BlockSize) + ctr.XORKeyStream(m, ct[params.BlockSize:]) + return +} + +// Encrypt encrypts a message using ECIES as specified in SEC 1, 5.1. +// +// s1 and s2 contain shared information that is not part of the resulting +// ciphertext. s1 is fed into key derivation, s2 is fed into the MAC. If the +// shared information parameters aren't being used, they should be nil. +func Encrypt(rand io.Reader, pub *PublicKey, m, s1, s2 []byte) (ct []byte, err error) { + params, err := pubkeyParams(pub) + if err != nil { + return nil, err + } + + R, err := GenerateKey(rand, pub.Curve, params) + if err != nil { + return nil, err + } + + z, err := R.GenerateShared(pub, params.KeyLen, params.KeyLen) + if err != nil { + return nil, err + } + + hash := params.Hash() + Ke, Km := deriveKeys(hash, z, s1, params.KeyLen) + + em, err := symEncrypt(rand, params, Ke, m) + if err != nil || len(em) <= params.BlockSize { + return nil, err + } + + d := messageTag(params.Hash, Km, em, s2) + + Rb := elliptic.Marshal(pub.Curve, R.PublicKey.X, R.PublicKey.Y) + ct = make([]byte, len(Rb)+len(em)+len(d)) + copy(ct, Rb) + copy(ct[len(Rb):], em) + copy(ct[len(Rb)+len(em):], d) + return ct, nil +} + +// Decrypt decrypts an ECIES ciphertext. +func (prv *PrivateKey) Decrypt(c, s1, s2 []byte) (m []byte, err error) { + if len(c) == 0 { + return nil, ErrInvalidMessage + } + params, err := pubkeyParams(&prv.PublicKey) + if err != nil { + return nil, err + } + + hash := params.Hash() + + var ( + rLen int + hLen int = hash.Size() + mStart int + mEnd int + ) + + switch c[0] { + case 2, 3, 4: + rLen = (prv.PublicKey.Curve.Params().BitSize + 7) / 4 + if len(c) < (rLen + hLen + 1) { + return nil, ErrInvalidMessage + } + default: + return nil, ErrInvalidPublicKey + } + + mStart = rLen + mEnd = len(c) - hLen + + R := new(PublicKey) + R.Curve = prv.PublicKey.Curve + R.X, R.Y = elliptic.Unmarshal(R.Curve, c[:rLen]) + if R.X == nil { + return nil, ErrInvalidPublicKey + } + + z, err := prv.GenerateShared(R, params.KeyLen, params.KeyLen) + if err != nil { + return nil, err + } + Ke, Km := deriveKeys(hash, z, s1, params.KeyLen) + + d := messageTag(params.Hash, Km, c[mStart:mEnd], s2) + if subtle.ConstantTimeCompare(c[mEnd:], d) != 1 { + return nil, ErrInvalidMessage + } + + return symDecrypt(params, Ke, c[mStart:mEnd]) +} + diff --git a/internal/ecies_params_ethereum.go b/internal/ecies_params_ethereum.go new file mode 100644 index 0000000..93bf8d9 --- /dev/null +++ b/internal/ecies_params_ethereum.go @@ -0,0 +1,137 @@ +// Copyright (c) 2013 Kyle Isom +// Copyright (c) 2012 The Go Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package ecies + +// This file contains parameters for ECIES encryption, specifying the +// symmetric encryption and HMAC parameters. + +import ( + "crypto" + "crypto/aes" + "crypto/cipher" + "crypto/elliptic" + "crypto/sha256" + "crypto/sha512" + "fmt" + "hash" + + ethcrypto "github.com/ethereum/go-ethereum/crypto" +) + +var ( + DefaultCurve = ethcrypto.S256() + ErrUnsupportedECDHAlgorithm = fmt.Errorf("ecies: unsupported ECDH algorithm") + ErrUnsupportedECIESParameters = fmt.Errorf("ecies: unsupported ECIES parameters") + ErrInvalidKeyLen = fmt.Errorf("ecies: invalid key size (> %d) in ECIESParams", maxKeyLen) +) + +// KeyLen is limited to prevent overflow of the counter +// in concatKDF. While the theoretical limit is much higher, +// no known cipher uses keys larger than 512 bytes. +const maxKeyLen = 512 + +type ECIESParams struct { + Hash func() hash.Hash // hash function + hashAlgo crypto.Hash + Cipher func([]byte) (cipher.Block, error) // symmetric cipher + BlockSize int // block size of symmetric cipher + KeyLen int // length of symmetric key +} + +// Standard ECIES parameters: +// * ECIES using AES128 and HMAC-SHA-256-16 +// * ECIES using AES256 and HMAC-SHA-256-32 +// * ECIES using AES256 and HMAC-SHA-384-48 +// * ECIES using AES256 and HMAC-SHA-512-64 + +var ( + ECIES_AES128_SHA256 = &ECIESParams{ + Hash: sha256.New, + hashAlgo: crypto.SHA256, + Cipher: aes.NewCipher, + BlockSize: aes.BlockSize, + KeyLen: 16, + } + + ECIES_AES256_SHA256 = &ECIESParams{ + Hash: sha256.New, + hashAlgo: crypto.SHA256, + Cipher: aes.NewCipher, + BlockSize: aes.BlockSize, + KeyLen: 32, + } + + ECIES_AES256_SHA384 = &ECIESParams{ + Hash: sha512.New384, + hashAlgo: crypto.SHA384, + Cipher: aes.NewCipher, + BlockSize: aes.BlockSize, + KeyLen: 32, + } + + ECIES_AES256_SHA512 = &ECIESParams{ + Hash: sha512.New, + hashAlgo: crypto.SHA512, + Cipher: aes.NewCipher, + BlockSize: aes.BlockSize, + KeyLen: 32, + } +) + +var paramsFromCurve = map[elliptic.Curve]*ECIESParams{ + ethcrypto.S256(): ECIES_AES128_SHA256, + elliptic.P256(): ECIES_AES128_SHA256, + elliptic.P384(): ECIES_AES256_SHA384, + elliptic.P521(): ECIES_AES256_SHA512, +} + +func AddParamsForCurve(curve elliptic.Curve, params *ECIESParams) { + paramsFromCurve[curve] = params +} + +// ParamsFromCurve selects parameters optimal for the selected elliptic curve. +// Only the curves P256, P384, and P512 are supported. +func ParamsFromCurve(curve elliptic.Curve) (params *ECIESParams) { + return paramsFromCurve[curve] +} + +func pubkeyParams(key *PublicKey) (*ECIESParams, error) { + params := key.Params + if params == nil { + if params = ParamsFromCurve(key.Curve); params == nil { + return nil, ErrUnsupportedECIESParameters + } + } + if params.KeyLen > maxKeyLen { + return nil, ErrInvalidKeyLen + } + return params, nil +} + From bbbb84196208403b9516c5c1767d8accca71d5e7 Mon Sep 17 00:00:00 2001 From: Andy Doan Date: Fri, 26 Jun 2020 13:37:23 -0500 Subject: [PATCH 4/7] use new ecies library in application This required some golang tidy updates and I removed the unused functions. Signed-off-by: Andy Doan --- internal/ecies.go | 5 +- internal/ecies_ethereum.go | 134 +++++++----------------------- internal/ecies_params_ethereum.go | 3 +- 3 files changed, 31 insertions(+), 111 deletions(-) diff --git a/internal/ecies.go b/internal/ecies.go index 62c72f8..74ce969 100644 --- a/internal/ecies.go +++ b/internal/ecies.go @@ -7,16 +7,15 @@ import ( "fmt" "github.com/ThalesIgnite/crypto11" - "github.com/ethereum/go-ethereum/crypto/ecies" ) type EciesCrypto struct { - PrivKey *ecies.PrivateKey + PrivKey *PrivateKey } func NewEciesLocalHandler(privKey crypto.PrivateKey) CryptoHandler { if ec, ok := privKey.(*ecdsa.PrivateKey); ok { - return &EciesCrypto{ecies.ImportECDSA(ec)} + return &EciesCrypto{ImportECDSA(ec)} } return nil } diff --git a/internal/ecies_ethereum.go b/internal/ecies_ethereum.go index d01cb25..5e8101a 100644 --- a/internal/ecies_ethereum.go +++ b/internal/ecies_ethereum.go @@ -31,8 +31,7 @@ // https://github.com/ethereum/go-ethereum/blob/02cea2330d6b4822b43a7fbaeacc12ddc8e8b1db/crypto/ecies/ecies.go // to work with both local private keys and pcks11 based keys - -package ecies +package internal import ( "crypto/cipher" @@ -43,7 +42,6 @@ import ( "encoding/binary" "fmt" "hash" - "io" "math/big" ) @@ -63,11 +61,6 @@ type PublicKey struct { Params *ECIESParams } -// Export an ECIES public key as an ECDSA public key. -func (pub *PublicKey) ExportECDSA() *ecdsa.PublicKey { - return &ecdsa.PublicKey{Curve: pub.Curve, X: pub.X, Y: pub.Y} -} - // Import an ECDSA public key as an ECIES public key. func ImportECDSAPublic(pub *ecdsa.PublicKey) *PublicKey { return &PublicKey{ @@ -84,38 +77,12 @@ type PrivateKey struct { D *big.Int } -// Export an ECIES private key as an ECDSA private key. -func (prv *PrivateKey) ExportECDSA() *ecdsa.PrivateKey { - pub := &prv.PublicKey - pubECDSA := pub.ExportECDSA() - return &ecdsa.PrivateKey{PublicKey: *pubECDSA, D: prv.D} -} - // Import an ECDSA private key as an ECIES private key. func ImportECDSA(prv *ecdsa.PrivateKey) *PrivateKey { pub := ImportECDSAPublic(&prv.PublicKey) return &PrivateKey{*pub, prv.D} } -// Generate an elliptic curve public / private keypair. If params is nil, -// the recommended default parameters for the key will be chosen. -func GenerateKey(rand io.Reader, curve elliptic.Curve, params *ECIESParams) (prv *PrivateKey, err error) { - pb, x, y, err := elliptic.GenerateKey(curve, rand) - if err != nil { - return - } - prv = new(PrivateKey) - prv.PublicKey.X = x - prv.PublicKey.Y = y - prv.PublicKey.Curve = curve - prv.D = new(big.Int).SetBytes(pb) - if params == nil { - params = ParamsFromCurve(curve) - } - prv.PublicKey.Params = params - return -} - // MaxSharedKeyLength returns the maximum length of the shared key the // public key can produce. func MaxSharedKeyLength(pub *PublicKey) int { @@ -154,9 +121,15 @@ func concatKDF(hash hash.Hash, z, s1 []byte, kdLen int) []byte { for counter := uint32(1); len(k) < kdLen; counter++ { binary.BigEndian.PutUint32(counterBytes, counter) hash.Reset() - hash.Write(counterBytes) - hash.Write(z) - hash.Write(s1) + if _, err := hash.Write(counterBytes); err != nil { + return nil + } + if _, err := hash.Write(z); err != nil { + return nil + } + if _, err := hash.Write(s1); err != nil { + return nil + } k = hash.Sum(k) } return k[:kdLen] @@ -170,10 +143,15 @@ func roundup(size, blocksize int) int { // deriveKeys creates the encryption and MAC keys using concatKDF. func deriveKeys(hash hash.Hash, z, s1 []byte, keyLen int) (Ke, Km []byte) { K := concatKDF(hash, z, s1, 2*keyLen) + if K == nil { + return nil, nil + } Ke = K[:keyLen] Km = K[keyLen:] hash.Reset() - hash.Write(Km) + if _, err := hash.Write(Km); err != nil { + return nil, nil + } Km = hash.Sum(Km[:0]) return Ke, Km } @@ -182,36 +160,14 @@ func deriveKeys(hash hash.Hash, z, s1 []byte, keyLen int) (Ke, Km []byte) { // SEC 1, 3.5. func messageTag(hash func() hash.Hash, km, msg, shared []byte) []byte { mac := hmac.New(hash, km) - mac.Write(msg) - mac.Write(shared) - tag := mac.Sum(nil) - return tag -} - -// Generate an initialisation vector for CTR mode. -func generateIV(params *ECIESParams, rand io.Reader) (iv []byte, err error) { - iv = make([]byte, params.BlockSize) - _, err = io.ReadFull(rand, iv) - return -} - -// symEncrypt carries out CTR encryption using the block cipher specified in the -func symEncrypt(rand io.Reader, params *ECIESParams, key, m []byte) (ct []byte, err error) { - c, err := params.Cipher(key) - if err != nil { - return + if _, err := mac.Write(msg); err != nil { + return nil } - - iv, err := generateIV(params, rand) - if err != nil { - return + if _, err := mac.Write(shared); err != nil { + return nil } - ctr := cipher.NewCTR(c, iv) - - ct = make([]byte, len(m)+params.BlockSize) - copy(ct, iv) - ctr.XORKeyStream(ct[params.BlockSize:], m) - return + tag := mac.Sum(nil) + return tag } // symDecrypt carries out CTR decryption using the block cipher specified in @@ -229,45 +185,6 @@ func symDecrypt(params *ECIESParams, key, ct []byte) (m []byte, err error) { return } -// Encrypt encrypts a message using ECIES as specified in SEC 1, 5.1. -// -// s1 and s2 contain shared information that is not part of the resulting -// ciphertext. s1 is fed into key derivation, s2 is fed into the MAC. If the -// shared information parameters aren't being used, they should be nil. -func Encrypt(rand io.Reader, pub *PublicKey, m, s1, s2 []byte) (ct []byte, err error) { - params, err := pubkeyParams(pub) - if err != nil { - return nil, err - } - - R, err := GenerateKey(rand, pub.Curve, params) - if err != nil { - return nil, err - } - - z, err := R.GenerateShared(pub, params.KeyLen, params.KeyLen) - if err != nil { - return nil, err - } - - hash := params.Hash() - Ke, Km := deriveKeys(hash, z, s1, params.KeyLen) - - em, err := symEncrypt(rand, params, Ke, m) - if err != nil || len(em) <= params.BlockSize { - return nil, err - } - - d := messageTag(params.Hash, Km, em, s2) - - Rb := elliptic.Marshal(pub.Curve, R.PublicKey.X, R.PublicKey.Y) - ct = make([]byte, len(Rb)+len(em)+len(d)) - copy(ct, Rb) - copy(ct[len(Rb):], em) - copy(ct[len(Rb)+len(em):], d) - return ct, nil -} - // Decrypt decrypts an ECIES ciphertext. func (prv *PrivateKey) Decrypt(c, s1, s2 []byte) (m []byte, err error) { if len(c) == 0 { @@ -312,12 +229,17 @@ func (prv *PrivateKey) Decrypt(c, s1, s2 []byte) (m []byte, err error) { return nil, err } Ke, Km := deriveKeys(hash, z, s1, params.KeyLen) + if Ke == nil || Km == nil { + return nil, ErrInvalidPublicKey + } d := messageTag(params.Hash, Km, c[mStart:mEnd], s2) + if d == nil { + return nil, ErrInvalidMessage + } if subtle.ConstantTimeCompare(c[mEnd:], d) != 1 { return nil, ErrInvalidMessage } return symDecrypt(params, Ke, c[mStart:mEnd]) } - diff --git a/internal/ecies_params_ethereum.go b/internal/ecies_params_ethereum.go index 93bf8d9..d215021 100644 --- a/internal/ecies_params_ethereum.go +++ b/internal/ecies_params_ethereum.go @@ -27,7 +27,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -package ecies +package internal // This file contains parameters for ECIES encryption, specifying the // symmetric encryption and HMAC parameters. @@ -134,4 +134,3 @@ func pubkeyParams(key *PublicKey) (*ECIESParams, error) { } return params, nil } - From b1cb35a0fda45270b3b3dd15d330bf152bdb5a68 Mon Sep 17 00:00:00 2001 From: Andy Doan Date: Fri, 26 Jun 2020 14:37:03 -0500 Subject: [PATCH 5/7] ecies: Make handler generic to key source Signed-off-by: Andy Doan --- internal/ecies.go | 4 +-- internal/ecies_ethereum.go | 52 ++++++++++++------------------- internal/ecies_params_ethereum.go | 9 +++--- 3 files changed, 26 insertions(+), 39 deletions(-) diff --git a/internal/ecies.go b/internal/ecies.go index 74ce969..81f71b8 100644 --- a/internal/ecies.go +++ b/internal/ecies.go @@ -10,7 +10,7 @@ import ( ) type EciesCrypto struct { - PrivKey *PrivateKey + PrivKey PrivateKey } func NewEciesLocalHandler(privKey crypto.PrivateKey) CryptoHandler { @@ -25,7 +25,7 @@ func (ec *EciesCrypto) Decrypt(value string) ([]byte, error) { if err != nil { return nil, fmt.Errorf("Unable to base64 decode: %v", err) } - decrypted, err := ec.PrivKey.Decrypt(data, nil, nil) + decrypted, err := EciesDecrypt(ec.PrivKey, data, nil, nil) if err != nil { return nil, fmt.Errorf("Unable to ECIES decrypt %v", err) } diff --git a/internal/ecies_ethereum.go b/internal/ecies_ethereum.go index 5e8101a..8a418c6 100644 --- a/internal/ecies_ethereum.go +++ b/internal/ecies_ethereum.go @@ -42,55 +42,42 @@ import ( "encoding/binary" "fmt" "hash" - "math/big" ) var ( - ErrImport = fmt.Errorf("ecies: failed to import key") ErrInvalidCurve = fmt.Errorf("ecies: invalid elliptic curve") ErrInvalidPublicKey = fmt.Errorf("ecies: invalid public key") ErrSharedKeyIsPointAtInfinity = fmt.Errorf("ecies: shared key is point at infinity") ErrSharedKeyTooBig = fmt.Errorf("ecies: shared key params are too big") ) -// PublicKey is a representation of an elliptic curve public key. -type PublicKey struct { - X *big.Int - Y *big.Int - elliptic.Curve - Params *ECIESParams +type PrivateKey interface { + GenerateShared(pub *ecdsa.PublicKey, skLen, macLen int) (sk []byte, err error) + Public() *ecdsa.PublicKey } -// Import an ECDSA public key as an ECIES public key. -func ImportECDSAPublic(pub *ecdsa.PublicKey) *PublicKey { - return &PublicKey{ - X: pub.X, - Y: pub.Y, - Curve: pub.Curve, - Params: ParamsFromCurve(pub.Curve), - } -} - -// PrivateKey is a representation of an elliptic curve private key. -type PrivateKey struct { - PublicKey - D *big.Int +// PrivateKeyLocal is a representation of an elliptic curve private key. +type PrivateKeyLocal struct { + *ecdsa.PrivateKey } // Import an ECDSA private key as an ECIES private key. -func ImportECDSA(prv *ecdsa.PrivateKey) *PrivateKey { - pub := ImportECDSAPublic(&prv.PublicKey) - return &PrivateKey{*pub, prv.D} +func ImportECDSA(prv *ecdsa.PrivateKey) *PrivateKeyLocal { + return &PrivateKeyLocal{prv} } // MaxSharedKeyLength returns the maximum length of the shared key the // public key can produce. -func MaxSharedKeyLength(pub *PublicKey) int { +func MaxSharedKeyLength(pub *ecdsa.PublicKey) int { return (pub.Curve.Params().BitSize + 7) / 8 } +func (prv *PrivateKeyLocal) Public() *ecdsa.PublicKey { + return &prv.PublicKey +} + // ECDH key agreement method used to establish secret keys for encryption. -func (prv *PrivateKey) GenerateShared(pub *PublicKey, skLen, macLen int) (sk []byte, err error) { +func (prv *PrivateKeyLocal) GenerateShared(pub *ecdsa.PublicKey, skLen, macLen int) (sk []byte, err error) { if prv.PublicKey.Curve != pub.Curve { return nil, ErrInvalidCurve } @@ -186,11 +173,12 @@ func symDecrypt(params *ECIESParams, key, ct []byte) (m []byte, err error) { } // Decrypt decrypts an ECIES ciphertext. -func (prv *PrivateKey) Decrypt(c, s1, s2 []byte) (m []byte, err error) { +func EciesDecrypt(prv PrivateKey, c, s1, s2 []byte) (m []byte, err error) { if len(c) == 0 { return nil, ErrInvalidMessage } - params, err := pubkeyParams(&prv.PublicKey) + pub := prv.Public() + params, err := pubkeyParams(pub) if err != nil { return nil, err } @@ -206,7 +194,7 @@ func (prv *PrivateKey) Decrypt(c, s1, s2 []byte) (m []byte, err error) { switch c[0] { case 2, 3, 4: - rLen = (prv.PublicKey.Curve.Params().BitSize + 7) / 4 + rLen = (pub.Curve.Params().BitSize + 7) / 4 if len(c) < (rLen + hLen + 1) { return nil, ErrInvalidMessage } @@ -217,8 +205,8 @@ func (prv *PrivateKey) Decrypt(c, s1, s2 []byte) (m []byte, err error) { mStart = rLen mEnd = len(c) - hLen - R := new(PublicKey) - R.Curve = prv.PublicKey.Curve + R := new(ecdsa.PublicKey) + R.Curve = pub.Curve R.X, R.Y = elliptic.Unmarshal(R.Curve, c[:rLen]) if R.X == nil { return nil, ErrInvalidPublicKey diff --git a/internal/ecies_params_ethereum.go b/internal/ecies_params_ethereum.go index d215021..ace72bb 100644 --- a/internal/ecies_params_ethereum.go +++ b/internal/ecies_params_ethereum.go @@ -36,6 +36,7 @@ import ( "crypto" "crypto/aes" "crypto/cipher" + "crypto/ecdsa" "crypto/elliptic" "crypto/sha256" "crypto/sha512" @@ -122,12 +123,10 @@ func ParamsFromCurve(curve elliptic.Curve) (params *ECIESParams) { return paramsFromCurve[curve] } -func pubkeyParams(key *PublicKey) (*ECIESParams, error) { - params := key.Params +func pubkeyParams(key *ecdsa.PublicKey) (*ECIESParams, error) { + params := ParamsFromCurve(key.Curve) if params == nil { - if params = ParamsFromCurve(key.Curve); params == nil { - return nil, ErrUnsupportedECIESParameters - } + return nil, ErrUnsupportedECIESParameters } if params.KeyLen > maxKeyLen { return nil, ErrInvalidKeyLen From 29a6033f3c3ac7f31139c8fd845ae1339f1b89a9 Mon Sep 17 00:00:00 2001 From: Andy Doan Date: Fri, 26 Jun 2020 15:39:44 -0500 Subject: [PATCH 6/7] ecies: Pull in pkcs11 implementation Signed-off-by: Andy Doan --- internal/app.go | 2 +- internal/ecies.go | 4 ++-- internal/ecies_ethereum.go | 20 ++++++++++++++++++++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/internal/app.go b/internal/app.go index afa6896..9617500 100644 --- a/internal/app.go +++ b/internal/app.go @@ -119,7 +119,7 @@ func createClientPkcs11(sota *toml.Tree) (*http.Client, CryptoHandler) { } transport := &http.Transport{TLSClientConfig: tlsConfig} client := &http.Client{Timeout: time.Second * 30, Transport: transport} - return client, NewEciesPkcs11Handler(privKey) + return client, NewEciesPkcs11Handler(ctx, privKey) } func createClientLocal(sota *toml.Tree) (*http.Client, CryptoHandler) { diff --git a/internal/ecies.go b/internal/ecies.go index 81f71b8..b5d7791 100644 --- a/internal/ecies.go +++ b/internal/ecies.go @@ -32,6 +32,6 @@ func (ec *EciesCrypto) Decrypt(value string) ([]byte, error) { return decrypted, nil } -func NewEciesPkcs11Handler(privKey crypto11.Signer) CryptoHandler { - panic("NOT IMPLEMENTED") +func NewEciesPkcs11Handler(ctx *crypto11.Context, privKey crypto11.Signer) CryptoHandler { + return &EciesCrypto{ImportPcks11(ctx, privKey)} } diff --git a/internal/ecies_ethereum.go b/internal/ecies_ethereum.go index 8a418c6..faf8d24 100644 --- a/internal/ecies_ethereum.go +++ b/internal/ecies_ethereum.go @@ -34,6 +34,7 @@ package internal import ( + "crypto" "crypto/cipher" "crypto/ecdsa" "crypto/elliptic" @@ -42,6 +43,8 @@ import ( "encoding/binary" "fmt" "hash" + + "github.com/ThalesIgnite/crypto11" ) var ( @@ -66,6 +69,23 @@ func ImportECDSA(prv *ecdsa.PrivateKey) *PrivateKeyLocal { return &PrivateKeyLocal{prv} } +type PrivateKeyPkcs11 struct { + ctx *crypto11.Context + signer crypto11.Signer +} + +func ImportPcks11(ctx *crypto11.Context, privKey crypto.PrivateKey) *PrivateKeyPkcs11 { + return &PrivateKeyPkcs11{ctx, privKey.(crypto11.Signer)} +} + +func (prv *PrivateKeyPkcs11) GenerateShared(pub *ecdsa.PublicKey, skLen, macLen int) (sk []byte, err error) { + return prv.ctx.ECDH1Derive(prv.signer, pub) +} +func (prv *PrivateKeyPkcs11) Public() *ecdsa.PublicKey { + pub := prv.signer.Public() + return pub.(*ecdsa.PublicKey) +} + // MaxSharedKeyLength returns the maximum length of the shared key the // public key can produce. func MaxSharedKeyLength(pub *ecdsa.PublicKey) int { From fee3235bcbb7fd1c1634b5caeb2e13cb65c7e408 Mon Sep 17 00:00:00 2001 From: Andy Doan Date: Thu, 16 Jul 2020 14:30:50 -0500 Subject: [PATCH 7/7] Replace ThalesIgnite/crypto11 with patched version This is a temporary work-around while the PR gets sorted out: https://github.com/ThalesIgnite/crypto11/pull/70 Signed-off-by: Andy Doan --- go.mod | 2 ++ go.sum | 2 ++ 2 files changed, 4 insertions(+) diff --git a/go.mod b/go.mod index ffbf273..02600cc 100644 --- a/go.mod +++ b/go.mod @@ -8,3 +8,5 @@ require ( github.com/pelletier/go-toml v1.8.0 github.com/urfave/cli/v2 v2.2.0 ) + +replace github.com/ThalesIgnite/crypto11 => github.com/doanac/crypto11 v1.2.2-0.20200715151421-f3d2e17ac497 diff --git a/go.sum b/go.sum index 2a1c41a..dd3e64d 100644 --- a/go.sum +++ b/go.sum @@ -38,6 +38,8 @@ github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vs github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/doanac/crypto11 v1.2.2-0.20200715151421-f3d2e17ac497 h1:iyvvQeLbHqdu5L6x8OJLZ7rZb4tvoBs0h5liRkvIh6M= +github.com/doanac/crypto11 v1.2.2-0.20200715151421-f3d2e17ac497/go.mod h1:vmlYtalkn8uCp3eStRZ0r7Sslmf1jAtL8De0PIyqPks= github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/dop251/goja v0.0.0-20200106141417-aaec0e7bde29/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=