Skip to content

Commit

Permalink
pkcs11: backport integration test to release-1.4
Browse files Browse the repository at this point in the history
Signed-off-by: Matthew Sykes <sykesmat@us.ibm.com>
  • Loading branch information
sykesm authored and denyeart committed Mar 26, 2021
1 parent c810dca commit d276ee1
Show file tree
Hide file tree
Showing 5 changed files with 601 additions and 0 deletions.
9 changes: 9 additions & 0 deletions integration/nwo/fabricconfig/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,13 +146,22 @@ type Authentication struct {
type BCCSP struct {
Default string `yaml:"Default,omitempty"`
SW *SoftwareProvider `yaml:"SW,omitempty"`
PKCS11 *PKCS11 `yaml:"PKCS11,omitempty"`
}

type SoftwareProvider struct {
Hash string `yaml:"Hash,omitempty"`
Security int `yaml:"Security,omitempty"`
}

type PKCS11 struct {
Hash string `yaml:"Hash,omitempty"`
Security int `yaml:"Security,omitempty"`
Pin string `yaml:"Pin,omitempty"`
Label string `yaml:"Label,omitempty"`
Library string `yaml:"Library,omitempty"`
}

type DeliveryClient struct {
ReconnectTotalTimeThreshold time.Duration `yaml:"reconnectTotalTimeThreshold,omitempty"`
AddressOverrides []*AddressOverride `yaml:"addressOverrides,omitempty"`
Expand Down
22 changes: 22 additions & 0 deletions integration/nwo/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,28 @@ func (n *Network) userCryptoDir(org *Organization, nodeOrganizationType, user, c
)
}

// PeerOrgCADir returns the path to the folder containing the CA certificate(s) and/or
// keys for the specified peer organization.
func (n *Network) PeerOrgCADir(o *Organization) string {
return filepath.Join(
n.CryptoPath(),
"peerOrganizations",
o.Domain,
"ca",
)
}

// OrdererOrgCADir returns the path to the folder containing the CA certificate(s) and/or
// keys for the specified orderer organization.
func (n *Network) OrdererOrgCADir(o *Organization) string {
return filepath.Join(
n.CryptoPath(),
"ordererOrganizations",
o.Domain,
"ca",
)
}

// PeerUserMSPDir returns the path to the MSP directory containing the
// certificates and keys for the specified user of the peer.
func (n *Network) PeerUserMSPDir(p *Peer, user string) string {
Expand Down
62 changes: 62 additions & 0 deletions integration/pkcs11/p11key.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package pkcs11

import (
"crypto"
"crypto/ecdsa"
"encoding/asn1"
"fmt"
"io"
"math/big"

"github.com/miekg/pkcs11"
)

// P11ECDSAKey test implementation of crypto.Signer.
type P11ECDSAKey struct {
ctx *pkcs11.Ctx
session pkcs11.SessionHandle
publicKey *ecdsa.PublicKey
privateKeyHandle pkcs11.ObjectHandle
}

// Public returns the corresponding public key for the
// private key.
func (k *P11ECDSAKey) Public() crypto.PublicKey {
return k.publicKey
}

// Sign implements crypto.Signer Sign(). Signs the digest the with the private key and returns a byte signature.
func (k *P11ECDSAKey) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) (signature []byte, err error) {
if len(digest) != opts.HashFunc().Size() {
return nil, fmt.Errorf("digest length does not equal hash function length")
}

mech := []*pkcs11.Mechanism{
pkcs11.NewMechanism(pkcs11.CKM_ECDSA, nil),
}

err = k.ctx.SignInit(k.session, mech, k.privateKeyHandle)
if err != nil {
return nil, fmt.Errorf("sign init failed: %s", err)
}

signature, err = k.ctx.Sign(k.session, digest)
if err != nil {
return nil, fmt.Errorf("sign failed: %s", err)
}

type ECDSASignature struct{ R, S *big.Int }

R := new(big.Int)
S := new(big.Int)
R.SetBytes(signature[0 : len(signature)/2])
S.SetBytes(signature[len(signature)/2:])

return asn1.Marshal(ECDSASignature{R: R, S: S})
}
89 changes: 89 additions & 0 deletions integration/pkcs11/pkcs11_suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package pkcs11

import (
"encoding/json"
"testing"

bpkcs11 "github.com/hyperledger/fabric/bccsp/pkcs11"
"github.com/hyperledger/fabric/integration/nwo"
"github.com/hyperledger/fabric/integration/nwo/commands"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gbytes"
"github.com/onsi/gomega/gexec"
)

func TestPKCS11(t *testing.T) {
RegisterFailHandler(Fail)
lib, pin, label := bpkcs11.FindPKCS11Lib()
if lib == "" || pin == "" || label == "" {
t.Skip("Skipping PKCS11 Suite: Required ENV variables not set")
}
RunSpecs(t, "PKCS11 Suite")
}

var components *nwo.Components

var _ = SynchronizedBeforeSuite(func() []byte {
components = &nwo.Components{}
components.Build("-tags=pkcs11")

payload, err := json.Marshal(components)
Expect(err).NotTo(HaveOccurred())

return payload
}, func(payload []byte) {
err := json.Unmarshal(payload, &components)
Expect(err).NotTo(HaveOccurred())
})

var _ = SynchronizedAfterSuite(func() {
}, func() {
components.Cleanup()
})

func StartPort() int {
return 23000 + 300*GinkgoParallelNode()
}

func runQueryInvokeQuery(n *nwo.Network, orderer *nwo.Orderer, peer *nwo.Peer, channel string) {
By("querying the chaincode")
sess, err := n.PeerUserSession(peer, "User1", commands.ChaincodeQuery{
ChannelID: channel,
Name: "mycc",
Ctor: `{"Args":["query","a"]}`,
})
Expect(err).NotTo(HaveOccurred())
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
Expect(sess).To(gbytes.Say("100"))

sess, err = n.PeerUserSession(peer, "User1", commands.ChaincodeInvoke{
ChannelID: channel,
Orderer: n.OrdererAddress(orderer, nwo.ListenPort),
Name: "mycc",
Ctor: `{"Args":["invoke","a","b","10"]}`,
PeerAddresses: []string{
n.PeerAddress(n.Peer("Org1", "peer0"), nwo.ListenPort),
n.PeerAddress(n.Peer("Org2", "peer0"), nwo.ListenPort),
},
WaitForEvent: true,
})
Expect(err).NotTo(HaveOccurred())
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
Expect(sess.Err).To(gbytes.Say("Chaincode invoke successful. result: status:200"))

sess, err = n.PeerUserSession(peer, "User1", commands.ChaincodeQuery{
ChannelID: channel,
Name: "mycc",
Ctor: `{"Args":["query","a"]}`,
})
Expect(err).NotTo(HaveOccurred())
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
Expect(sess).To(gbytes.Say("90"))
}
Loading

0 comments on commit d276ee1

Please sign in to comment.